author | Zibi Braniecki <gandalf@mozilla.com> |
Sat, 11 Mar 2017 18:43:11 -0800 (2017-03-12) | |
changeset 353505 | 39a903b099a6b50e3921fd6cb2ecc7d2b53b94d3 |
parent 353504 | 54f983e0eb8143559c35a5d45f32fabd253932b3 |
child 353506 | a72aba07d51cd804e3adfc6047121960e83e1464 |
push id | 31670 |
push user | cbook@mozilla.com |
push date | Tue, 18 Apr 2017 08:20:28 +0000 (2017-04-18) |
treeherder | mozilla-central@92f94fc0993b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jfkthame, Pike |
bugs | 1346616 |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/addon-sdk/source/lib/sdk/l10n/locale.js +++ b/addon-sdk/source/lib/sdk/l10n/locale.js @@ -6,68 +6,18 @@ module.metadata = { "stability": "unstable" }; const prefs = require("../preferences/service"); const { Cu, Cc, Ci } = require("chrome"); const { Services } = Cu.import("resource://gre/modules/Services.jsm"); -/** - * Gets the currently selected locale for display. - * Gets all usable locale that we can use sorted by priority of relevance - * @return Array of locales, begins with highest priority - */ -const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; -const PREF_SELECTED_LOCALE = "general.useragent.locale"; -const PREF_ACCEPT_LANGUAGES = "intl.accept_languages"; - function getPreferedLocales(caseSensitve) { - let locales = []; - function addLocale(locale) { - locale = locale.trim(); - if (!caseSensitve) - locale = locale.toLowerCase(); - if (locales.indexOf(locale) === -1) - locales.push(locale); - } - - // Most important locale is OS one. But we use it, only if - // "intl.locale.matchOS" pref is set to `true`. - // Currently only used for multi-locales mobile builds. - // http://mxr.mozilla.org/mozilla-central/source/mobile/android/installer/Makefile.in#46 - if (prefs.get(PREF_MATCH_OS_LOCALE, false)) { - let localeService = Cc["@mozilla.org/intl/nslocaleservice;1"]. - getService(Ci.nsILocaleService); - let osLocale = localeService.getLocaleComponentForUserAgent(); - addLocale(osLocale); - } - - // In some cases, mainly on Fennec and on Linux version, - // `general.useragent.locale` is a special 'localized' value, like: - // "chrome://global/locale/intl.properties" - let browserUiLocale = prefs.getLocalized(PREF_SELECTED_LOCALE, "") || - prefs.get(PREF_SELECTED_LOCALE, ""); - if (browserUiLocale) - addLocale(browserUiLocale); - - // Third priority is the list of locales used for web content - let contentLocales = prefs.getLocalized(PREF_ACCEPT_LANGUAGES, "") || - prefs.get(PREF_ACCEPT_LANGUAGES, ""); - if (contentLocales) { - // This list is a string of locales seperated by commas. - // There is spaces after commas, so strip each item - for (let locale of contentLocales.split(",")) - addLocale(locale.replace(/(^\s+)|(\s+$)/g, "")); - } - - // Finally, we ensure that en-US is the final fallback if it wasn't added - addLocale("en-US"); - - return locales; + return Services.locale.getRequestedLocales(); } exports.getPreferedLocales = getPreferedLocales; /** * Selects the closest matching locale from a list of locales. * * @param aLocales * An array of available locales
--- a/addon-sdk/source/test/test-l10n-locale.js +++ b/addon-sdk/source/test/test-l10n-locale.js @@ -1,134 +1,13 @@ /* 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/. */ -const { getPreferedLocales, findClosestLocale } = require("sdk/l10n/locale"); -const prefs = require("sdk/preferences/service"); -const { Cc, Ci, Cu } = require("chrome"); -const { Services } = Cu.import("resource://gre/modules/Services.jsm"); -const BundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService); - -const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; -const PREF_SELECTED_LOCALE = "general.useragent.locale"; -const PREF_ACCEPT_LANGUAGES = "intl.accept_languages"; - -function assertPrefered(assert, expected, msg) { - assert.equal(JSON.stringify(getPreferedLocales()), JSON.stringify(expected), - msg); -} - -exports.testGetPreferedLocales = function(assert) { - prefs.set(PREF_MATCH_OS_LOCALE, false); - prefs.set(PREF_SELECTED_LOCALE, ""); - prefs.set(PREF_ACCEPT_LANGUAGES, ""); - assertPrefered(assert, ["en-us"], - "When all preferences are empty, we only have en-us"); - - prefs.set(PREF_SELECTED_LOCALE, "fr"); - prefs.set(PREF_ACCEPT_LANGUAGES, "jp"); - assertPrefered(assert, ["fr", "jp", "en-us"], - "We first have useragent locale, then web one and finally en-US"); - - prefs.set(PREF_SELECTED_LOCALE, "en-US"); - prefs.set(PREF_ACCEPT_LANGUAGES, "en-US"); - assertPrefered(assert, ["en-us"], - "We do not have duplicates"); - - prefs.set(PREF_SELECTED_LOCALE, "en-US"); - prefs.set(PREF_ACCEPT_LANGUAGES, "fr"); - assertPrefered(assert, ["en-us", "fr"], - "en-US can be first if specified by higher priority preference"); - - // Reset what we changed - prefs.reset(PREF_MATCH_OS_LOCALE); - prefs.reset(PREF_SELECTED_LOCALE); - prefs.reset(PREF_ACCEPT_LANGUAGES); -} - -// In some cases, mainly on Fennec and on Linux version, -// `general.useragent.locale` is a special 'localized' value, like: -// "chrome://global/locale/intl.properties" -exports.testPreferedLocalizedLocale = function(assert) { - prefs.set(PREF_MATCH_OS_LOCALE, false); - let bundleURL = "chrome://global/locale/intl.properties"; - prefs.setLocalized(PREF_SELECTED_LOCALE, bundleURL); - let contentLocale = "ja"; - prefs.set(PREF_ACCEPT_LANGUAGES, contentLocale); - - // Read manually the expected locale value from the property file - let expectedLocale = BundleService.createBundle(bundleURL). - GetStringFromName(PREF_SELECTED_LOCALE). - toLowerCase(); - - // First add the useragent locale - let expectedLocaleList = [expectedLocale]; - - // Then the content locale - if (expectedLocaleList.indexOf(contentLocale) == -1) - expectedLocaleList.push(contentLocale); - - // Add default "en-us" fallback if the main language is not already en-us - if (expectedLocaleList.indexOf("en-us") == -1) - expectedLocaleList.push("en-us"); - - assertPrefered(assert, expectedLocaleList, "test localized pref value"); - - // Reset what we have changed - prefs.reset(PREF_MATCH_OS_LOCALE); - prefs.reset(PREF_SELECTED_LOCALE); - prefs.reset(PREF_ACCEPT_LANGUAGES); -} - -// On Linux the PREF_ACCEPT_LANGUAGES pref can be a localized pref. -exports.testPreferedContentLocale = function(assert) { - prefs.set(PREF_MATCH_OS_LOCALE, false); - let noLocale = "", - bundleURL = "chrome://global/locale/intl.properties"; - prefs.set(PREF_SELECTED_LOCALE, noLocale); - prefs.setLocalized(PREF_ACCEPT_LANGUAGES, bundleURL); - - // Read the expected locale values from the property file - let expectedLocaleList = BundleService.createBundle(bundleURL). - GetStringFromName(PREF_ACCEPT_LANGUAGES). - split(","). - map(locale => locale.trim().toLowerCase()); - - // Add default "en-us" fallback if the main language is not already en-us - if (expectedLocaleList.indexOf("en-us") == -1) - expectedLocaleList.push("en-us"); - - assertPrefered(assert, expectedLocaleList, "test localized content locale pref value"); - - // Reset what we have changed - prefs.reset(PREF_MATCH_OS_LOCALE); - prefs.reset(PREF_SELECTED_LOCALE); - prefs.reset(PREF_ACCEPT_LANGUAGES); -} - -exports.testPreferedOsLocale = function(assert) { - prefs.set(PREF_MATCH_OS_LOCALE, true); - prefs.set(PREF_SELECTED_LOCALE, ""); - prefs.set(PREF_ACCEPT_LANGUAGES, ""); - - let expectedLocale = Services.locale.getAppLocaleAsLangTag().toLowerCase(); - let expectedLocaleList = [expectedLocale]; - - // Add default "en-us" fallback if the main language is not already en-us - if (expectedLocale != "en-us") - expectedLocaleList.push("en-us"); - - assertPrefered(assert, expectedLocaleList, "Ensure that we select OS locale when related preference is set"); - - // Reset what we have changed - prefs.reset(PREF_MATCH_OS_LOCALE); - prefs.reset(PREF_SELECTED_LOCALE); - prefs.reset(PREF_ACCEPT_LANGUAGES); -} +const { findClosestLocale } = require("sdk/l10n/locale"); exports.testFindClosestLocale = function(assert) { // Second param of findClosestLocale (aMatchLocales) have to be in lowercase assert.equal(findClosestLocale([], []), null, "When everything is empty we get null"); assert.equal(findClosestLocale(["en", "en-US"], ["en"]), "en", "We always accept exact match first 1/5");
--- a/browser/components/dirprovider/DirectoryProvider.cpp +++ b/browser/components/dirprovider/DirectoryProvider.cpp @@ -14,21 +14,24 @@ #include "nsEnumeratorUtils.h" #include "nsAppDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h" #include "nsCategoryManagerUtils.h" #include "nsComponentManagerUtils.h" #include "nsCOMArray.h" #include "nsDirectoryServiceUtils.h" #include "mozilla/ModuleUtils.h" +#include "mozilla/intl/LocaleService.h" #include "nsServiceManagerUtils.h" #include "nsString.h" #include "nsXULAppAPI.h" #include "nsIPrefLocalizedString.h" +using mozilla::intl::LocaleService; + namespace mozilla { namespace browser { NS_IMPL_ISUPPORTS(DirectoryProvider, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2) NS_IMETHODIMP @@ -120,41 +123,28 @@ AppendDistroSearchDirs(nsIProperties* aD if (NS_SUCCEEDED(rv) && exists) { array.AppendObject(defLocalePlugins); return; // all done } } } // we didn't have a defaultLocale, use the user agent locale - nsCString locale; - nsCOMPtr<nsIPrefLocalizedString> prefString; - rv = prefs->GetComplexValue("general.useragent.locale", - NS_GET_IID(nsIPrefLocalizedString), - getter_AddRefs(prefString)); - if (NS_SUCCEEDED(rv)) { - nsAutoString wLocale; - prefString->GetData(getter_Copies(wLocale)); - CopyUTF16toUTF8(wLocale, locale); - } else { - rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale)); - } + nsAutoCString locale; + LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale); + nsCOMPtr<nsIFile> curLocalePlugins; + rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins)); if (NS_SUCCEEDED(rv)) { - nsCOMPtr<nsIFile> curLocalePlugins; - rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins)); - if (NS_SUCCEEDED(rv)) { - - curLocalePlugins->AppendNative(locale); - rv = curLocalePlugins->Exists(&exists); - if (NS_SUCCEEDED(rv) && exists) { - array.AppendObject(curLocalePlugins); - return; // all done - } + curLocalePlugins->AppendNative(locale); + rv = curLocalePlugins->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) { + array.AppendObject(curLocalePlugins); + return; // all done } } } } NS_IMETHODIMP DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult) {
--- a/browser/components/distribution.js +++ b/browser/components/distribution.js @@ -52,17 +52,17 @@ DistributionCustomizer.prototype = { // Unable to parse INI. Cu.reportError("Unable to parse distribution.ini"); } this.__defineGetter__("_ini", () => ini); return this._ini; }, get _locale() { - let locale = this._prefs.getCharPref("general.useragent.locale", "en-US"); + const locale = Services.locale.getRequestedLocale() || "en-US"; this.__defineGetter__("_locale", () => locale); return this._locale; }, get _language() { let language = this._locale.split("-")[0]; this.__defineGetter__("_language", () => language); return this._language;
--- a/browser/components/extensions/test/browser/head_pageAction.js +++ b/browser/components/extensions/test/browser/head_pageAction.js @@ -128,25 +128,26 @@ function* runTests(options) { extension.sendMessage("runTests"); }); } else { resolve(); } }); }); - yield SpecialPowers.pushPrefEnv({set: [["general.useragent.locale", "es-ES"]]}); + let reqLoc = Services.locale.getRequestedLocales(); + Services.locale.setRequestedLocales(["es-ES"]); yield extension.startup(); yield awaitFinish; yield extension.unload(); - yield SpecialPowers.popPrefEnv(); + Services.locale.setRequestedLocales(reqLoc); let node = document.getElementById(pageActionId); is(node, null, "pageAction image removed from document"); currentWindow = null; for (let win of windows.splice(0)) { node = win.document.getElementById(pageActionId); is(node, null, "pageAction image removed from second document");
--- a/browser/components/search/test/head.js +++ b/browser/components/search/test/head.js @@ -16,32 +16,17 @@ function isSubObjectOf(expectedObj, actu isSubObjectOf(expectedObj[prop], actualObj[prop], name + "[" + prop + "]"); } else { is(actualObj[prop], expectedObj[prop], name + "[" + prop + "]"); } } } function getLocale() { - const localePref = "general.useragent.locale"; - return getLocalizedPref(localePref, Services.prefs.getCharPref(localePref)); -} - -/** - * Wrapper for nsIPrefBranch::getComplexValue. - * @param aPrefName - * The name of the pref to get. - * @returns aDefault if the requested pref doesn't exist. - */ -function getLocalizedPref(aPrefName, aDefault) { - try { - return Services.prefs.getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data; - } catch (ex) { - return aDefault; - } + return Services.locale.getRequestedLocale() || undefined; } function promiseEvent(aTarget, aEventName, aPreventDefault) { function cancelEvent(event) { if (aPreventDefault) { event.preventDefault(); }
--- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm +++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm @@ -309,17 +309,17 @@ class ChromeActions { } }; channel.asyncOpen2(listener); }); } getLocale() { - return getStringPref("general.useragent.locale", "en-US"); + return Services.locale.getRequestedLocale() || "en-US"; } getStrings(data) { try { // Lazy initialization of localizedStrings if (!("localizedStrings" in this)) { this.localizedStrings = getLocalizedStrings("viewer.properties"); }
--- a/browser/modules/DirectoryLinksProvider.jsm +++ b/browser/modules/DirectoryLinksProvider.jsm @@ -44,22 +44,16 @@ XPCOMUtils.defineLazyGetter(this, "gUnic return converter; }); // The filename where directory links are stored locally const DIRECTORY_LINKS_FILE = "directoryLinks.json"; const DIRECTORY_LINKS_TYPE = "application/json"; -// The preference that tells whether to match the OS locale -const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; - -// The preference that tells what locale the user selected -const PREF_SELECTED_LOCALE = "general.useragent.locale"; - // The preference that tells where to obtain directory links const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directory.source"; // The preference that tells where to send click/view pings const PREF_DIRECTORY_PING = "browser.newtabpage.directory.ping"; // The preference that tells if newtab is enhanced const PREF_NEWTAB_ENHANCED = "browser.newtabpage.enhanced"; @@ -161,18 +155,16 @@ var DirectoryLinksProvider = { * an inadjacent site in the new tab */ _newTabHasInadjacentSite: false, get _observedPrefs() { return Object.freeze({ enhanced: PREF_NEWTAB_ENHANCED, linksURL: PREF_DIRECTORY_SOURCE, - matchOSLocale: PREF_MATCH_OS_LOCALE, - prefSelectedLocale: PREF_SELECTED_LOCALE, }); }, get _linksURL() { if (!this.__linksURL) { try { this.__linksURL = Services.prefs.getCharPref(this._observedPrefs["linksURL"]); this.__linksURLModified = Services.prefs.prefHasUserValue(this._observedPrefs["linksURL"]); @@ -183,36 +175,17 @@ var DirectoryLinksProvider = { return this.__linksURL; }, /** * Gets the currently selected locale for display. * @return the selected locale or "en-US" if none is selected */ get locale() { - let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE, false); - - if (matchOS) { - return Cc["@mozilla.org/intl/ospreferences;1"]. - getService(Ci.mozIOSPreferences).systemLocale; - } - - try { - let locale = Services.prefs.getComplexValue(PREF_SELECTED_LOCALE, - Ci.nsIPrefLocalizedString); - if (locale) { - return locale.data; - } - } catch (e) {} - - try { - return Services.prefs.getCharPref(PREF_SELECTED_LOCALE); - } catch (e) {} - - return "en-US"; + return Services.locale.getRequestedLocale() || "en-US"; }, /** * Set appropriate default ping behavior controlled by enhanced pref */ _setDefaultEnhanced: function DirectoryLinksProvider_setDefaultEnhanced() { if (!Services.prefs.prefHasUserValue(PREF_NEWTAB_ENHANCED)) { let enhanced = Services.prefs.getBoolPref(PREF_NEWTAB_ENHANCED); @@ -231,24 +204,21 @@ var DirectoryLinksProvider = { switch (aData) { // Re-set the default in case the user clears the pref case this._observedPrefs.enhanced: this._setDefaultEnhanced(); break; case this._observedPrefs.linksURL: delete this.__linksURL; - // fallthrough - - // Force directory download on changes to fetch related prefs - case this._observedPrefs.matchOSLocale: - case this._observedPrefs.prefSelectedLocale: this._fetchAndCacheLinksIfNecessary(true); break; } + } else if (aTopic === "intl:requested-locales-changed") { + this._fetchAndCacheLinksIfNecessary(true); } }, _addPrefsObserver: function DirectoryLinksProvider_addObserver() { for (let pref in this._observedPrefs) { let prefName = this._observedPrefs[pref]; Services.prefs.addObserver(prefName, this); } @@ -685,16 +655,17 @@ var DirectoryLinksProvider = { aCallback(links); this._populatePlacesLinks(); }); }, init: function DirectoryLinksProvider_init() { this._setDefaultEnhanced(); this._addPrefsObserver(); + Services.obs.addObserver(this, "intl:requested-locales-changed"); // setup directory file path and last download timestamp this._directoryFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, DIRECTORY_LINKS_FILE); this._lastDownloadMS = 0; // setup frequency cap file path this._frequencyCapFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, FREQUENCY_CAP_FILE); // setup inadjacent sites URL this._inadjacentSitesUrl = INADJACENCY_SOURCE; @@ -1208,16 +1179,17 @@ var DirectoryLinksProvider = { /** * Return the object to its pre-init state */ reset: function DirectoryLinksProvider_reset() { delete this.__linksURL; this._removePrefsObserver(); this._removeObservers(); + Services.obs.removeObserver(this, "intl:requested-locales-changed"); }, addObserver: function DirectoryLinksProvider_addObserver(aObserver) { this._observers.add(aObserver); }, removeObserver: function DirectoryLinksProvider_removeObserver(aObserver) { this._observers.delete(aObserver);
--- a/browser/modules/test/unit/test_DirectoryLinksProvider.js +++ b/browser/modules/test/unit/test_DirectoryLinksProvider.js @@ -29,34 +29,34 @@ do_get_profile(); const DIRECTORY_LINKS_FILE = "directoryLinks.json"; const DIRECTORY_FRECENCY = 1000; const SUGGESTED_FRECENCY = Infinity; const kURLData = {"directory": [{"url": "http://example.com", "title": "LocalSource"}]}; const kTestURL = "data:application/json," + JSON.stringify(kURLData); // DirectoryLinksProvider preferences -const kLocalePref = DirectoryLinksProvider._observedPrefs.prefSelectedLocale; const kSourceUrlPref = DirectoryLinksProvider._observedPrefs.linksURL; const kPingUrlPref = "browser.newtabpage.directory.ping"; const kNewtabEnhancedPref = "browser.newtabpage.enhanced"; // httpd settings var server; const kDefaultServerPort = 9000; const kBaseUrl = "http://localhost:" + kDefaultServerPort; const kExamplePath = "/exampleTest/"; const kFailPath = "/fail/"; const kPingPath = "/ping/"; const kExampleURL = kBaseUrl + kExamplePath; const kFailURL = kBaseUrl + kFailPath; const kPingUrl = kBaseUrl + kPingPath; // app/profile/firefox.js are not avaialble in xpcshell: hence, preset them -Services.prefs.setCharPref(kLocalePref, "en-US"); +const origReqLocales = Services.locale.getRequestedLocales(); +Services.locale.setRequestedLocales(["en-US"]); Services.prefs.setCharPref(kSourceUrlPref, kTestURL); Services.prefs.setCharPref(kPingUrlPref, kPingUrl); Services.prefs.setBoolPref(kNewtabEnhancedPref, true); const kHttpHandlerData = {}; kHttpHandlerData[kExamplePath] = {"directory": [{"url": "http://example.com", "title": "RemoteSource"}]}; const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", @@ -196,26 +196,26 @@ function promiseDirectoryDownloadOnPrefC } return Promise.resolve(); } function promiseSetupDirectoryLinksProvider(options = {}) { return Task.spawn(function*() { let linksURL = options.linksURL || kTestURL; yield DirectoryLinksProvider.init(); - yield promiseDirectoryDownloadOnPrefChange(kLocalePref, options.locale || "en-US"); + Services.locale.setRequestedLocales([options.locale || "en-US"]); yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, linksURL); do_check_eq(DirectoryLinksProvider._linksURL, linksURL); DirectoryLinksProvider._lastDownloadMS = options.lastDownloadMS || 0; }); } function promiseCleanDirectoryLinksProvider() { return Task.spawn(function*() { - yield promiseDirectoryDownloadOnPrefChange(kLocalePref, "en-US"); + Services.locale.setRequestedLocales(["en-US"]); yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kTestURL); yield DirectoryLinksProvider._clearFrequencyCap(); yield DirectoryLinksProvider._loadInadjacentSites(); DirectoryLinksProvider._lastDownloadMS = 0; DirectoryLinksProvider.reset(); }); } @@ -228,17 +228,17 @@ function run_test() { NewTabUtils.init(); run_next_test(); // Teardown. do_register_cleanup(function() { server.stop(function() { }); DirectoryLinksProvider.reset(); - Services.prefs.clearUserPref(kLocalePref); + Services.locale.setRequestedLocales(origReqLocales); Services.prefs.clearUserPref(kSourceUrlPref); Services.prefs.clearUserPref(kPingUrlPref); Services.prefs.clearUserPref(kNewtabEnhancedPref); }); } function setTimeout(fun, timeout) {
--- a/dom/encoding/FallbackEncoding.cpp +++ b/dom/encoding/FallbackEncoding.cpp @@ -5,16 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/FallbackEncoding.h" #include "mozilla/dom/EncodingUtils.h" #include "nsUConvPropertySearch.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" +#include "nsIObserverService.h" #include "mozilla/intl/LocaleService.h" using mozilla::intl::LocaleService; namespace mozilla { namespace dom { static constexpr nsUConvProp localesFallbacks[] = { @@ -24,31 +25,27 @@ static constexpr nsUConvProp localesFall static constexpr nsUConvProp domainsFallbacks[] = { #include "domainsfallbacks.properties.h" }; static constexpr nsUConvProp nonParticipatingDomains[] = { #include "nonparticipatingdomains.properties.h" }; +NS_IMPL_ISUPPORTS(FallbackEncoding, nsIObserver) + FallbackEncoding* FallbackEncoding::sInstance = nullptr; bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true; FallbackEncoding::FallbackEncoding() { - MOZ_COUNT_CTOR(FallbackEncoding); MOZ_ASSERT(!FallbackEncoding::sInstance, "Singleton already exists."); } -FallbackEncoding::~FallbackEncoding() -{ - MOZ_COUNT_DTOR(FallbackEncoding); -} - void FallbackEncoding::Get(nsACString& aFallback) { if (!mFallback.IsEmpty()) { aFallback = mFallback; return; } @@ -113,37 +110,53 @@ FallbackEncoding::FromLocale(nsACString& void FallbackEncoding::PrefChanged(const char*, void*) { MOZ_ASSERT(FallbackEncoding::sInstance, "Pref callback called with null fallback cache."); FallbackEncoding::sInstance->Invalidate(); } +NS_IMETHODIMP +FallbackEncoding::Observe(nsISupports *aSubject, const char *aTopic, + const char16_t *aData) +{ + MOZ_ASSERT(FallbackEncoding::sInstance, + "Observe callback called with null fallback cache."); + FallbackEncoding::sInstance->Invalidate(); + return NS_OK; +} + void FallbackEncoding::Initialize() { MOZ_ASSERT(!FallbackEncoding::sInstance, "Initializing pre-existing fallback cache."); FallbackEncoding::sInstance = new FallbackEncoding; Preferences::RegisterCallback(FallbackEncoding::PrefChanged, "intl.charset.fallback.override", nullptr); - Preferences::RegisterCallback(FallbackEncoding::PrefChanged, - "general.useragent.locale", - nullptr); Preferences::AddBoolVarCache(&sGuessFallbackFromTopLevelDomain, "intl.charset.fallback.tld"); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->AddObserver(sInstance, "intl:requested-locales-changed", true); + } } void FallbackEncoding::Shutdown() { MOZ_ASSERT(FallbackEncoding::sInstance, "Releasing non-existent fallback cache."); + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(sInstance, "intl:requested-locales-changed"); + } delete FallbackEncoding::sInstance; FallbackEncoding::sInstance = nullptr; } bool FallbackEncoding::IsParticipatingTopLevelDomain(const nsACString& aTLD) { nsAutoCString dummy;
--- a/dom/encoding/FallbackEncoding.h +++ b/dom/encoding/FallbackEncoding.h @@ -2,24 +2,27 @@ /* vim: set ts=8 sts=2 et sw=2 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/. */ #ifndef mozilla_dom_FallbackEncoding_h_ #define mozilla_dom_FallbackEncoding_h_ +#include "nsIObserver.h" #include "nsString.h" namespace mozilla { namespace dom { -class FallbackEncoding +class FallbackEncoding : public nsIObserver { public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER /** * Whether FromTopLevelDomain() should be used. */ static bool sGuessFallbackFromTopLevelDomain; /** * Gets the locale-dependent fallback encoding for legacy HTML and plain @@ -63,17 +66,17 @@ public: private: /** * The fallback cache. */ static FallbackEncoding* sInstance; FallbackEncoding(); - ~FallbackEncoding(); + virtual ~FallbackEncoding() {}; /** * Invalidates the cache. */ void Invalidate() { mFallback.Truncate(); }
--- a/intl/locale/LocaleService.cpp +++ b/intl/locale/LocaleService.cpp @@ -743,16 +743,34 @@ LocaleService::GetRequestedLocales(uint3 *aCount = requestedLocales.Length(); *aOutArray = CreateOutArray(requestedLocales); return NS_OK; } NS_IMETHODIMP +LocaleService::GetRequestedLocale(nsACString& aRetVal) +{ + AutoTArray<nsCString, 16> requestedLocales; + bool res = GetRequestedLocales(requestedLocales); + + if (!res) { + NS_ERROR("Couldn't retrieve selected locales from prefs!"); + return NS_ERROR_FAILURE; + } + + if (requestedLocales.Length() > 0) { + aRetVal = requestedLocales[0]; + } + + return NS_OK; +} + +NS_IMETHODIMP LocaleService::SetRequestedLocales(const char** aRequested, uint32_t aRequestedCount) { MOZ_ASSERT(aRequestedCount < 2, "We can only handle one requested locale"); if (aRequestedCount == 0) { Preferences::ClearUser(SELECTED_LOCALE_PREF); } else {
--- a/intl/locale/mozILocaleService.idl +++ b/intl/locale/mozILocaleService.idl @@ -139,16 +139,21 @@ interface mozILocaleService : nsISupport * used as a requestedLocales input list for language negotiation. * * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"] */ void getRequestedLocales([optional] out unsigned long aCount, [retval, array, size_is(aCount)] out string aLocales); /** + * Returns the top-requested locale from the user, or an empty string if none is set. + */ + ACString getRequestedLocale(); + + /** * Sets a list of locales that the user requested the app to be * localized to. * * The argument is an ordered list of locale IDs which should be * used as a requestedLocales input list for language negotiation. * * The current implementation is limited to handle at most one * locale passed to the API. In the future we'll transition to support
--- a/intl/locale/tests/unit/test_localeService.js +++ b/intl/locale/tests/unit/test_localeService.js @@ -112,16 +112,34 @@ add_test(function test_getRequestedLocal }; Services.obs.addObserver(observer, REQ_LOC_CHANGE_EVENT); Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "sr-RU"); run_next_test(); }); +add_test(function test_getRequestedLocale() { + Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false); + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "tlh"); + + let requestedLocale = localeService.getRequestedLocale(); + do_check_true(requestedLocale === "tlh", "requestedLocale returns the right value"); + + Services.prefs.setCharPref(PREF_SELECTED_LOCALE, ""); + + requestedLocale = localeService.getRequestedLocale(); + do_check_true(requestedLocale === "", "requestedLocale returns empty value value"); + + Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE); + Services.prefs.clearUserPref(PREF_SELECTED_LOCALE); + + run_next_test(); +}); + add_test(function test_setRequestedLocales() { localeService.setRequestedLocales([]); let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE); do_check_true(matchOS === true); localeService.setRequestedLocales(['de-AT']);
--- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1642,25 +1642,17 @@ var BrowserApp = { if (!gotResizeWindow) { aBrowser.contentWindow.removeEventListener("resize", resizeWindow); dwu.zoomToFocusedInput(); } }, 500); }, getUALocalePref: function () { - try { - return Services.prefs.getComplexValue("general.useragent.locale", Ci.nsIPrefLocalizedString).data; - } catch (e) { - try { - return Services.prefs.getCharPref("general.useragent.locale"); - } catch (ee) { - return undefined; - } - } + return Services.locale.getRequestedLocale() || undefined; }, getOSLocalePref: function () { try { return Services.prefs.getCharPref("intl.locale.os"); } catch (e) { return undefined; }
--- a/mobile/android/components/DirectoryProvider.js +++ b/mobile/android/components/DirectoryProvider.js @@ -108,24 +108,19 @@ DirectoryProvider.prototype = { array.push(commonPlugins); let localePlugins = searchPlugins.clone(); localePlugins.append("locale"); if (!localePlugins.exists()) return; let curLocale = ""; - try { - curLocale = Services.prefs.getComplexValue("general.useragent.locale", Ci.nsIPrefLocalizedString).data; - } catch (e) { - // eslint-disable-next-line mozilla/use-default-preference-values - try { - curLocale = Services.prefs.getCharPref("general.useragent.locale"); - } catch (ee) { - } + let reqLocales = Services.locales.getRequestedLocales(); + if (reqLocales.length > 0) { + curLocale = reqLocales[0]; } if (curLocale) { let curLocalePlugins = localePlugins.clone(); curLocalePlugins.append(curLocale); if (curLocalePlugins.exists()) { array.push(curLocalePlugins); return;
--- a/toolkit/components/downloads/ApplicationReputation.cpp +++ b/toolkit/components/downloads/ApplicationReputation.cpp @@ -31,16 +31,17 @@ #include "mozilla/BasePrincipal.h" #include "mozilla/ErrorNames.h" #include "mozilla/LoadContext.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/SizePrintfMacros.h" #include "mozilla/Telemetry.h" #include "mozilla/TimeStamp.h" +#include "mozilla/intl/LocaleService.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsDebug.h" #include "nsDependentSubstring.h" #include "nsError.h" #include "nsNetCID.h" #include "nsReadableUtils.h" @@ -57,28 +58,28 @@ using namespace mozilla::downloads; using mozilla::ArrayLength; using mozilla::BasePrincipal; using mozilla::OriginAttributes; using mozilla::Preferences; using mozilla::TimeStamp; using mozilla::Telemetry::Accumulate; +using mozilla::intl::LocaleService; using safe_browsing::ClientDownloadRequest; using safe_browsing::ClientDownloadRequest_CertificateChain; using safe_browsing::ClientDownloadRequest_Resource; using safe_browsing::ClientDownloadRequest_SignatureInfo; // Preferences that we need to initialize the query. #define PREF_SB_APP_REP_URL "browser.safebrowsing.downloads.remote.url" #define PREF_SB_MALWARE_ENABLED "browser.safebrowsing.malware.enabled" #define PREF_SB_DOWNLOADS_ENABLED "browser.safebrowsing.downloads.enabled" #define PREF_SB_DOWNLOADS_REMOTE_ENABLED "browser.safebrowsing.downloads.remote.enabled" #define PREF_SB_DOWNLOADS_REMOTE_TIMEOUT "browser.safebrowsing.downloads.remote.timeout_ms" -#define PREF_GENERAL_LOCALE "general.useragent.locale" #define PREF_DOWNLOAD_BLOCK_TABLE "urlclassifier.downloadBlockTable" #define PREF_DOWNLOAD_ALLOW_TABLE "urlclassifier.downloadAllowTable" // Preferences that are needed to action the verdict. #define PREF_BLOCK_DANGEROUS "browser.safebrowsing.downloads.remote.block_dangerous" #define PREF_BLOCK_DANGEROUS_HOST "browser.safebrowsing.downloads.remote.block_dangerous_host" #define PREF_BLOCK_POTENTIALLY_UNWANTED "browser.safebrowsing.downloads.remote.block_potentially_unwanted" #define PREF_BLOCK_UNCOMMON "browser.safebrowsing.downloads.remote.block_uncommon" @@ -1314,18 +1315,18 @@ PendingLookup::SendRemoteQueryInternal() rv = mQuery->GetFileSize(&fileSize); NS_ENSURE_SUCCESS(rv, rv); mRequest.set_length(fileSize); // We have no way of knowing whether or not a user initiated the // download. Set it to true to lessen the chance of false positives. mRequest.set_user_initiated(true); nsCString locale; - NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_GENERAL_LOCALE, &locale), - NS_ERROR_NOT_AVAILABLE); + rv = LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale); + NS_ENSURE_SUCCESS(rv, rv); mRequest.set_locale(locale.get()); nsCString sha256Hash; rv = mQuery->GetSha256Hash(sha256Hash); NS_ENSURE_SUCCESS(rv, rv); mRequest.mutable_digests()->set_sha256(sha256Hash.Data()); nsString fileName; rv = mQuery->GetSuggestedFileName(fileName); NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -870,22 +870,17 @@ function getDir(aKey, aIFace) { } /** * Gets the current value of the locale. It's possible for this preference to * be localized, so we have to do a little extra work here. Similar code * exists in nsHttpHandler.cpp when building the UA string. */ function getLocale() { - let locale = getLocalizedPref(LOCALE_PREF); - if (locale) - return locale; - - // Not localized. - return Services.prefs.getCharPref(LOCALE_PREF); + return Services.locale.getRequestedLocale(); } /** * Wrapper for nsIPrefBranch::getComplexValue. * @param aPrefName * The name of the pref to get. * @returns aDefault if the requested pref doesn't exist. */
--- a/toolkit/modules/Locale.jsm +++ b/toolkit/modules/Locale.jsm @@ -4,36 +4,23 @@ this.EXPORTED_SYMBOLS = ["Locale"]; const { classes: Cc, interfaces: Ci, utils: Cu } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); -const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; -const PREF_SELECTED_LOCALE = "general.useragent.locale"; - this.Locale = { /** * Gets the currently selected locale for display. * @return the selected locale or "en-US" if none is selected */ getLocale() { - if (Preferences.get(PREF_MATCH_OS_LOCALE, false)) { - const osPrefs = - Cc["@mozilla.org/intl/ospreferences;1"].getService(Ci.mozIOSPreferences); - return osPrefs.systemLocale; - } - try { - let locale = Preferences.get(PREF_SELECTED_LOCALE, null, Ci.nsIPrefLocalizedString); - if (locale) - return locale; - } catch (e) {} - return Preferences.get(PREF_SELECTED_LOCALE, "en-US"); + return Services.locale.getRequestedLocale() || "en-US"; }, /** * Selects the closest matching locale from a list of locales. * * @param aLocales * An array of locales * @return the best match for the currently selected locale
--- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -36,18 +36,16 @@ const PREF_EM_CHECK_UPDATE_SECURITY = const PREF_EM_UPDATE_BACKGROUND_URL = "extensions.update.background.url"; const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_AUTO = "app.update.auto"; const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; const PREF_EM_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion"; const PREF_EM_HOTFIX_URL = "extensions.hotfix.url"; const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; -const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; -const PREF_SELECTED_LOCALE = "general.useragent.locale"; const UNKNOWN_XPCOM_ABI = "unknownABI"; const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion"; const PREF_WEBAPI_TESTING = "extensions.webapi.testing"; const PREF_WEBEXT_PERM_PROMPTS = "extensions.webextPermissionPrompts"; const UPDATE_REQUEST_VERSION = 2; const CATEGORY_UPDATE_PARAMS = "extension-update-params"; @@ -321,36 +319,17 @@ function promiseCallProvider(aProvider, }); } /** * Gets the currently selected locale for display. * @return the selected locale or "en-US" if none is selected */ function getLocale() { - try { - if (Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE)) { - const osPrefs = - Cc["@mozilla.org/intl/ospreferences;1"].getService(Ci.mozIOSPreferences); - return osPrefs.systemLocale; - } - } catch (e) { } - - try { - let locale = Services.prefs.getComplexValue(PREF_SELECTED_LOCALE, - Ci.nsIPrefLocalizedString); - if (locale) - return locale; - } catch (e) { } - - try { - return Services.prefs.getCharPref(PREF_SELECTED_LOCALE); - } catch (e) { } - - return "en-US"; + return Services.locale.getRequestedLocale() || "en-US"; } function webAPIForAddon(addon) { if (!addon) { return null; } let result = {};
--- a/toolkit/mozapps/extensions/nsBlocklistService.js +++ b/toolkit/mozapps/extensions/nsBlocklistService.js @@ -43,17 +43,16 @@ const PREF_BLOCKLIST_URL = const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL"; const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled"; const PREF_BLOCKLIST_LEVEL = "extensions.blocklist.level"; const PREF_BLOCKLIST_PINGCOUNTTOTAL = "extensions.blocklist.pingCountTotal"; const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion"; const PREF_BLOCKLIST_SUPPRESSUI = "extensions.blocklist.suppressUI"; const PREF_ONECRL_VIA_AMO = "security.onecrl.via.amo"; const PREF_BLOCKLIST_UPDATE_ENABLED = "services.blocklist.update_enabled"; -const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale"; const PREF_APP_DISTRIBUTION = "distribution.id"; const PREF_APP_DISTRIBUTION_VERSION = "distribution.version"; const PREF_EM_LOGGING_ENABLED = "extensions.logging.enabled"; const XMLURI_BLOCKLIST = "http://www.mozilla.org/2006/addons-blocklist"; const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml" const URI_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul" const DEFAULT_SEVERITY = 3; const DEFAULT_LEVEL = 2; @@ -237,24 +236,17 @@ function matchesOSABI(blocklistElement) } /** * Gets the current value of the locale. It's possible for this preference to * be localized, so we have to do a little extra work here. Similar code * exists in nsHttpHandler.cpp when building the UA string. */ function getLocale() { - try { - // Get the default branch - var defaultPrefs = gPref.getDefaultBranch(null); - return defaultPrefs.getComplexValue(PREF_GENERAL_USERAGENT_LOCALE, - Ci.nsIPrefLocalizedString).data; - } catch (e) {} - - return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE); + return Services.locale.getRequestedLocales(); } /* Get the distribution pref values, from defaults only */ function getDistributionPrefValue(aPrefName) { return gPref.getDefaultBranch(null).getCharPref(aPrefName, "default"); } /**
--- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -14,16 +14,17 @@ #include "mozilla/Likely.h" #include "mozilla/MemoryChecking.h" #include "mozilla/Poison.h" #include "mozilla/Preferences.h" #include "mozilla/Printf.h" #include "mozilla/ScopeExit.h" #include "mozilla/Services.h" #include "mozilla/Telemetry.h" +#include "mozilla/intl/LocaleService.h" #include "nsAppRunner.h" #include "mozilla/XREAppData.h" #include "mozilla/Bootstrap.h" #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID) #include "nsUpdateDriver.h" #endif #include "ProfileReset.h" @@ -283,16 +284,17 @@ namespace mozilla { int (*RunGTest)(int*, char**) = 0; } // namespace mozilla using namespace mozilla; using mozilla::Unused; using mozilla::scache::StartupCache; using mozilla::dom::ContentParent; using mozilla::dom::ContentChild; +using mozilla::intl::LocaleService; // Save literal putenv string to environment variable. static void SaveToEnv(const char *putenv) { char *expr = strdup(putenv); if (expr) PR_SetEnv(expr); @@ -4366,23 +4368,18 @@ XREMain::XRE_mainRun() } mDirProvider.DoStartup(); OverrideDefaultLocaleIfNeeded(); #ifdef MOZ_CRASHREPORTER nsCString userAgentLocale; - // Try a localized string first. This pref is always a localized string in - // Fennec, and might be elsewhere, too. - if (NS_SUCCEEDED(Preferences::GetLocalizedCString("general.useragent.locale", &userAgentLocale))) { - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale); - } else if (NS_SUCCEEDED(Preferences::GetCString("general.useragent.locale", &userAgentLocale))) { - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale); - } + LocaleService::GetInstance()->GetAppLocaleAsLangTag(userAgentLocale); + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("useragent_locale"), userAgentLocale); #endif appStartup->GetShuttingDown(&mShuttingDown); nsCOMPtr<nsICommandLineRunner> cmdLine; nsCOMPtr<nsIFile> workingDir; rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));