Line data Source code
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/. */
6 :
7 : /*
8 :
9 : A protocol handler for ``chrome:''
10 :
11 : */
12 :
13 : #include "nsChromeProtocolHandler.h"
14 : #include "nsChromeRegistry.h"
15 : #include "nsCOMPtr.h"
16 : #include "nsThreadUtils.h"
17 : #include "nsIChannel.h"
18 : #include "nsIChromeRegistry.h"
19 : #include "nsIFile.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"
26 : #include "nsNetCID.h"
27 : #include "nsIURL.h"
28 : #include "nsString.h"
29 : #include "nsStandardURL.h"
30 :
31 : ////////////////////////////////////////////////////////////////////////////////
32 :
33 8461 : NS_IMPL_ISUPPORTS(nsChromeProtocolHandler,
34 : nsIProtocolHandler,
35 : nsISupportsWeakReference)
36 :
37 : ////////////////////////////////////////////////////////////////////////////////
38 : // nsIProtocolHandler methods:
39 :
40 : NS_IMETHODIMP
41 0 : nsChromeProtocolHandler::GetScheme(nsACString &result)
42 : {
43 0 : result.AssignLiteral("chrome");
44 0 : return NS_OK;
45 : }
46 :
47 : NS_IMETHODIMP
48 0 : nsChromeProtocolHandler::GetDefaultPort(int32_t *result)
49 : {
50 0 : *result = -1; // no port for chrome: URLs
51 0 : return NS_OK;
52 : }
53 :
54 : NS_IMETHODIMP
55 0 : nsChromeProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
56 : {
57 : // don't override anything.
58 0 : *_retval = false;
59 0 : return NS_OK;
60 : }
61 :
62 : NS_IMETHODIMP
63 788 : nsChromeProtocolHandler::GetProtocolFlags(uint32_t *result)
64 : {
65 788 : *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
66 788 : return NS_OK;
67 : }
68 :
69 : NS_IMETHODIMP
70 464 : nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
71 : const char *aCharset,
72 : nsIURI *aBaseURI,
73 : nsIURI **result)
74 : {
75 :
76 : // Chrome: URLs (currently) have no additional structure beyond that provided
77 : // by standard URLs, so there is no "outer" given to CreateInstance
78 :
79 928 : RefPtr<mozilla::net::nsStandardURL> surl = new mozilla::net::nsStandardURL();
80 :
81 464 : nsresult rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec,
82 464 : aCharset, aBaseURI);
83 464 : if (NS_FAILED(rv))
84 0 : return rv;
85 :
86 : // Canonify the "chrome:" URL; e.g., so that we collapse
87 : // "chrome://navigator/content/" and "chrome://navigator/content"
88 : // and "chrome://navigator/content/navigator.xul".
89 :
90 464 : rv = nsChromeRegistry::Canonify(surl);
91 464 : if (NS_FAILED(rv))
92 0 : return rv;
93 :
94 464 : surl->SetMutable(false);
95 :
96 464 : surl.forget(result);
97 464 : return NS_OK;
98 : }
99 :
100 : NS_IMETHODIMP
101 125 : nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
102 : nsILoadInfo* aLoadInfo,
103 : nsIChannel** aResult)
104 : {
105 : nsresult rv;
106 :
107 125 : NS_ENSURE_ARG_POINTER(aURI);
108 125 : NS_ENSURE_ARG_POINTER(aLoadInfo);
109 :
110 125 : NS_PRECONDITION(aResult, "Null out param");
111 :
112 : #ifdef DEBUG
113 : // Check that the uri we got is already canonified
114 : nsresult debug_rv;
115 250 : nsCOMPtr<nsIURI> debugClone;
116 125 : debug_rv = aURI->Clone(getter_AddRefs(debugClone));
117 125 : if (NS_SUCCEEDED(debug_rv)) {
118 250 : nsCOMPtr<nsIURL> debugURL (do_QueryInterface(debugClone));
119 125 : debug_rv = nsChromeRegistry::Canonify(debugURL);
120 125 : if (NS_SUCCEEDED(debug_rv)) {
121 : bool same;
122 125 : debug_rv = aURI->Equals(debugURL, &same);
123 125 : if (NS_SUCCEEDED(debug_rv)) {
124 125 : NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
125 : }
126 : }
127 : }
128 : #endif
129 :
130 250 : nsCOMPtr<nsIChannel> result;
131 :
132 125 : if (!nsChromeRegistry::gChromeRegistry) {
133 : // We don't actually want this ref, we just want the service to
134 : // initialize if it hasn't already.
135 : nsCOMPtr<nsIChromeRegistry> reg =
136 0 : mozilla::services::GetChromeRegistryService();
137 0 : NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
138 : }
139 :
140 250 : nsCOMPtr<nsIURI> resolvedURI;
141 125 : rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
142 125 : if (NS_FAILED(rv)) {
143 : #ifdef DEBUG
144 0 : printf("Couldn't convert chrome URL: %s\n",
145 0 : aURI->GetSpecOrDefault().get());
146 : #endif
147 0 : return rv;
148 : }
149 :
150 : // We don't want to allow the inner protocol handler modify the result principal URI
151 : // since we want either |aURI| or anything pre-set by upper layers to prevail.
152 250 : nsCOMPtr<nsIURI> savedResultPrincipalURI;
153 125 : rv = aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI));
154 125 : NS_ENSURE_SUCCESS(rv, rv);
155 :
156 125 : rv = NS_NewChannelInternal(getter_AddRefs(result),
157 : resolvedURI,
158 : aLoadInfo);
159 125 : NS_ENSURE_SUCCESS(rv, rv);
160 :
161 : #ifdef DEBUG
162 250 : nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
163 125 : if (fileChan) {
164 250 : nsCOMPtr<nsIFile> file;
165 125 : fileChan->GetFile(getter_AddRefs(file));
166 :
167 125 : bool exists = false;
168 125 : file->Exists(&exists);
169 125 : if (!exists) {
170 0 : nsAutoCString path;
171 0 : file->GetNativePath(path);
172 0 : printf("Chrome file doesn't exist: %s\n", path.get());
173 : }
174 : }
175 : #endif
176 :
177 : // Make sure that the channel remembers where it was
178 : // originally loaded from.
179 125 : rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI);
180 125 : NS_ENSURE_SUCCESS(rv, rv);
181 125 : rv = result->SetOriginalURI(aURI);
182 125 : if (NS_FAILED(rv)) return rv;
183 :
184 : // Get a system principal for content files and set the owner
185 : // property of the result
186 250 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
187 250 : nsAutoCString path;
188 125 : rv = url->GetPath(path);
189 125 : if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/")))
190 : {
191 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
192 78 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
193 39 : if (NS_FAILED(rv)) return rv;
194 :
195 78 : nsCOMPtr<nsIPrincipal> principal;
196 39 : rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
197 39 : if (NS_FAILED(rv)) return rv;
198 :
199 78 : nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
200 39 : result->SetOwner(owner);
201 : }
202 :
203 : // XXX Removed dependency-tracking code from here, because we're not
204 : // tracking them anyways (with fastload we checked only in DEBUG
205 : // and with startupcache not at all), but this is where we would start
206 : // if we need to re-add.
207 : // See bug 531886, bug 533038.
208 125 : result->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
209 :
210 125 : *aResult = result;
211 125 : NS_ADDREF(*aResult);
212 125 : return NS_OK;
213 : }
214 :
215 : NS_IMETHODIMP
216 0 : nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
217 : nsIChannel* *aResult)
218 : {
219 0 : return NewChannel2(aURI, nullptr, aResult);
220 : }
221 :
222 : ////////////////////////////////////////////////////////////////////////////////
|