Source code

Revision control

Other Tools

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