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