/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 sts=2 sw=2 et tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/ContentParent.h" #include "RegistryMessageUtils.h" #include "nsResProtocolHandler.h" #include "nsChromeRegistryChrome.h" #if defined(XP_WIN) #include #elif defined(XP_MACOSX) #include #endif #include "nsArrayEnumerator.h" #include "nsComponentManager.h" #include "nsEnumeratorUtils.h" #include "nsNetUtil.h" #include "nsStringEnumerator.h" #include "nsTextFormatter.h" #include "nsXPCOMCIDInternal.h" #include "mozilla/LookAndFeel.h" #include "mozilla/unused.h" #include "nsICommandLine.h" #include "nsILocaleService.h" #include "nsIObserverService.h" #include "nsIPrefBranch.h" #include "nsIPrefService.h" #include "mozilla/Preferences.h" #include "nsIResProtocolHandler.h" #include "nsIScriptError.h" #include "nsIXPConnect.h" #include "nsIXULRuntime.h" #define UILOCALE_CMD_LINE_ARG "UILocale" #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS" #define SELECTED_LOCALE_PREF "general.useragent.locale" #define SELECTED_SKIN_PREF "general.skins.selectedSkin" #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package." using namespace mozilla; using mozilla::dom::ContentParent; using mozilla::dom::PContentParent; static PLDHashOperator RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, uint32_t number, void *arg) { return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE); } // We use a "best-fit" algorithm for matching locales and themes. // 1) the exact selected locale/theme // 2) (locales only) same language, different country // e.g. en-GB is the selected locale, only en-US is available // 3) any available locale/theme /** * Match the language-part of two lang-COUNTRY codes, hopefully but * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also * work, any other garbage-in will produce undefined results as long * as it does not crash. */ static bool LanguagesMatch(const nsACString& a, const nsACString& b) { if (a.Length() < 2 || b.Length() < 2) return false; nsACString::const_iterator as, ae, bs, be; a.BeginReading(as); a.EndReading(ae); b.BeginReading(bs); b.EndReading(be); while (*as == *bs) { if (*as == '-') return true; ++as; ++bs; // reached the end if (as == ae && bs == be) return true; // "a" is short if (as == ae) return (*bs == '-'); // "b" is short if (bs == be) return (*as == '-'); } return false; } nsChromeRegistryChrome::nsChromeRegistryChrome() : mProfileLoaded(false) , mDynamicRegistration(true) { mPackagesHash.ops = nullptr; } nsChromeRegistryChrome::~nsChromeRegistryChrome() { if (mPackagesHash.ops) PL_DHashTableFinish(&mPackagesHash); } nsresult nsChromeRegistryChrome::Init() { nsresult rv = nsChromeRegistry::Init(); if (NS_FAILED(rv)) return rv; mSelectedLocale = NS_LITERAL_CSTRING("en-US"); mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0"); PL_DHashTableInit(&mPackagesHash, &kTableOps, nullptr, sizeof(PackageEntry), 16); bool safeMode = false; nsCOMPtr xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID)); if (xulrun) xulrun->GetInSafeMode(&safeMode); nsCOMPtr prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID)); nsCOMPtr prefs; if (safeMode) prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs)); else prefs = do_QueryInterface(prefserv); if (!prefs) { NS_WARNING("Could not get pref service!"); } else { nsXPIDLCString provider; rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider)); if (NS_SUCCEEDED(rv)) mSelectedSkin = provider; SelectLocaleFromPref(prefs); rv = prefs->AddObserver(MATCH_OS_LOCALE_PREF, this, true); rv = prefs->AddObserver(SELECTED_LOCALE_PREF, this, true); rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true); } nsCOMPtr obsService = mozilla::services::GetObserverService(); if (obsService) { obsService->AddObserver(this, "command-line-startup", true); obsService->AddObserver(this, "profile-initial-state", true); } return NS_OK; } NS_IMETHODIMP nsChromeRegistryChrome::CheckForOSAccessibility() { int32_t useAccessibilityTheme = LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0); if (useAccessibilityTheme) { /* Set the skin to classic and remove pref observers */ if (!mSelectedSkin.EqualsLiteral("classic/1.0")) { mSelectedSkin.AssignLiteral("classic/1.0"); RefreshSkins(); } nsCOMPtr prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefs) { prefs->RemoveObserver(SELECTED_SKIN_PREF, this); } } return NS_OK; } NS_IMETHODIMP nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage, nsIUTF8StringEnumerator* *aResult) { nsCString realpackage; nsresult rv = OverrideLocalePackage(aPackage, realpackage); if (NS_FAILED(rv)) return rv; nsTArray *a = new nsTArray; if (!a) return NS_ERROR_OUT_OF_MEMORY; PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, & realpackage, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { entry->locales.EnumerateToArray(a); } rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a); if (NS_FAILED(rv)) delete a; return rv; } static nsresult getUILangCountry(nsACString& aUILang) { nsresult rv; nsCOMPtr localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsAutoString uiLang; rv = localeService->GetLocaleComponentForUserAgent(uiLang); NS_ENSURE_SUCCESS(rv, rv); CopyUTF16toUTF8(uiLang, aUILang); return NS_OK; } NS_IMETHODIMP nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult) { *aResult = false; nsAutoCString locale; GetSelectedLocale(package, locale); if (locale.Length() < 2) return NS_OK; // first check the intl.uidirection. preference, and if that is not // set, check the same preference but with just the first two characters of // the locale. If that isn't set, default to left-to-right. nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale; nsCOMPtr prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID)); if (!prefBranch) return NS_OK; nsXPIDLCString dir; prefBranch->GetCharPref(prefString.get(), getter_Copies(dir)); if (dir.IsEmpty()) { int32_t hyphen = prefString.FindChar('-'); if (hyphen >= 1) { nsAutoCString shortPref(Substring(prefString, 0, hyphen)); prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir)); } } *aResult = dir.EqualsLiteral("rtl"); return NS_OK; } nsresult nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage, nsACString& aLocale) { nsCString realpackage; nsresult rv = OverrideLocalePackage(aPackage, realpackage); if (NS_FAILED(rv)) return rv; PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, & realpackage, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_FREE(entry)) return NS_ERROR_FILE_NOT_FOUND; aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE); if (aLocale.IsEmpty()) return NS_ERROR_FAILURE; return NS_OK; } nsresult nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage, nsACString& aOverride) { const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage; nsAdoptingCString override = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get()); if (override) { aOverride = override; } else { aOverride = aPackage; } return NS_OK; } nsresult nsChromeRegistryChrome::SelectLocaleFromPref(nsIPrefBranch* prefs) { nsresult rv; bool matchOSLocale = false; rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale); if (NS_SUCCEEDED(rv) && matchOSLocale) { // compute lang and region code only when needed! nsAutoCString uiLocale; rv = getUILangCountry(uiLocale); if (NS_SUCCEEDED(rv)) mSelectedLocale = uiLocale; } else { nsXPIDLCString provider; rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider)); if (NS_SUCCEEDED(rv)) { mSelectedLocale = provider; } } if (NS_FAILED(rv)) NS_ERROR("Couldn't select locale from pref!"); return rv; } NS_IMETHODIMP nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData) { nsresult rv = NS_OK; if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { nsCOMPtr prefs (do_QueryInterface(aSubject)); NS_ASSERTION(prefs, "Bad observer call!"); NS_ConvertUTF16toUTF8 pref(someData); if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) || pref.EqualsLiteral(SELECTED_LOCALE_PREF)) { rv = UpdateSelectedLocale(); if (NS_SUCCEEDED(rv) && mProfileLoaded) FlushAllCaches(); } else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) { nsXPIDLCString provider; rv = prefs->GetCharPref(pref.get(), getter_Copies(provider)); if (NS_FAILED(rv)) { NS_ERROR("Couldn't get new skin pref!"); return rv; } mSelectedSkin = provider; RefreshSkins(); } else { NS_ERROR("Unexpected pref!"); } } else if (!strcmp("command-line-startup", aTopic)) { nsCOMPtr cmdLine (do_QueryInterface(aSubject)); if (cmdLine) { nsAutoString uiLocale; rv = cmdLine->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG), false, uiLocale); if (NS_SUCCEEDED(rv) && !uiLocale.IsEmpty()) { CopyUTF16toUTF8(uiLocale, mSelectedLocale); nsCOMPtr prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefs) { prefs->RemoveObserver(SELECTED_LOCALE_PREF, this); } } } } else if (!strcmp("profile-initial-state", aTopic)) { mProfileLoaded = true; } else { NS_ERROR("Unexpected observer topic!"); } return rv; } NS_IMETHODIMP nsChromeRegistryChrome::CheckForNewChrome() { PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nullptr); mOverlayHash.Clear(); mStyleHash.Clear(); mOverrideTable.Clear(); mDynamicRegistration = false; nsComponentManagerImpl::gComponentManager->RereadChromeManifests(); mDynamicRegistration = true; SendRegisteredChrome(nullptr); return NS_OK; } nsresult nsChromeRegistryChrome::UpdateSelectedLocale() { nsresult rv = NS_OK; nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefs) { rv = SelectLocaleFromPref(prefs); if (NS_SUCCEEDED(rv)) { nsCOMPtr obsSvc = mozilla::services::GetObserverService(); NS_ASSERTION(obsSvc, "Couldn't get observer service."); obsSvc->NotifyObservers((nsIChromeRegistry*) this, "selected-locale-has-changed", nullptr); } } return rv; } static void SerializeURI(nsIURI* aURI, SerializedURI& aSerializedURI) { if (!aURI) return; aURI->GetSpec(aSerializedURI.spec); aURI->GetOriginCharset(aSerializedURI.charset); } static PLDHashOperator EnumerateOverride(nsIURI* aURIKey, nsIURI* aURI, void* aArg) { nsTArray* overrides = static_cast*>(aArg); SerializedURI chromeURI, overrideURI; SerializeURI(aURIKey, chromeURI); SerializeURI(aURI, overrideURI); OverrideMapping override = { chromeURI, overrideURI }; overrides->AppendElement(override); return (PLDHashOperator)PL_DHASH_NEXT; } struct EnumerationArgs { InfallibleTArray& packages; const nsCString& selectedLocale; const nsCString& selectedSkin; }; void nsChromeRegistryChrome::SendRegisteredChrome( mozilla::dom::PContentParent* aParent) { InfallibleTArray packages; InfallibleTArray resources; InfallibleTArray overrides; EnumerationArgs args = { packages, mSelectedLocale, mSelectedSkin }; PL_DHashTableEnumerate(&mPackagesHash, CollectPackages, &args); nsCOMPtr io (do_GetIOService()); NS_ENSURE_TRUE_VOID(io); nsCOMPtr ph; nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); NS_ENSURE_SUCCESS_VOID(rv); //FIXME: Some substitutions are set up lazily and might not exist yet nsCOMPtr irph (do_QueryInterface(ph)); nsResProtocolHandler* rph = static_cast(irph.get()); rph->CollectSubstitutions(resources); mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides); if (aParent) { bool success = aParent->SendRegisterChrome(packages, resources, overrides, mSelectedLocale, false); NS_ENSURE_TRUE_VOID(success); } else { nsTArray parents; ContentParent::GetAll(parents); if (!parents.Length()) return; for (PRUint32 i = 0; i < parents.Length(); i++) { DebugOnly success = parents[i]->SendRegisterChrome(packages, resources, overrides, mSelectedLocale, true); NS_WARN_IF_FALSE(success, "couldn't reset a child's registered chrome"); } } } /* static */ void nsChromeRegistryChrome::ChromePackageFromPackageEntry(PackageEntry* aPackage, ChromePackage* aChromePackage, const nsCString& aSelectedLocale, const nsCString& aSelectedSkin) { SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI); SerializeURI(aPackage->locales.GetBase(aSelectedLocale, nsProviderArray::LOCALE), aChromePackage->localeBaseURI); SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY), aChromePackage->skinBaseURI); aChromePackage->package = aPackage->package; aChromePackage->flags = aPackage->flags; } PLDHashOperator nsChromeRegistryChrome::CollectPackages(PLDHashTable *table, PLDHashEntryHdr *entry, uint32_t number, void *arg) { EnumerationArgs* args = static_cast(arg); PackageEntry* package = static_cast(entry); ChromePackage chromePackage; ChromePackageFromPackageEntry(package, &chromePackage, args->selectedLocale, args->selectedSkin); args->packages.AppendElement(chromePackage); return (PLDHashOperator)PL_DHASH_NEXT; } static bool CanLoadResource(nsIURI* aResourceURI) { bool isLocalResource = false; (void)NS_URIChainHasFlags(aResourceURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &isLocalResource); return isLocalResource; } nsIURI* nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage, const nsCString& aProvider, const nsCString& aPath) { PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, &aPackage, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_FREE(entry)) { if (!mInitialized) return nullptr; LogMessage("No chrome package registered for chrome://%s/%s/%s", aPackage.get(), aProvider.get(), aPath.get()); return nullptr; } if (aProvider.EqualsLiteral("locale")) { return entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE); } else if (aProvider.EqualsLiteral("skin")) { return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY); } else if (aProvider.EqualsLiteral("content")) { return entry->baseURI; } return nullptr; } nsresult nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage, uint32_t* aFlags) { PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, & (nsACString&) aPackage, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_FREE(entry)) return NS_ERROR_FILE_NOT_FOUND; *aFlags = entry->flags; return NS_OK; } PLHashNumber nsChromeRegistryChrome::HashKey(PLDHashTable *table, const void *key) { const nsACString& str = *reinterpret_cast(key); return HashString(str); } bool nsChromeRegistryChrome::MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, const void *key) { const nsACString& str = *reinterpret_cast(key); const PackageEntry* pentry = static_cast(entry); return str.Equals(pentry->package); } void nsChromeRegistryChrome::ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) { PackageEntry* pentry = static_cast(entry); pentry->~PackageEntry(); } bool nsChromeRegistryChrome::InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key) { const nsACString& str = *reinterpret_cast(key); new (entry) PackageEntry(str); return true; } const PLDHashTableOps nsChromeRegistryChrome::kTableOps = { PL_DHashAllocTable, PL_DHashFreeTable, HashKey, MatchKey, PL_DHashMoveEntryStub, ClearEntry, PL_DHashFinalizeStub, InitEntry }; nsChromeRegistryChrome::ProviderEntry* nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType) { size_t i = mArray.Length(); if (!i) return nullptr; ProviderEntry* found = nullptr; // Only set if we find a partial-match locale ProviderEntry* entry = nullptr; while (i--) { entry = &mArray[i]; if (aPreferred.Equals(entry->provider)) return entry; if (aType != LOCALE) continue; if (LanguagesMatch(aPreferred, entry->provider)) { found = entry; continue; } if (!found && entry->provider.EqualsLiteral("en-US")) found = entry; } if (!found && aType != EXACT) return entry; return found; } nsIURI* nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType) { ProviderEntry* provider = GetProvider(aPreferred, aType); if (!provider) return nullptr; return provider->baseURI; } const nsACString& nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType) { ProviderEntry* entry = GetProvider(aPreferred, aType); if (entry) return entry->provider; return EmptyCString(); } void nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL) { ProviderEntry* provider = GetProvider(aProvider, EXACT); if (provider) { provider->baseURI = aBaseURL; return; } // no existing entries, add a new one mArray.AppendElement(ProviderEntry(aProvider, aBaseURL)); } void nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray *a) { int32_t i = mArray.Length(); while (i--) { a->AppendElement(mArray[i].provider); } } void nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI) { int32_t i = mArray.Count(); while (i--) { bool equals; if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals) return; } mArray.AppendObject(aURI); } void nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay) { OverlayListEntry* entry = mTable.PutEntry(aBase); if (entry) entry->AddURI(aOverlay); } const nsCOMArray* nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase) { OverlayListEntry* entry = mTable.GetEntry(aBase); if (!entry) return nullptr; return &entry->mArray; } #ifdef MOZ_XUL NS_IMETHODIMP nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL, nsISimpleEnumerator **aResult) { const nsCOMArray* parray = mStyleHash.GetArray(aChromeURL); if (!parray) return NS_NewEmptyEnumerator(aResult); return NS_NewArrayEnumerator(aResult, *parray); } NS_IMETHODIMP nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL, nsISimpleEnumerator **aResult) { const nsCOMArray* parray = mOverlayHash.GetArray(aChromeURL); if (!parray) return NS_NewEmptyEnumerator(aResult); return NS_NewArrayEnumerator(aResult, *parray); } #endif // MOZ_XUL nsIURI* nsChromeRegistry::ManifestProcessingContext::GetManifestURI() { if (!mManifestURI) { nsCString uri; mFile.GetURIString(uri); NS_NewURI(getter_AddRefs(mManifestURI), uri); } return mManifestURI; } nsIXPConnect* nsChromeRegistry::ManifestProcessingContext::GetXPConnect() { if (!mXPConnect) mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1"); return mXPConnect; } already_AddRefed nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri) { nsIURI* baseuri = GetManifestURI(); if (!baseuri) return nullptr; nsCOMPtr resolved; nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri); if (NS_FAILED(rv)) return nullptr; return resolved.forget(); } static void EnsureLowerCase(char *aBuf) { for (; *aBuf; ++aBuf) { char ch = *aBuf; if (ch >= 'A' && ch <= 'Z') *aBuf = ch + 'a' - 'A'; } } static void SendManifestEntry(const ChromeRegistryItem &aItem) { nsTArray parents; ContentParent::GetAll(parents); if (!parents.Length()) return; for (uint32_t i = 0; i < parents.Length(); i++) { unused << parents[i]->SendRegisterChromeItem(aItem); } } void nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* package = argv[0]; char* uri = argv[1]; EnsureLowerCase(package); nsCOMPtr resolved = cx.ResolveURI(uri); if (!resolved) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI '%s'.", uri); return; } if (!CanLoadResource(resolved)) { LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, "During chrome registration, cannot register non-local URI '%s' as content.", uri); return; } PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, & (const nsACString&) nsDependentCString(package), PL_DHASH_ADD)); if (!entry) return; entry->baseURI = resolved; if (platform) entry->flags |= PLATFORM_PACKAGE; if (contentaccessible) entry->flags |= CONTENT_ACCESSIBLE; if (mDynamicRegistration) { ChromePackage chromePackage; ChromePackageFromPackageEntry(entry, &chromePackage, mSelectedLocale, mSelectedSkin); SendManifestEntry(chromePackage); } } void nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* package = argv[0]; char* provider = argv[1]; char* uri = argv[2]; EnsureLowerCase(package); nsCOMPtr resolved = cx.ResolveURI(uri); if (!resolved) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI '%s'.", uri); return; } if (!CanLoadResource(resolved)) { LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, "During chrome registration, cannot register non-local URI '%s' as content.", uri); return; } PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, & (const nsACString&) nsDependentCString(package), PL_DHASH_ADD)); if (!entry) return; entry->locales.SetBase(nsDependentCString(provider), resolved); if (mDynamicRegistration) { ChromePackage chromePackage; ChromePackageFromPackageEntry(entry, &chromePackage, mSelectedLocale, mSelectedSkin); SendManifestEntry(chromePackage); } } void nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* package = argv[0]; char* provider = argv[1]; char* uri = argv[2]; EnsureLowerCase(package); nsCOMPtr resolved = cx.ResolveURI(uri); if (!resolved) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI '%s'.", uri); return; } if (!CanLoadResource(resolved)) { LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, "During chrome registration, cannot register non-local URI '%s' as content.", uri); return; } PackageEntry* entry = static_cast(PL_DHashTableOperate(&mPackagesHash, & (const nsACString&) nsDependentCString(package), PL_DHASH_ADD)); if (!entry) return; entry->skins.SetBase(nsDependentCString(provider), resolved); if (mDynamicRegistration) { ChromePackage chromePackage; ChromePackageFromPackageEntry(entry, &chromePackage, mSelectedLocale, mSelectedSkin); SendManifestEntry(chromePackage); } } void nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* base = argv[0]; char* overlay = argv[1]; nsCOMPtr baseuri = cx.ResolveURI(base); nsCOMPtr overlayuri = cx.ResolveURI(overlay); if (!baseuri || !overlayuri) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI."); return; } if (!CanLoadResource(overlayuri)) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "Cannot register non-local URI '%s' as an overlay.", overlay); return; } mOverlayHash.Add(baseuri, overlayuri); } void nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* base = argv[0]; char* overlay = argv[1]; nsCOMPtr baseuri = cx.ResolveURI(base); nsCOMPtr overlayuri = cx.ResolveURI(overlay); if (!baseuri || !overlayuri) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI."); return; } if (!CanLoadResource(overlayuri)) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "Cannot register non-local URI '%s' as a style overlay.", overlay); return; } mStyleHash.Add(baseuri, overlayuri); } void nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* chrome = argv[0]; char* resolved = argv[1]; nsCOMPtr chromeuri = cx.ResolveURI(chrome); nsCOMPtr resolveduri = cx.ResolveURI(resolved); if (!chromeuri || !resolveduri) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI."); return; } if (!CanLoadResource(resolveduri)) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "Cannot register non-local URI '%s' for an override.", resolved); return; } mOverrideTable.Put(chromeuri, resolveduri); if (mDynamicRegistration) { SerializedURI serializedChrome; SerializedURI serializedOverride; SerializeURI(chromeuri, serializedChrome); SerializeURI(resolveduri, serializedOverride); OverrideMapping override = { serializedChrome, serializedOverride }; SendManifestEntry(override); } } void nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno, char *const * argv, bool platform, bool contentaccessible) { char* package = argv[0]; char* uri = argv[1]; EnsureLowerCase(package); nsDependentCString host(package); nsCOMPtr io = mozilla::services::GetIOService(); if (!io) { NS_WARNING("No IO service trying to process chrome manifests"); return; } nsCOMPtr ph; nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); if (NS_FAILED(rv)) return; nsCOMPtr rph = do_QueryInterface(ph); bool exists = false; rv = rph->HasSubstitution(host, &exists); if (exists) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "Duplicate resource declaration for '%s' ignored.", package); return; } nsCOMPtr resolved = cx.ResolveURI(uri); if (!resolved) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "During chrome registration, unable to create URI '%s'.", uri); return; } if (!CanLoadResource(resolved)) { LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, "Warning: cannot register non-local URI '%s' as a resource.", uri); return; } rph->SetSubstitution(host, resolved); }