1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set ts=4 sw=4 sts=4 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 "nsThreadUtils.h"
17 #include "nsIChannel.h"
18 #include "nsIChromeRegistry.h"
20 #include "nsIFileChannel.h"
21 #include "nsIIOService.h"
22 #include "nsILoadGroup.h"
23 #include "nsIScriptSecurityManager.h"
24 #include "nsIStandardURL.h"
25 #include "nsNetUtil.h"
28 ////////////////////////////////////////////////////////////////////////////////
30 NS_IMPL_ISUPPORTS(nsChromeProtocolHandler
,
32 nsISupportsWeakReference
)
34 ////////////////////////////////////////////////////////////////////////////////
35 // nsIProtocolHandler methods:
38 nsChromeProtocolHandler::GetScheme(nsACString
&result
)
40 result
.AssignLiteral("chrome");
45 nsChromeProtocolHandler::GetDefaultPort(int32_t *result
)
47 *result
= -1; // no port for chrome: URLs
52 nsChromeProtocolHandler::AllowPort(int32_t port
, const char *scheme
, bool *_retval
)
54 // don't override anything.
60 nsChromeProtocolHandler::GetProtocolFlags(uint32_t *result
)
62 *result
= URI_STD
| URI_IS_UI_RESOURCE
| URI_IS_LOCAL_RESOURCE
;
67 nsChromeProtocolHandler::NewURI(const nsACString
&aSpec
,
74 // Chrome: URLs (currently) have no additional structure beyond that provided
75 // by standard URLs, so there is no "outer" given to CreateInstance
77 nsCOMPtr
<nsIStandardURL
> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID
, &rv
));
78 NS_ENSURE_SUCCESS(rv
, rv
);
80 rv
= surl
->Init(nsIStandardURL::URLTYPE_STANDARD
, -1, aSpec
, aCharset
, aBaseURI
);
84 nsCOMPtr
<nsIURL
> url(do_QueryInterface(surl
, &rv
));
85 NS_ENSURE_SUCCESS(rv
, rv
);
87 // Canonify the "chrome:" URL; e.g., so that we collapse
88 // "chrome://navigator/content/" and "chrome://navigator/content"
89 // and "chrome://navigator/content/navigator.xul".
91 rv
= nsChromeRegistry::Canonify(url
);
95 surl
->SetMutable(false);
97 NS_ADDREF(*result
= url
);
102 nsChromeProtocolHandler::NewChannel2(nsIURI
* aURI
,
103 nsILoadInfo
* aLoadInfo
,
104 nsIChannel
** aResult
)
108 NS_ENSURE_ARG_POINTER(aURI
);
109 NS_PRECONDITION(aResult
, "Null out param");
112 // Check that the uri we got is already canonified
114 nsCOMPtr
<nsIURI
> debugClone
;
115 debug_rv
= aURI
->Clone(getter_AddRefs(debugClone
));
116 if (NS_SUCCEEDED(debug_rv
)) {
117 nsCOMPtr
<nsIURL
> debugURL (do_QueryInterface(debugClone
));
118 debug_rv
= nsChromeRegistry::Canonify(debugURL
);
119 if (NS_SUCCEEDED(debug_rv
)) {
121 debug_rv
= aURI
->Equals(debugURL
, &same
);
122 if (NS_SUCCEEDED(debug_rv
)) {
123 NS_ASSERTION(same
, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
129 nsCOMPtr
<nsIChannel
> result
;
131 if (!nsChromeRegistry::gChromeRegistry
) {
132 // We don't actually want this ref, we just want the service to
133 // initialize if it hasn't already.
134 nsCOMPtr
<nsIChromeRegistry
> reg
=
135 mozilla::services::GetChromeRegistryService();
136 NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry
, NS_ERROR_FAILURE
);
139 nsCOMPtr
<nsIURI
> resolvedURI
;
140 rv
= nsChromeRegistry::gChromeRegistry
->ConvertChromeURL(aURI
, getter_AddRefs(resolvedURI
));
145 printf("Couldn't convert chrome URL: %s\n", spec
.get());
150 // Bug 1087720 (and Bug 1099296):
151 // Once all callsites have been updated to call NewChannel2() instead of NewChannel()
152 // we should have a non-null loadInfo consistently. Until then we have to branch on the
155 rv
= NS_NewChannelInternal(getter_AddRefs(result
),
160 nsCOMPtr
<nsIIOService
> ioServ(do_GetIOService(&rv
));
161 NS_ENSURE_SUCCESS(rv
, rv
);
162 rv
= ioServ
->NewChannelFromURI(resolvedURI
, getter_AddRefs(result
));
164 NS_ENSURE_SUCCESS(rv
, rv
);
167 nsCOMPtr
<nsIFileChannel
> fileChan(do_QueryInterface(result
));
169 nsCOMPtr
<nsIFile
> file
;
170 fileChan
->GetFile(getter_AddRefs(file
));
173 file
->Exists(&exists
);
176 file
->GetNativePath(path
);
177 printf("Chrome file doesn't exist: %s\n", path
.get());
182 // Make sure that the channel remembers where it was
183 // originally loaded from.
184 nsLoadFlags loadFlags
= 0;
185 result
->GetLoadFlags(&loadFlags
);
186 result
->SetLoadFlags(loadFlags
& ~nsIChannel::LOAD_REPLACE
);
187 rv
= result
->SetOriginalURI(aURI
);
188 if (NS_FAILED(rv
)) return rv
;
190 // Get a system principal for content files and set the owner
191 // property of the result
192 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(aURI
);
194 rv
= url
->GetPath(path
);
195 if (StringBeginsWith(path
, NS_LITERAL_CSTRING("/content/")))
197 nsCOMPtr
<nsIScriptSecurityManager
> securityManager
=
198 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID
, &rv
);
199 if (NS_FAILED(rv
)) return rv
;
201 nsCOMPtr
<nsIPrincipal
> principal
;
202 rv
= securityManager
->GetSystemPrincipal(getter_AddRefs(principal
));
203 if (NS_FAILED(rv
)) return rv
;
205 nsCOMPtr
<nsISupports
> owner
= do_QueryInterface(principal
);
206 result
->SetOwner(owner
);
209 // XXX Removed dependency-tracking code from here, because we're not
210 // tracking them anyways (with fastload we checked only in DEBUG
211 // and with startupcache not at all), but this is where we would start
212 // if we need to re-add.
213 // See bug 531886, bug 533038.
214 result
->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
222 nsChromeProtocolHandler::NewChannel(nsIURI
* aURI
,
223 nsIChannel
* *aResult
)
225 return NewChannel2(aURI
, nullptr, aResult
);
228 ////////////////////////////////////////////////////////////////////////////////