Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sw=2 et tw=78: */
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 : #include "nsChromeRegistry.h"
8 : #include "nsChromeRegistryChrome.h"
9 : #include "nsChromeRegistryContent.h"
10 :
11 : #include "nsCOMPtr.h"
12 : #include "nsError.h"
13 : #include "nsEscape.h"
14 : #include "nsNetUtil.h"
15 : #include "nsString.h"
16 : #include "nsQueryObject.h"
17 :
18 : #include "mozilla/dom/URL.h"
19 : #include "nsIConsoleService.h"
20 : #include "nsIDocument.h"
21 : #include "nsIDOMDocument.h"
22 : #include "nsIDOMWindowCollection.h"
23 : #include "nsIDOMWindow.h"
24 : #include "nsIObserverService.h"
25 : #include "nsIPresShell.h"
26 : #include "nsIScriptError.h"
27 : #include "nsIWindowMediator.h"
28 : #include "nsIPrefService.h"
29 : #include "mozilla/Preferences.h"
30 : #include "mozilla/Printf.h"
31 : #include "mozilla/StyleSheet.h"
32 : #include "mozilla/StyleSheetInlines.h"
33 : #include "mozilla/dom/Location.h"
34 :
35 : #ifdef ENABLE_INTL_API
36 : #include "unicode/uloc.h"
37 : #endif
38 :
39 : nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
40 :
41 : // DO NOT use namespace mozilla; it'll break due to a naming conflict between
42 : // mozilla::TextRange and a TextRange in OSX headers.
43 : using mozilla::StyleSheet;
44 : using mozilla::dom::IsChromeURI;
45 : using mozilla::dom::Location;
46 :
47 : ////////////////////////////////////////////////////////////////////////////////
48 :
49 : void
50 0 : nsChromeRegistry::LogMessage(const char* aMsg, ...)
51 : {
52 : nsCOMPtr<nsIConsoleService> console
53 0 : (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
54 0 : if (!console)
55 0 : return;
56 :
57 : va_list args;
58 0 : va_start(args, aMsg);
59 0 : mozilla::SmprintfPointer formatted = mozilla::Vsmprintf(aMsg, args);
60 0 : va_end(args);
61 0 : if (!formatted)
62 0 : return;
63 :
64 0 : console->LogStringMessage(NS_ConvertUTF8toUTF16(formatted.get()).get());
65 : }
66 :
67 : void
68 0 : nsChromeRegistry::LogMessageWithContext(nsIURI* aURL, uint32_t aLineNumber, uint32_t flags,
69 : const char* aMsg, ...)
70 : {
71 : nsresult rv;
72 :
73 : nsCOMPtr<nsIConsoleService> console
74 0 : (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
75 :
76 : nsCOMPtr<nsIScriptError> error
77 0 : (do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
78 0 : if (!console || !error)
79 0 : return;
80 :
81 : va_list args;
82 0 : va_start(args, aMsg);
83 0 : mozilla::SmprintfPointer formatted = mozilla::Vsmprintf(aMsg, args);
84 0 : va_end(args);
85 0 : if (!formatted)
86 0 : return;
87 :
88 0 : nsCString spec;
89 0 : if (aURL)
90 0 : aURL->GetSpec(spec);
91 :
92 0 : rv = error->Init(NS_ConvertUTF8toUTF16(formatted.get()),
93 0 : NS_ConvertUTF8toUTF16(spec),
94 0 : EmptyString(),
95 0 : aLineNumber, 0, flags, "chrome registration");
96 :
97 0 : if (NS_FAILED(rv))
98 0 : return;
99 :
100 0 : console->LogMessage(error);
101 : }
102 :
103 0 : nsChromeRegistry::~nsChromeRegistry()
104 : {
105 0 : gChromeRegistry = nullptr;
106 0 : }
107 :
108 981 : NS_INTERFACE_MAP_BEGIN(nsChromeRegistry)
109 981 : NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry)
110 88 : NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry)
111 30 : NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry)
112 : #ifdef MOZ_XUL
113 23 : NS_INTERFACE_MAP_ENTRY(nsIXULOverlayProvider)
114 : #endif
115 10 : NS_INTERFACE_MAP_ENTRY(nsIObserver)
116 8 : NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
117 4 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChromeRegistry)
118 0 : NS_INTERFACE_MAP_END
119 :
120 1468 : NS_IMPL_ADDREF(nsChromeRegistry)
121 1458 : NS_IMPL_RELEASE(nsChromeRegistry)
122 :
123 : ////////////////////////////////////////////////////////////////////////////////
124 : // nsIChromeRegistry methods:
125 :
126 : already_AddRefed<nsIChromeRegistry>
127 4 : nsChromeRegistry::GetService()
128 : {
129 4 : if (!gChromeRegistry)
130 : {
131 : // We don't actually want this ref, we just want the service to
132 : // initialize if it hasn't already.
133 : nsCOMPtr<nsIChromeRegistry> reg(
134 4 : do_GetService(NS_CHROMEREGISTRY_CONTRACTID));
135 2 : if (!gChromeRegistry)
136 0 : return nullptr;
137 : }
138 8 : nsCOMPtr<nsIChromeRegistry> registry = gChromeRegistry;
139 4 : return registry.forget();
140 : }
141 :
142 : nsresult
143 3 : nsChromeRegistry::Init()
144 : {
145 : // This initialization process is fairly complicated and may cause reentrant
146 : // getservice calls to resolve chrome URIs (especially locale files). We
147 : // don't want that, so we inform the protocol handler about our existence
148 : // before we are actually fully initialized.
149 3 : gChromeRegistry = this;
150 :
151 3 : mInitialized = true;
152 :
153 3 : return NS_OK;
154 : }
155 :
156 : nsresult
157 822 : nsChromeRegistry::GetProviderAndPath(nsIURL* aChromeURL,
158 : nsACString& aProvider, nsACString& aPath)
159 : {
160 : nsresult rv;
161 :
162 : #ifdef DEBUG
163 : bool isChrome;
164 822 : aChromeURL->SchemeIs("chrome", &isChrome);
165 822 : NS_ASSERTION(isChrome, "Non-chrome URI?");
166 : #endif
167 :
168 1644 : nsAutoCString path;
169 822 : rv = aChromeURL->GetPath(path);
170 822 : NS_ENSURE_SUCCESS(rv, rv);
171 :
172 822 : if (path.Length() < 3) {
173 0 : LogMessage("Invalid chrome URI: %s", path.get());
174 0 : return NS_ERROR_FAILURE;
175 : }
176 :
177 822 : path.SetLength(nsUnescapeCount(path.BeginWriting()));
178 822 : NS_ASSERTION(path.First() == '/', "Path should always begin with a slash!");
179 :
180 822 : int32_t slash = path.FindChar('/', 1);
181 822 : if (slash == 1) {
182 0 : LogMessage("Invalid chrome URI: %s", path.get());
183 0 : return NS_ERROR_FAILURE;
184 : }
185 :
186 822 : if (slash == -1) {
187 0 : aPath.Truncate();
188 : }
189 : else {
190 822 : if (slash == (int32_t) path.Length() - 1)
191 3 : aPath.Truncate();
192 : else
193 819 : aPath.Assign(path.get() + slash + 1, path.Length() - slash - 1);
194 :
195 822 : --slash;
196 : }
197 :
198 822 : aProvider.Assign(path.get() + 1, slash);
199 822 : return NS_OK;
200 : }
201 :
202 :
203 : nsresult
204 589 : nsChromeRegistry::Canonify(nsIURL* aChromeURL)
205 : {
206 589 : NS_NAMED_LITERAL_CSTRING(kSlash, "/");
207 :
208 : nsresult rv;
209 :
210 1178 : nsAutoCString provider, path;
211 589 : rv = GetProviderAndPath(aChromeURL, provider, path);
212 589 : NS_ENSURE_SUCCESS(rv, rv);
213 :
214 589 : if (path.IsEmpty()) {
215 6 : nsAutoCString package;
216 3 : rv = aChromeURL->GetHost(package);
217 3 : NS_ENSURE_SUCCESS(rv, rv);
218 :
219 : // we re-use the "path" local string to build a new URL path
220 3 : path.Assign(kSlash + provider + kSlash + package);
221 3 : if (provider.EqualsLiteral("content")) {
222 1 : path.AppendLiteral(".xul");
223 : }
224 2 : else if (provider.EqualsLiteral("locale")) {
225 0 : path.AppendLiteral(".dtd");
226 : }
227 2 : else if (provider.EqualsLiteral("skin")) {
228 2 : path.AppendLiteral(".css");
229 : }
230 : else {
231 0 : return NS_ERROR_INVALID_ARG;
232 : }
233 3 : aChromeURL->SetPath(path);
234 : }
235 : else {
236 : // prevent directory traversals ("..")
237 : // path is already unescaped once, but uris can get unescaped twice
238 586 : const char* pos = path.BeginReading();
239 586 : const char* end = path.EndReading();
240 25118 : while (pos < end) {
241 12266 : switch (*pos) {
242 : case ':':
243 0 : return NS_ERROR_DOM_BAD_URI;
244 : case '.':
245 583 : if (pos[1] == '.')
246 0 : return NS_ERROR_DOM_BAD_URI;
247 583 : break;
248 : case '%':
249 : // chrome: URIs with double-escapes are trying to trick us.
250 : // watch for %2e, and %25 in case someone triple unescapes
251 0 : if (pos[1] == '2' &&
252 0 : ( pos[2] == 'e' || pos[2] == 'E' ||
253 0 : pos[2] == '5' ))
254 0 : return NS_ERROR_DOM_BAD_URI;
255 0 : break;
256 : case '?':
257 : case '#':
258 180 : pos = end;
259 180 : continue;
260 : }
261 12086 : ++pos;
262 : }
263 : }
264 :
265 589 : return NS_OK;
266 : }
267 :
268 : NS_IMETHODIMP
269 207 : nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURI, nsIURI* *aResult)
270 : {
271 : nsresult rv;
272 207 : if (NS_WARN_IF(!aChromeURI)) {
273 0 : return NS_ERROR_INVALID_ARG;
274 : }
275 :
276 207 : if (mOverrideTable.Get(aChromeURI, aResult))
277 0 : return NS_OK;
278 :
279 414 : nsCOMPtr<nsIURL> chromeURL (do_QueryInterface(aChromeURI));
280 207 : NS_ENSURE_TRUE(chromeURL, NS_NOINTERFACE);
281 :
282 414 : nsAutoCString package, provider, path;
283 207 : rv = chromeURL->GetHostPort(package);
284 207 : NS_ENSURE_SUCCESS(rv, rv);
285 :
286 207 : rv = GetProviderAndPath(chromeURL, provider, path);
287 207 : NS_ENSURE_SUCCESS(rv, rv);
288 :
289 207 : nsIURI* baseURI = GetBaseURIFromPackage(package, provider, path);
290 :
291 : uint32_t flags;
292 207 : rv = GetFlagsFromPackage(package, &flags);
293 207 : if (NS_FAILED(rv))
294 0 : return rv;
295 :
296 207 : if (!baseURI) {
297 0 : LogMessage("No chrome package registered for chrome://%s/%s/%s",
298 0 : package.get(), provider.get(), path.get());
299 0 : return NS_ERROR_FILE_NOT_FOUND;
300 : }
301 :
302 207 : return NS_NewURI(aResult, path, nullptr, baseURI);
303 : }
304 :
305 : ////////////////////////////////////////////////////////////////////////
306 :
307 : // theme stuff
308 :
309 :
310 0 : static void FlushSkinBindingsForWindow(nsPIDOMWindowOuter* aWindow)
311 : {
312 : // Get the document.
313 0 : nsCOMPtr<nsIDocument> document = aWindow->GetDoc();
314 0 : if (!document)
315 0 : return;
316 :
317 : // Annihilate all XBL bindings.
318 0 : document->FlushSkinBindings();
319 : }
320 :
321 : // XXXbsmedberg: move this to nsIWindowMediator
322 0 : NS_IMETHODIMP nsChromeRegistry::RefreshSkins()
323 : {
324 : nsCOMPtr<nsIWindowMediator> windowMediator
325 0 : (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
326 0 : if (!windowMediator)
327 0 : return NS_OK;
328 :
329 0 : nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
330 0 : windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
331 : bool more;
332 0 : windowEnumerator->HasMoreElements(&more);
333 0 : while (more) {
334 0 : nsCOMPtr<nsISupports> protoWindow;
335 0 : windowEnumerator->GetNext(getter_AddRefs(protoWindow));
336 0 : if (protoWindow) {
337 0 : nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
338 0 : if (domWindow)
339 0 : FlushSkinBindingsForWindow(domWindow);
340 : }
341 0 : windowEnumerator->HasMoreElements(&more);
342 : }
343 :
344 0 : FlushSkinCaches();
345 :
346 0 : windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
347 0 : windowEnumerator->HasMoreElements(&more);
348 0 : while (more) {
349 0 : nsCOMPtr<nsISupports> protoWindow;
350 0 : windowEnumerator->GetNext(getter_AddRefs(protoWindow));
351 0 : if (protoWindow) {
352 0 : nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
353 0 : if (domWindow)
354 0 : RefreshWindow(domWindow);
355 : }
356 0 : windowEnumerator->HasMoreElements(&more);
357 : }
358 :
359 0 : return NS_OK;
360 : }
361 :
362 : void
363 0 : nsChromeRegistry::FlushSkinCaches()
364 : {
365 : nsCOMPtr<nsIObserverService> obsSvc =
366 0 : mozilla::services::GetObserverService();
367 0 : NS_ASSERTION(obsSvc, "Couldn't get observer service.");
368 :
369 0 : obsSvc->NotifyObservers(static_cast<nsIChromeRegistry*>(this),
370 0 : NS_CHROME_FLUSH_SKINS_TOPIC, nullptr);
371 0 : }
372 :
373 : // XXXbsmedberg: move this to windowmediator
374 0 : nsresult nsChromeRegistry::RefreshWindow(nsPIDOMWindowOuter* aWindow)
375 : {
376 : // Deal with our subframes first.
377 0 : nsCOMPtr<nsIDOMWindowCollection> frames = aWindow->GetFrames();
378 : uint32_t length;
379 0 : frames->GetLength(&length);
380 : uint32_t j;
381 0 : for (j = 0; j < length; j++) {
382 0 : nsCOMPtr<mozIDOMWindowProxy> childWin;
383 0 : frames->Item(j, getter_AddRefs(childWin));
384 0 : nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(childWin);
385 0 : RefreshWindow(piWindow);
386 : }
387 :
388 : nsresult rv;
389 : // Get the document.
390 0 : nsCOMPtr<nsIDocument> document = aWindow->GetDoc();
391 0 : if (!document)
392 0 : return NS_OK;
393 :
394 : // Deal with the agent sheets first. Have to do all the style sets by hand.
395 0 : nsCOMPtr<nsIPresShell> shell = document->GetShell();
396 0 : if (shell) {
397 : // Reload only the chrome URL agent style sheets.
398 0 : nsTArray<RefPtr<StyleSheet>> agentSheets;
399 0 : rv = shell->GetAgentStyleSheets(agentSheets);
400 0 : NS_ENSURE_SUCCESS(rv, rv);
401 :
402 0 : nsTArray<RefPtr<StyleSheet>> newAgentSheets;
403 0 : for (StyleSheet* sheet : agentSheets) {
404 0 : nsIURI* uri = sheet->GetSheetURI();
405 :
406 0 : if (IsChromeURI(uri)) {
407 : // Reload the sheet.
408 0 : RefPtr<StyleSheet> newSheet;
409 0 : rv = document->LoadChromeSheetSync(uri, true, &newSheet);
410 0 : if (NS_FAILED(rv)) return rv;
411 0 : if (newSheet) {
412 0 : rv = newAgentSheets.AppendElement(newSheet) ? NS_OK : NS_ERROR_FAILURE;
413 0 : if (NS_FAILED(rv)) return rv;
414 : }
415 : }
416 : else { // Just use the same sheet.
417 0 : rv = newAgentSheets.AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
418 0 : if (NS_FAILED(rv)) return rv;
419 : }
420 : }
421 :
422 0 : rv = shell->SetAgentStyleSheets(newAgentSheets);
423 0 : NS_ENSURE_SUCCESS(rv, rv);
424 : }
425 :
426 0 : int32_t count = document->GetNumberOfStyleSheets();
427 :
428 : // Build an array of style sheets we need to reload.
429 0 : nsTArray<RefPtr<StyleSheet>> oldSheets(count);
430 0 : nsTArray<RefPtr<StyleSheet>> newSheets(count);
431 :
432 : // Iterate over the style sheets.
433 0 : for (int32_t i = 0; i < count; i++) {
434 : // Get the style sheet
435 0 : StyleSheet* styleSheet = document->GetStyleSheetAt(i);
436 0 : oldSheets.AppendElement(styleSheet);
437 : }
438 :
439 : // Iterate over our old sheets and kick off a sync load of the new
440 : // sheet if and only if it's a non-inline sheet with a chrome URL.
441 0 : for (StyleSheet* sheet : oldSheets) {
442 0 : MOZ_ASSERT(sheet, "GetStyleSheetAt shouldn't return nullptr for "
443 : "in-range sheet indexes");
444 0 : nsIURI* uri = sheet->GetSheetURI();
445 :
446 0 : if (!sheet->IsInline() && IsChromeURI(uri)) {
447 : // Reload the sheet.
448 0 : RefPtr<StyleSheet> newSheet;
449 : // XXX what about chrome sheets that have a title or are disabled? This
450 : // only works by sheer dumb luck.
451 0 : document->LoadChromeSheetSync(uri, false, &newSheet);
452 : // Even if it's null, we put in in there.
453 0 : newSheets.AppendElement(newSheet);
454 : } else {
455 : // Just use the same sheet.
456 0 : newSheets.AppendElement(sheet);
457 : }
458 : }
459 :
460 : // Now notify the document that multiple sheets have been added and removed.
461 0 : document->UpdateStyleSheets(oldSheets, newSheets);
462 0 : return NS_OK;
463 : }
464 :
465 : void
466 0 : nsChromeRegistry::FlushAllCaches()
467 : {
468 : nsCOMPtr<nsIObserverService> obsSvc =
469 0 : mozilla::services::GetObserverService();
470 0 : NS_ASSERTION(obsSvc, "Couldn't get observer service.");
471 :
472 0 : obsSvc->NotifyObservers((nsIChromeRegistry*) this,
473 0 : NS_CHROME_FLUSH_TOPIC, nullptr);
474 0 : }
475 :
476 : // xxxbsmedberg Move me to nsIWindowMediator
477 : NS_IMETHODIMP
478 0 : nsChromeRegistry::ReloadChrome()
479 : {
480 0 : FlushAllCaches();
481 : // Do a reload of all top level windows.
482 0 : nsresult rv = NS_OK;
483 :
484 : // Get the window mediator
485 : nsCOMPtr<nsIWindowMediator> windowMediator
486 0 : (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
487 0 : if (windowMediator) {
488 0 : nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
489 :
490 0 : rv = windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator));
491 0 : if (NS_SUCCEEDED(rv)) {
492 : // Get each dom window
493 : bool more;
494 0 : rv = windowEnumerator->HasMoreElements(&more);
495 0 : if (NS_FAILED(rv)) return rv;
496 0 : while (more) {
497 0 : nsCOMPtr<nsISupports> protoWindow;
498 0 : rv = windowEnumerator->GetNext(getter_AddRefs(protoWindow));
499 0 : if (NS_SUCCEEDED(rv)) {
500 0 : nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
501 0 : if (domWindow) {
502 0 : Location* location = domWindow->GetLocation();
503 0 : if (location) {
504 0 : rv = location->Reload(false);
505 0 : if (NS_FAILED(rv)) return rv;
506 : }
507 : }
508 : }
509 0 : rv = windowEnumerator->HasMoreElements(&more);
510 0 : if (NS_FAILED(rv)) return rv;
511 : }
512 : }
513 : }
514 0 : return rv;
515 : }
516 :
517 : NS_IMETHODIMP
518 26 : nsChromeRegistry::AllowScriptsForPackage(nsIURI* aChromeURI, bool *aResult)
519 : {
520 : nsresult rv;
521 26 : *aResult = false;
522 :
523 : #ifdef DEBUG
524 : bool isChrome;
525 26 : aChromeURI->SchemeIs("chrome", &isChrome);
526 26 : NS_ASSERTION(isChrome, "Non-chrome URI passed to AllowScriptsForPackage!");
527 : #endif
528 :
529 52 : nsCOMPtr<nsIURL> url (do_QueryInterface(aChromeURI));
530 26 : NS_ENSURE_TRUE(url, NS_NOINTERFACE);
531 :
532 52 : nsAutoCString provider, file;
533 26 : rv = GetProviderAndPath(url, provider, file);
534 26 : NS_ENSURE_SUCCESS(rv, rv);
535 :
536 26 : if (!provider.EqualsLiteral("skin"))
537 26 : *aResult = true;
538 :
539 26 : return NS_OK;
540 : }
541 :
542 : NS_IMETHODIMP
543 2 : nsChromeRegistry::AllowContentToAccess(nsIURI *aURI, bool *aResult)
544 : {
545 : nsresult rv;
546 :
547 2 : *aResult = false;
548 :
549 : #ifdef DEBUG
550 : bool isChrome;
551 2 : aURI->SchemeIs("chrome", &isChrome);
552 2 : NS_ASSERTION(isChrome, "Non-chrome URI passed to AllowContentToAccess!");
553 : #endif
554 :
555 4 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
556 2 : if (!url) {
557 0 : NS_ERROR("Chrome URL doesn't implement nsIURL.");
558 0 : return NS_ERROR_UNEXPECTED;
559 : }
560 :
561 4 : nsAutoCString package;
562 2 : rv = url->GetHostPort(package);
563 2 : NS_ENSURE_SUCCESS(rv, rv);
564 :
565 : uint32_t flags;
566 2 : rv = GetFlagsFromPackage(package, &flags);
567 :
568 2 : if (NS_SUCCEEDED(rv)) {
569 2 : *aResult = !!(flags & CONTENT_ACCESSIBLE);
570 : }
571 2 : return NS_OK;
572 : }
573 :
574 : NS_IMETHODIMP
575 0 : nsChromeRegistry::CanLoadURLRemotely(nsIURI *aURI, bool *aResult)
576 : {
577 : nsresult rv;
578 :
579 0 : *aResult = false;
580 :
581 : #ifdef DEBUG
582 : bool isChrome;
583 0 : aURI->SchemeIs("chrome", &isChrome);
584 0 : NS_ASSERTION(isChrome, "Non-chrome URI passed to CanLoadURLRemotely!");
585 : #endif
586 :
587 0 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
588 0 : if (!url) {
589 0 : NS_ERROR("Chrome URL doesn't implement nsIURL.");
590 0 : return NS_ERROR_UNEXPECTED;
591 : }
592 :
593 0 : nsAutoCString package;
594 0 : rv = url->GetHostPort(package);
595 0 : NS_ENSURE_SUCCESS(rv, rv);
596 :
597 : uint32_t flags;
598 0 : rv = GetFlagsFromPackage(package, &flags);
599 :
600 0 : if (NS_SUCCEEDED(rv)) {
601 0 : *aResult = !!(flags & REMOTE_ALLOWED);
602 : }
603 0 : return NS_OK;
604 : }
605 :
606 : NS_IMETHODIMP
607 0 : nsChromeRegistry::MustLoadURLRemotely(nsIURI *aURI, bool *aResult)
608 : {
609 : nsresult rv;
610 :
611 0 : *aResult = false;
612 :
613 : #ifdef DEBUG
614 : bool isChrome;
615 0 : aURI->SchemeIs("chrome", &isChrome);
616 0 : NS_ASSERTION(isChrome, "Non-chrome URI passed to MustLoadURLRemotely!");
617 : #endif
618 :
619 0 : nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
620 0 : if (!url) {
621 0 : NS_ERROR("Chrome URL doesn't implement nsIURL.");
622 0 : return NS_ERROR_UNEXPECTED;
623 : }
624 :
625 0 : nsAutoCString package;
626 0 : rv = url->GetHostPort(package);
627 0 : NS_ENSURE_SUCCESS(rv, rv);
628 :
629 : uint32_t flags;
630 0 : rv = GetFlagsFromPackage(package, &flags);
631 :
632 0 : if (NS_SUCCEEDED(rv)) {
633 0 : *aResult = !!(flags & REMOTE_REQUIRED);
634 : }
635 0 : return NS_OK;
636 : }
637 :
638 : bool
639 1 : nsChromeRegistry::GetDirectionForLocale(const nsACString& aLocale)
640 : {
641 : #ifdef ENABLE_INTL_API
642 1 : int pref = mozilla::Preferences::GetInt("intl.uidirection", -1);
643 1 : if (pref >= 0) {
644 0 : return (pref > 0);
645 : }
646 2 : nsAutoCString locale(aLocale);
647 1 : SanitizeForBCP47(locale);
648 1 : return uloc_isRightToLeft(locale.get());
649 : #else
650 : // first check the intl.uidirection.<locale> preference, and if that is not
651 : // set, check the same preference but with just the first two characters of
652 : // the locale. If that isn't set, default to left-to-right.
653 : nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + aLocale;
654 : nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID));
655 : if (!prefBranch) {
656 : return false;
657 : }
658 :
659 : nsXPIDLCString dir;
660 : prefBranch->GetCharPref(prefString.get(), getter_Copies(dir));
661 : if (dir.IsEmpty()) {
662 : int32_t hyphen = prefString.FindChar('-');
663 : if (hyphen >= 1) {
664 : nsAutoCString shortPref(Substring(prefString, 0, hyphen));
665 : prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir));
666 : }
667 : }
668 :
669 : return dir.EqualsLiteral("rtl");
670 : #endif
671 : }
672 :
673 : NS_IMETHODIMP_(bool)
674 714 : nsChromeRegistry::WrappersEnabled(nsIURI *aURI)
675 : {
676 1428 : nsCOMPtr<nsIURL> chromeURL (do_QueryInterface(aURI));
677 714 : if (!chromeURL)
678 0 : return false;
679 :
680 714 : bool isChrome = false;
681 714 : nsresult rv = chromeURL->SchemeIs("chrome", &isChrome);
682 714 : if (NS_FAILED(rv) || !isChrome)
683 0 : return false;
684 :
685 1428 : nsAutoCString package;
686 714 : rv = chromeURL->GetHostPort(package);
687 714 : if (NS_FAILED(rv))
688 0 : return false;
689 :
690 : uint32_t flags;
691 714 : rv = GetFlagsFromPackage(package, &flags);
692 714 : return NS_SUCCEEDED(rv) && (flags & XPCNATIVEWRAPPERS);
693 : }
694 :
695 : already_AddRefed<nsChromeRegistry>
696 3 : nsChromeRegistry::GetSingleton()
697 : {
698 3 : if (gChromeRegistry) {
699 0 : RefPtr<nsChromeRegistry> registry = gChromeRegistry;
700 0 : return registry.forget();
701 : }
702 :
703 6 : RefPtr<nsChromeRegistry> cr;
704 3 : if (GeckoProcessType_Content == XRE_GetProcessType())
705 2 : cr = new nsChromeRegistryContent();
706 : else
707 1 : cr = new nsChromeRegistryChrome();
708 :
709 3 : if (NS_FAILED(cr->Init()))
710 0 : return nullptr;
711 :
712 3 : return cr.forget();
713 : }
714 :
715 : void
716 1 : nsChromeRegistry::SanitizeForBCP47(nsACString& aLocale)
717 : {
718 : #ifdef ENABLE_INTL_API
719 : // Currently, the only locale code we use that's not BCP47-conformant is
720 : // "ja-JP-mac" on OS X, but let's try to be more general than just
721 : // hard-coding that here.
722 1 : const int32_t LANG_TAG_CAPACITY = 128;
723 : char langTag[LANG_TAG_CAPACITY];
724 2 : nsAutoCString locale(aLocale);
725 1 : UErrorCode err = U_ZERO_ERROR;
726 : // This is a fail-safe method that will set langTag to "und" if it cannot
727 : // match any part of the input locale code.
728 1 : int32_t len = uloc_toLanguageTag(locale.get(), langTag, LANG_TAG_CAPACITY,
729 1 : false, &err);
730 1 : if (U_SUCCESS(err) && len > 0) {
731 1 : aLocale.Assign(langTag, len);
732 : }
733 : #else
734 : // This is only really needed for Intl API purposes, AFAIK,
735 : // so probably won't be used in a non-ENABLE_INTL_API build.
736 : // But let's fix up the single anomalous code we actually ship,
737 : // just in case:
738 : if (aLocale.EqualsLiteral("ja-JP-mac")) {
739 : aLocale.AssignLiteral("ja-JP");
740 : }
741 : #endif
742 1 : }
|