Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sts=2 sw=2 et tw=80: */
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 "mozilla/dom/ContentParent.h"
8 : #include "RegistryMessageUtils.h"
9 : #include "nsResProtocolHandler.h"
10 :
11 : #include "nsChromeRegistryChrome.h"
12 :
13 : #if defined(XP_WIN)
14 : #include <windows.h>
15 : #elif defined(XP_MACOSX)
16 : #include <CoreServices/CoreServices.h>
17 : #endif
18 :
19 : #include "nsArrayEnumerator.h"
20 : #include "nsComponentManager.h"
21 : #include "nsEnumeratorUtils.h"
22 : #include "nsNetUtil.h"
23 : #include "nsStringEnumerator.h"
24 : #include "nsTextFormatter.h"
25 : #include "nsXPCOMCIDInternal.h"
26 :
27 : #include "mozilla/LookAndFeel.h"
28 : #include "mozilla/Unused.h"
29 : #include "mozilla/intl/LocaleService.h"
30 :
31 : #include "nsIObserverService.h"
32 : #include "nsIPrefBranch.h"
33 : #include "nsIPrefService.h"
34 : #include "mozilla/Preferences.h"
35 : #include "nsIResProtocolHandler.h"
36 : #include "nsIScriptError.h"
37 : #include "nsIXULRuntime.h"
38 :
39 : #define SELECTED_SKIN_PREF "general.skins.selectedSkin"
40 : #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
41 :
42 : using namespace mozilla;
43 : using mozilla::dom::ContentParent;
44 : using mozilla::dom::PContentParent;
45 : using mozilla::intl::LocaleService;
46 :
47 : // We use a "best-fit" algorithm for matching locales and themes.
48 : // 1) the exact selected locale/theme
49 : // 2) (locales only) same language, different country
50 : // e.g. en-GB is the selected locale, only en-US is available
51 : // 3) any available locale/theme
52 :
53 : /**
54 : * Match the language-part of two lang-COUNTRY codes, hopefully but
55 : * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
56 : * work, any other garbage-in will produce undefined results as long
57 : * as it does not crash.
58 : */
59 : static bool
60 0 : LanguagesMatch(const nsACString& a, const nsACString& b)
61 : {
62 0 : if (a.Length() < 2 || b.Length() < 2)
63 : return false;
64 :
65 0 : nsACString::const_iterator as, ae, bs, be;
66 0 : a.BeginReading(as);
67 0 : a.EndReading(ae);
68 0 : b.BeginReading(bs);
69 0 : b.EndReading(be);
70 :
71 0 : while (*as == *bs) {
72 0 : if (*as == '-')
73 : return true;
74 :
75 0 : ++as; ++bs;
76 :
77 : // reached the end
78 0 : if (as == ae && bs == be)
79 : return true;
80 :
81 : // "a" is short
82 0 : if (as == ae)
83 0 : return (*bs == '-');
84 :
85 : // "b" is short
86 0 : if (bs == be)
87 0 : return (*as == '-');
88 : }
89 :
90 : return false;
91 : }
92 :
93 0 : nsChromeRegistryChrome::nsChromeRegistryChrome()
94 : : mProfileLoaded(false)
95 0 : , mDynamicRegistration(true)
96 : {
97 0 : }
98 :
99 0 : nsChromeRegistryChrome::~nsChromeRegistryChrome()
100 : {
101 0 : }
102 :
103 : nsresult
104 0 : nsChromeRegistryChrome::Init()
105 : {
106 0 : nsresult rv = nsChromeRegistry::Init();
107 0 : if (NS_FAILED(rv))
108 : return rv;
109 :
110 0 : mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
111 :
112 0 : bool safeMode = false;
113 0 : nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
114 0 : if (xulrun)
115 0 : xulrun->GetInSafeMode(&safeMode);
116 :
117 0 : nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
118 0 : nsCOMPtr<nsIPrefBranch> prefs;
119 :
120 0 : if (prefserv) {
121 0 : if (safeMode) {
122 0 : prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
123 : } else {
124 0 : prefs = do_QueryInterface(prefserv);
125 : }
126 : }
127 :
128 0 : if (!prefs) {
129 0 : NS_WARNING("Could not get pref service!");
130 : } else {
131 0 : nsAutoCString provider;
132 0 : rv = prefs->GetCharPref(SELECTED_SKIN_PREF, provider);
133 0 : if (NS_SUCCEEDED(rv))
134 0 : mSelectedSkin = provider;
135 :
136 0 : rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true);
137 : }
138 :
139 0 : nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
140 0 : if (obsService) {
141 0 : obsService->AddObserver(this, "profile-initial-state", true);
142 0 : obsService->AddObserver(this, "intl:app-locales-changed", true);
143 : }
144 :
145 : return NS_OK;
146 : }
147 :
148 : NS_IMETHODIMP
149 0 : nsChromeRegistryChrome::CheckForOSAccessibility()
150 : {
151 : int32_t useAccessibilityTheme =
152 0 : LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0);
153 :
154 0 : if (useAccessibilityTheme) {
155 : /* Set the skin to classic and remove pref observers */
156 0 : if (!mSelectedSkin.EqualsLiteral("classic/1.0")) {
157 0 : mSelectedSkin.AssignLiteral("classic/1.0");
158 0 : RefreshSkins();
159 : }
160 :
161 0 : nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
162 0 : if (prefs) {
163 0 : prefs->RemoveObserver(SELECTED_SKIN_PREF, this);
164 : }
165 : }
166 :
167 0 : return NS_OK;
168 : }
169 :
170 : NS_IMETHODIMP
171 0 : nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage,
172 : nsIUTF8StringEnumerator* *aResult)
173 : {
174 0 : nsCString realpackage;
175 0 : nsresult rv = OverrideLocalePackage(aPackage, realpackage);
176 0 : if (NS_FAILED(rv))
177 : return rv;
178 :
179 0 : nsTArray<nsCString> *a = new nsTArray<nsCString>;
180 0 : if (!a)
181 : return NS_ERROR_OUT_OF_MEMORY;
182 :
183 : PackageEntry* entry;
184 0 : if (mPackagesHash.Get(realpackage, &entry)) {
185 0 : entry->locales.EnumerateToArray(a);
186 : }
187 :
188 0 : rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
189 0 : if (NS_FAILED(rv))
190 0 : delete a;
191 :
192 : return rv;
193 : }
194 :
195 : NS_IMETHODIMP
196 0 : nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult)
197 : {
198 0 : *aResult = false;
199 :
200 0 : nsAutoCString locale;
201 0 : GetSelectedLocale(package, false, locale);
202 0 : if (locale.Length() < 2)
203 : return NS_OK;
204 :
205 0 : *aResult = GetDirectionForLocale(locale);
206 0 : return NS_OK;
207 : }
208 :
209 : /**
210 : * This method negotiates only between the app locale and the available
211 : * chrome packages.
212 : *
213 : * If you want to get the current application's UI locale, please use
214 : * LocaleService::GetAppLocaleAsLangTag.
215 : */
216 : nsresult
217 0 : nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
218 : bool aAsBCP47,
219 : nsACString& aLocale)
220 : {
221 0 : nsAutoCString reqLocale;
222 0 : if (aPackage.EqualsLiteral("global")) {
223 0 : LocaleService::GetInstance()->GetAppLocaleAsLangTag(reqLocale);
224 : } else {
225 0 : AutoTArray<nsCString, 10> requestedLocales;
226 0 : LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
227 0 : reqLocale.Assign(requestedLocales[0]);
228 : }
229 :
230 0 : nsCString realpackage;
231 0 : nsresult rv = OverrideLocalePackage(aPackage, realpackage);
232 0 : if (NS_FAILED(rv))
233 : return rv;
234 : PackageEntry* entry;
235 0 : if (!mPackagesHash.Get(realpackage, &entry))
236 : return NS_ERROR_FILE_NOT_FOUND;
237 :
238 0 : aLocale = entry->locales.GetSelected(reqLocale, nsProviderArray::LOCALE);
239 0 : if (aLocale.IsEmpty())
240 : return NS_ERROR_FAILURE;
241 :
242 0 : if (aAsBCP47) {
243 0 : SanitizeForBCP47(aLocale);
244 : }
245 :
246 : return NS_OK;
247 : }
248 :
249 : nsresult
250 0 : nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage,
251 : nsACString& aOverride)
252 : {
253 0 : const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage;
254 0 : nsAutoCString override;
255 : nsresult rv =
256 0 : mozilla::Preferences::GetCString(PromiseFlatCString(pref).get(), override);
257 0 : if (NS_SUCCEEDED(rv)) {
258 : aOverride = override;
259 : } else {
260 : aOverride = aPackage;
261 : }
262 0 : return NS_OK;
263 : }
264 :
265 : NS_IMETHODIMP
266 0 : nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic,
267 : const char16_t *someData)
268 : {
269 0 : nsresult rv = NS_OK;
270 :
271 0 : if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
272 0 : nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject));
273 0 : NS_ASSERTION(prefs, "Bad observer call!");
274 :
275 0 : NS_ConvertUTF16toUTF8 pref(someData);
276 :
277 0 : if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
278 0 : nsAutoCString provider;
279 0 : rv = prefs->GetCharPref(pref.get(), provider);
280 0 : if (NS_FAILED(rv)) {
281 0 : NS_ERROR("Couldn't get new skin pref!");
282 0 : return rv;
283 : }
284 :
285 0 : mSelectedSkin = provider;
286 0 : RefreshSkins();
287 : } else {
288 0 : NS_ERROR("Unexpected pref!");
289 : }
290 : }
291 0 : else if (!strcmp("profile-initial-state", aTopic)) {
292 0 : mProfileLoaded = true;
293 : }
294 0 : else if (!strcmp("intl:app-locales-changed", aTopic)) {
295 0 : if (mProfileLoaded) {
296 0 : FlushAllCaches();
297 : }
298 : }
299 : else {
300 0 : NS_ERROR("Unexpected observer topic!");
301 : }
302 :
303 : return rv;
304 : }
305 :
306 : NS_IMETHODIMP
307 0 : nsChromeRegistryChrome::CheckForNewChrome()
308 : {
309 0 : mPackagesHash.Clear();
310 0 : mOverlayHash.Clear();
311 0 : mOverrideTable.Clear();
312 :
313 0 : mDynamicRegistration = false;
314 :
315 0 : nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
316 :
317 0 : mDynamicRegistration = true;
318 :
319 0 : SendRegisteredChrome(nullptr);
320 0 : return NS_OK;
321 : }
322 :
323 : static void
324 345 : SerializeURI(nsIURI* aURI,
325 : SerializedURI& aSerializedURI)
326 : {
327 345 : if (!aURI)
328 : return;
329 :
330 207 : aURI->GetSpec(aSerializedURI.spec);
331 : }
332 :
333 : void
334 1 : nsChromeRegistryChrome::SendRegisteredChrome(
335 : mozilla::dom::PContentParent* aParent)
336 : {
337 2 : InfallibleTArray<ChromePackage> packages;
338 0 : InfallibleTArray<SubstitutionMapping> resources;
339 0 : InfallibleTArray<OverrideMapping> overrides;
340 :
341 75 : for (auto iter = mPackagesHash.Iter(); !iter.Done(); iter.Next()) {
342 0 : ChromePackage chromePackage;
343 0 : ChromePackageFromPackageEntry(iter.Key(), iter.UserData(), &chromePackage,
344 0 : mSelectedSkin);
345 0 : packages.AppendElement(chromePackage);
346 : }
347 :
348 : // If we were passed a parent then a new child process has been created and
349 : // has requested all of the chrome so send it the resources too. Otherwise
350 : // resource mappings are sent by the resource protocol handler dynamically.
351 1 : if (aParent) {
352 0 : nsCOMPtr<nsIIOService> io (do_GetIOService());
353 0 : NS_ENSURE_TRUE_VOID(io);
354 :
355 2 : nsCOMPtr<nsIProtocolHandler> ph;
356 0 : nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
357 0 : NS_ENSURE_SUCCESS_VOID(rv);
358 :
359 3 : nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
360 0 : nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
361 0 : rv = rph->CollectSubstitutions(resources);
362 0 : NS_ENSURE_SUCCESS_VOID(rv);
363 : }
364 :
365 39 : for (auto iter = mOverrideTable.Iter(); !iter.Done(); iter.Next()) {
366 0 : SerializedURI chromeURI, overrideURI;
367 :
368 18 : SerializeURI(iter.Key(), chromeURI);
369 0 : SerializeURI(iter.UserData(), overrideURI);
370 :
371 54 : OverrideMapping override = { chromeURI, overrideURI };
372 0 : overrides.AppendElement(override);
373 : }
374 :
375 2 : nsAutoCString appLocale;
376 0 : LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
377 :
378 1 : if (aParent) {
379 0 : bool success = aParent->SendRegisterChrome(packages, resources, overrides,
380 0 : appLocale, false);
381 0 : NS_ENSURE_TRUE_VOID(success);
382 : } else {
383 0 : nsTArray<ContentParent*> parents;
384 0 : ContentParent::GetAll(parents);
385 0 : if (!parents.Length())
386 0 : return;
387 :
388 0 : for (uint32_t i = 0; i < parents.Length(); i++) {
389 : DebugOnly<bool> success =
390 0 : parents[i]->SendRegisterChrome(packages, resources, overrides,
391 0 : appLocale, true);
392 0 : NS_WARNING_ASSERTION(success,
393 : "couldn't reset a child's registered chrome");
394 : }
395 : }
396 : }
397 :
398 : /* static */ void
399 91 : nsChromeRegistryChrome::ChromePackageFromPackageEntry(const nsACString& aPackageName,
400 : PackageEntry* aPackage,
401 : ChromePackage* aChromePackage,
402 : const nsCString& aSelectedSkin)
403 : {
404 182 : nsAutoCString appLocale;
405 0 : LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
406 :
407 182 : SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
408 0 : SerializeURI(aPackage->locales.GetBase(appLocale, nsProviderArray::LOCALE),
409 0 : aChromePackage->localeBaseURI);
410 0 : SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
411 0 : aChromePackage->skinBaseURI);
412 0 : aChromePackage->package = aPackageName;
413 0 : aChromePackage->flags = aPackage->flags;
414 0 : }
415 :
416 : static bool
417 90 : CanLoadResource(nsIURI* aResourceURI)
418 : {
419 90 : bool isLocalResource = false;
420 : (void)NS_URIChainHasFlags(aResourceURI,
421 : nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
422 90 : &isLocalResource);
423 0 : return isLocalResource;
424 : }
425 :
426 : nsIURI*
427 364 : nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage,
428 : const nsCString& aProvider,
429 : const nsCString& aPath)
430 : {
431 : PackageEntry* entry;
432 364 : if (!mPackagesHash.Get(aPackage, &entry)) {
433 0 : if (!mInitialized)
434 : return nullptr;
435 :
436 0 : LogMessage("No chrome package registered for chrome://%s/%s/%s",
437 0 : aPackage.get(), aProvider.get(), aPath.get());
438 :
439 0 : return nullptr;
440 : }
441 :
442 364 : if (aProvider.EqualsLiteral("locale")) {
443 0 : nsAutoCString appLocale;
444 0 : LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
445 0 : return entry->locales.GetBase(appLocale, nsProviderArray::LOCALE);
446 : }
447 317 : else if (aProvider.EqualsLiteral("skin")) {
448 0 : return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
449 : }
450 275 : else if (aProvider.EqualsLiteral("content")) {
451 0 : return entry->baseURI;
452 : }
453 : return nullptr;
454 : }
455 :
456 : nsresult
457 664 : nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
458 : uint32_t* aFlags)
459 : {
460 : PackageEntry* entry;
461 664 : if (!mPackagesHash.Get(aPackage, &entry))
462 : return NS_ERROR_FILE_NOT_FOUND;
463 :
464 664 : *aFlags = entry->flags;
465 0 : return NS_OK;
466 : }
467 :
468 : nsChromeRegistryChrome::ProviderEntry*
469 308 : nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
470 : {
471 616 : size_t i = mArray.Length();
472 0 : if (!i)
473 : return nullptr;
474 :
475 : ProviderEntry* found = nullptr; // Only set if we find a partial-match locale
476 : ProviderEntry* entry = nullptr;
477 :
478 164 : while (i--) {
479 0 : entry = &mArray[i];
480 0 : if (aPreferred.Equals(entry->provider))
481 : return entry;
482 :
483 0 : if (aType != LOCALE)
484 : continue;
485 :
486 0 : if (LanguagesMatch(aPreferred, entry->provider)) {
487 : found = entry;
488 : continue;
489 : }
490 :
491 0 : if (!found && entry->provider.EqualsLiteral("en-US"))
492 0 : found = entry;
493 : }
494 :
495 0 : if (!found && aType != EXACT)
496 : return entry;
497 :
498 0 : return found;
499 : }
500 :
501 : nsIURI*
502 271 : nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType)
503 : {
504 271 : ProviderEntry* provider = GetProvider(aPreferred, aType);
505 :
506 271 : if (!provider)
507 : return nullptr;
508 :
509 326 : return provider->baseURI;
510 : }
511 :
512 : const nsACString&
513 3 : nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType)
514 : {
515 3 : ProviderEntry* entry = GetProvider(aPreferred, aType);
516 :
517 3 : if (entry)
518 0 : return entry->provider;
519 :
520 2 : return EmptyCString();
521 : }
522 :
523 : void
524 34 : nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL)
525 : {
526 34 : ProviderEntry* provider = GetProvider(aProvider, EXACT);
527 :
528 34 : if (provider) {
529 0 : provider->baseURI = aBaseURL;
530 0 : return;
531 : }
532 :
533 : // no existing entries, add a new one
534 34 : mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
535 : }
536 :
537 : void
538 0 : nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
539 : {
540 0 : int32_t i = mArray.Length();
541 0 : while (i--) {
542 0 : a->AppendElement(mArray[i].provider);
543 : }
544 0 : }
545 :
546 : void
547 0 : nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI)
548 : {
549 0 : int32_t i = mArray.Count();
550 0 : while (i--) {
551 : bool equals;
552 0 : if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals)
553 0 : return;
554 : }
555 :
556 0 : mArray.AppendObject(aURI);
557 : }
558 :
559 : void
560 0 : nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay)
561 : {
562 0 : OverlayListEntry* entry = mTable.PutEntry(aBase);
563 0 : if (entry)
564 0 : entry->AddURI(aOverlay);
565 0 : }
566 :
567 : const nsCOMArray<nsIURI>*
568 3 : nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
569 : {
570 6 : OverlayListEntry* entry = mTable.GetEntry(aBase);
571 0 : if (!entry)
572 : return nullptr;
573 :
574 0 : return &entry->mArray;
575 : }
576 :
577 : #ifdef MOZ_XUL
578 : NS_IMETHODIMP
579 3 : nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
580 : nsISimpleEnumerator **aResult)
581 : {
582 6 : nsCOMPtr<nsIURI> chromeURLWithoutHash;
583 0 : if (aChromeURL) {
584 0 : aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
585 : }
586 3 : const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(chromeURLWithoutHash);
587 0 : if (!parray)
588 0 : return NS_NewEmptyEnumerator(aResult);
589 :
590 0 : return NS_NewArrayEnumerator(aResult, *parray);
591 : }
592 : #endif // MOZ_XUL
593 :
594 : nsIURI*
595 0 : nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
596 : {
597 216 : if (!mManifestURI) {
598 0 : nsCString uri;
599 0 : mFile.GetURIString(uri);
600 0 : NS_NewURI(getter_AddRefs(mManifestURI), uri);
601 : }
602 0 : return mManifestURI;
603 : }
604 :
605 : already_AddRefed<nsIURI>
606 1 : nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
607 : {
608 108 : nsIURI* baseuri = GetManifestURI();
609 108 : if (!baseuri)
610 : return nullptr;
611 :
612 216 : nsCOMPtr<nsIURI> resolved;
613 0 : nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
614 0 : if (NS_FAILED(rv))
615 : return nullptr;
616 :
617 108 : return resolved.forget();
618 : }
619 :
620 : static void
621 72 : EnsureLowerCase(char *aBuf)
622 : {
623 1618 : for (; *aBuf; ++aBuf) {
624 0 : char ch = *aBuf;
625 0 : if (ch >= 'A' && ch <= 'Z')
626 0 : *aBuf = ch + 'a' - 'A';
627 : }
628 0 : }
629 :
630 : static void
631 73 : SendManifestEntry(const ChromeRegistryItem &aItem)
632 : {
633 0 : nsTArray<ContentParent*> parents;
634 73 : ContentParent::GetAll(parents);
635 73 : if (!parents.Length())
636 73 : return;
637 :
638 0 : for (uint32_t i = 0; i < parents.Length(); i++) {
639 0 : Unused << parents[i]->SendRegisterChromeItem(aItem);
640 : }
641 : }
642 :
643 : void
644 0 : nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
645 : char *const * argv, int flags)
646 : {
647 0 : char* package = argv[0];
648 21 : char* uri = argv[1];
649 :
650 0 : EnsureLowerCase(package);
651 :
652 0 : nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
653 21 : if (!resolved) {
654 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
655 0 : "During chrome registration, unable to create URI '%s'.", uri);
656 0 : return;
657 : }
658 :
659 21 : if (!CanLoadResource(resolved)) {
660 0 : LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
661 : "During chrome registration, cannot register non-local URI '%s' as content.",
662 0 : uri);
663 0 : return;
664 : }
665 :
666 0 : nsDependentCString packageName(package);
667 21 : PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
668 0 : entry->baseURI = resolved;
669 0 : entry->flags = flags;
670 :
671 1 : if (mDynamicRegistration) {
672 1 : ChromePackage chromePackage;
673 21 : ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
674 21 : mSelectedSkin);
675 0 : SendManifestEntry(chromePackage);
676 : }
677 : }
678 :
679 : void
680 23 : nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
681 : char *const * argv, int flags)
682 : {
683 0 : char* package = argv[0];
684 0 : char* provider = argv[1];
685 0 : char* uri = argv[2];
686 :
687 0 : EnsureLowerCase(package);
688 :
689 0 : nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
690 0 : if (!resolved) {
691 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
692 0 : "During chrome registration, unable to create URI '%s'.", uri);
693 0 : return;
694 : }
695 :
696 0 : if (!CanLoadResource(resolved)) {
697 0 : LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
698 : "During chrome registration, cannot register non-local URI '%s' as content.",
699 0 : uri);
700 0 : return;
701 : }
702 :
703 0 : nsDependentCString packageName(package);
704 23 : PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
705 0 : entry->locales.SetBase(nsDependentCString(provider), resolved);
706 :
707 1 : if (mDynamicRegistration) {
708 1 : ChromePackage chromePackage;
709 0 : ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
710 23 : mSelectedSkin);
711 23 : SendManifestEntry(chromePackage);
712 : }
713 :
714 : // We use mainPackage as the package we track for reporting new locales being
715 : // registered. For most cases it will be "global", but for Fennec it will be
716 : // "browser".
717 46 : nsAutoCString mainPackage;
718 46 : nsresult rv = OverrideLocalePackage(NS_LITERAL_CSTRING("global"), mainPackage);
719 0 : if (NS_FAILED(rv)) {
720 0 : return;
721 : }
722 : }
723 :
724 : void
725 0 : nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
726 : char *const * argv, int flags)
727 : {
728 11 : char* package = argv[0];
729 11 : char* provider = argv[1];
730 11 : char* uri = argv[2];
731 :
732 11 : EnsureLowerCase(package);
733 :
734 0 : nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
735 0 : if (!resolved) {
736 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
737 0 : "During chrome registration, unable to create URI '%s'.", uri);
738 0 : return;
739 : }
740 :
741 0 : if (!CanLoadResource(resolved)) {
742 0 : LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
743 : "During chrome registration, cannot register non-local URI '%s' as content.",
744 0 : uri);
745 0 : return;
746 : }
747 :
748 0 : nsDependentCString packageName(package);
749 11 : PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
750 0 : entry->skins.SetBase(nsDependentCString(provider), resolved);
751 :
752 1 : if (mDynamicRegistration) {
753 1 : ChromePackage chromePackage;
754 1 : ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
755 11 : mSelectedSkin);
756 11 : SendManifestEntry(chromePackage);
757 : }
758 : }
759 :
760 : void
761 0 : nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
762 : char *const * argv, int flags)
763 : {
764 0 : char* base = argv[0];
765 0 : char* overlay = argv[1];
766 :
767 0 : nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
768 0 : nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
769 0 : if (!baseuri || !overlayuri) {
770 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
771 0 : "During chrome registration, unable to create URI.");
772 0 : return;
773 : }
774 :
775 0 : if (!CanLoadResource(overlayuri)) {
776 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
777 0 : "Cannot register non-local URI '%s' as an overlay.", overlay);
778 0 : return;
779 : }
780 :
781 0 : nsCOMPtr<nsIURI> baseuriWithoutHash;
782 0 : baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
783 :
784 0 : mOverlayHash.Add(baseuriWithoutHash, overlayuri);
785 : }
786 :
787 : void
788 1 : nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
789 : char *const * argv, int flags)
790 : {
791 1 : char* chrome = argv[0];
792 1 : char* resolved = argv[1];
793 :
794 1 : nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
795 36 : nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
796 36 : if (!chromeuri || !resolveduri) {
797 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
798 0 : "During chrome registration, unable to create URI.");
799 0 : return;
800 : }
801 :
802 18 : if (cx.mType == NS_SKIN_LOCATION) {
803 0 : bool chromeSkinOnly = false;
804 0 : nsresult rv = chromeuri->SchemeIs("chrome", &chromeSkinOnly);
805 0 : chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
806 0 : if (chromeSkinOnly) {
807 0 : rv = resolveduri->SchemeIs("chrome", &chromeSkinOnly);
808 0 : chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
809 : }
810 0 : if (chromeSkinOnly) {
811 0 : nsAutoCString chromePath, resolvedPath;
812 0 : chromeuri->GetPathQueryRef(chromePath);
813 0 : resolveduri->GetPathQueryRef(resolvedPath);
814 0 : chromeSkinOnly = StringBeginsWith(chromePath, NS_LITERAL_CSTRING("/skin/")) &&
815 0 : StringBeginsWith(resolvedPath, NS_LITERAL_CSTRING("/skin/"));
816 : }
817 0 : if (!chromeSkinOnly) {
818 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
819 : "Cannot register non-chrome://.../skin/ URIs '%s' and '%s' as overrides and/or to be overridden from a skin manifest.",
820 0 : chrome, resolved);
821 0 : return;
822 : }
823 : }
824 :
825 1 : if (!CanLoadResource(resolveduri)) {
826 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
827 0 : "Cannot register non-local URI '%s' for an override.", resolved);
828 0 : return;
829 : }
830 36 : mOverrideTable.Put(chromeuri, resolveduri);
831 :
832 18 : if (mDynamicRegistration) {
833 36 : SerializedURI serializedChrome;
834 0 : SerializedURI serializedOverride;
835 :
836 18 : SerializeURI(chromeuri, serializedChrome);
837 0 : SerializeURI(resolveduri, serializedOverride);
838 :
839 0 : OverrideMapping override = { serializedChrome, serializedOverride };
840 1 : SendManifestEntry(override);
841 : }
842 : }
843 :
844 : void
845 0 : nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
846 : char *const * argv, int flags)
847 : {
848 1 : char* package = argv[0];
849 1 : char* uri = argv[1];
850 :
851 1 : EnsureLowerCase(package);
852 34 : nsDependentCString host(package);
853 :
854 1 : nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
855 1 : if (!io) {
856 0 : NS_WARNING("No IO service trying to process chrome manifests");
857 0 : return;
858 : }
859 :
860 1 : nsCOMPtr<nsIProtocolHandler> ph;
861 1 : nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
862 17 : if (NS_FAILED(rv))
863 0 : return;
864 :
865 51 : nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
866 :
867 34 : nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
868 0 : if (!resolved) {
869 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
870 0 : "During chrome registration, unable to create URI '%s'.", uri);
871 0 : return;
872 : }
873 :
874 17 : if (!CanLoadResource(resolved)) {
875 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
876 : "Warning: cannot register non-local URI '%s' as a resource.",
877 0 : uri);
878 0 : return;
879 : }
880 :
881 : // By default, Firefox resources are not content-accessible unless the
882 : // manifests opts in.
883 0 : bool contentAccessible = (flags & nsChromeRegistry::CONTENT_ACCESSIBLE);
884 :
885 17 : uint32_t substitutionFlags = 0;
886 17 : if (contentAccessible) {
887 6 : substitutionFlags |= nsIResProtocolHandler::ALLOW_CONTENT_ACCESS;
888 : }
889 34 : rv = rph->SetSubstitutionWithFlags(host, resolved, substitutionFlags);
890 17 : if (NS_FAILED(rv)) {
891 0 : LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
892 : "Warning: cannot set substitution for '%s'.",
893 0 : uri);
894 : }
895 : }
|