Bug 1609637 [wpt PR 21217] - [WPT/common/security-features] Support sub projects...
[gecko.git] / chrome / nsChromeProtocolHandler.cpp
blob9edbbdeafe4eb92b660b041584047af2ab281fa4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=4 sw=2 sts=2 et cin: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
9 A protocol handler for ``chrome:''
13 #include "nsChromeProtocolHandler.h"
14 #include "nsChromeRegistry.h"
15 #include "nsCOMPtr.h"
16 #include "nsContentUtils.h"
17 #include "nsThreadUtils.h"
18 #include "nsIChannel.h"
19 #include "nsIChromeRegistry.h"
20 #include "nsIFile.h"
21 #include "nsIFileChannel.h"
22 #include "nsIStandardURL.h"
23 #include "nsNetUtil.h"
24 #include "nsNetCID.h"
25 #include "nsIURL.h"
26 #include "nsString.h"
27 #include "nsStandardURL.h"
29 ////////////////////////////////////////////////////////////////////////////////
31 NS_IMPL_ISUPPORTS(nsChromeProtocolHandler, nsIProtocolHandler,
32 nsISupportsWeakReference)
34 ////////////////////////////////////////////////////////////////////////////////
35 // nsIProtocolHandler methods:
37 NS_IMETHODIMP
38 nsChromeProtocolHandler::GetScheme(nsACString& result) {
39 result.AssignLiteral("chrome");
40 return NS_OK;
43 NS_IMETHODIMP
44 nsChromeProtocolHandler::GetDefaultPort(int32_t* result) {
45 *result = -1; // no port for chrome: URLs
46 return NS_OK;
49 NS_IMETHODIMP
50 nsChromeProtocolHandler::AllowPort(int32_t port, const char* scheme,
51 bool* _retval) {
52 // don't override anything.
53 *_retval = false;
54 return NS_OK;
57 NS_IMETHODIMP
58 nsChromeProtocolHandler::GetProtocolFlags(uint32_t* result) {
59 *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
60 return NS_OK;
63 /* static */ nsresult nsChromeProtocolHandler::CreateNewURI(
64 const nsACString& aSpec, const char* aCharset, nsIURI* aBaseURI,
65 nsIURI** result) {
66 // Chrome: URLs (currently) have no additional structure beyond that provided
67 // by standard URLs, so there is no "outer" given to CreateInstance
68 nsresult rv;
69 nsCOMPtr<nsIURI> surl;
70 nsCOMPtr<nsIURI> base(aBaseURI);
71 rv = NS_MutateURI(new mozilla::net::nsStandardURL::Mutator())
72 .Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
73 nsIStandardURL::URLTYPE_STANDARD, -1,
74 nsCString(aSpec), aCharset, base, nullptr))
75 .Finalize(surl);
76 if (NS_FAILED(rv)) {
77 return rv;
80 // Canonify the "chrome:" URL; e.g., so that we collapse
81 // "chrome://navigator/content/" and "chrome://navigator/content"
82 // and "chrome://navigator/content/navigator.xul".
84 rv = nsChromeRegistry::Canonify(surl);
85 if (NS_FAILED(rv)) return rv;
87 surl.forget(result);
88 return NS_OK;
91 NS_IMETHODIMP
92 nsChromeProtocolHandler::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
93 nsIChannel** aResult) {
94 nsresult rv;
96 NS_ENSURE_ARG_POINTER(aURI);
97 NS_ENSURE_ARG_POINTER(aLoadInfo);
99 MOZ_ASSERT(aResult, "Null out param");
101 #ifdef DEBUG
102 // Check that the uri we got is already canonified
103 nsresult debug_rv;
104 nsCOMPtr<nsIURI> debugURL = aURI;
105 debug_rv = nsChromeRegistry::Canonify(debugURL);
106 if (NS_SUCCEEDED(debug_rv)) {
107 bool same;
108 debug_rv = aURI->Equals(debugURL, &same);
109 if (NS_SUCCEEDED(debug_rv)) {
110 NS_ASSERTION(same,
111 "Non-canonified chrome uri passed to "
112 "nsChromeProtocolHandler::NewChannel!");
115 #endif
117 nsCOMPtr<nsIChannel> result;
119 if (!nsChromeRegistry::gChromeRegistry) {
120 // We don't actually want this ref, we just want the service to
121 // initialize if it hasn't already.
122 nsCOMPtr<nsIChromeRegistry> reg =
123 mozilla::services::GetChromeRegistryService();
124 NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
127 nsCOMPtr<nsIURI> resolvedURI;
128 rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(
129 aURI, getter_AddRefs(resolvedURI));
130 if (NS_FAILED(rv)) {
131 #ifdef DEBUG
132 printf("Couldn't convert chrome URL: %s\n", aURI->GetSpecOrDefault().get());
133 #endif
134 return rv;
137 // We don't want to allow the inner protocol handler modify the result
138 // principal URI since we want either |aURI| or anything pre-set by upper
139 // layers to prevail.
140 nsCOMPtr<nsIURI> savedResultPrincipalURI;
141 rv =
142 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI));
143 NS_ENSURE_SUCCESS(rv, rv);
145 rv = NS_NewChannelInternal(getter_AddRefs(result), resolvedURI, aLoadInfo);
146 NS_ENSURE_SUCCESS(rv, rv);
148 #ifdef DEBUG
149 nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
150 if (fileChan) {
151 nsCOMPtr<nsIFile> file;
152 fileChan->GetFile(getter_AddRefs(file));
154 bool exists = false;
155 file->Exists(&exists);
156 if (!exists) {
157 printf("Chrome file doesn't exist: %s\n",
158 file->HumanReadablePath().get());
161 #endif
163 // Make sure that the channel remembers where it was
164 // originally loaded from.
165 rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI);
166 NS_ENSURE_SUCCESS(rv, rv);
167 rv = result->SetOriginalURI(aURI);
168 if (NS_FAILED(rv)) return rv;
170 // Get a system principal for content files and set the owner
171 // property of the result
172 nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
173 nsAutoCString path;
174 rv = url->GetPathQueryRef(path);
175 if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/"))) {
176 result->SetOwner(nsContentUtils::GetSystemPrincipal());
179 // XXX Removed dependency-tracking code from here, because we're not
180 // tracking them anyways (with fastload we checked only in DEBUG
181 // and with startupcache not at all), but this is where we would start
182 // if we need to re-add.
183 // See bug 531886, bug 533038.
184 result->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
186 *aResult = result;
187 NS_ADDREF(*aResult);
188 return NS_OK;
191 ////////////////////////////////////////////////////////////////////////////////