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 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : /*
40 :
41 : A protocol handler for ``chrome:''
42 :
43 : */
44 :
45 : #include "nsAutoPtr.h"
46 : #include "nsChromeProtocolHandler.h"
47 : #include "nsChromeRegistry.h"
48 : #include "nsCOMPtr.h"
49 : #include "nsContentCID.h"
50 : #include "nsCRT.h"
51 : #include "nsThreadUtils.h"
52 : #include "nsIChannel.h"
53 : #include "nsIChromeRegistry.h"
54 : #include "nsIComponentManager.h"
55 : #include "nsIFile.h"
56 : #include "nsIFileURL.h"
57 : #include "nsIFileChannel.h"
58 : #include "nsIIOService.h"
59 : #include "nsIJARChannel.h"
60 : #include "nsIJARURI.h"
61 : #include "nsILoadGroup.h"
62 : #include "nsIObjectOutputStream.h"
63 : #include "nsIScriptSecurityManager.h"
64 : #include "nsIServiceManager.h"
65 : #include "nsIStandardURL.h"
66 : #include "nsIStreamListener.h"
67 : #include "nsNetUtil.h"
68 : #include "nsXPIDLString.h"
69 : #include "nsString.h"
70 : #include "prlog.h"
71 :
72 : ////////////////////////////////////////////////////////////////////////////////
73 :
74 428889 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsChromeProtocolHandler,
75 : nsIProtocolHandler,
76 : nsISupportsWeakReference)
77 :
78 : ////////////////////////////////////////////////////////////////////////////////
79 : // nsIProtocolHandler methods:
80 :
81 : NS_IMETHODIMP
82 0 : nsChromeProtocolHandler::GetScheme(nsACString &result)
83 : {
84 0 : result.AssignLiteral("chrome");
85 0 : return NS_OK;
86 : }
87 :
88 : NS_IMETHODIMP
89 0 : nsChromeProtocolHandler::GetDefaultPort(PRInt32 *result)
90 : {
91 0 : *result = -1; // no port for chrome: URLs
92 0 : return NS_OK;
93 : }
94 :
95 : NS_IMETHODIMP
96 0 : nsChromeProtocolHandler::AllowPort(PRInt32 port, const char *scheme, bool *_retval)
97 : {
98 : // don't override anything.
99 0 : *_retval = false;
100 0 : return NS_OK;
101 : }
102 :
103 : NS_IMETHODIMP
104 23168 : nsChromeProtocolHandler::GetProtocolFlags(PRUint32 *result)
105 : {
106 23168 : *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
107 23168 : return NS_OK;
108 : }
109 :
110 : NS_IMETHODIMP
111 45356 : nsChromeProtocolHandler::NewURI(const nsACString &aSpec,
112 : const char *aCharset,
113 : nsIURI *aBaseURI,
114 : nsIURI **result)
115 : {
116 : nsresult rv;
117 :
118 : // Chrome: URLs (currently) have no additional structure beyond that provided
119 : // by standard URLs, so there is no "outer" given to CreateInstance
120 :
121 90712 : nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv));
122 45356 : NS_ENSURE_SUCCESS(rv, rv);
123 :
124 45356 : rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI);
125 45356 : if (NS_FAILED(rv))
126 0 : return rv;
127 :
128 90712 : nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv));
129 45356 : NS_ENSURE_SUCCESS(rv, rv);
130 :
131 : // Canonify the "chrome:" URL; e.g., so that we collapse
132 : // "chrome://navigator/content/" and "chrome://navigator/content"
133 : // and "chrome://navigator/content/navigator.xul".
134 :
135 45356 : rv = nsChromeRegistry::Canonify(url);
136 45356 : if (NS_FAILED(rv))
137 4 : return rv;
138 :
139 45352 : surl->SetMutable(false);
140 :
141 45352 : NS_ADDREF(*result = url);
142 45352 : return NS_OK;
143 : }
144 :
145 : NS_IMETHODIMP
146 2754 : nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
147 : nsIChannel* *aResult)
148 : {
149 : nsresult rv;
150 :
151 2754 : NS_ENSURE_ARG_POINTER(aURI);
152 2754 : NS_PRECONDITION(aResult, "Null out param");
153 :
154 : #ifdef DEBUG
155 : // Check that the uri we got is already canonified
156 : nsresult debug_rv;
157 5508 : nsCOMPtr<nsIURI> debugClone;
158 2754 : debug_rv = aURI->Clone(getter_AddRefs(debugClone));
159 2754 : if (NS_SUCCEEDED(debug_rv)) {
160 5508 : nsCOMPtr<nsIURL> debugURL (do_QueryInterface(debugClone));
161 2754 : debug_rv = nsChromeRegistry::Canonify(debugURL);
162 2754 : if (NS_SUCCEEDED(debug_rv)) {
163 : bool same;
164 2754 : debug_rv = aURI->Equals(debugURL, &same);
165 2754 : if (NS_SUCCEEDED(debug_rv)) {
166 2754 : NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
167 : }
168 : }
169 : }
170 : #endif
171 :
172 5508 : nsCOMPtr<nsIChannel> result;
173 :
174 2754 : if (!nsChromeRegistry::gChromeRegistry) {
175 : // We don't actually want this ref, we just want the service to
176 : // initialize if it hasn't already.
177 : nsCOMPtr<nsIChromeRegistry> reg =
178 0 : mozilla::services::GetChromeRegistryService();
179 0 : NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE);
180 : }
181 :
182 5508 : nsCOMPtr<nsIURI> resolvedURI;
183 2754 : rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
184 2754 : if (NS_FAILED(rv)) {
185 : #ifdef DEBUG
186 1754 : nsCAutoString spec;
187 877 : aURI->GetSpec(spec);
188 877 : printf("Couldn't convert chrome URL: %s\n", spec.get());
189 : #endif
190 877 : return rv;
191 : }
192 :
193 3754 : nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
194 1877 : NS_ENSURE_SUCCESS(rv, rv);
195 :
196 1877 : rv = ioServ->NewChannelFromURI(resolvedURI, getter_AddRefs(result));
197 1877 : if (NS_FAILED(rv)) return rv;
198 :
199 : #ifdef DEBUG
200 3754 : nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
201 1877 : if (fileChan) {
202 3748 : nsCOMPtr<nsIFile> file;
203 1874 : fileChan->GetFile(getter_AddRefs(file));
204 :
205 1874 : bool exists = false;
206 1874 : file->Exists(&exists);
207 1874 : if (!exists) {
208 0 : nsCAutoString path;
209 0 : file->GetNativePath(path);
210 0 : printf("Chrome file doesn't exist: %s\n", path.get());
211 : }
212 : }
213 : #endif
214 :
215 : // Make sure that the channel remembers where it was
216 : // originally loaded from.
217 1877 : rv = result->SetOriginalURI(aURI);
218 1877 : if (NS_FAILED(rv)) return rv;
219 :
220 : // Get a system principal for content files and set the owner
221 : // property of the result
222 3754 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
223 3754 : nsCAutoString path;
224 1877 : rv = url->GetPath(path);
225 1877 : if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/")))
226 : {
227 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
228 326 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
229 163 : if (NS_FAILED(rv)) return rv;
230 :
231 326 : nsCOMPtr<nsIPrincipal> principal;
232 163 : rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
233 163 : if (NS_FAILED(rv)) return rv;
234 :
235 489 : nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
236 163 : result->SetOwner(owner);
237 : }
238 :
239 : // XXX Removed dependency-tracking code from here, because we're not
240 : // tracking them anyways (with fastload we checked only in DEBUG
241 : // and with startupcache not at all), but this is where we would start
242 : // if we need to re-add.
243 : // See bug 531886, bug 533038.
244 :
245 1877 : *aResult = result;
246 1877 : NS_ADDREF(*aResult);
247 1877 : return NS_OK;
248 : }
249 :
250 : ////////////////////////////////////////////////////////////////////////////////
|