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/. */
9 A protocol handler for ``chrome:''
13 #include "nsChromeProtocolHandler.h"
14 #include "nsChromeRegistry.h"
16 #include "nsContentUtils.h"
17 #include "nsThreadUtils.h"
18 #include "nsIChannel.h"
19 #include "nsIChromeRegistry.h"
21 #include "nsIFileChannel.h"
22 #include "nsIIOService.h"
23 #include "nsILoadGroup.h"
24 #include "nsIScriptSecurityManager.h"
25 #include "nsIStandardURL.h"
26 #include "nsNetUtil.h"
30 #include "nsStandardURL.h"
32 ////////////////////////////////////////////////////////////////////////////////
34 NS_IMPL_ISUPPORTS(nsChromeProtocolHandler
, nsIProtocolHandler
,
35 nsISupportsWeakReference
)
37 ////////////////////////////////////////////////////////////////////////////////
38 // nsIProtocolHandler methods:
41 nsChromeProtocolHandler::GetScheme(nsACString
&result
) {
42 result
.AssignLiteral("chrome");
47 nsChromeProtocolHandler::GetDefaultPort(int32_t *result
) {
48 *result
= -1; // no port for chrome: URLs
53 nsChromeProtocolHandler::AllowPort(int32_t port
, const char *scheme
,
55 // don't override anything.
61 nsChromeProtocolHandler::GetProtocolFlags(uint32_t *result
) {
62 *result
= URI_STD
| URI_IS_UI_RESOURCE
| URI_IS_LOCAL_RESOURCE
;
67 nsChromeProtocolHandler::NewURI(const nsACString
&aSpec
, const char *aCharset
,
68 nsIURI
*aBaseURI
, nsIURI
**result
) {
69 // Chrome: URLs (currently) have no additional structure beyond that provided
70 // by standard URLs, so there is no "outer" given to CreateInstance
72 nsCOMPtr
<nsIURI
> surl
;
73 nsCOMPtr
<nsIURI
> base(aBaseURI
);
74 rv
= NS_MutateURI(new mozilla::net::nsStandardURL::Mutator())
75 .Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init
,
76 nsIStandardURL::URLTYPE_STANDARD
, -1,
77 nsCString(aSpec
), aCharset
, base
, nullptr))
83 // Canonify the "chrome:" URL; e.g., so that we collapse
84 // "chrome://navigator/content/" and "chrome://navigator/content"
85 // and "chrome://navigator/content/navigator.xul".
87 rv
= nsChromeRegistry::Canonify(surl
);
88 if (NS_FAILED(rv
)) return rv
;
95 nsChromeProtocolHandler::NewChannel2(nsIURI
*aURI
, nsILoadInfo
*aLoadInfo
,
96 nsIChannel
**aResult
) {
99 NS_ENSURE_ARG_POINTER(aURI
);
100 NS_ENSURE_ARG_POINTER(aLoadInfo
);
102 MOZ_ASSERT(aResult
, "Null out param");
105 // Check that the uri we got is already canonified
107 nsCOMPtr
<nsIURI
> debugURL
= aURI
;
108 debug_rv
= nsChromeRegistry::Canonify(debugURL
);
109 if (NS_SUCCEEDED(debug_rv
)) {
111 debug_rv
= aURI
->Equals(debugURL
, &same
);
112 if (NS_SUCCEEDED(debug_rv
)) {
114 "Non-canonified chrome uri passed to "
115 "nsChromeProtocolHandler::NewChannel!");
120 nsCOMPtr
<nsIChannel
> result
;
122 if (!nsChromeRegistry::gChromeRegistry
) {
123 // We don't actually want this ref, we just want the service to
124 // initialize if it hasn't already.
125 nsCOMPtr
<nsIChromeRegistry
> reg
=
126 mozilla::services::GetChromeRegistryService();
127 NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry
, NS_ERROR_FAILURE
);
130 nsCOMPtr
<nsIURI
> resolvedURI
;
131 rv
= nsChromeRegistry::gChromeRegistry
->ConvertChromeURL(
132 aURI
, getter_AddRefs(resolvedURI
));
135 printf("Couldn't convert chrome URL: %s\n", aURI
->GetSpecOrDefault().get());
140 // We don't want to allow the inner protocol handler modify the result
141 // principal URI since we want either |aURI| or anything pre-set by upper
142 // layers to prevail.
143 nsCOMPtr
<nsIURI
> savedResultPrincipalURI
;
145 aLoadInfo
->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI
));
146 NS_ENSURE_SUCCESS(rv
, rv
);
148 rv
= NS_NewChannelInternal(getter_AddRefs(result
), resolvedURI
, aLoadInfo
);
149 NS_ENSURE_SUCCESS(rv
, rv
);
152 nsCOMPtr
<nsIFileChannel
> fileChan(do_QueryInterface(result
));
154 nsCOMPtr
<nsIFile
> file
;
155 fileChan
->GetFile(getter_AddRefs(file
));
158 file
->Exists(&exists
);
160 printf("Chrome file doesn't exist: %s\n",
161 file
->HumanReadablePath().get());
166 // Make sure that the channel remembers where it was
167 // originally loaded from.
168 rv
= aLoadInfo
->SetResultPrincipalURI(savedResultPrincipalURI
);
169 NS_ENSURE_SUCCESS(rv
, rv
);
170 rv
= result
->SetOriginalURI(aURI
);
171 if (NS_FAILED(rv
)) return rv
;
173 // Get a system principal for content files and set the owner
174 // property of the result
175 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(aURI
);
177 rv
= url
->GetPathQueryRef(path
);
178 if (StringBeginsWith(path
, NS_LITERAL_CSTRING("/content/"))) {
179 result
->SetOwner(nsContentUtils::GetSystemPrincipal());
182 // XXX Removed dependency-tracking code from here, because we're not
183 // tracking them anyways (with fastload we checked only in DEBUG
184 // and with startupcache not at all), but this is where we would start
185 // if we need to re-add.
186 // See bug 531886, bug 533038.
187 result
->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
195 nsChromeProtocolHandler::NewChannel(nsIURI
*aURI
, nsIChannel
**aResult
) {
196 return NewChannel2(aURI
, nullptr, aResult
);
199 ////////////////////////////////////////////////////////////////////////////////