Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : // See also: docshell/base/nsAboutRedirector.cpp
7 :
8 : #include "AboutRedirector.h"
9 : #include "nsNetUtil.h"
10 : #include "nsIAboutNewTabService.h"
11 : #include "nsIChannel.h"
12 : #include "nsIURI.h"
13 : #include "nsIScriptSecurityManager.h"
14 : #include "nsIProtocolHandler.h"
15 : #include "mozilla/ArrayUtils.h"
16 : #include "mozilla/Preferences.h"
17 : #include "nsServiceManagerUtils.h"
18 :
19 : namespace mozilla {
20 : namespace browser {
21 :
22 309 : NS_IMPL_ISUPPORTS(AboutRedirector, nsIAboutModule)
23 :
24 : bool AboutRedirector::sUseOldPreferences = false;
25 : bool AboutRedirector::sActivityStreamEnabled = false;
26 :
27 : struct RedirEntry {
28 : const char* id;
29 : const char* url;
30 : uint32_t flags;
31 : };
32 :
33 : /*
34 : Entries which do not have URI_SAFE_FOR_UNTRUSTED_CONTENT will run with chrome
35 : privileges. This is potentially dangerous. Please use
36 : URI_SAFE_FOR_UNTRUSTED_CONTENT in the third argument to each map item below
37 : unless your about: page really needs chrome privileges. Security review is
38 : required before adding new map entries without
39 : URI_SAFE_FOR_UNTRUSTED_CONTENT.
40 : */
41 : static const RedirEntry kRedirMap[] = {
42 : { "blocked", "chrome://browser/content/blockedSite.xhtml",
43 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
44 : nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
45 : nsIAboutModule::ALLOW_SCRIPT |
46 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
47 : { "certerror", "chrome://browser/content/aboutNetError.xhtml",
48 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
49 : nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
50 : nsIAboutModule::ALLOW_SCRIPT |
51 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
52 : { "socialerror", "chrome://browser/content/aboutSocialError.xhtml",
53 : nsIAboutModule::ALLOW_SCRIPT |
54 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
55 : { "providerdirectory", "chrome://browser/content/aboutProviderDirectory.xhtml",
56 : nsIAboutModule::ALLOW_SCRIPT |
57 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
58 : { "tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml",
59 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
60 : nsIAboutModule::ALLOW_SCRIPT |
61 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
62 : { "feeds", "chrome://browser/content/feeds/subscribe.xhtml",
63 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
64 : nsIAboutModule::ALLOW_SCRIPT |
65 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
66 : { "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
67 : nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
68 : nsIAboutModule::ALLOW_SCRIPT },
69 : { "rights",
70 : "chrome://global/content/aboutRights.xhtml",
71 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
72 : nsIAboutModule::MAKE_LINKABLE |
73 : nsIAboutModule::ALLOW_SCRIPT },
74 : { "robots", "chrome://browser/content/aboutRobots.xhtml",
75 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
76 : nsIAboutModule::ALLOW_SCRIPT },
77 : { "searchreset", "chrome://browser/content/search/searchReset.xhtml",
78 : nsIAboutModule::ALLOW_SCRIPT |
79 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
80 : { "sessionrestore", "chrome://browser/content/aboutSessionRestore.xhtml",
81 : nsIAboutModule::ALLOW_SCRIPT },
82 : { "welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml",
83 : nsIAboutModule::ALLOW_SCRIPT },
84 : // Linkable because of indexeddb use (bug 1228118)
85 : { "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
86 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
87 : nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
88 : nsIAboutModule::ALLOW_SCRIPT |
89 : nsIAboutModule::MAKE_LINKABLE |
90 : nsIAboutModule::ENABLE_INDEXED_DB },
91 : // the newtab's actual URL will be determined when the channel is created
92 : { "newtab", "about:blank",
93 : nsIAboutModule::ALLOW_SCRIPT },
94 : { "preferences", "chrome://browser/content/preferences/in-content/preferences.xul",
95 : nsIAboutModule::ALLOW_SCRIPT },
96 : { "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
97 : nsIAboutModule::ALLOW_SCRIPT },
98 : #ifdef MOZ_SERVICES_HEALTHREPORT
99 : { "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml",
100 : nsIAboutModule::ALLOW_SCRIPT },
101 : #endif
102 : { "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
103 : nsIAboutModule::ALLOW_SCRIPT },
104 : { "reader", "chrome://global/content/reader/aboutReader.html",
105 : nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
106 : nsIAboutModule::ALLOW_SCRIPT |
107 : nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
108 : nsIAboutModule::HIDE_FROM_ABOUTABOUT },
109 : };
110 :
111 : static nsAutoCString
112 31 : GetAboutModuleName(nsIURI *aURI)
113 : {
114 31 : nsAutoCString path;
115 31 : aURI->GetPath(path);
116 :
117 31 : int32_t f = path.FindChar('#');
118 31 : if (f >= 0)
119 0 : path.SetLength(f);
120 :
121 31 : f = path.FindChar('?');
122 31 : if (f >= 0)
123 0 : path.SetLength(f);
124 :
125 31 : ToLowerCase(path);
126 31 : return path;
127 : }
128 :
129 : NS_IMETHODIMP
130 0 : AboutRedirector::NewChannel(nsIURI* aURI,
131 : nsILoadInfo* aLoadInfo,
132 : nsIChannel** result)
133 : {
134 0 : NS_ENSURE_ARG_POINTER(aURI);
135 0 : NS_ENSURE_ARG_POINTER(aLoadInfo);
136 :
137 0 : NS_ASSERTION(result, "must not be null");
138 :
139 0 : nsAutoCString path = GetAboutModuleName(aURI);
140 :
141 : nsresult rv;
142 0 : nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
143 0 : NS_ENSURE_SUCCESS(rv, rv);
144 :
145 : static bool sPrefCacheInited = false;
146 0 : if (!sPrefCacheInited) {
147 : Preferences::AddBoolVarCache(&sUseOldPreferences,
148 0 : "browser.preferences.useOldOrganization");
149 0 : sPrefCacheInited = true;
150 : }
151 :
152 0 : for (auto & redir : kRedirMap) {
153 0 : if (!strcmp(path.get(), redir.id)) {
154 0 : nsAutoCString url;
155 :
156 0 : if (path.EqualsLiteral("newtab")) {
157 : // let the aboutNewTabService decide where to redirect
158 : nsCOMPtr<nsIAboutNewTabService> aboutNewTabService =
159 0 : do_GetService("@mozilla.org/browser/aboutnewtab-service;1", &rv);
160 0 : NS_ENSURE_SUCCESS(rv, rv);
161 0 : rv = aboutNewTabService->GetDefaultURL(url);
162 0 : NS_ENSURE_SUCCESS(rv, rv);
163 0 : } else if (path.EqualsLiteral("preferences") && !sUseOldPreferences) {
164 0 : url.AssignASCII("chrome://browser/content/preferences/in-content-new/preferences.xul");
165 : }
166 : // fall back to the specified url in the map
167 0 : if (url.IsEmpty()) {
168 0 : url.AssignASCII(redir.url);
169 : }
170 :
171 0 : nsCOMPtr<nsIChannel> tempChannel;
172 0 : nsCOMPtr<nsIURI> tempURI;
173 0 : rv = NS_NewURI(getter_AddRefs(tempURI), url);
174 0 : NS_ENSURE_SUCCESS(rv, rv);
175 :
176 : // If tempURI links to an external URI (i.e. something other than
177 : // chrome:// or resource://) then set the result principal URI on the
178 : // load info which forces the channel prncipal to reflect the displayed
179 : // URL rather then being the systemPrincipal.
180 0 : bool isUIResource = false;
181 0 : rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
182 : &isUIResource);
183 0 : NS_ENSURE_SUCCESS(rv, rv);
184 :
185 0 : rv = NS_NewChannelInternal(getter_AddRefs(tempChannel),
186 : tempURI,
187 : aLoadInfo);
188 0 : NS_ENSURE_SUCCESS(rv, rv);
189 :
190 0 : if (!isUIResource) {
191 0 : aLoadInfo->SetResultPrincipalURI(tempURI);
192 : }
193 0 : tempChannel->SetOriginalURI(aURI);
194 :
195 0 : NS_ADDREF(*result = tempChannel);
196 0 : return rv;
197 : }
198 : }
199 :
200 0 : return NS_ERROR_ILLEGAL_VALUE;
201 : }
202 :
203 : NS_IMETHODIMP
204 31 : AboutRedirector::GetURIFlags(nsIURI *aURI, uint32_t *result)
205 : {
206 31 : NS_ENSURE_ARG_POINTER(aURI);
207 :
208 62 : nsAutoCString name = GetAboutModuleName(aURI);
209 :
210 : static bool sASEnabledCacheInited = false;
211 31 : if (!sASEnabledCacheInited) {
212 : Preferences::AddBoolVarCache(&sActivityStreamEnabled,
213 3 : "browser.newtabpage.activity-stream.enabled");
214 3 : sASEnabledCacheInited = true;
215 : }
216 :
217 431 : for (auto & redir : kRedirMap) {
218 431 : if (name.Equals(redir.id)) {
219 :
220 : // Once ActivityStream is fully rolled out and we've removed Tiles,
221 : // this special case can go away and the flag can just become part
222 : // of the normal about:newtab entry in kRedirMap.
223 31 : if (name.EqualsLiteral("newtab")) {
224 28 : if (sActivityStreamEnabled) {
225 0 : *result = redir.flags | nsIAboutModule::URI_MUST_LOAD_IN_CHILD;
226 0 : return NS_OK;
227 : }
228 : }
229 :
230 31 : *result = redir.flags;
231 31 : return NS_OK;
232 : }
233 : }
234 :
235 0 : return NS_ERROR_ILLEGAL_VALUE;
236 : }
237 :
238 : nsresult
239 3 : AboutRedirector::Create(nsISupports *aOuter, REFNSIID aIID, void **result)
240 : {
241 3 : AboutRedirector* about = new AboutRedirector();
242 3 : if (about == nullptr)
243 0 : return NS_ERROR_OUT_OF_MEMORY;
244 3 : NS_ADDREF(about);
245 3 : nsresult rv = about->QueryInterface(aIID, result);
246 3 : NS_RELEASE(about);
247 3 : return rv;
248 : }
249 :
250 : } // namespace browser
251 : } // namespace mozilla
|