--- 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));