summaryrefslogtreecommitdiffstats
path: root/chrome/nsChromeRegistryChrome.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /chrome/nsChromeRegistryChrome.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'chrome/nsChromeRegistryChrome.cpp')
-rw-r--r--chrome/nsChromeRegistryChrome.cpp991
1 files changed, 991 insertions, 0 deletions
diff --git a/chrome/nsChromeRegistryChrome.cpp b/chrome/nsChromeRegistryChrome.cpp
new file mode 100644
index 000000000..037e86631
--- /dev/null
+++ b/chrome/nsChromeRegistryChrome.cpp
@@ -0,0 +1,991 @@
+/* -*- 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 <windows.h>
+#elif defined(XP_MACOSX)
+#include <CoreServices/CoreServices.h>
+#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;
+
+// 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)
+{
+}
+
+nsChromeRegistryChrome::~nsChromeRegistryChrome()
+{
+}
+
+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");
+
+ bool safeMode = false;
+ nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
+ if (xulrun)
+ xulrun->GetInSafeMode(&safeMode);
+
+ nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
+ nsCOMPtr<nsIPrefBranch> prefs;
+
+ if (prefserv) {
+ 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<nsIObserverService> 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<nsIPrefBranch> 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<nsCString> *a = new nsTArray<nsCString>;
+ if (!a)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PackageEntry* entry;
+ if (mPackagesHash.Get(realpackage, &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<nsILocaleService> 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, false, locale);
+ if (locale.Length() < 2)
+ return NS_OK;
+
+ *aResult = GetDirectionForLocale(locale);
+ return NS_OK;
+}
+
+nsresult
+nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
+ bool aAsBCP47,
+ nsACString& aLocale)
+{
+ nsCString realpackage;
+ nsresult rv = OverrideLocalePackage(aPackage, realpackage);
+ if (NS_FAILED(rv))
+ return rv;
+ PackageEntry* entry;
+ if (!mPackagesHash.Get(realpackage, &entry))
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE);
+ if (aLocale.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ if (aAsBCP47) {
+ SanitizeForBCP47(aLocale);
+ }
+
+ 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<nsIPrefBranch> 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<nsICommandLine> 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<nsIPrefBranch> 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()
+{
+ mPackagesHash.Clear();
+ 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<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
+ if (prefs) {
+ rv = SelectLocaleFromPref(prefs);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIObserverService> 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);
+}
+
+void
+nsChromeRegistryChrome::SendRegisteredChrome(
+ mozilla::dom::PContentParent* aParent)
+{
+ InfallibleTArray<ChromePackage> packages;
+ InfallibleTArray<SubstitutionMapping> resources;
+ InfallibleTArray<OverrideMapping> overrides;
+
+ for (auto iter = mPackagesHash.Iter(); !iter.Done(); iter.Next()) {
+ ChromePackage chromePackage;
+ ChromePackageFromPackageEntry(iter.Key(), iter.UserData(), &chromePackage,
+ mSelectedLocale, mSelectedSkin);
+ packages.AppendElement(chromePackage);
+ }
+
+ // If we were passed a parent then a new child process has been created and
+ // has requested all of the chrome so send it the resources too. Otherwise
+ // resource mappings are sent by the resource protocol handler dynamically.
+ if (aParent) {
+ nsCOMPtr<nsIIOService> io (do_GetIOService());
+ NS_ENSURE_TRUE_VOID(io);
+
+ nsCOMPtr<nsIProtocolHandler> ph;
+ nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
+ nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
+ rv = rph->CollectSubstitutions(resources);
+ NS_ENSURE_SUCCESS_VOID(rv);
+ }
+
+ for (auto iter = mOverrideTable.Iter(); !iter.Done(); iter.Next()) {
+ SerializedURI chromeURI, overrideURI;
+
+ SerializeURI(iter.Key(), chromeURI);
+ SerializeURI(iter.UserData(), overrideURI);
+
+ OverrideMapping override = { chromeURI, overrideURI };
+ overrides.AppendElement(override);
+ }
+
+ if (aParent) {
+ bool success = aParent->SendRegisterChrome(packages, resources, overrides,
+ mSelectedLocale, false);
+ NS_ENSURE_TRUE_VOID(success);
+ } else {
+ nsTArray<ContentParent*> parents;
+ ContentParent::GetAll(parents);
+ if (!parents.Length())
+ return;
+
+ for (uint32_t i = 0; i < parents.Length(); i++) {
+ DebugOnly<bool> success =
+ parents[i]->SendRegisterChrome(packages, resources, overrides,
+ mSelectedLocale, true);
+ NS_WARNING_ASSERTION(success,
+ "couldn't reset a child's registered chrome");
+ }
+ }
+}
+
+/* static */ void
+nsChromeRegistryChrome::ChromePackageFromPackageEntry(const nsACString& aPackageName,
+ 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 = aPackageName;
+ aChromePackage->flags = aPackage->flags;
+}
+
+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;
+ if (!mPackagesHash.Get(aPackage, &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;
+ if (!mPackagesHash.Get(aPackage, &entry))
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ *aFlags = entry->flags;
+ return NS_OK;
+}
+
+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<nsCString> *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<nsIURI>*
+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)
+{
+ nsCOMPtr<nsIURI> chromeURLWithoutHash;
+ if (aChromeURL) {
+ aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
+ }
+ const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(chromeURLWithoutHash);
+ if (!parray)
+ return NS_NewEmptyEnumerator(aResult);
+
+ return NS_NewArrayEnumerator(aResult, *parray);
+}
+
+NS_IMETHODIMP
+nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
+ nsISimpleEnumerator **aResult)
+{
+ nsCOMPtr<nsIURI> chromeURLWithoutHash;
+ if (aChromeURL) {
+ aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
+ }
+ const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(chromeURLWithoutHash);
+ 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<nsIURI>
+nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
+{
+ nsIURI* baseuri = GetManifestURI();
+ if (!baseuri)
+ return nullptr;
+
+ nsCOMPtr<nsIURI> 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<ContentParent*> 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, int flags)
+{
+ char* package = argv[0];
+ char* uri = argv[1];
+
+ EnsureLowerCase(package);
+
+ nsCOMPtr<nsIURI> 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;
+ }
+
+ nsDependentCString packageName(package);
+ PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
+ entry->baseURI = resolved;
+ entry->flags = flags;
+
+ if (mDynamicRegistration) {
+ ChromePackage chromePackage;
+ ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
+ mSelectedLocale, mSelectedSkin);
+ SendManifestEntry(chromePackage);
+ }
+}
+
+void
+nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
+ char *const * argv, int flags)
+{
+ char* package = argv[0];
+ char* provider = argv[1];
+ char* uri = argv[2];
+
+ EnsureLowerCase(package);
+
+ nsCOMPtr<nsIURI> 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;
+ }
+
+ nsDependentCString packageName(package);
+ PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
+ entry->locales.SetBase(nsDependentCString(provider), resolved);
+
+ if (mDynamicRegistration) {
+ ChromePackage chromePackage;
+ ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
+ mSelectedLocale, mSelectedSkin);
+ SendManifestEntry(chromePackage);
+ }
+}
+
+void
+nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
+ char *const * argv, int flags)
+{
+ char* package = argv[0];
+ char* provider = argv[1];
+ char* uri = argv[2];
+
+ EnsureLowerCase(package);
+
+ nsCOMPtr<nsIURI> 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;
+ }
+
+ nsDependentCString packageName(package);
+ PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
+ entry->skins.SetBase(nsDependentCString(provider), resolved);
+
+ if (mDynamicRegistration) {
+ ChromePackage chromePackage;
+ ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
+ mSelectedLocale, mSelectedSkin);
+ SendManifestEntry(chromePackage);
+ }
+}
+
+void
+nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
+ char *const * argv, int flags)
+{
+ char* base = argv[0];
+ char* overlay = argv[1];
+
+ nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
+ nsCOMPtr<nsIURI> 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;
+ }
+
+ nsCOMPtr<nsIURI> baseuriWithoutHash;
+ baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
+
+ mOverlayHash.Add(baseuriWithoutHash, overlayuri);
+}
+
+void
+nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
+ char *const * argv, int flags)
+{
+ char* base = argv[0];
+ char* overlay = argv[1];
+
+ nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
+ nsCOMPtr<nsIURI> 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;
+ }
+
+ nsCOMPtr<nsIURI> baseuriWithoutHash;
+ baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
+
+ mStyleHash.Add(baseuriWithoutHash, overlayuri);
+}
+
+void
+nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
+ char *const * argv, int flags)
+{
+ char* chrome = argv[0];
+ char* resolved = argv[1];
+
+ nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
+ nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
+ if (!chromeuri || !resolveduri) {
+ LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
+ "During chrome registration, unable to create URI.");
+ return;
+ }
+
+ if (cx.mType == NS_SKIN_LOCATION) {
+ bool chromeSkinOnly = false;
+ nsresult rv = chromeuri->SchemeIs("chrome", &chromeSkinOnly);
+ chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
+ if (chromeSkinOnly) {
+ rv = resolveduri->SchemeIs("chrome", &chromeSkinOnly);
+ chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
+ }
+ if (chromeSkinOnly) {
+ nsAutoCString chromePath, resolvedPath;
+ chromeuri->GetPath(chromePath);
+ resolveduri->GetPath(resolvedPath);
+ chromeSkinOnly = StringBeginsWith(chromePath, NS_LITERAL_CSTRING("/skin/")) &&
+ StringBeginsWith(resolvedPath, NS_LITERAL_CSTRING("/skin/"));
+ }
+ if (!chromeSkinOnly) {
+ LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
+ "Cannot register non-chrome://.../skin/ URIs '%s' and '%s' as overrides and/or to be overridden from a skin manifest.",
+ chrome, resolved);
+ 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, int flags)
+{
+ char* package = argv[0];
+ char* uri = argv[1];
+
+ EnsureLowerCase(package);
+ nsDependentCString host(package);
+
+ nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
+ if (!io) {
+ NS_WARNING("No IO service trying to process chrome manifests");
+ return;
+ }
+
+ nsCOMPtr<nsIProtocolHandler> ph;
+ nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
+
+ nsCOMPtr<nsIURI> 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);
+}