Bumping manifests a=b2g-bump
[gecko.git] / chrome / nsChromeRegistryChrome.cpp
blob15e077c8a16927213b4c994dec59d91d8ef52df0
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/. */
7 #include "mozilla/dom/ContentParent.h"
8 #include "RegistryMessageUtils.h"
9 #include "nsResProtocolHandler.h"
11 #include "nsChromeRegistryChrome.h"
13 #if defined(XP_WIN)
14 #include <windows.h>
15 #elif defined(XP_MACOSX)
16 #include <CoreServices/CoreServices.h>
17 #endif
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"
27 #include "mozilla/LookAndFeel.h"
28 #include "mozilla/unused.h"
30 #include "nsICommandLine.h"
31 #include "nsILocaleService.h"
32 #include "nsIObserverService.h"
33 #include "nsIPrefBranch.h"
34 #include "nsIPrefService.h"
35 #include "mozilla/Preferences.h"
36 #include "nsIResProtocolHandler.h"
37 #include "nsIScriptError.h"
38 #include "nsIXPConnect.h"
39 #include "nsIXULRuntime.h"
41 #define UILOCALE_CMD_LINE_ARG "UILocale"
43 #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
44 #define SELECTED_LOCALE_PREF "general.useragent.locale"
45 #define SELECTED_SKIN_PREF "general.skins.selectedSkin"
46 #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
48 using namespace mozilla;
49 using mozilla::dom::ContentParent;
50 using mozilla::dom::PContentParent;
52 // We use a "best-fit" algorithm for matching locales and themes.
53 // 1) the exact selected locale/theme
54 // 2) (locales only) same language, different country
55 // e.g. en-GB is the selected locale, only en-US is available
56 // 3) any available locale/theme
58 /**
59 * Match the language-part of two lang-COUNTRY codes, hopefully but
60 * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
61 * work, any other garbage-in will produce undefined results as long
62 * as it does not crash.
64 static bool
65 LanguagesMatch(const nsACString& a, const nsACString& b)
67 if (a.Length() < 2 || b.Length() < 2)
68 return false;
70 nsACString::const_iterator as, ae, bs, be;
71 a.BeginReading(as);
72 a.EndReading(ae);
73 b.BeginReading(bs);
74 b.EndReading(be);
76 while (*as == *bs) {
77 if (*as == '-')
78 return true;
80 ++as; ++bs;
82 // reached the end
83 if (as == ae && bs == be)
84 return true;
86 // "a" is short
87 if (as == ae)
88 return (*bs == '-');
90 // "b" is short
91 if (bs == be)
92 return (*as == '-');
95 return false;
98 nsChromeRegistryChrome::nsChromeRegistryChrome()
99 : mProfileLoaded(false)
100 , mDynamicRegistration(true)
104 nsChromeRegistryChrome::~nsChromeRegistryChrome()
108 nsresult
109 nsChromeRegistryChrome::Init()
111 nsresult rv = nsChromeRegistry::Init();
112 if (NS_FAILED(rv))
113 return rv;
115 mSelectedLocale = NS_LITERAL_CSTRING("en-US");
116 mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
118 bool safeMode = false;
119 nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
120 if (xulrun)
121 xulrun->GetInSafeMode(&safeMode);
123 nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
124 nsCOMPtr<nsIPrefBranch> prefs;
126 if (safeMode)
127 prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
128 else
129 prefs = do_QueryInterface(prefserv);
131 if (!prefs) {
132 NS_WARNING("Could not get pref service!");
134 else {
135 nsXPIDLCString provider;
136 rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider));
137 if (NS_SUCCEEDED(rv))
138 mSelectedSkin = provider;
140 SelectLocaleFromPref(prefs);
142 rv = prefs->AddObserver(MATCH_OS_LOCALE_PREF, this, true);
143 rv = prefs->AddObserver(SELECTED_LOCALE_PREF, this, true);
144 rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true);
147 nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
148 if (obsService) {
149 obsService->AddObserver(this, "command-line-startup", true);
150 obsService->AddObserver(this, "profile-initial-state", true);
153 return NS_OK;
156 NS_IMETHODIMP
157 nsChromeRegistryChrome::CheckForOSAccessibility()
159 int32_t useAccessibilityTheme =
160 LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0);
162 if (useAccessibilityTheme) {
163 /* Set the skin to classic and remove pref observers */
164 if (!mSelectedSkin.EqualsLiteral("classic/1.0")) {
165 mSelectedSkin.AssignLiteral("classic/1.0");
166 RefreshSkins();
169 nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
170 if (prefs) {
171 prefs->RemoveObserver(SELECTED_SKIN_PREF, this);
175 return NS_OK;
178 NS_IMETHODIMP
179 nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage,
180 nsIUTF8StringEnumerator* *aResult)
182 nsCString realpackage;
183 nsresult rv = OverrideLocalePackage(aPackage, realpackage);
184 if (NS_FAILED(rv))
185 return rv;
187 nsTArray<nsCString> *a = new nsTArray<nsCString>;
188 if (!a)
189 return NS_ERROR_OUT_OF_MEMORY;
191 PackageEntry* entry;
192 if (mPackagesHash.Get(realpackage, &entry)) {
193 entry->locales.EnumerateToArray(a);
196 rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
197 if (NS_FAILED(rv))
198 delete a;
200 return rv;
203 static nsresult
204 getUILangCountry(nsACString& aUILang)
206 nsresult rv;
208 nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
209 NS_ENSURE_SUCCESS(rv, rv);
211 nsAutoString uiLang;
212 rv = localeService->GetLocaleComponentForUserAgent(uiLang);
213 NS_ENSURE_SUCCESS(rv, rv);
215 CopyUTF16toUTF8(uiLang, aUILang);
216 return NS_OK;
219 NS_IMETHODIMP
220 nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult)
222 *aResult = false;
224 nsAutoCString locale;
225 GetSelectedLocale(package, locale);
226 if (locale.Length() < 2)
227 return NS_OK;
229 // first check the intl.uidirection.<locale> preference, and if that is not
230 // set, check the same preference but with just the first two characters of
231 // the locale. If that isn't set, default to left-to-right.
232 nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale;
233 nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID));
234 if (!prefBranch)
235 return NS_OK;
237 nsXPIDLCString dir;
238 prefBranch->GetCharPref(prefString.get(), getter_Copies(dir));
239 if (dir.IsEmpty()) {
240 int32_t hyphen = prefString.FindChar('-');
241 if (hyphen >= 1) {
242 nsAutoCString shortPref(Substring(prefString, 0, hyphen));
243 prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir));
246 *aResult = dir.EqualsLiteral("rtl");
247 return NS_OK;
250 nsresult
251 nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
252 nsACString& aLocale)
254 nsCString realpackage;
255 nsresult rv = OverrideLocalePackage(aPackage, realpackage);
256 if (NS_FAILED(rv))
257 return rv;
258 PackageEntry* entry;
259 if (!mPackagesHash.Get(realpackage, &entry))
260 return NS_ERROR_FILE_NOT_FOUND;
262 aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE);
263 if (aLocale.IsEmpty())
264 return NS_ERROR_FAILURE;
266 return NS_OK;
269 nsresult
270 nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage,
271 nsACString& aOverride)
273 const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage;
274 nsAdoptingCString override = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get());
275 if (override) {
276 aOverride = override;
278 else {
279 aOverride = aPackage;
281 return NS_OK;
284 nsresult
285 nsChromeRegistryChrome::SelectLocaleFromPref(nsIPrefBranch* prefs)
287 nsresult rv;
288 bool matchOSLocale = false;
289 rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale);
291 if (NS_SUCCEEDED(rv) && matchOSLocale) {
292 // compute lang and region code only when needed!
293 nsAutoCString uiLocale;
294 rv = getUILangCountry(uiLocale);
295 if (NS_SUCCEEDED(rv))
296 mSelectedLocale = uiLocale;
298 else {
299 nsXPIDLCString provider;
300 rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider));
301 if (NS_SUCCEEDED(rv)) {
302 mSelectedLocale = provider;
306 if (NS_FAILED(rv))
307 NS_ERROR("Couldn't select locale from pref!");
309 return rv;
312 NS_IMETHODIMP
313 nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic,
314 const char16_t *someData)
316 nsresult rv = NS_OK;
318 if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
319 nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject));
320 NS_ASSERTION(prefs, "Bad observer call!");
322 NS_ConvertUTF16toUTF8 pref(someData);
324 if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) ||
325 pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
326 rv = UpdateSelectedLocale();
327 if (NS_SUCCEEDED(rv) && mProfileLoaded)
328 FlushAllCaches();
330 else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
331 nsXPIDLCString provider;
332 rv = prefs->GetCharPref(pref.get(), getter_Copies(provider));
333 if (NS_FAILED(rv)) {
334 NS_ERROR("Couldn't get new skin pref!");
335 return rv;
338 mSelectedSkin = provider;
339 RefreshSkins();
340 } else {
341 NS_ERROR("Unexpected pref!");
344 else if (!strcmp("command-line-startup", aTopic)) {
345 nsCOMPtr<nsICommandLine> cmdLine (do_QueryInterface(aSubject));
346 if (cmdLine) {
347 nsAutoString uiLocale;
348 rv = cmdLine->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG),
349 false, uiLocale);
350 if (NS_SUCCEEDED(rv) && !uiLocale.IsEmpty()) {
351 CopyUTF16toUTF8(uiLocale, mSelectedLocale);
352 nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
353 if (prefs) {
354 prefs->RemoveObserver(SELECTED_LOCALE_PREF, this);
359 else if (!strcmp("profile-initial-state", aTopic)) {
360 mProfileLoaded = true;
362 else {
363 NS_ERROR("Unexpected observer topic!");
366 return rv;
369 NS_IMETHODIMP
370 nsChromeRegistryChrome::CheckForNewChrome()
372 mPackagesHash.Clear();
373 mOverlayHash.Clear();
374 mStyleHash.Clear();
375 mOverrideTable.Clear();
377 mDynamicRegistration = false;
379 nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
381 mDynamicRegistration = true;
383 SendRegisteredChrome(nullptr);
384 return NS_OK;
387 nsresult nsChromeRegistryChrome::UpdateSelectedLocale()
389 nsresult rv = NS_OK;
390 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
391 if (prefs) {
392 rv = SelectLocaleFromPref(prefs);
393 if (NS_SUCCEEDED(rv)) {
394 nsCOMPtr<nsIObserverService> obsSvc =
395 mozilla::services::GetObserverService();
396 NS_ASSERTION(obsSvc, "Couldn't get observer service.");
397 obsSvc->NotifyObservers((nsIChromeRegistry*) this,
398 "selected-locale-has-changed", nullptr);
402 return rv;
405 static void
406 SerializeURI(nsIURI* aURI,
407 SerializedURI& aSerializedURI)
409 if (!aURI)
410 return;
412 aURI->GetSpec(aSerializedURI.spec);
413 aURI->GetOriginCharset(aSerializedURI.charset);
416 static PLDHashOperator
417 EnumerateOverride(nsIURI* aURIKey,
418 nsIURI* aURI,
419 void* aArg)
421 nsTArray<OverrideMapping>* overrides =
422 static_cast<nsTArray<OverrideMapping>*>(aArg);
424 SerializedURI chromeURI, overrideURI;
426 SerializeURI(aURIKey, chromeURI);
427 SerializeURI(aURI, overrideURI);
429 OverrideMapping override = {
430 chromeURI, overrideURI
432 overrides->AppendElement(override);
433 return (PLDHashOperator)PL_DHASH_NEXT;
436 struct EnumerationArgs
438 InfallibleTArray<ChromePackage>& packages;
439 const nsCString& selectedLocale;
440 const nsCString& selectedSkin;
443 void
444 nsChromeRegistryChrome::SendRegisteredChrome(
445 mozilla::dom::PContentParent* aParent)
447 InfallibleTArray<ChromePackage> packages;
448 InfallibleTArray<ResourceMapping> resources;
449 InfallibleTArray<OverrideMapping> overrides;
451 EnumerationArgs args = {
452 packages, mSelectedLocale, mSelectedSkin
454 mPackagesHash.EnumerateRead(CollectPackages, &args);
456 // If we were passed a parent then a new child process has been created and
457 // has requested all of the chrome so send it the resources too. Otherwise
458 // resource mappings are sent by the resource protocol handler dynamically.
459 if (aParent) {
460 nsCOMPtr<nsIIOService> io (do_GetIOService());
461 NS_ENSURE_TRUE_VOID(io);
463 nsCOMPtr<nsIProtocolHandler> ph;
464 nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
465 NS_ENSURE_SUCCESS_VOID(rv);
467 nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
468 nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
469 rph->CollectSubstitutions(resources);
472 mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides);
474 if (aParent) {
475 bool success = aParent->SendRegisterChrome(packages, resources, overrides,
476 mSelectedLocale, false);
477 NS_ENSURE_TRUE_VOID(success);
478 } else {
479 nsTArray<ContentParent*> parents;
480 ContentParent::GetAll(parents);
481 if (!parents.Length())
482 return;
484 for (uint32_t i = 0; i < parents.Length(); i++) {
485 DebugOnly<bool> success =
486 parents[i]->SendRegisterChrome(packages, resources, overrides,
487 mSelectedLocale, true);
488 NS_WARN_IF_FALSE(success, "couldn't reset a child's registered chrome");
493 /* static */ void
494 nsChromeRegistryChrome::ChromePackageFromPackageEntry(const nsACString& aPackageName,
495 PackageEntry* aPackage,
496 ChromePackage* aChromePackage,
497 const nsCString& aSelectedLocale,
498 const nsCString& aSelectedSkin)
500 SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
501 SerializeURI(aPackage->locales.GetBase(aSelectedLocale,
502 nsProviderArray::LOCALE),
503 aChromePackage->localeBaseURI);
504 SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
505 aChromePackage->skinBaseURI);
506 aChromePackage->package = aPackageName;
507 aChromePackage->flags = aPackage->flags;
510 PLDHashOperator
511 nsChromeRegistryChrome::CollectPackages(const nsACString &aKey,
512 PackageEntry *package,
513 void *arg)
515 EnumerationArgs* args = static_cast<EnumerationArgs*>(arg);
517 ChromePackage chromePackage;
518 ChromePackageFromPackageEntry(aKey, package, &chromePackage,
519 args->selectedLocale, args->selectedSkin);
520 args->packages.AppendElement(chromePackage);
521 return PL_DHASH_NEXT;
524 static bool
525 CanLoadResource(nsIURI* aResourceURI)
527 bool isLocalResource = false;
528 (void)NS_URIChainHasFlags(aResourceURI,
529 nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
530 &isLocalResource);
531 return isLocalResource;
534 nsIURI*
535 nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage,
536 const nsCString& aProvider,
537 const nsCString& aPath)
539 PackageEntry* entry;
540 if (!mPackagesHash.Get(aPackage, &entry)) {
541 if (!mInitialized)
542 return nullptr;
544 LogMessage("No chrome package registered for chrome://%s/%s/%s",
545 aPackage.get(), aProvider.get(), aPath.get());
547 return nullptr;
550 if (aProvider.EqualsLiteral("locale")) {
551 return entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE);
553 else if (aProvider.EqualsLiteral("skin")) {
554 return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
556 else if (aProvider.EqualsLiteral("content")) {
557 return entry->baseURI;
559 return nullptr;
562 nsresult
563 nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
564 uint32_t* aFlags)
566 PackageEntry* entry;
567 if (!mPackagesHash.Get(aPackage, &entry))
568 return NS_ERROR_FILE_NOT_FOUND;
570 *aFlags = entry->flags;
571 return NS_OK;
574 nsChromeRegistryChrome::ProviderEntry*
575 nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
577 size_t i = mArray.Length();
578 if (!i)
579 return nullptr;
581 ProviderEntry* found = nullptr; // Only set if we find a partial-match locale
582 ProviderEntry* entry = nullptr;
584 while (i--) {
585 entry = &mArray[i];
586 if (aPreferred.Equals(entry->provider))
587 return entry;
589 if (aType != LOCALE)
590 continue;
592 if (LanguagesMatch(aPreferred, entry->provider)) {
593 found = entry;
594 continue;
597 if (!found && entry->provider.EqualsLiteral("en-US"))
598 found = entry;
601 if (!found && aType != EXACT)
602 return entry;
604 return found;
607 nsIURI*
608 nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType)
610 ProviderEntry* provider = GetProvider(aPreferred, aType);
612 if (!provider)
613 return nullptr;
615 return provider->baseURI;
618 const nsACString&
619 nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType)
621 ProviderEntry* entry = GetProvider(aPreferred, aType);
623 if (entry)
624 return entry->provider;
626 return EmptyCString();
629 void
630 nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL)
632 ProviderEntry* provider = GetProvider(aProvider, EXACT);
634 if (provider) {
635 provider->baseURI = aBaseURL;
636 return;
639 // no existing entries, add a new one
640 mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
643 void
644 nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
646 int32_t i = mArray.Length();
647 while (i--) {
648 a->AppendElement(mArray[i].provider);
652 void
653 nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI)
655 int32_t i = mArray.Count();
656 while (i--) {
657 bool equals;
658 if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals)
659 return;
662 mArray.AppendObject(aURI);
665 void
666 nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay)
668 OverlayListEntry* entry = mTable.PutEntry(aBase);
669 if (entry)
670 entry->AddURI(aOverlay);
673 const nsCOMArray<nsIURI>*
674 nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
676 OverlayListEntry* entry = mTable.GetEntry(aBase);
677 if (!entry)
678 return nullptr;
680 return &entry->mArray;
683 #ifdef MOZ_XUL
684 NS_IMETHODIMP
685 nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL,
686 nsISimpleEnumerator **aResult)
688 nsCOMPtr<nsIURI> chromeURLWithoutHash;
689 if (aChromeURL) {
690 aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
692 const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(chromeURLWithoutHash);
693 if (!parray)
694 return NS_NewEmptyEnumerator(aResult);
696 return NS_NewArrayEnumerator(aResult, *parray);
699 NS_IMETHODIMP
700 nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
701 nsISimpleEnumerator **aResult)
703 nsCOMPtr<nsIURI> chromeURLWithoutHash;
704 if (aChromeURL) {
705 aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
707 const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(chromeURLWithoutHash);
708 if (!parray)
709 return NS_NewEmptyEnumerator(aResult);
711 return NS_NewArrayEnumerator(aResult, *parray);
713 #endif // MOZ_XUL
715 nsIURI*
716 nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
718 if (!mManifestURI) {
719 nsCString uri;
720 mFile.GetURIString(uri);
721 NS_NewURI(getter_AddRefs(mManifestURI), uri);
723 return mManifestURI;
726 nsIXPConnect*
727 nsChromeRegistry::ManifestProcessingContext::GetXPConnect()
729 if (!mXPConnect)
730 mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1");
732 return mXPConnect;
735 already_AddRefed<nsIURI>
736 nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
738 nsIURI* baseuri = GetManifestURI();
739 if (!baseuri)
740 return nullptr;
742 nsCOMPtr<nsIURI> resolved;
743 nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
744 if (NS_FAILED(rv))
745 return nullptr;
747 return resolved.forget();
750 static void
751 EnsureLowerCase(char *aBuf)
753 for (; *aBuf; ++aBuf) {
754 char ch = *aBuf;
755 if (ch >= 'A' && ch <= 'Z')
756 *aBuf = ch + 'a' - 'A';
760 static void
761 SendManifestEntry(const ChromeRegistryItem &aItem)
763 nsTArray<ContentParent*> parents;
764 ContentParent::GetAll(parents);
765 if (!parents.Length())
766 return;
768 for (uint32_t i = 0; i < parents.Length(); i++) {
769 unused << parents[i]->SendRegisterChromeItem(aItem);
773 void
774 nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
775 char *const * argv, bool platform,
776 bool contentaccessible)
778 char* package = argv[0];
779 char* uri = argv[1];
781 EnsureLowerCase(package);
783 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
784 if (!resolved) {
785 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
786 "During chrome registration, unable to create URI '%s'.", uri);
787 return;
790 if (!CanLoadResource(resolved)) {
791 LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
792 "During chrome registration, cannot register non-local URI '%s' as content.",
793 uri);
794 return;
797 nsDependentCString packageName(package);
798 PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
799 entry->baseURI = resolved;
801 if (platform)
802 entry->flags |= PLATFORM_PACKAGE;
803 if (contentaccessible)
804 entry->flags |= CONTENT_ACCESSIBLE;
806 if (mDynamicRegistration) {
807 ChromePackage chromePackage;
808 ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
809 mSelectedLocale, mSelectedSkin);
810 SendManifestEntry(chromePackage);
814 void
815 nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
816 char *const * argv, bool platform,
817 bool contentaccessible)
819 char* package = argv[0];
820 char* provider = argv[1];
821 char* uri = argv[2];
823 EnsureLowerCase(package);
825 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
826 if (!resolved) {
827 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
828 "During chrome registration, unable to create URI '%s'.", uri);
829 return;
832 if (!CanLoadResource(resolved)) {
833 LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
834 "During chrome registration, cannot register non-local URI '%s' as content.",
835 uri);
836 return;
839 nsDependentCString packageName(package);
840 PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
841 entry->locales.SetBase(nsDependentCString(provider), resolved);
843 if (mDynamicRegistration) {
844 ChromePackage chromePackage;
845 ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
846 mSelectedLocale, mSelectedSkin);
847 SendManifestEntry(chromePackage);
851 void
852 nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
853 char *const * argv, bool platform,
854 bool contentaccessible)
856 char* package = argv[0];
857 char* provider = argv[1];
858 char* uri = argv[2];
860 EnsureLowerCase(package);
862 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
863 if (!resolved) {
864 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
865 "During chrome registration, unable to create URI '%s'.", uri);
866 return;
869 if (!CanLoadResource(resolved)) {
870 LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
871 "During chrome registration, cannot register non-local URI '%s' as content.",
872 uri);
873 return;
876 nsDependentCString packageName(package);
877 PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
878 entry->skins.SetBase(nsDependentCString(provider), resolved);
880 if (mDynamicRegistration) {
881 ChromePackage chromePackage;
882 ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
883 mSelectedLocale, mSelectedSkin);
884 SendManifestEntry(chromePackage);
888 void
889 nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
890 char *const * argv, bool platform,
891 bool contentaccessible)
893 char* base = argv[0];
894 char* overlay = argv[1];
896 nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
897 nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
898 if (!baseuri || !overlayuri) {
899 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
900 "During chrome registration, unable to create URI.");
901 return;
904 if (!CanLoadResource(overlayuri)) {
905 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
906 "Cannot register non-local URI '%s' as an overlay.", overlay);
907 return;
910 nsCOMPtr<nsIURI> baseuriWithoutHash;
911 baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
913 mOverlayHash.Add(baseuriWithoutHash, overlayuri);
916 void
917 nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
918 char *const * argv, bool platform,
919 bool contentaccessible)
921 char* base = argv[0];
922 char* overlay = argv[1];
924 nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
925 nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
926 if (!baseuri || !overlayuri) {
927 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
928 "During chrome registration, unable to create URI.");
929 return;
932 if (!CanLoadResource(overlayuri)) {
933 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
934 "Cannot register non-local URI '%s' as a style overlay.", overlay);
935 return;
938 nsCOMPtr<nsIURI> baseuriWithoutHash;
939 baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
941 mStyleHash.Add(baseuriWithoutHash, overlayuri);
944 void
945 nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
946 char *const * argv, bool platform,
947 bool contentaccessible)
949 char* chrome = argv[0];
950 char* resolved = argv[1];
952 nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
953 nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
954 if (!chromeuri || !resolveduri) {
955 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
956 "During chrome registration, unable to create URI.");
957 return;
960 if (!CanLoadResource(resolveduri)) {
961 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
962 "Cannot register non-local URI '%s' for an override.", resolved);
963 return;
965 mOverrideTable.Put(chromeuri, resolveduri);
967 if (mDynamicRegistration) {
968 SerializedURI serializedChrome;
969 SerializedURI serializedOverride;
971 SerializeURI(chromeuri, serializedChrome);
972 SerializeURI(resolveduri, serializedOverride);
974 OverrideMapping override = { serializedChrome, serializedOverride };
975 SendManifestEntry(override);
979 void
980 nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
981 char *const * argv, bool platform,
982 bool contentaccessible)
984 char* package = argv[0];
985 char* uri = argv[1];
987 EnsureLowerCase(package);
988 nsDependentCString host(package);
990 nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
991 if (!io) {
992 NS_WARNING("No IO service trying to process chrome manifests");
993 return;
996 nsCOMPtr<nsIProtocolHandler> ph;
997 nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
998 if (NS_FAILED(rv))
999 return;
1001 nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
1003 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
1004 if (!resolved) {
1005 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
1006 "During chrome registration, unable to create URI '%s'.", uri);
1007 return;
1010 if (!CanLoadResource(resolved)) {
1011 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
1012 "Warning: cannot register non-local URI '%s' as a resource.",
1013 uri);
1014 return;
1017 rph->SetSubstitution(host, resolved);