2010-03-11 08:33:00 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2014-07-26 00:17:36 +04:00
|
|
|
/* vim: set ts=2 sts=2 sw=2 et tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2014-07-26 00:17:36 +04:00
|
|
|
#include "mozilla/dom/ContentParent.h"
|
2010-03-11 08:33:00 +03:00
|
|
|
#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"
|
2010-07-01 19:55:57 +04:00
|
|
|
#include "nsComponentManager.h"
|
2010-03-11 08:33:00 +03:00
|
|
|
#include "nsEnumeratorUtils.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsStringEnumerator.h"
|
|
|
|
#include "nsTextFormatter.h"
|
|
|
|
#include "nsXPCOMCIDInternal.h"
|
|
|
|
|
2011-09-09 06:27:12 +04:00
|
|
|
#include "mozilla/LookAndFeel.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2017-01-26 02:58:14 +03:00
|
|
|
#include "mozilla/intl/LocaleService.h"
|
2011-09-09 06:27:12 +04:00
|
|
|
|
2010-03-11 08:33:00 +03:00
|
|
|
#include "nsIObserverService.h"
|
2012-01-18 14:23:28 +04:00
|
|
|
#include "nsIPrefBranch.h"
|
2010-03-11 08:33:00 +03:00
|
|
|
#include "nsIPrefService.h"
|
2013-04-26 19:11:47 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2010-03-23 08:18:53 +03:00
|
|
|
#include "nsIResProtocolHandler.h"
|
2010-03-11 08:33:00 +03:00
|
|
|
#include "nsIScriptError.h"
|
|
|
|
#include "nsIXULRuntime.h"
|
|
|
|
|
|
|
|
#define SELECTED_SKIN_PREF "general.skins.selectedSkin"
|
2013-04-26 19:11:47 +04:00
|
|
|
#define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2011-09-09 06:27:12 +04:00
|
|
|
using namespace mozilla;
|
2014-07-26 00:17:36 +04:00
|
|
|
using mozilla::dom::ContentParent;
|
|
|
|
using mozilla::dom::PContentParent;
|
2017-03-15 01:28:47 +03:00
|
|
|
using mozilla::intl::LocaleService;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2014-08-11 22:13:36 +04:00
|
|
|
// We use a "best-fit" algorithm for matching locales and themes.
|
2010-03-11 08:33:00 +03:00
|
|
|
// 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;
|
2014-08-11 22:13:36 +04:00
|
|
|
|
2010-03-11 08:33:00 +03:00
|
|
|
++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 == '-');
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsChromeRegistryChrome::nsChromeRegistryChrome()
|
2014-07-26 00:17:36 +04:00
|
|
|
: mProfileLoaded(false), mDynamicRegistration(true) {}
|
2010-03-11 08:33:00 +03:00
|
|
|
|
|
|
|
nsChromeRegistryChrome::~nsChromeRegistryChrome() {}
|
|
|
|
|
|
|
|
nsresult nsChromeRegistryChrome::Init() {
|
|
|
|
nsresult rv = nsChromeRegistry::Init();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool safeMode = false;
|
2010-03-11 08:33:00 +03:00
|
|
|
nsCOMPtr<nsIXULRuntime> xulrun(do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
|
|
|
|
if (xulrun) xulrun->GetInSafeMode(&safeMode);
|
2014-02-27 22:04:09 +04:00
|
|
|
|
2010-03-11 08:33:00 +03:00
|
|
|
nsCOMPtr<nsIPrefService> prefserv(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefs;
|
|
|
|
|
2016-07-14 06:47:49 +03:00
|
|
|
if (prefserv) {
|
|
|
|
if (safeMode) {
|
|
|
|
prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
|
|
|
|
} else {
|
|
|
|
prefs = do_QueryInterface(prefserv);
|
|
|
|
}
|
|
|
|
}
|
2010-03-11 08:33:00 +03:00
|
|
|
|
|
|
|
if (!prefs) {
|
|
|
|
NS_WARNING("Could not get pref service!");
|
2016-07-14 06:47:49 +03:00
|
|
|
} else {
|
2017-10-27 02:30:33 +03:00
|
|
|
nsAutoCString provider;
|
|
|
|
rv = prefs->GetCharPref(SELECTED_SKIN_PREF, provider);
|
2010-03-11 08:33:00 +03:00
|
|
|
if (NS_SUCCEEDED(rv)) mSelectedSkin = provider;
|
|
|
|
|
2012-01-18 14:23:28 +04:00
|
|
|
rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true);
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
2010-05-14 10:41:14 +04:00
|
|
|
nsCOMPtr<nsIObserverService> obsService =
|
|
|
|
mozilla::services::GetObserverService();
|
2010-03-11 08:33:00 +03:00
|
|
|
if (obsService) {
|
2011-10-17 18:59:28 +04:00
|
|
|
obsService->AddObserver(this, "profile-initial-state", true);
|
2017-03-15 01:28:47 +03:00
|
|
|
obsService->AddObserver(this, "intl:app-locales-changed", true);
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChromeRegistryChrome::CheckForOSAccessibility() {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t useAccessibilityTheme =
|
2011-09-09 06:27:12 +04:00
|
|
|
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();
|
|
|
|
}
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2012-01-18 14:23:28 +04:00
|
|
|
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
2011-09-09 06:27:12 +04:00
|
|
|
if (prefs) {
|
|
|
|
prefs->RemoveObserver(SELECTED_SKIN_PREF, this);
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChromeRegistryChrome::GetLocalesForPackage(
|
|
|
|
const nsACString& aPackage, nsIUTF8StringEnumerator** aResult) {
|
2013-04-26 19:11:47 +04:00
|
|
|
nsCString realpackage;
|
|
|
|
nsresult rv = OverrideLocalePackage(aPackage, realpackage);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2010-03-11 08:33:00 +03:00
|
|
|
nsTArray<nsCString>* a = new nsTArray<nsCString>;
|
|
|
|
if (!a) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2014-08-11 22:13:36 +04:00
|
|
|
PackageEntry* entry;
|
|
|
|
if (mPackagesHash.Get(realpackage, &entry)) {
|
2010-03-11 08:33:00 +03:00
|
|
|
entry->locales.EnumerateToArray(a);
|
|
|
|
}
|
|
|
|
|
2013-04-26 19:11:47 +04:00
|
|
|
rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
|
2010-03-11 08:33:00 +03:00
|
|
|
if (NS_FAILED(rv)) delete a;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool* aResult) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*aResult = false;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString locale;
|
2016-10-28 14:04:06 +03:00
|
|
|
GetSelectedLocale(package, false, locale);
|
2010-03-11 08:33:00 +03:00
|
|
|
if (locale.Length() < 2) return NS_OK;
|
|
|
|
|
2015-08-28 10:13:06 +03:00
|
|
|
*aResult = GetDirectionForLocale(locale);
|
2010-03-11 08:33:00 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-03-15 01:28:47 +03:00
|
|
|
/**
|
|
|
|
* This method negotiates only between the app locale and the available
|
|
|
|
* chrome packages.
|
|
|
|
*
|
|
|
|
* If you want to get the current application's UI locale, please use
|
|
|
|
* LocaleService::GetAppLocaleAsLangTag.
|
|
|
|
*/
|
2010-03-11 08:33:00 +03:00
|
|
|
nsresult nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
|
2016-10-28 14:04:06 +03:00
|
|
|
bool aAsBCP47,
|
2010-03-11 08:33:00 +03:00
|
|
|
nsACString& aLocale) {
|
2017-03-15 01:28:47 +03:00
|
|
|
nsAutoCString reqLocale;
|
2017-09-06 11:13:45 +03:00
|
|
|
if (aPackage.EqualsLiteral("global")) {
|
2017-03-15 01:28:47 +03:00
|
|
|
LocaleService::GetInstance()->GetAppLocaleAsLangTag(reqLocale);
|
|
|
|
} else {
|
|
|
|
AutoTArray<nsCString, 10> requestedLocales;
|
|
|
|
LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
|
|
|
|
reqLocale.Assign(requestedLocales[0]);
|
|
|
|
}
|
|
|
|
|
2013-04-26 19:11:47 +04:00
|
|
|
nsCString realpackage;
|
|
|
|
nsresult rv = OverrideLocalePackage(aPackage, realpackage);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2014-08-11 22:13:36 +04:00
|
|
|
PackageEntry* entry;
|
|
|
|
if (!mPackagesHash.Get(realpackage, &entry)) return NS_ERROR_FILE_NOT_FOUND;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2017-03-15 01:28:47 +03:00
|
|
|
aLocale = entry->locales.GetSelected(reqLocale, nsProviderArray::LOCALE);
|
2010-03-11 08:33:00 +03:00
|
|
|
if (aLocale.IsEmpty()) return NS_ERROR_FAILURE;
|
|
|
|
|
2016-10-28 14:04:06 +03:00
|
|
|
if (aAsBCP47) {
|
|
|
|
SanitizeForBCP47(aLocale);
|
|
|
|
}
|
|
|
|
|
2010-03-11 08:33:00 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-26 19:11:47 +04:00
|
|
|
nsresult nsChromeRegistryChrome::OverrideLocalePackage(
|
|
|
|
const nsACString& aPackage, nsACString& aOverride) {
|
|
|
|
const nsACString& pref =
|
|
|
|
NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage;
|
2017-07-31 07:28:48 +03:00
|
|
|
nsAutoCString override;
|
|
|
|
nsresult rv = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get(),
|
|
|
|
override);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2013-04-26 19:11:47 +04:00
|
|
|
aOverride = override;
|
2017-07-31 07:28:48 +03:00
|
|
|
} else {
|
2013-04-26 19:11:47 +04:00
|
|
|
aOverride = aPackage;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-03-11 08:33:00 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChromeRegistryChrome::Observe(nsISupports* aSubject, const char* aTopic,
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t* someData) {
|
2010-03-11 08:33:00 +03:00
|
|
|
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);
|
|
|
|
|
2017-03-15 01:28:47 +03:00
|
|
|
if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
|
2017-10-27 02:30:33 +03:00
|
|
|
nsAutoCString provider;
|
|
|
|
rv = prefs->GetCharPref(pref.get(), provider);
|
2010-03-11 08:33:00 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
2010-11-30 17:02:23 +03:00
|
|
|
NS_ERROR("Couldn't get new skin pref!");
|
2010-03-11 08:33:00 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSelectedSkin = provider;
|
|
|
|
RefreshSkins();
|
|
|
|
} else {
|
|
|
|
NS_ERROR("Unexpected pref!");
|
|
|
|
}
|
|
|
|
} else if (!strcmp("profile-initial-state", aTopic)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mProfileLoaded = true;
|
2017-03-15 01:28:47 +03:00
|
|
|
} else if (!strcmp("intl:app-locales-changed", aTopic)) {
|
|
|
|
if (mProfileLoaded) {
|
|
|
|
FlushAllCaches();
|
|
|
|
}
|
2010-03-11 08:33:00 +03:00
|
|
|
} else {
|
|
|
|
NS_ERROR("Unexpected observer topic!");
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsChromeRegistryChrome::CheckForNewChrome() {
|
2014-08-11 22:13:36 +04:00
|
|
|
mPackagesHash.Clear();
|
2010-03-11 08:33:00 +03:00
|
|
|
mOverrideTable.Clear();
|
|
|
|
|
2014-07-26 00:17:36 +04:00
|
|
|
mDynamicRegistration = false;
|
|
|
|
|
2010-07-01 19:55:57 +04:00
|
|
|
nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
|
2014-07-26 00:17:36 +04:00
|
|
|
|
|
|
|
mDynamicRegistration = true;
|
|
|
|
|
|
|
|
SendRegisteredChrome(nullptr);
|
2010-03-11 08:33:00 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SerializeURI(nsIURI* aURI, SerializedURI& aSerializedURI) {
|
|
|
|
if (!aURI) return;
|
|
|
|
|
|
|
|
aURI->GetSpec(aSerializedURI.spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsChromeRegistryChrome::SendRegisteredChrome(
|
2010-07-19 22:33:33 +04:00
|
|
|
mozilla::dom::PContentParent* aParent) {
|
2010-11-09 05:49:00 +03:00
|
|
|
InfallibleTArray<ChromePackage> packages;
|
2015-07-17 01:50:07 +03:00
|
|
|
InfallibleTArray<SubstitutionMapping> resources;
|
2010-11-09 05:49:00 +03:00
|
|
|
InfallibleTArray<OverrideMapping> overrides;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2015-11-18 04:58:34 +03:00
|
|
|
for (auto iter = mPackagesHash.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
ChromePackage chromePackage;
|
|
|
|
ChromePackageFromPackageEntry(iter.Key(), iter.UserData(), &chromePackage,
|
2017-03-15 01:28:47 +03:00
|
|
|
mSelectedSkin);
|
2015-11-18 04:58:34 +03:00
|
|
|
packages.AppendElement(chromePackage);
|
|
|
|
}
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2014-10-07 21:29:40 +04:00
|
|
|
// 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());
|
2016-08-26 09:40:57 +03:00
|
|
|
rv = rph->CollectSubstitutions(resources);
|
|
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
2014-10-07 21:29:40 +04:00
|
|
|
}
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2015-11-18 04:58:36 +03:00
|
|
|
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);
|
|
|
|
}
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2017-03-15 01:28:47 +03:00
|
|
|
nsAutoCString appLocale;
|
|
|
|
LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
|
|
|
|
|
2014-07-26 00:17:36 +04:00
|
|
|
if (aParent) {
|
|
|
|
bool success = aParent->SendRegisterChrome(packages, resources, overrides,
|
2017-03-15 01:28:47 +03:00
|
|
|
appLocale, false);
|
2014-07-26 00:17:36 +04:00
|
|
|
NS_ENSURE_TRUE_VOID(success);
|
|
|
|
} else {
|
|
|
|
nsTArray<ContentParent*> parents;
|
|
|
|
ContentParent::GetAll(parents);
|
|
|
|
if (!parents.Length()) return;
|
|
|
|
|
2014-08-08 16:39:07 +04:00
|
|
|
for (uint32_t i = 0; i < parents.Length(); i++) {
|
2014-07-26 00:17:36 +04:00
|
|
|
DebugOnly<bool> success = parents[i]->SendRegisterChrome(
|
|
|
|
packages, resources, overrides, appLocale, true);
|
2016-09-01 08:01:16 +03:00
|
|
|
NS_WARNING_ASSERTION(success,
|
|
|
|
"couldn't reset a child's registered chrome");
|
2014-07-26 00:17:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-11 22:13:36 +04:00
|
|
|
/* static */ void nsChromeRegistryChrome::ChromePackageFromPackageEntry(
|
|
|
|
const nsACString& aPackageName, PackageEntry* aPackage,
|
2014-07-26 00:17:36 +04:00
|
|
|
ChromePackage* aChromePackage, const nsCString& aSelectedSkin) {
|
2017-03-15 01:28:47 +03:00
|
|
|
nsAutoCString appLocale;
|
|
|
|
LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
|
|
|
|
|
2014-07-26 00:17:36 +04:00
|
|
|
SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
|
2017-03-15 01:28:47 +03:00
|
|
|
SerializeURI(aPackage->locales.GetBase(appLocale, nsProviderArray::LOCALE),
|
2014-07-26 00:17:36 +04:00
|
|
|
aChromePackage->localeBaseURI);
|
|
|
|
SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
|
|
|
|
aChromePackage->skinBaseURI);
|
2014-08-11 22:13:36 +04:00
|
|
|
aChromePackage->package = aPackageName;
|
2014-07-26 00:17:36 +04:00
|
|
|
aChromePackage->flags = aPackage->flags;
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool CanLoadResource(nsIURI* aResourceURI) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isLocalResource = false;
|
2010-03-11 08:33:00 +03:00
|
|
|
(void)NS_URIChainHasFlags(aResourceURI,
|
|
|
|
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
|
|
|
|
&isLocalResource);
|
|
|
|
return isLocalResource;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIURI* nsChromeRegistryChrome::GetBaseURIFromPackage(
|
|
|
|
const nsCString& aPackage, const nsCString& aProvider,
|
2010-10-13 23:46:05 +04:00
|
|
|
const nsCString& aPath) {
|
2014-08-11 22:13:36 +04:00
|
|
|
PackageEntry* entry;
|
|
|
|
if (!mPackagesHash.Get(aPackage, &entry)) {
|
2010-03-11 08:33:00 +03:00
|
|
|
if (!mInitialized) return nullptr;
|
|
|
|
|
|
|
|
LogMessage("No chrome package registered for chrome://%s/%s/%s",
|
|
|
|
aPackage.get(), aProvider.get(), aPath.get());
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aProvider.EqualsLiteral("locale")) {
|
2017-03-15 01:28:47 +03:00
|
|
|
nsAutoCString appLocale;
|
|
|
|
LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
|
|
|
|
return entry->locales.GetBase(appLocale, nsProviderArray::LOCALE);
|
2010-03-11 08:33:00 +03:00
|
|
|
} else if (aProvider.EqualsLiteral("skin")) {
|
2010-10-13 23:46:05 +04:00
|
|
|
return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
|
2010-03-11 08:33:00 +03:00
|
|
|
} else if (aProvider.EqualsLiteral("content")) {
|
2010-10-13 23:46:05 +04:00
|
|
|
return entry->baseURI;
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t* aFlags) {
|
2014-08-11 22:13:36 +04:00
|
|
|
PackageEntry* entry;
|
|
|
|
if (!mPackagesHash.Get(aPackage, &entry)) return NS_ERROR_FILE_NOT_FOUND;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
|
|
|
*aFlags = entry->flags;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsChromeRegistryChrome::ProviderEntry*
|
|
|
|
nsChromeRegistryChrome::nsProviderArray::GetProvider(
|
|
|
|
const nsACString& aPreferred, MatchType aType) {
|
2014-06-09 19:38:13 +04:00
|
|
|
size_t i = mArray.Length();
|
2012-07-30 18:20:58 +04:00
|
|
|
if (!i) return nullptr;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
ProviderEntry* found = nullptr; // Only set if we find a partial-match locale
|
2014-06-09 19:38:13 +04:00
|
|
|
ProviderEntry* entry = nullptr;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
|
|
|
while (i--) {
|
2014-05-02 12:01:11 +04:00
|
|
|
entry = &mArray[i];
|
2010-03-11 08:33:00 +03:00
|
|
|
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);
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (!provider) return nullptr;
|
2010-03-11 08:33:00 +03:00
|
|
|
|
|
|
|
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
|
2014-05-02 12:01:11 +04:00
|
|
|
mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(
|
|
|
|
nsTArray<nsCString>* a) {
|
2014-05-02 12:01:11 +04:00
|
|
|
int32_t i = mArray.Length();
|
2010-03-11 08:33:00 +03:00
|
|
|
while (i--) {
|
2014-05-02 12:01:11 +04:00
|
|
|
a->AppendElement(mArray[i].provider);
|
2010-03-11 08:33:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-01 19:55:57 +04:00
|
|
|
nsIURI* nsChromeRegistry::ManifestProcessingContext::GetManifestURI() {
|
|
|
|
if (!mManifestURI) {
|
2011-11-08 21:10:51 +04:00
|
|
|
nsCString uri;
|
|
|
|
mFile.GetURIString(uri);
|
|
|
|
NS_NewURI(getter_AddRefs(mManifestURI), uri);
|
2010-07-01 19:55:57 +04:00
|
|
|
}
|
|
|
|
return mManifestURI;
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIURI>
|
|
|
|
nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri) {
|
|
|
|
nsIURI* baseuri = GetManifestURI();
|
2013-04-03 04:15:07 +04:00
|
|
|
if (!baseuri) return nullptr;
|
2010-07-01 19:55:57 +04:00
|
|
|
|
|
|
|
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';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-26 00:17:36 +04:00
|
|
|
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++) {
|
2015-11-02 08:53:26 +03:00
|
|
|
Unused << parents[i]->SendRegisterChromeItem(aItem);
|
2014-07-26 00:17:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-01 19:55:57 +04:00
|
|
|
void nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx,
|
2015-02-05 19:09:15 +03:00
|
|
|
int lineno, char* const* argv,
|
|
|
|
int flags) {
|
2010-07-01 19:55:57 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-08-11 22:13:36 +04:00
|
|
|
nsDependentCString packageName(package);
|
|
|
|
PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
|
2010-07-01 19:55:57 +04:00
|
|
|
entry->baseURI = resolved;
|
2015-02-05 19:09:15 +03:00
|
|
|
entry->flags = flags;
|
2014-07-26 00:17:36 +04:00
|
|
|
|
|
|
|
if (mDynamicRegistration) {
|
|
|
|
ChromePackage chromePackage;
|
2014-08-11 22:13:36 +04:00
|
|
|
ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
|
2017-03-15 01:28:47 +03:00
|
|
|
mSelectedSkin);
|
2014-07-26 00:17:36 +04:00
|
|
|
SendManifestEntry(chromePackage);
|
|
|
|
}
|
2010-07-01 19:55:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx,
|
2015-02-05 19:09:15 +03:00
|
|
|
int lineno, char* const* argv,
|
|
|
|
int flags) {
|
2010-07-01 19:55:57 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-08-11 22:13:36 +04:00
|
|
|
nsDependentCString packageName(package);
|
|
|
|
PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
|
2010-07-01 19:55:57 +04:00
|
|
|
entry->locales.SetBase(nsDependentCString(provider), resolved);
|
2014-07-26 00:17:36 +04:00
|
|
|
|
|
|
|
if (mDynamicRegistration) {
|
|
|
|
ChromePackage chromePackage;
|
2014-08-11 22:13:36 +04:00
|
|
|
ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
|
2017-03-15 01:28:47 +03:00
|
|
|
mSelectedSkin);
|
2014-07-26 00:17:36 +04:00
|
|
|
SendManifestEntry(chromePackage);
|
|
|
|
}
|
2017-03-15 01:28:47 +03:00
|
|
|
|
2017-05-04 20:38:53 +03:00
|
|
|
// We use mainPackage as the package we track for reporting new locales being
|
|
|
|
// registered. For most cases it will be "global", but for Fennec it will be
|
|
|
|
// "browser".
|
|
|
|
nsAutoCString mainPackage;
|
|
|
|
nsresult rv =
|
|
|
|
OverrideLocalePackage(NS_LITERAL_CSTRING("global"), mainPackage);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
2010-07-01 19:55:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx,
|
2015-02-05 19:09:15 +03:00
|
|
|
int lineno, char* const* argv,
|
|
|
|
int flags) {
|
2010-07-01 19:55:57 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-08-11 22:13:36 +04:00
|
|
|
nsDependentCString packageName(package);
|
|
|
|
PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
|
2010-07-01 19:55:57 +04:00
|
|
|
entry->skins.SetBase(nsDependentCString(provider), resolved);
|
2014-07-26 00:17:36 +04:00
|
|
|
|
|
|
|
if (mDynamicRegistration) {
|
|
|
|
ChromePackage chromePackage;
|
2014-08-11 22:13:36 +04:00
|
|
|
ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
|
2017-03-15 01:28:47 +03:00
|
|
|
mSelectedSkin);
|
2014-07-26 00:17:36 +04:00
|
|
|
SendManifestEntry(chromePackage);
|
|
|
|
}
|
2010-07-01 19:55:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx,
|
2015-02-05 19:09:15 +03:00
|
|
|
int lineno, char* const* argv,
|
|
|
|
int flags) {
|
2010-07-01 19:55:57 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-06-01 19:05:39 +03:00
|
|
|
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;
|
2017-07-29 14:50:21 +03:00
|
|
|
chromeuri->GetPathQueryRef(chromePath);
|
|
|
|
resolveduri->GetPathQueryRef(resolvedPath);
|
2015-06-01 19:05:39 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-01 19:55:57 +04:00
|
|
|
if (!CanLoadResource(resolveduri)) {
|
|
|
|
LogMessageWithContext(
|
|
|
|
cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
|
|
|
|
"Cannot register non-local URI '%s' for an override.", resolved);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mOverrideTable.Put(chromeuri, resolveduri);
|
2014-07-26 00:17:36 +04:00
|
|
|
|
|
|
|
if (mDynamicRegistration) {
|
|
|
|
SerializedURI serializedChrome;
|
|
|
|
SerializedURI serializedOverride;
|
|
|
|
|
|
|
|
SerializeURI(chromeuri, serializedChrome);
|
|
|
|
SerializeURI(resolveduri, serializedOverride);
|
|
|
|
|
|
|
|
OverrideMapping override = {serializedChrome, serializedOverride};
|
|
|
|
SendManifestEntry(override);
|
|
|
|
}
|
2010-07-01 19:55:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx,
|
2015-02-05 19:09:15 +03:00
|
|
|
int lineno, char* const* argv,
|
|
|
|
int flags) {
|
2010-07-01 19:55:57 +04:00
|
|
|
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;
|
2014-08-11 22:13:36 +04:00
|
|
|
|
2010-07-01 19:55:57 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-06-08 12:44:09 +03:00
|
|
|
// By default, Firefox resources are not content-accessible unless the
|
|
|
|
// manifests opts in.
|
|
|
|
bool contentAccessible = (flags & nsChromeRegistry::CONTENT_ACCESSIBLE);
|
|
|
|
|
|
|
|
uint32_t substitutionFlags = 0;
|
|
|
|
if (contentAccessible) {
|
|
|
|
substitutionFlags |= nsIResProtocolHandler::ALLOW_CONTENT_ACCESS;
|
|
|
|
}
|
|
|
|
rv = rph->SetSubstitutionWithFlags(host, resolved, substitutionFlags);
|
2016-11-04 13:13:13 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LogMessageWithContext(cx.GetManifestURI(), lineno,
|
|
|
|
nsIScriptError::warningFlag,
|
|
|
|
"Warning: cannot set substitution for '%s'.", uri);
|
|
|
|
}
|
2010-07-01 19:55:57 +04:00
|
|
|
}
|