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 442731 : 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 23885 : nsChromeProtocolHandler::GetProtocolFlags(PRUint32 *result)
105 : {
106 23885 : *result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE;
107 23885 : return NS_OK;
108 : }
109 :
110 : NS_IMETHODIMP
111 46829 : 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 93658 : nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv));
122 46829 : NS_ENSURE_SUCCESS(rv, rv);
123 :
124 46829 : rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI);
125 46829 : if (NS_FAILED(rv))
126 0 : return rv;
127 :
128 93658 : nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv));
129 46829 : 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 46829 : rv = nsChromeRegistry::Canonify(url);
136 46829 : if (NS_FAILED(rv))
137 4 : return rv;
138 :
139 46825 : surl->SetMutable(false);
140 :
141 46825 : NS_ADDREF(*result = url);
142 46825 : return NS_OK;
143 : }
144 :
145 : NS_IMETHODIMP
146 2769 : nsChromeProtocolHandler::NewChannel(nsIURI* aURI,
147 : nsIChannel* *aResult)
148 : {
149 : nsresult rv;
150 :
151 2769 : NS_ENSURE_ARG_POINTER(aURI);
152 2769 : 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 5538 : nsCOMPtr<nsIURI> debugClone;
158 2769 : debug_rv = aURI->Clone(getter_AddRefs(debugClone));
159 2769 : if (NS_SUCCEEDED(debug_rv)) {
160 5538 : nsCOMPtr<nsIURL> debugURL (do_QueryInterface(debugClone));
161 2769 : debug_rv = nsChromeRegistry::Canonify(debugURL);
162 2769 : if (NS_SUCCEEDED(debug_rv)) {
163 : bool same;
164 2769 : debug_rv = aURI->Equals(debugURL, &same);
165 2769 : if (NS_SUCCEEDED(debug_rv)) {
166 2769 : NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!");
167 : }
168 : }
169 : }
170 : #endif
171 :
172 5538 : nsCOMPtr<nsIChannel> result;
173 :
174 2769 : 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 5538 : nsCOMPtr<nsIURI> resolvedURI;
183 2769 : rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI));
184 2769 : if (NS_FAILED(rv)) {
185 : #ifdef DEBUG
186 1764 : nsCAutoString spec;
187 882 : aURI->GetSpec(spec);
188 882 : printf("Couldn't convert chrome URL: %s\n", spec.get());
189 : #endif
190 882 : return rv;
191 : }
192 :
193 3774 : nsCOMPtr<nsIIOService> ioServ(do_GetIOService(&rv));
194 1887 : NS_ENSURE_SUCCESS(rv, rv);
195 :
196 1887 : rv = ioServ->NewChannelFromURI(resolvedURI, getter_AddRefs(result));
197 1887 : if (NS_FAILED(rv)) return rv;
198 :
199 : #ifdef DEBUG
200 3774 : nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result));
201 1887 : if (fileChan) {
202 3768 : nsCOMPtr<nsIFile> file;
203 1884 : fileChan->GetFile(getter_AddRefs(file));
204 :
205 1884 : bool exists = false;
206 1884 : file->Exists(&exists);
207 1884 : 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 1887 : nsLoadFlags loadFlags = 0;
218 1887 : result->GetLoadFlags(&loadFlags);
219 1887 : result->SetLoadFlags(loadFlags & ~nsIChannel::LOAD_REPLACE);
220 1887 : rv = result->SetOriginalURI(aURI);
221 1887 : if (NS_FAILED(rv)) return rv;
222 :
223 : // Get a system principal for content files and set the owner
224 : // property of the result
225 3774 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
226 3774 : nsCAutoString path;
227 1887 : rv = url->GetPath(path);
228 1887 : if (StringBeginsWith(path, NS_LITERAL_CSTRING("/content/")))
229 : {
230 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
231 326 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
232 163 : if (NS_FAILED(rv)) return rv;
233 :
234 326 : nsCOMPtr<nsIPrincipal> principal;
235 163 : rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
236 163 : if (NS_FAILED(rv)) return rv;
237 :
238 489 : nsCOMPtr<nsISupports> owner = do_QueryInterface(principal);
239 163 : result->SetOwner(owner);
240 : }
241 :
242 : // XXX Removed dependency-tracking code from here, because we're not
243 : // tracking them anyways (with fastload we checked only in DEBUG
244 : // and with startupcache not at all), but this is where we would start
245 : // if we need to re-add.
246 : // See bug 531886, bug 533038.
247 :
248 1887 : *aResult = result;
249 1887 : NS_ADDREF(*aResult);
250 1887 : return NS_OK;
251 : }
252 :
253 : ////////////////////////////////////////////////////////////////////////////////
|