Bumping manifests a=b2g-bump
[gecko.git] / chrome / nsChromeRegistryChrome.cpp
blob416cd97c749a1f573f1f8d83bee019beebbc769c
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 nsCOMPtr<nsIIOService> io (do_GetIOService());
457 NS_ENSURE_TRUE_VOID(io);
459 nsCOMPtr<nsIProtocolHandler> ph;
460 nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
461 NS_ENSURE_SUCCESS_VOID(rv);
463 //FIXME: Some substitutions are set up lazily and might not exist yet
464 nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
465 nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
466 rph->CollectSubstitutions(resources);
468 mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides);
470 if (aParent) {
471 bool success = aParent->SendRegisterChrome(packages, resources, overrides,
472 mSelectedLocale, false);
473 NS_ENSURE_TRUE_VOID(success);
474 } else {
475 nsTArray<ContentParent*> parents;
476 ContentParent::GetAll(parents);
477 if (!parents.Length())
478 return;
480 for (uint32_t i = 0; i < parents.Length(); i++) {
481 DebugOnly<bool> success =
482 parents[i]->SendRegisterChrome(packages, resources, overrides,
483 mSelectedLocale, true);
484 NS_WARN_IF_FALSE(success, "couldn't reset a child's registered chrome");
489 /* static */ void
490 nsChromeRegistryChrome::ChromePackageFromPackageEntry(const nsACString& aPackageName,
491 PackageEntry* aPackage,
492 ChromePackage* aChromePackage,
493 const nsCString& aSelectedLocale,
494 const nsCString& aSelectedSkin)
496 SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
497 SerializeURI(aPackage->locales.GetBase(aSelectedLocale,
498 nsProviderArray::LOCALE),
499 aChromePackage->localeBaseURI);
500 SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
501 aChromePackage->skinBaseURI);
502 aChromePackage->package = aPackageName;
503 aChromePackage->flags = aPackage->flags;
506 PLDHashOperator
507 nsChromeRegistryChrome::CollectPackages(const nsACString &aKey,
508 PackageEntry *package,
509 void *arg)
511 EnumerationArgs* args = static_cast<EnumerationArgs*>(arg);
513 ChromePackage chromePackage;
514 ChromePackageFromPackageEntry(aKey, package, &chromePackage,
515 args->selectedLocale, args->selectedSkin);
516 args->packages.AppendElement(chromePackage);
517 return PL_DHASH_NEXT;
520 static bool
521 CanLoadResource(nsIURI* aResourceURI)
523 bool isLocalResource = false;
524 (void)NS_URIChainHasFlags(aResourceURI,
525 nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
526 &isLocalResource);
527 return isLocalResource;
530 nsIURI*
531 nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage,
532 const nsCString& aProvider,
533 const nsCString& aPath)
535 PackageEntry* entry;
536 if (!mPackagesHash.Get(aPackage, &entry)) {
537 if (!mInitialized)
538 return nullptr;
540 LogMessage("No chrome package registered for chrome://%s/%s/%s",
541 aPackage.get(), aProvider.get(), aPath.get());
543 return nullptr;
546 if (aProvider.EqualsLiteral("locale")) {
547 return entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE);
549 else if (aProvider.EqualsLiteral("skin")) {
550 return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
552 else if (aProvider.EqualsLiteral("content")) {
553 return entry->baseURI;
555 return nullptr;
558 nsresult
559 nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
560 uint32_t* aFlags)
562 PackageEntry* entry;
563 if (!mPackagesHash.Get(aPackage, &entry))
564 return NS_ERROR_FILE_NOT_FOUND;
566 *aFlags = entry->flags;
567 return NS_OK;
570 nsChromeRegistryChrome::ProviderEntry*
571 nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
573 size_t i = mArray.Length();
574 if (!i)
575 return nullptr;
577 ProviderEntry* found = nullptr; // Only set if we find a partial-match locale
578 ProviderEntry* entry = nullptr;
580 while (i--) {
581 entry = &mArray[i];
582 if (aPreferred.Equals(entry->provider))
583 return entry;
585 if (aType != LOCALE)
586 continue;
588 if (LanguagesMatch(aPreferred, entry->provider)) {
589 found = entry;
590 continue;
593 if (!found && entry->provider.EqualsLiteral("en-US"))
594 found = entry;
597 if (!found && aType != EXACT)
598 return entry;
600 return found;
603 nsIURI*
604 nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType)
606 ProviderEntry* provider = GetProvider(aPreferred, aType);
608 if (!provider)
609 return nullptr;
611 return provider->baseURI;
614 const nsACString&
615 nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType)
617 ProviderEntry* entry = GetProvider(aPreferred, aType);
619 if (entry)
620 return entry->provider;
622 return EmptyCString();
625 void
626 nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL)
628 ProviderEntry* provider = GetProvider(aProvider, EXACT);
630 if (provider) {
631 provider->baseURI = aBaseURL;
632 return;
635 // no existing entries, add a new one
636 mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
639 void
640 nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
642 int32_t i = mArray.Length();
643 while (i--) {
644 a->AppendElement(mArray[i].provider);
648 void
649 nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI)
651 int32_t i = mArray.Count();
652 while (i--) {
653 bool equals;
654 if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals)
655 return;
658 mArray.AppendObject(aURI);
661 void
662 nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay)
664 OverlayListEntry* entry = mTable.PutEntry(aBase);
665 if (entry)
666 entry->AddURI(aOverlay);
669 const nsCOMArray<nsIURI>*
670 nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
672 OverlayListEntry* entry = mTable.GetEntry(aBase);
673 if (!entry)
674 return nullptr;
676 return &entry->mArray;
679 #ifdef MOZ_XUL
680 NS_IMETHODIMP
681 nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL,
682 nsISimpleEnumerator **aResult)
684 const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(aChromeURL);
685 if (!parray)
686 return NS_NewEmptyEnumerator(aResult);
688 return NS_NewArrayEnumerator(aResult, *parray);
691 NS_IMETHODIMP
692 nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
693 nsISimpleEnumerator **aResult)
695 const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(aChromeURL);
696 if (!parray)
697 return NS_NewEmptyEnumerator(aResult);
699 return NS_NewArrayEnumerator(aResult, *parray);
701 #endif // MOZ_XUL
703 nsIURI*
704 nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
706 if (!mManifestURI) {
707 nsCString uri;
708 mFile.GetURIString(uri);
709 NS_NewURI(getter_AddRefs(mManifestURI), uri);
711 return mManifestURI;
714 nsIXPConnect*
715 nsChromeRegistry::ManifestProcessingContext::GetXPConnect()
717 if (!mXPConnect)
718 mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1");
720 return mXPConnect;
723 already_AddRefed<nsIURI>
724 nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
726 nsIURI* baseuri = GetManifestURI();
727 if (!baseuri)
728 return nullptr;
730 nsCOMPtr<nsIURI> resolved;
731 nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
732 if (NS_FAILED(rv))
733 return nullptr;
735 return resolved.forget();
738 static void
739 EnsureLowerCase(char *aBuf)
741 for (; *aBuf; ++aBuf) {
742 char ch = *aBuf;
743 if (ch >= 'A' && ch <= 'Z')
744 *aBuf = ch + 'a' - 'A';
748 static void
749 SendManifestEntry(const ChromeRegistryItem &aItem)
751 nsTArray<ContentParent*> parents;
752 ContentParent::GetAll(parents);
753 if (!parents.Length())
754 return;
756 for (uint32_t i = 0; i < parents.Length(); i++) {
757 unused << parents[i]->SendRegisterChromeItem(aItem);
761 void
762 nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
763 char *const * argv, bool platform,
764 bool contentaccessible)
766 char* package = argv[0];
767 char* uri = argv[1];
769 EnsureLowerCase(package);
771 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
772 if (!resolved) {
773 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
774 "During chrome registration, unable to create URI '%s'.", uri);
775 return;
778 if (!CanLoadResource(resolved)) {
779 LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
780 "During chrome registration, cannot register non-local URI '%s' as content.",
781 uri);
782 return;
785 nsDependentCString packageName(package);
786 PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
787 entry->baseURI = resolved;
789 if (platform)
790 entry->flags |= PLATFORM_PACKAGE;
791 if (contentaccessible)
792 entry->flags |= CONTENT_ACCESSIBLE;
794 if (mDynamicRegistration) {
795 ChromePackage chromePackage;
796 ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
797 mSelectedLocale, mSelectedSkin);
798 SendManifestEntry(chromePackage);
802 void
803 nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
804 char *const * argv, bool platform,
805 bool contentaccessible)
807 char* package = argv[0];
808 char* provider = argv[1];
809 char* uri = argv[2];
811 EnsureLowerCase(package);
813 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
814 if (!resolved) {
815 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
816 "During chrome registration, unable to create URI '%s'.", uri);
817 return;
820 if (!CanLoadResource(resolved)) {
821 LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
822 "During chrome registration, cannot register non-local URI '%s' as content.",
823 uri);
824 return;
827 nsDependentCString packageName(package);
828 PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
829 entry->locales.SetBase(nsDependentCString(provider), resolved);
831 if (mDynamicRegistration) {
832 ChromePackage chromePackage;
833 ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
834 mSelectedLocale, mSelectedSkin);
835 SendManifestEntry(chromePackage);
839 void
840 nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
841 char *const * argv, bool platform,
842 bool contentaccessible)
844 char* package = argv[0];
845 char* provider = argv[1];
846 char* uri = argv[2];
848 EnsureLowerCase(package);
850 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
851 if (!resolved) {
852 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
853 "During chrome registration, unable to create URI '%s'.", uri);
854 return;
857 if (!CanLoadResource(resolved)) {
858 LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
859 "During chrome registration, cannot register non-local URI '%s' as content.",
860 uri);
861 return;
864 nsDependentCString packageName(package);
865 PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
866 entry->skins.SetBase(nsDependentCString(provider), resolved);
868 if (mDynamicRegistration) {
869 ChromePackage chromePackage;
870 ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
871 mSelectedLocale, mSelectedSkin);
872 SendManifestEntry(chromePackage);
876 void
877 nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
878 char *const * argv, bool platform,
879 bool contentaccessible)
881 char* base = argv[0];
882 char* overlay = argv[1];
884 nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
885 nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
886 if (!baseuri || !overlayuri) {
887 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
888 "During chrome registration, unable to create URI.");
889 return;
892 if (!CanLoadResource(overlayuri)) {
893 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
894 "Cannot register non-local URI '%s' as an overlay.", overlay);
895 return;
898 mOverlayHash.Add(baseuri, overlayuri);
901 void
902 nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
903 char *const * argv, bool platform,
904 bool contentaccessible)
906 char* base = argv[0];
907 char* overlay = argv[1];
909 nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
910 nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
911 if (!baseuri || !overlayuri) {
912 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
913 "During chrome registration, unable to create URI.");
914 return;
917 if (!CanLoadResource(overlayuri)) {
918 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
919 "Cannot register non-local URI '%s' as a style overlay.", overlay);
920 return;
923 mStyleHash.Add(baseuri, overlayuri);
926 void
927 nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
928 char *const * argv, bool platform,
929 bool contentaccessible)
931 char* chrome = argv[0];
932 char* resolved = argv[1];
934 nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
935 nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
936 if (!chromeuri || !resolveduri) {
937 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
938 "During chrome registration, unable to create URI.");
939 return;
942 if (!CanLoadResource(resolveduri)) {
943 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
944 "Cannot register non-local URI '%s' for an override.", resolved);
945 return;
947 mOverrideTable.Put(chromeuri, resolveduri);
949 if (mDynamicRegistration) {
950 SerializedURI serializedChrome;
951 SerializedURI serializedOverride;
953 SerializeURI(chromeuri, serializedChrome);
954 SerializeURI(resolveduri, serializedOverride);
956 OverrideMapping override = { serializedChrome, serializedOverride };
957 SendManifestEntry(override);
961 void
962 nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
963 char *const * argv, bool platform,
964 bool contentaccessible)
966 char* package = argv[0];
967 char* uri = argv[1];
969 EnsureLowerCase(package);
970 nsDependentCString host(package);
972 nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
973 if (!io) {
974 NS_WARNING("No IO service trying to process chrome manifests");
975 return;
978 nsCOMPtr<nsIProtocolHandler> ph;
979 nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
980 if (NS_FAILED(rv))
981 return;
983 nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
985 bool exists = false;
986 rv = rph->HasSubstitution(host, &exists);
987 if (exists) {
988 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
989 "Duplicate resource declaration for '%s' ignored.", package);
990 return;
993 nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
994 if (!resolved) {
995 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
996 "During chrome registration, unable to create URI '%s'.", uri);
997 return;
1000 if (!CanLoadResource(resolved)) {
1001 LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
1002 "Warning: cannot register non-local URI '%s' as a resource.",
1003 uri);
1004 return;
1007 rph->SetSubstitution(host, resolved);