chrome/nsChromeProtocolHandler.cpp
author L10n Bumper Bot <release+l10nbumper@mozilla.com>
Mon, 17 Dec 2018 05:00:11 -0800
changeset 506261 e8f9d8975d0f9702b320f8cfcd989bd88db6273d
parent 505471 66eb1f485c1a3ea81372758bc92292c9428b17cd
child 517975 ec2056010064217db0dc48b9a70a7174eb3d254a
permissions -rw-r--r--
no bug - Bumping Fennec l10n changesets r=release a=l10n-bump DONTBUILD an -> 176758dc0404 dsb -> 4614a05cf396 fy-NL -> 329815f0d288 gd -> 3d6b27ee5e58 hi-IN -> a886e2b55636 hsb -> a1da7baaac2c hy-AM -> 6f231310c387 kab -> 2cbdc076a185 kk -> 1753bd996be6 lo -> 18b2a9d5cd35 mai -> 0de2b15a802b mr -> 69f8bd0a8e45 ru -> 49be174d9b2b sv-SE -> 4eb4d6069f79 tr -> ace765b25800 trs -> ccc0b3063a5b uk -> 4013e6bffec1 ur -> 8df00f58a967 uz -> a36b000cfbb4

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=4 sw=2 sts=2 et cin: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*

  A protocol handler for ``chrome:''

*/

#include "nsChromeProtocolHandler.h"
#include "nsChromeRegistry.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "nsIChannel.h"
#include "nsIChromeRegistry.h"
#include "nsIFile.h"
#include "nsIFileChannel.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIScriptSecurityManager.h"
#include "nsIStandardURL.h"
#include "nsNetUtil.h"
#include "nsNetCID.h"
#include "nsIURL.h"
#include "nsString.h"
#include "nsStandardURL.h"

////////////////////////////////////////////////////////////////////////////////

NS_IMPL_ISUPPORTS(nsChromeProtocolHandler, nsIProtocolHandler,
                  nsISupportsWeakReference)

////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:

NS_IMETHODIMP
nsChromeProtocolHandler::GetScheme(nsACString &result) {
  result.AssignLiteral("chrome");
  return NS_OK;
}

NS_IMETHODIMP
nsChromeProtocolHandler::GetDefaultPort(int32_t *result) {
  *result = -1;  // no port for chrome: URLs
  return NS_OK;
}

NS_IMETHODIMP
nsChromeProtocolHandler::AllowPort(int32_t port, const char *scheme,
                                   bool *_retval) {
  // don't override anything.
  *_retval = false;
  return NS_OK;
}

NS_IMETHODIMP
nsChromeProtocolHandler::GetProtocolFlags(uint32_t *result) {
  *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
  return NS_OK;
}

NS_IMETHODIMP
nsChromeProtocolHandler::NewURI(const nsACString &aSpec, const char *aCharset,
                                nsIURI *aBaseURI, nsIURI **result) {
  // Chrome: URLs (currently) have no additional structure beyond that provided
  // by standard URLs, so there is no "outer" given to CreateInstance
  nsresult rv;
  nsCOMPtr<nsIURI> surl;
  nsCOMPtr<nsIURI> base(aBaseURI);
  rv = NS_MutateURI(new mozilla::net::nsStandardURL::Mutator())
           .Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
                                   nsIStandardURL::URLTYPE_STANDARD, -1,
                                   nsCString(aSpec), aCharset, base, nullptr))
           .Finalize(surl);
  if (NS_FAILED(rv)) {
    return rv;
  }

  // Canonify the "chrome:" URL; e.g., so that we collapse
  // "chrome://navigator/content/" and "chrome://navigator/content"
  // and "chrome://navigator/content/navigator.xul".

  rv = nsChromeRegistry::Canonify(surl);
  if (NS_FAILED(rv)) return rv;

  surl.forget(result);
  return NS_OK;
}

NS_IMETHODIMP
nsChromeProtocolHandler::NewChannel2(nsIURI *aURI, nsILoadInfo *aLoadInfo,
                                     nsIChannel **aResult) {
  nsresult rv;

  NS_ENSURE_ARG_POINTER(aURI);
  NS_ENSURE_ARG_POINTER(aLoadInfo);

  MOZ_ASSERT(aResult, "Null out param");

#ifdef DEBUG
  // Check that the uri we got is already canonified
  nsresult debug_rv;
  nsCOMPtr<nsIURI> debugURL = aURI;
  debug_rv = nsChromeRegistry::Canonify(debugURL);
  if (NS_SUCCEEDED(debug_rv)) {
    bool same;
    debug_rv = aURI->Equals(debugURL, &same);
    if (NS_SUCCEEDED(debug_rv)) {
      NS_ASSERTION(same,
                   "Non-canonified chrome uri passed to "
                   "nsChromeProtocolHandler::NewChannel!");
    }
  }
#endif

  nsCOMPtr<nsIChannel> result;

  if (!nsChromeRegistry::gChromeRegistry) {
    // We don't actually want this ref, we just want the service to
    // initialize if it hasn't already.
    nsCOMPtr<nsIChromeRegistry> reg =
        mozilla::services::GetChromeRegistryService();
    NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
  }

  nsCOMPtr<nsIURI> resolvedURI;
  rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(
      aURI, getter_AddRefs(resolvedURI));
  if (NS_FAILED(rv)) {
#ifdef DEBUG
    printf("Couldn't convert chrome URL: %s\n", aURI->GetSpecOrDefault().get());
#endif
    return rv;
  }

  // We don't want to allow the inner protocol handler modify the result
  // principal URI since we want either |aURI| or anything pre-set by upper
  // layers to prevail.
  nsCOMPtr<nsIURI> savedResultPrincipalURI;
  rv =
      aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = NS_NewChannelInternal(getter_AddRefs(result), resolvedURI, aLoadInfo);
  NS_ENSURE_SUCCESS(rv, rv);

#ifdef DEBUG
  nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
  if (fileChan) {
    nsCOMPtr<nsIFile> file;
    fileChan->GetFile(getter_AddRefs(file));

    bool exists = false;
    file->Exists(&exists);
    if (!exists) {
      printf("Chrome file doesn't exist: %s\n",
             file->HumanReadablePath().get());
    }
  }
#endif

  // Make sure that the channel remembers where it was
  // originally loaded from.
  rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = result->SetOriginalURI(aURI);
  if (NS_FAILED(rv)) return rv;

  // Get a system principal for content files and set the owner
  // property of the result
  nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
  nsAutoCString path;
  rv = url->GetPathQueryRef(path);
  if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/"))) {
    result->SetOwner(nsContentUtils::GetSystemPrincipal());
  }

  // XXX Removed dependency-tracking code from here, because we're not
  // tracking them anyways (with fastload we checked only in DEBUG
  // and with startupcache not at all), but this is where we would start
  // if we need to re-add.
  // See bug 531886, bug 533038.
  result->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));

  *aResult = result;
  NS_ADDREF(*aResult);
  return NS_OK;
}

NS_IMETHODIMP
nsChromeProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult) {
  return NewChannel2(aURI, nullptr, aResult);
}

////////////////////////////////////////////////////////////////////////////////