summaryrefslogtreecommitdiffstats
path: root/chrome/nsChromeProtocolHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/nsChromeProtocolHandler.cpp')
-rw-r--r--chrome/nsChromeProtocolHandler.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/chrome/nsChromeProtocolHandler.cpp b/chrome/nsChromeProtocolHandler.cpp
new file mode 100644
index 0000000000..b2e1e4d361
--- /dev/null
+++ b/chrome/nsChromeProtocolHandler.cpp
@@ -0,0 +1,166 @@
+/* -*- 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 "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::AllowPort(int32_t port, const char* scheme,
+ bool* _retval) {
+ // don't override anything.
+ *_retval = false;
+ return NS_OK;
+}
+
+/* static */ nsresult nsChromeProtocolHandler::CreateNewURI(
+ 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;
+ rv =
+ NS_MutateURI(new mozilla::net::nsStandardURL::Mutator())
+ .Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_STANDARD,
+ -1, aSpec, aCharset, aBaseURI, 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);
+ mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
+
+ surl.forget(result);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsChromeProtocolHandler::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
+ nsIChannel** aResult) {
+ nsresult rv;
+
+ NS_ENSURE_ARG_POINTER(aURI);
+ NS_ENSURE_ARG_POINTER(aLoadInfo);
+
+ MOZ_ASSERT(aResult, "Null out param");
+
+ nsCOMPtr<nsIURI> debugURL = aURI;
+ rv = nsChromeRegistry::Canonify(debugURL);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ 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::GetChromeRegistry();
+ 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;
+
+ // Use a system principal for /content and /skin files.
+ // See bug 1855225 for discussion about whether to extend it more generally
+ // to other chrome:// URIs.
+ nsAutoCString path;
+ aURI->GetPathQueryRef(path);
+ if (StringBeginsWith(path, "/content/"_ns) ||
+ StringBeginsWith(path, "/skin/"_ns)) {
+ 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("UTF-8"_ns);
+
+ result.forget(aResult);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////