Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Sat, 22 Sep 2018 01:06:13 +0300
changeset 493515 f125ee6d1cef0ac302c3b4570b10b251a4638c54
parent 493514 be7d67d74770825ae80c8b0fd40585cf1ced575e (current diff)
parent 493472 eddbfdc38cbc0d25be44ea92588126db3d0b9a78 (diff)
child 493516 4f0db2886781fc12b645cd7ae415fe8e094edf2b
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.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
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_sidebar_network_runtimes.js
dom/base/nsDocument.cpp
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -860,17 +860,17 @@ const PanelUI = {
 
 XPCOMUtils.defineConstant(this, "PanelUI", PanelUI);
 
 /**
  * Gets the currently selected locale for display.
  * @return  the selected locale
  */
 function getLocale() {
-  return Services.locale.getAppLocaleAsLangTag();
+  return Services.locale.appLocaleAsLangTag;
 }
 
 function getNotificationFromElement(aElement) {
   // Need to find the associated notification object, which is a bit tricky
   // since it isn't associated with the element directly - this is kind of
   // gross and very dependent on the structure of the popupnotification
   // binding's content.
   let notificationEl;
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -77,17 +77,17 @@ DistributionCustomizer.prototype = {
         Cu.reportError("Unable to parse distribution.ini");
       }
     }
     this.__defineGetter__("_ini", () => ini);
     return this._ini;
   },
 
   get _locale() {
-    const locale = Services.locale.getRequestedLocale() || "en-US";
+    const locale = Services.locale.requestedLocale || "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
@@ -8,21 +8,21 @@
 
 {
   // At the moment extension language negotiation is tied to Firefox language
   // negotiation result. That means that to test an extension in `es-ES`, we need
   // to mock `es-ES` being available in Firefox and then request it.
   //
   // In the future, we should provide some way for tests to decouple their
   // language selection from that of Firefox.
-  const avLocales = Services.locale.getAvailableLocales();
+  const avLocales = Services.locale.availableLocales;
 
-  Services.locale.setAvailableLocales(["en-US", "es-ES"]);
+  Services.locale.availableLocales = ["en-US", "es-ES"];
   registerCleanupFunction(() => {
-    Services.locale.setAvailableLocales(avLocales);
+    Services.locale.availableLocales = avLocales;
   });
 }
 
 async function runTests(options) {
   function background(getTests) {
     let tests;
 
     // Gets the current details of the page action, and returns a
@@ -147,26 +147,26 @@ async function runTests(options) {
           extension.sendMessage("runTests");
         });
       } else {
         resolve();
       }
     });
   });
 
-  let reqLoc = Services.locale.getRequestedLocales();
-  Services.locale.setRequestedLocales(["es-ES"]);
+  let reqLoc = Services.locale.requestedLocales;
+  Services.locale.requestedLocales = ["es-ES"];
 
   await extension.startup();
 
   await awaitFinish;
 
   await extension.unload();
 
-  Services.locale.setRequestedLocales(reqLoc);
+  Services.locale.requestedLocales = 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/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -656,17 +656,17 @@ const AutoMigrate = {
     let canDoSurveyInLocale = false;
     try {
       let surveyLocales = Preferences.get(kAutoMigrateUndoSurveyLocalePref, "");
       surveyLocales = surveyLocales.split(",").map(str => str.trim());
       // Strip out any empty elements, so an empty pref doesn't
       // lead to a an array with 1 empty string in it.
       surveyLocales = new Set(surveyLocales.filter(str => !!str));
       canDoSurveyInLocale =
-        surveyLocales.has(Services.locale.getAppLocaleAsLangTag());
+        surveyLocales.has(Services.locale.appLocaleAsLangTag);
     } catch (ex) {
       /* ignore exceptions and just don't do the survey. */
     }
 
     let migrationBrowser = this.getBrowserUsedForMigration();
     let rawURL = Preferences.get(kAutoMigrateUndoSurveyPref, "");
     if (!canDoSurveyInLocale || !migrationBrowser || !rawURL) {
       return;
--- a/browser/components/newtab/aboutNewTabService.js
+++ b/browser/components/newtab/aboutNewTabService.js
@@ -305,17 +305,17 @@ AboutNewTabService.prototype = {
     return this._activityStreamDebug;
   },
 
   get activityStreamLocale() {
     // Pick the best available locale to match the app locales
     return Services.locale.negotiateLanguages(
       // Fix up incorrect BCP47 that are actually lang tags as a workaround for
       // bug 1479606 returning the wrong values in the content process
-      Services.locale.getAppLocalesAsBCP47().map(l => l.replace(/^(ja-JP-mac)$/, "$1os")),
+      Services.locale.appLocalesAsBCP47.map(l => l.replace(/^(ja-JP-mac)$/, "$1os")),
       ACTIVITY_STREAM_BCP47,
       // defaultLocale's strings aren't necessarily packaged, but en-US' are
       "en-US",
       Services.locale.langNegStrategyLookup
     // Convert the BCP47 to lang tag, which is what is used in our paths, as a
     // workaround for bug 1478930 negotiating incorrectly with lang tags
     )[0].replace(/^(ja-JP-mac)os$/, "$1");
   },
--- a/browser/components/newtab/lib/ASRouter.jsm
+++ b/browser/components/newtab/lib/ASRouter.jsm
@@ -146,17 +146,17 @@ const MessageLoaderUtils = {
       } catch (e) {
         Cu.reportError(e);
       }
     }
     return messages;
   },
 
   _getRemoteSettingsMessages(bucket) {
-    return RemoteSettings(bucket).get({filters: {locale: Services.locale.getAppLocaleAsLangTag()}});
+    return RemoteSettings(bucket).get({filters: {locale: Services.locale.appLocaleAsLangTag}});
   },
 
   /**
    * _getMessageLoader - return the right loading function given the provider's type
    *
    * @param {obj} provider An AS Router provider
    * @returns {func} A loading function
    */
--- a/browser/components/newtab/lib/ActivityStream.jsm
+++ b/browser/components/newtab/lib/ActivityStream.jsm
@@ -436,17 +436,17 @@ this.ActivityStream = class ActivityStre
     if (Services.prefs.prefHasUserValue(GEO_PREF)) {
       this.geo = Services.prefs.getStringPref(GEO_PREF);
     } else if (this.geo !== "") {
       // Watch for geo changes and use a dummy value for now
       Services.prefs.addObserver(GEO_PREF, this);
       this.geo = "";
     }
 
-    this.locale = Services.locale.getAppLocaleAsLangTag();
+    this.locale = Services.locale.appLocaleAsLangTag;
 
     // Update the pref config of those with dynamic values
     for (const pref of PREFS_CONFIG.keys()) {
       const prefConfig = PREFS_CONFIG.get(pref);
       if (!prefConfig.getValue) {
         continue;
       }
 
--- a/browser/components/newtab/lib/TelemetryFeed.jsm
+++ b/browser/components/newtab/lib/TelemetryFeed.jsm
@@ -323,17 +323,17 @@ this.TelemetryFeed = class TelemetryFeed
    * createPing - Create a ping with common properties
    *
    * @param  {string} id The portID of the session, if a session is relevant (optional)
    * @return {obj}    A telemetry ping
    */
   createPing(portID) {
     const ping = {
       addon_version: Services.appinfo.appBuildID,
-      locale: Services.locale.getAppLocaleAsLangTag(),
+      locale: Services.locale.appLocaleAsLangTag,
       user_prefs: this.userPreferences,
     };
 
     // If the ping is part of a user session, add session-related info
     if (portID) {
       const session = this.sessions.get(portID) || this.addSession(portID);
       Object.assign(ping, {session_id: session.session_id});
 
@@ -407,17 +407,17 @@ this.TelemetryFeed = class TelemetryFeed
    * AS router components could change that by including a boolean "includeClientID"
    * to the payload of the action, impression_id would be set to "n/a" at the same time.
    * Note that "includeClientID" will not be included in the result ping.
    */
   createASRouterEvent(action) {
     const ping = {
       client_id: "n/a",
       addon_version: Services.appinfo.appBuildID,
-      locale: Services.locale.getAppLocaleAsLangTag(),
+      locale: Services.locale.appLocaleAsLangTag,
       impression_id: this._impressionId,
     };
     if (action.data.includeClientID) {
       // Ping-centre client will fill in the client_id if it's not provided in the ping
       delete ping.client_id;
       delete action.data.includeClientID;
       ping.impression_id = "n/a";
     }
--- a/browser/components/newtab/test/browser/browser_packaged_as_locales.js
+++ b/browser/components/newtab/test/browser/browser_packaged_as_locales.js
@@ -5,26 +5,26 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 // Tests are by default run with non-debug en-US configuration
 const DEFAULT_URL = "resource://activity-stream/prerendered/en-US/activity-stream-prerendered.html";
 
 /**
  * Temporarily change the app locale to get the localized activity stream url
  */
 async function getUrlForLocale(locale) {
-  const origAvailable = Services.locale.getAvailableLocales();
-  const origRequested = Services.locale.getRequestedLocales();
+  const origAvailable = Services.locale.availableLocales;
+  const origRequested = Services.locale.requestedLocales;
   try {
-    Services.locale.setAvailableLocales([locale]);
-    Services.locale.setRequestedLocales([locale]);
+    Services.locale.availableLocales = [locale];
+    Services.locale.requestedLocales = [locale];
     return aboutNewTabService.defaultURL;
   } finally {
     // Always clean up after returning the url
-    Services.locale.setAvailableLocales(origAvailable);
-    Services.locale.setRequestedLocales(origRequested);
+    Services.locale.availableLocales = origAvailable;
+    Services.locale.requestedLocales = origRequested;
   }
 }
 
 /**
  * Test that an unknown locale defaults to en-US
  */
 add_task(async function test_unknown_locale() {
   const url = await getUrlForLocale("und");
--- a/browser/components/newtab/test/unit/lib/ActivityStream.test.js
+++ b/browser/components/newtab/test/unit/lib/ActivityStream.test.js
@@ -250,39 +250,39 @@ describe("ActivityStream", () => {
 
       as._updateDynamicPrefs();
 
       assert.isFalse(PREFS_CONFIG.get("feeds.section.topstories").value);
     });
     it("should be false with expected geo and unexpected locale", () => {
       sandbox.stub(global.Services.prefs, "prefHasUserValue").returns(true);
       sandbox.stub(global.Services.prefs, "getStringPref").returns("US");
-      sandbox.stub(global.Services.locale, "getAppLocaleAsLangTag").returns("no-LOCALE");
+      sandbox.stub(global.Services.locale, "appLocaleAsLangTag").returns("no-LOCALE");
 
       as._updateDynamicPrefs();
 
       assert.isFalse(PREFS_CONFIG.get("feeds.section.topstories").value);
     });
     it("should be true with expected geo and locale", () => {
       sandbox.stub(global.Services.prefs, "prefHasUserValue").returns(true);
       sandbox.stub(global.Services.prefs, "getStringPref").returns("US");
-      sandbox.stub(global.Services.locale, "getAppLocaleAsLangTag").returns("en-US");
+      sandbox.stub(global.Services.locale, "appLocaleAsLangTag").returns("en-US");
 
       as._updateDynamicPrefs();
 
       assert.isTrue(PREFS_CONFIG.get("feeds.section.topstories").value);
     });
     it("should be false after expected geo and locale then unexpected", () => {
       sandbox.stub(global.Services.prefs, "prefHasUserValue").returns(true);
       sandbox.stub(global.Services.prefs, "getStringPref")
         .onFirstCall()
         .returns("US")
         .onSecondCall()
         .returns("NOGEO");
-      sandbox.stub(global.Services.locale, "getAppLocaleAsLangTag").returns("en-US");
+      sandbox.stub(global.Services.locale, "appLocaleAsLangTag").returns("en-US");
 
       as._updateDynamicPrefs();
       as._updateDynamicPrefs();
 
       assert.isFalse(PREFS_CONFIG.get("feeds.section.topstories").value);
     });
   });
   describe("_updateDynamicPrefs topstories delayed default value", () => {
@@ -303,17 +303,17 @@ describe("ActivityStream", () => {
 
       as._updateDynamicPrefs();
       clock.tick(1);
 
       assert.isFalse(PREFS_CONFIG.get("feeds.section.topstories").value);
     });
     it("should set true with expected geo and locale", () => {
       sandbox.stub(global.Services.prefs, "getStringPref").returns("US");
-      sandbox.stub(global.Services.locale, "getAppLocaleAsLangTag").returns("en-US");
+      sandbox.stub(global.Services.locale, "appLocaleAsLangTag").returns("en-US");
 
       as._updateDynamicPrefs();
       clock.tick(1);
 
       assert.isTrue(PREFS_CONFIG.get("feeds.section.topstories").value);
     });
   });
   describe("telemetry reporting on init failure", () => {
--- a/browser/components/newtab/test/unit/unit-entry.js
+++ b/browser/components/newtab/test/unit/unit-entry.js
@@ -101,18 +101,18 @@ const TEST_GLOBAL = {
     },
   },
   PluralForm: {get() {}},
   Preferences: FakePrefs,
   PrivateBrowsingUtils: {isWindowPrivate: () => false},
   DownloadsViewUI: {DownloadElementShell},
   Services: {
     locale: {
-      getAppLocaleAsLangTag() { return "en-US"; },
-      getAppLocalesAsLangTags() {},
+      appLocaleAsLangTag: "en-US",
+      appLocalesAsLangtags: [],
       negotiateLanguages() {},
     },
     urlFormatter: {formatURL: str => str, formatURLPref: str => str},
     mm: {
       addMessageListener: (msg, cb) => cb(),
       removeMessageListener() {},
     },
     appShell: {hiddenDOMWindow: {performance: new FakePerformance()}},
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1056,17 +1056,17 @@ BrowserGlue.prototype = {
       author: vendorShortName,
     }, {
       useInDarkMode: true,
     });
 
     Normandy.init();
 
     // Initialize the default l10n resource sources for L10nRegistry.
-    let locales = Services.locale.getPackagedLocales();
+    let locales = Services.locale.packagedLocales;
     const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
     L10nRegistry.registerSource(greSource);
 
     const appSource = new FileSource("app", locales, "resource://app/localization/{locale}/");
     L10nRegistry.registerSource(appSource);
 
     Services.obs.notifyObservers(null, "browser-ui-startup-complete");
   },
@@ -2340,23 +2340,23 @@ BrowserGlue.prototype = {
 
       // Migrate the old requested locales prefs to use the new model
       const SELECTED_LOCALE_PREF = "general.useragent.locale";
       const MATCHOS_LOCALE_PREF = "intl.locale.matchOS";
 
       if (Services.prefs.prefHasUserValue(MATCHOS_LOCALE_PREF) ||
           Services.prefs.prefHasUserValue(SELECTED_LOCALE_PREF)) {
         if (Services.prefs.getBoolPref(MATCHOS_LOCALE_PREF, false)) {
-          Services.locale.setRequestedLocales([]);
+          Services.locale.requestedLocales = [];
         } else {
           let locale = Services.prefs.getComplexValue(SELECTED_LOCALE_PREF,
             Ci.nsIPrefLocalizedString);
           if (locale) {
             try {
-              Services.locale.setRequestedLocales([locale.data]);
+              Services.locale.requestedLocales = [locale.data];
             } catch (e) { /* Don't panic if the value is not a valid locale code. */ }
           }
         }
         Services.prefs.clearUserPref(SELECTED_LOCALE_PREF);
         Services.prefs.clearUserPref(MATCHOS_LOCALE_PREF);
       }
     }
 
--- a/browser/components/preferences/browserLanguages.js
+++ b/browser/components/preferences/browserLanguages.js
@@ -192,17 +192,17 @@ class SortedItemSelectList {
     let item = document.createElement("menuitem");
     item.value = value;
     item.setAttribute("label", label);
     return item;
   }
 }
 
 function getLocaleDisplayInfo(localeCodes) {
-  let packagedLocales = new Set(Services.locale.getPackagedLocales());
+  let packagedLocales = new Set(Services.locale.packagedLocales);
   let localeNames = Services.intl.getLocaleDisplayNames(undefined, localeCodes);
   return localeCodes.map((code, i) => {
     return {
       id: "locale-" + code,
       label: localeNames[i],
       value: code,
       canRemove: !packagedLocales.has(code),
     };
@@ -218,19 +218,19 @@ var gBrowserLanguagesDialog = {
     this.requestedLocales = this._requestedLocales.items.map(item => item.value);
     return true;
   },
 
   onLoad() {
     // Maintain the previously requested locales even if we cancel out.
     this.requestedLocales = window.arguments[0];
 
-    let requested = this.requestedLocales || Services.locale.getRequestedLocales();
+    let requested = this.requestedLocales || Services.locale.requestedLocales;
     let requestedSet = new Set(requested);
-    let available = Services.locale.getAvailableLocales()
+    let available = Services.locale.availableLocales
       .filter(locale => !requestedSet.has(locale));
 
     this.initRequestedLocales(requested);
     this.initAvailableLocales(available);
     this.initialized = true;
   },
 
   initRequestedLocales(requested) {
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -233,17 +233,17 @@ if (AppConstants.MOZ_UPDATER) {
 // A promise that resolves when the list of application handlers is loaded.
 // We store this in a global so tests can await it.
 var promiseLoadHandlersList;
 
 // Load the preferences string bundle for other locales with fallbacks.
 function getBundleForLocales(newLocales) {
   let locales = Array.from(new Set([
     ...newLocales,
-    ...Services.locale.getRequestedLocales(),
+    ...Services.locale.requestedLocales,
     Services.locale.lastFallbackLocale,
   ]));
   function generateContexts(resourceIds) {
     return L10nRegistry.generateContexts(locales, resourceIds);
   }
   return new Localization([
     "browser/preferences/preferences.ftl",
     "branding/brand.ftl",
@@ -780,32 +780,32 @@ var gMainPane = {
       newValue = startupPref.value === this.STARTUP_PREF_RESTORE_SESSION;
     }
     if (checkbox.checked !== newValue) {
       checkbox.checked = newValue;
     }
   },
 
   initBrowserLocale() {
-    let localeCodes = Services.locale.getAvailableLocales();
+    let localeCodes = Services.locale.availableLocales;
     let localeNames = Services.intl.getLocaleDisplayNames(undefined, localeCodes);
     let locales = localeCodes.map((code, i) => ({code, name: localeNames[i]}));
     locales.sort((a, b) => a.name > b.name);
 
     let fragment = document.createDocumentFragment();
     for (let {code, name} of locales) {
       let menuitem = document.createXULElement("menuitem");
       menuitem.setAttribute("value", code);
       menuitem.setAttribute("label", name);
       fragment.appendChild(menuitem);
     }
     let menulist = document.getElementById("defaultBrowserLanguage");
     let menupopup = menulist.querySelector("menupopup");
     menupopup.appendChild(fragment);
-    menulist.value = Services.locale.getRequestedLocale();
+    menulist.value = Services.locale.requestedLocale;
 
     document.getElementById("browserLanguagesBox").hidden = false;
   },
 
   /* Show the confirmation message bar to allow a restart into the new locales. */
   async showConfirmLanguageChangeMessageBar(locales) {
     let messageBar = document.getElementById("confirmBrowserLanguage");
     // Set the text in the message bar for the new locale.
@@ -831,36 +831,36 @@ var gMainPane = {
 
   /* Confirm the locale change and restart the browser in the new locale. */
   confirmBrowserLanguageChange() {
     let localesString = (event.target.getAttribute("locales") || "").trim();
     if (!localesString || localesString.length == 0) {
       return;
     }
     let locales = localesString.split(",");
-    Services.locale.setRequestedLocales(locales);
+    Services.locale.requestedLocales = locales;
 
     // Restart with the new locale.
     let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
     Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
     if (!cancelQuit.data) {
       Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
     }
   },
 
   /* Show or hide the confirm change message bar based on the new locale. */
   onBrowserLanguageChange(event) {
     let locale = event.target.value;
-    if (locale == Services.locale.getRequestedLocale()) {
+    if (locale == Services.locale.requestedLocale) {
       this.hideConfirmLanguageChangeMessageBar();
       return;
     }
     let locales = Array.from(new Set([
       locale,
-      ...Services.locale.getRequestedLocales(),
+      ...Services.locale.requestedLocales,
     ]).values());
     this.showConfirmLanguageChangeMessageBar(locales);
   },
 
   onBrowserRestoreSessionChange(event) {
     const value = event.target.checked;
     const startupPref = Preferences.get("browser.startup.page");
     let newValue;
@@ -988,24 +988,24 @@ var gMainPane = {
     gSubDialog.open(
       "chrome://browser/content/preferences/browserLanguages.xul",
       null, gMainPane.requestingLocales, this.browserLanguagesClosed);
   },
 
   /* Show or hide the confirm change message bar based on the updated ordering. */
   browserLanguagesClosed() {
     let requesting = this.gBrowserLanguagesDialog.requestedLocales;
-    let requested = Services.locale.getRequestedLocales();
+    let requested = Services.locale.requestedLocales;
     let defaultBrowserLanguage = document.getElementById("defaultBrowserLanguage");
     if (requesting && requesting.join(",") != requested.join(",")) {
       gMainPane.showConfirmLanguageChangeMessageBar(requesting);
       defaultBrowserLanguage.value = requesting[0];
       return;
     }
-    defaultBrowserLanguage.value = Services.locale.getRequestedLocale();
+    defaultBrowserLanguage.value = Services.locale.requestedLocale;
     gMainPane.hideConfirmLanguageChangeMessageBar();
   },
 
   /**
    * Displays the translation exceptions dialog where specific site and language
    * translation preferences can be set.
    */
   showTranslationExceptions() {
--- a/browser/components/resistfingerprinting/test/chrome/test_bug1409973_date_time_format.html
+++ b/browser/components/resistfingerprinting/test/chrome/test_bug1409973_date_time_format.html
@@ -3,20 +3,20 @@
 <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 <script>
   /* globals SpecialPowers, SimpleTest */
   ChromeUtils.import("resource://gre/modules/Services.jsm");
 
   SimpleTest.waitForExplicitFinish();
 
-  const originalAvailable = Services.locale.getAvailableLocales();
-  const originalRequested = Services.locale.getRequestedLocales();
-  Services.locale.setAvailableLocales(["ko-KR"]);
-  Services.locale.setRequestedLocales(["ko-KR"]);
+  const originalAvailable = Services.locale.availableLocales;
+  const originalRequested = Services.locale.requestedLocales;
+  Services.locale.availableLocales = ["ko-KR"];
+  Services.locale.requestedLocales = ["ko-KR"];
 
   // First be sure we have a non-UTC timezone and a non en-US locale.
   var setTimeZone = SpecialPowers.Cu.getJSTestingFunctions().setTimeZone;
   setTimeZone("EST5EDT");
   // Now sanity check the defaults
   let date = new Date(2003, 4, 6, 2, 30, 15);
   // These tests should pass, but we don't enable them because every time CLDR data changed,
   // the test would start failing. We leave them here for future debugging.
@@ -53,13 +53,13 @@
       month: "numeric", day: "numeric", year: "numeric", hour: "numeric", minute: "numeric", second: "numeric",
       timeZoneName: "long",
     }).resolvedOptions();
     SimpleTest.is(options.locale, "en-US", "Resist Fingerprinting Intl.DateTimeFormat.format.locale");
     SimpleTest.is(options.timeZone, "UTC", "Resist Fingerprinting Intl.DateTimeFormat.format.timeZone");
     SimpleTest.is(options.timeZoneName, "long", "Resist Fingerprinting Intl.DateTimeFormat.format.timeZoneName");
 
     // Cleanup
-    Services.locale.setRequestedLocales(originalRequested);
-    Services.locale.setAvailableLocales(originalAvailable);
+    Services.locale.requestedLocales = originalRequested;
+    Services.locale.availableLocales = originalAvailable;
     SimpleTest.finish();
   });
 </script>
--- a/browser/components/search/test/head.js
+++ b/browser/components/search/test/head.js
@@ -17,17 +17,17 @@ function isSubObjectOf(expectedObj, actu
       isSubObjectOf(expectedObj[prop], actualObj[prop], name + "[" + prop + "]");
     } else {
       is(actualObj[prop], expectedObj[prop], name + "[" + prop + "]");
     }
   }
 }
 
 function getLocale() {
-  return Services.locale.getRequestedLocale() || undefined;
+  return Services.locale.requestedLocale || undefined;
 }
 
 function promiseEvent(aTarget, aEventName, aPreventDefault) {
   function cancelEvent(event) {
     if (aPreventDefault) {
       event.preventDefault();
     }
 
--- a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
@@ -126,18 +126,18 @@ add_task(async function testObserver() {
   Assert.equal(component.updatePanel.callCount, 3, "triggers panel update again");
 
   Services.obs.notifyObservers(null, "weave:service:login:change");
 
   Assert.ok(component.observe.calledWith(null, "weave:service:login:change"),
     "component is notified of login change");
   Assert.equal(component.updatePanel.callCount, 4, "triggers panel update again");
 
-  Services.locale.setAvailableLocales(["ab-CD"]);
-  Services.locale.setRequestedLocales(["ab-CD"]);
+  Services.locale.availableLocales = ["ab-CD"];
+  Services.locale.requestedLocales = ["ab-CD"];
 
   Assert.ok(component.updateDir.calledTwice, "locale change triggers UI direction update");
 
   Services.prefs.setIntPref("intl.uidirection", 1);
 
   Assert.equal(component.updateDir.callCount, 3, "pref change triggers UI direction update");
 });
 
--- a/browser/components/translation/Translation.jsm
+++ b/browser/components/translation/Translation.jsm
@@ -24,17 +24,17 @@ var Translation = {
   serviceUnavailable: false,
 
   supportedSourceLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"],
   supportedTargetLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"],
 
   _defaultTargetLanguage: "",
   get defaultTargetLanguage() {
     if (!this._defaultTargetLanguage) {
-      this._defaultTargetLanguage = Services.locale.getAppLocaleAsLangTag()
+      this._defaultTargetLanguage = Services.locale.appLocaleAsLangTag
                                       .split("-")[0];
     }
     return this._defaultTargetLanguage;
   },
 
   documentStateReceived(aBrowser, aData) {
     if (aData.state == this.STATE_OFFER) {
       if (aData.detectedLanguage == this.defaultTargetLanguage) {
--- a/browser/components/translation/translation-infobar.xml
+++ b/browser/components/translation/translation-infobar.xml
@@ -265,17 +265,17 @@
                      "Daha fazla bilgi al\u0131n.",
                      "Te\u015Fekk\xFCrler"],
                 vi: ["Nh\xECn n\xE0y! \u0110\u1ED3 m\u1EDBi!",
                      "Gi\u1EDD \u0111\xE2y ch\xFAng ta c\xF3 th\u1EC3 ti\u1EBFp c\u1EADn web d\u1EC5 d\xE0ng h\u01A1n n\u1EEFa v\u1EDBi t\xEDnh n\u0103ng d\u1ECBch ngay trong trang.  Hay nh\u1EA5n n\xFAt d\u1ECBch \u0111\u1EC3 th\u1EED!",
                      "T\xECm hi\u1EC3u th\xEAm.",
                      "C\u1EA3m \u01A1n"],
               };
 
-              let locale = Services.locale.getAppLocaleAsLangTag();
+              let locale = Services.locale.appLocaleAsLangTag;
               if (!(locale in localizedStrings))
                 locale = "en";
               let strings = localizedStrings[locale];
 
               this._getAnonElt("welcomeHeadline").setAttribute("value", strings[0]);
               this._getAnonElt("welcomeBody").textContent = strings[1];
               this._getAnonElt("learnMore").setAttribute("value", strings[2]);
               this._getAnonElt("thanksButton").setAttribute("label", strings[3]);
--- a/browser/extensions/formautofill/api.js
+++ b/browser/extensions/formautofill/api.js
@@ -48,17 +48,17 @@ function onMaybeOpenPopup(evt) {
   insertStyleSheet(domWindow, "resource://formautofill/autocomplete-item.css");
 }
 
 function isAvailable() {
   let availablePref = Services.prefs.getCharPref("extensions.formautofill.available");
   if (availablePref == "on") {
     return true;
   } else if (availablePref == "detect") {
-    let locale = Services.locale.getRequestedLocale();
+    let locale = Services.locale.requestedLocale;
     let region = Services.prefs.getCharPref("browser.search.region", "");
     let supportedCountries = Services.prefs.getCharPref("extensions.formautofill.supportedCountries")
                                            .split(",");
     if (!Services.prefs.getBoolPref("extensions.formautofill.supportRTL") &&
         Services.locale.isAppLocaleRTL) {
       return false;
     }
     return locale == "en-US" && supportedCountries.includes(region);
--- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
@@ -301,17 +301,17 @@ class ChromeActions {
         },
       };
 
       channel.asyncOpen2(listener);
     });
   }
 
   getLocale() {
-    return Services.locale.getRequestedLocale() || "en-US";
+    return Services.locale.requestedLocale || "en-US";
   }
 
   getStrings(data) {
     try {
       // Lazy initialization of localizedStrings
       if (!("localizedStrings" in this)) {
         this.localizedStrings = getLocalizedStrings("viewer.properties");
       }
--- a/browser/extensions/pocket/content/main.js
+++ b/browser/extensions/pocket/content/main.js
@@ -619,17 +619,17 @@ var pktUI = (function() {
         fxAccounts.getSignedInUser().then(userData => {
             callback(userData);
         }).then(null, error => {
             callback();
         });
     }
 
     function getUILocale() {
-        return Services.locale.getAppLocaleAsLangTag();
+        return Services.locale.appLocaleAsLangTag;
     }
 
     /**
      * Public functions
      */
     return {
         setPhotonPageActionPanelFrame,
         getPanelFrame,
--- a/browser/extensions/pocket/content/pktApi.jsm
+++ b/browser/extensions/pocket/content/pktApi.jsm
@@ -241,17 +241,17 @@ var pktApi = (function() {
     */
     function apiRequest(options) {
         if ((typeof options === "undefined") || (typeof options.path === "undefined")) {
             return false;
         }
 
         var url = baseAPIUrl + options.path;
         var data = options.data || {};
-        data.locale_lang = Services.locale.getAppLocaleAsLangTag();
+        data.locale_lang = Services.locale.appLocaleAsLangTag;
         data.consumer_key = oAuthConsumerKey;
 
         var request = new XMLHttpRequest();
         request.open("POST", url, true);
         request.onreadystatechange = function(e) {
             if (request.readyState == 4) {
                 if (request.status === 200) {
                     // There could still be an error if the response is no valid json
@@ -353,17 +353,17 @@ var pktApi = (function() {
                     setSetting("premium_status", premiumStatus);
                 }
 
                 // Save since value for further requests
                 setSetting("latestSince", data.since);
 
                 // Define variant for ho2
                 if (data.flags) {
-                    var showHo2 = (Services.locale.getAppLocaleAsLangTag() === "en-US") ? data.flags.show_ffx_mobile_prompt : "control";
+                    var showHo2 = (Services.locale.appLocaleAsLangTag === "en-US") ? data.flags.show_ffx_mobile_prompt : "control";
                     setSetting("test.ho2", showHo2);
                 }
                 data.ho2 = getSetting("test.ho2");
 
                 if (options.success) {
                     options.success.apply(options, Array.apply(null, arguments));
                 }
             },
--- a/browser/modules/PingCentre.jsm
+++ b/browser/modules/PingCentre.jsm
@@ -138,17 +138,17 @@ class PingCentre {
     let filter = options && options.filter;
     let experiments = TelemetryEnvironment.getActiveExperiments();
     let experimentsString = this._createExperimentsString(experiments, filter);
     if (!this.enabled) {
       return Promise.resolve();
     }
 
     let clientID = data.client_id || await this.telemetryClientId;
-    let locale = data.locale || Services.locale.getAppLocalesAsLangTags().pop();
+    let locale = data.locale || Services.locale.appLocaleAsLangTag;
     let profileCreationDate = TelemetryEnvironment.currentEnvironment.profile.resetDate ||
       TelemetryEnvironment.currentEnvironment.profile.creationDate;
     const payload = Object.assign({
       locale,
       topic: this._topic,
       client_id: clientID,
       version: AppConstants.MOZ_APP_VERSION,
       release_channel: AppConstants.MOZ_UPDATE_CHANNEL,
--- a/chrome/test/unit/test_bug848297.js
+++ b/chrome/test/unit/test_bug848297.js
@@ -20,17 +20,17 @@ chromeReg.checkForNewChrome();
 
 function enum_to_array(strings) {
   return Array.from(strings).sort();
 }
 
 function run_test() {
 
   // without override
-  Services.locale.setRequestedLocales(["de"]);
+  Services.locale.requestedLocales = ["de"];
   Assert.equal(chromeReg.getSelectedLocale("basepack"), "en-US");
   Assert.equal(chromeReg.getSelectedLocale("overpack"), "de");
   Assert.deepEqual(enum_to_array(chromeReg.getLocalesForPackage("basepack")),
                    ["en-US", "fr"]);
 
   // with override
   Services.prefs.setCharPref("chrome.override_package.basepack", "overpack");
   Assert.equal(chromeReg.getSelectedLocale("basepack"), "de");
--- a/devtools/client/aboutdebugging-new/aboutdebugging.js
+++ b/devtools/client/aboutdebugging-new/aboutdebugging.js
@@ -75,17 +75,17 @@ const AboutDebugging = {
       const temporarySource = new FileSource(
         "aboutdebugging",
         ["en-US"],
         "chrome://devtools/content/aboutdebugging-new/tmp-locale/{locale}/"
       );
       L10nRegistry.registerSource(temporarySource);
     }
 
-    const locales = Services.locale.getAppLocalesAsBCP47();
+    const locales = Services.locale.appLocalesAsBCP47;
     const generator =
       L10nRegistry.generateContexts(locales, ["aboutdebugging.ftl"]);
 
     const contexts = [];
     for await (const context of generator) {
       contexts.push(context);
     }
 
--- a/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
@@ -32,17 +32,17 @@ class Sidebar extends PureComponent {
   renderDevices() {
     const { dispatch, runtimes, selectedPage } = this.props;
     if (!runtimes.networkRuntimes.length && !runtimes.usbRuntimes.length) {
       return Localized(
         {
           id: "about-debugging-sidebar-no-devices"
         }, dom.span(
           {
-            className: "sidebar__devices__no-devices-message js-sidebar-no-devices"
+            className: "sidebar__devices__no-devices-message"
           },
           "No devices discovered"
         )
       );
     }
 
     return [
       ...runtimes.networkRuntimes.map(runtime => {
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -2,13 +2,12 @@
 tags = devtools
 subsuite = devtools
 support-files =
   debug-target-pane_collapsibilities_head.js
   head.js
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
 
-[browser_aboutdebugging_connect_networklocations.js]
 [browser_aboutdebugging_debug-target-pane_collapsibilities_interaction.js]
 [browser_aboutdebugging_debug-target-pane_collapsibilities_preference.js]
-[browser_aboutdebugging_sidebar_network_runtimes.js]
 [browser_aboutdebugging_thisfirefox.js]
+[browser_aboutdebugging_connect_networklocations.js]
deleted file mode 100644
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_sidebar_network_runtimes.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-const networkLocationsModule =
-  require("devtools/client/aboutdebugging-new/src/modules/network-locations.js");
-
-/**
- * Test the sidebar is updated correctly when network runtimes are added/removed.
- */
-
-add_task(async function() {
-  registerCleanupFunction(() => {
-    Services.prefs.clearUserPref("devtools.aboutdebugging.network-locations");
-  });
-
-  const { document, tab } = await openAboutDebugging();
-
-  const noDevicesElement = document.querySelector(".js-sidebar-no-devices");
-  ok(noDevicesElement, "Sidebar shows the 'no devices' element");
-
-  info("Add a network location");
-  networkLocationsModule.addNetworkLocation("localhost:6080");
-
-  info("Wait for 'no devices' element to disappear");
-  waitUntil(() => !document.querySelector(".js-sidebar-no-devices"));
-  ok(findSidebarItemByText("localhost:6080", document),
-    "Found a sidebar item for localhost:6080");
-
-  info("Remove the network location");
-  networkLocationsModule.removeNetworkLocation("localhost:6080");
-
-  info("Wait for 'no devices' element to reappear");
-  waitUntil(() => document.querySelector(".js-sidebar-no-devices"));
-  ok(!findSidebarItemByText("localhost:6080", document),
-    "Sidebar item for localhost:6080 removed");
-
-  await removeTab(tab);
-});
-
-function findSidebarItemByText(text, document) {
-  const sidebarItems = document.querySelectorAll(".js-sidebar-item");
-  return [...sidebarItems].find(element => {
-    return element.textContent.includes(text);
-  });
-}
--- a/devtools/client/application/initializer.js
+++ b/devtools/client/application/initializer.js
@@ -60,17 +60,17 @@ window.Application = {
     render(Provider({ store: this.store }, app), this.mount);
   },
 
   /**
    * Retrieve message contexts for the current locales, and return them as an array of
    * MessageContext elements.
    */
   async createMessageContexts() {
-    const locales = Services.locale.getAppLocalesAsBCP47();
+    const locales = Services.locale.appLocalesAsBCP47;
     const generator =
       L10nRegistry.generateContexts(locales, ["devtools/application.ftl"]);
 
     // Return value of generateContexts is a generator and should be converted to
     // a sync iterable before using it with React.
     const contexts = [];
     for await (const message of generator) {
       contexts.push(message);
--- a/devtools/client/performance-new/components/Description.js
+++ b/devtools/client/performance-new/components/Description.js
@@ -1,30 +1,24 @@
 /* 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/. */
 "use strict";
 
 const { PureComponent } = require("devtools/client/shared/vendor/react");
 const { div, button, p } = require("devtools/client/shared/vendor/react-dom-factories");
 const { openDocLink } = require("devtools/client/shared/link");
-const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
-const { connect } = require("devtools/client/shared/vendor/react-redux");
-const selectors = require("devtools/client/performance-new/store/selectors");
 
 /**
  * This component provides a helpful description for what is going on in the component
  * and provides some external links.
  */
 class Description extends PureComponent {
   static get propTypes() {
-    return {
-      // StateProps:
-      toolbox: PropTypes.object.isRequired
-    };
+    return {};
   }
 
   constructor(props) {
     super(props);
     this.handleLinkClick = this.handleLinkClick.bind(this);
   }
 
   handleLinkClick(event) {
@@ -66,13 +60,9 @@ class Description extends PureComponent 
           "github.com/devtools-html/perf.html"
         ),
         "."
       )
     );
   }
 }
 
-const mapStateToProps = state => ({
-  toolbox: selectors.getToolbox(state)
-});
-
-module.exports = connect(mapStateToProps)(Description);
+module.exports = Description;
--- a/devtools/client/performance-new/initializer.js
+++ b/devtools/client/performance-new/initializer.js
@@ -23,26 +23,25 @@ const {
   receiveProfile,
   getRecordingPreferences,
   setRecordingPreferences
 } = require("devtools/client/performance-new/browser");
 
 /**
  * Initialize the panel by creating a redux store, and render the root component.
  *
- * @param toolbox - The toolbox
  * @param perfFront - The Perf actor's front. Used to start and stop recordings.
+ * @param preferenceFront - Used to get the recording preferences from the device.
  */
-async function gInit(toolbox, perfFront, preferenceFront) {
+async function gInit(perfFront, preferenceFront) {
   const store = createStore(reducers);
 
   // Do some initialization, especially with privileged things that are part of the
   // the browser.
   store.dispatch(actions.initializeStore({
-    toolbox,
     perfFront,
     receiveProfile,
     // Pull the default recording settings from the reducer, and update them according
     // to what's in the target's preferences. This way the preferences are stored
     // on the target. This could be useful for something like Android where you might
     // want to tweak the settings.
     recordingSettingsFromPreferences: await getRecordingPreferences(
       preferenceFront,
--- a/devtools/client/performance-new/panel.js
+++ b/devtools/client/performance-new/panel.js
@@ -30,17 +30,17 @@ class PerformancePanel {
     this.panelWin.gTarget = this.target;
 
     const rootForm = await this.target.root;
     const perfFront = new PerfFront(this.target.client, rootForm);
     const preferenceFront = this.target.client.mainRoot.getFront("preference");
 
     this.isReady = true;
     this.emit("ready");
-    this.panelWin.gInit(this.toolbox, perfFront, preferenceFront);
+    this.panelWin.gInit(perfFront, preferenceFront);
     return this;
   }
 
   // DevToolPanel API:
 
   get target() {
     return this.toolbox.target;
   }
--- a/devtools/client/performance-new/store/reducers.js
+++ b/devtools/client/performance-new/store/reducers.js
@@ -124,17 +124,16 @@ function threads(state = ["GeckoMain", "
  *   receiveProfile - A function to receive the profile and open it into a new window.
  *   setRecordingPreferences - A function to set the recording settings.
  * }
  */
 function initializedValues(state = null, action) {
   switch (action.type) {
     case "INITIALIZE_STORE":
       return {
-        toolbox: action.toolbox,
         perfFront: action.perfFront,
         receiveProfile: action.receiveProfile,
         setRecordingPreferences: action.setRecordingPreferences
       };
     default:
       return state;
   }
 }
--- a/devtools/client/performance-new/store/selectors.js
+++ b/devtools/client/performance-new/store/selectors.js
@@ -25,29 +25,27 @@ const getInitializedValues = state => {
   const values = state.initializedValues;
   if (!values) {
     throw new Error("The store must be initialized before it can be used.");
   }
   return values;
 };
 
 const getPerfFront = state => getInitializedValues(state).perfFront;
-const getToolbox = state => getInitializedValues(state).toolbox;
 const getReceiveProfileFn = state => getInitializedValues(state).receiveProfile;
 const getSetRecordingPreferencesFn =
   state => getInitializedValues(state).setRecordingPreferences;
 
 module.exports = {
   getRecordingState,
   getRecordingUnexpectedlyStopped,
   getIsSupportedPlatform,
   getInterval,
   getEntries,
   getFeatures,
   getThreads,
   getThreadsString,
   getRecordingSettings,
   getInitializedValues,
   getPerfFront,
-  getToolbox,
   getReceiveProfileFn,
   getSetRecordingPreferencesFn
 };
--- a/devtools/client/performance-new/test/chrome/head.js
+++ b/devtools/client/performance-new/test/chrome/head.js
@@ -164,33 +164,31 @@ function createPerfComponent() {
   const ReactDOM = require("devtools/client/shared/vendor/react-dom");
   const ReactRedux = require("devtools/client/shared/vendor/react-redux");
   const createStore = require("devtools/client/shared/redux/create-store")();
   const reducers = require("devtools/client/performance-new/store/reducers");
   const actions = require("devtools/client/performance-new/store/actions");
   const selectors = require("devtools/client/performance-new/store/selectors");
 
   const perfFrontMock = new MockPerfFront();
-  const toolboxMock = {};
   const store = createStore(reducers);
   const container = document.querySelector("#container");
   const receiveProfileCalls = [];
   const recordingPreferencesCalls = [];
 
   function receiveProfileMock(profile) {
     receiveProfileCalls.push(profile);
   }
 
   function recordingPreferencesMock(settings) {
     recordingPreferencesCalls.push(settings);
   }
 
   function mountComponent() {
     store.dispatch(actions.initializeStore({
-      toolbox: toolboxMock,
       perfFront: perfFrontMock,
       receiveProfile: receiveProfileMock,
       recordingSettingsFromPreferences: selectors.getRecordingSettings(store.getState()),
       setRecordingPreferences: recordingPreferencesMock
     }));
 
     return ReactDOM.render(
       React.createElement(
--- a/devtools/server/tests/mochitest/test_device.html
+++ b/devtools/server/tests/mochitest/test_device.html
@@ -40,17 +40,17 @@ window.onload = function() {
         name: appInfo.name,
         version: appInfo.version,
         appbuildid: appInfo.appBuildID,
         platformbuildid: appInfo.platformBuildID,
         platformversion: appInfo.platformVersion,
         geckobuildid: appInfo.platformBuildID,
         geckoversion: appInfo.platformVersion,
         useragent: window.navigator.userAgent,
-        locale: Services.locale.getAppLocaleAsLangTag(),
+        locale: Services.locale.appLocaleAsLangTag,
         os: appInfo.OS,
         processor: appInfo.XPCOMABI.split("-")[0],
         compiler: appInfo.XPCOMABI.split("-")[1],
         dpi: utils.displayDPI,
         width: window.screen.width,
         height: window.screen.height
       };
 
--- a/devtools/shared/system.js
+++ b/devtools/shared/system.js
@@ -109,17 +109,17 @@ async function getSystemInfo() {
 
     // The version of Gecko or XULRunner platform, for example "1.8.1.19" or
     // "1.9.3pre". In "Firefox 3.7 alpha 1" the application version is "3.7a1pre"
     // while the platform version is "1.9.3pre"
     platformversion: geckoVersion,
     geckoversion: geckoVersion,
 
     // Locale used in this build
-    locale: Services.locale.getAppLocaleAsLangTag(),
+    locale: Services.locale.appLocaleAsLangTag,
 
     /**
      * Information regarding the operating system.
      */
 
     // Returns the endianness of the architecture: either "LE" or "BE"
     endianness: endianness,
 
--- a/dom/animation/test/chrome/test_animation_performance_warning.html
+++ b/dom/animation/test/chrome/test_animation_performance_warning.html
@@ -27,17 +27,17 @@
 'use strict';
 
 // This is used for obtaining localized strings.
 var gStringBundle;
 
 W3CTest.runner.requestLongerTimeout(2);
 
 const { Services } = SpecialPowers.Cu.import("resource://gre/modules/Services.jsm");
-Services.locale.setRequestedLocales(["en-US"]);
+Services.locale.requestedLocales = ["en-US"];
 
 SpecialPowers.pushPrefEnv({ "set": [
                             // Need to set devPixelsPerPx explicitly to gain
                             // consistent pixel values in warning messages
                             // regardless of platform DPIs.
                             ["layout.css.devPixelsPerPx", 1],
                           ] },
                           start);
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -7294,16 +7294,22 @@ nsIDocument::GetViewportInfo(const Scree
     mViewportSize.width = widthStr.ToInteger(&widthErrorCode);
     mViewportSize.height = heightStr.ToInteger(&heightErrorCode);
 
     // If width or height has not been set to a valid number by this point,
     // fall back to a default value.
     mValidWidth = (!widthStr.IsEmpty() && NS_SUCCEEDED(widthErrorCode) && mViewportSize.width > 0);
     mValidHeight = (!heightStr.IsEmpty() && NS_SUCCEEDED(heightErrorCode) && mViewportSize.height > 0);
 
+    // If the width is set to some unrecognized value, and there is no
+    // height set, treat it as if device-width were specified.
+    if ((!mValidWidth && !widthStr.IsEmpty()) && !mValidHeight) {
+      mAutoSize = true;
+    }
+
     mAllowZoom = true;
     nsAutoString userScalable;
     GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
 
     if ((userScalable.EqualsLiteral("0")) ||
         (userScalable.EqualsLiteral("no")) ||
         (userScalable.EqualsLiteral("false"))) {
       mAllowZoom = false;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1143,34 +1143,51 @@ NativeInterface2JSObjectAndThrowIfFailed
       Throw(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
     }
     return false;
   }
   return true;
 }
 
 bool
-TryPreserveWrapper(JSObject* obj)
+TryPreserveWrapper(JS::Handle<JSObject*> obj)
 {
   MOZ_ASSERT(IsDOMObject(obj));
 
+  // nsISupports objects are special cased because DOM proxies are nsISupports
+  // and have addProperty hooks that do more than wrapper preservation (so we
+  // don't want to call them).
   if (nsISupports* native = UnwrapDOMObjectToISupports(obj)) {
     nsWrapperCache* cache = nullptr;
     CallQueryInterface(native, &cache);
     if (cache) {
       cache->PreserveWrapper(native);
     }
     return true;
   }
 
-  // If this DOMClass is not cycle collected, then it isn't wrappercached,
-  // so it does not need to be preserved. If it is cycle collected, then
-  // we can't tell if it is wrappercached or not, so we just return false.
+  // The addProperty hook for WebIDL classes does wrapper preservation, and
+  // nothing else, so call it, if present.
   const DOMJSClass* domClass = GetDOMClass(obj);
-  return domClass && !domClass->mParticipant;
+  const JSClass* clasp = domClass->ToJSClass();
+  JSAddPropertyOp addProperty = clasp->getAddProperty();
+
+  // We expect all proxies to be nsISupports.
+  MOZ_RELEASE_ASSERT(!js::Valueify(clasp)->isProxy(), "Should not call addProperty for proxies.");
+
+  // The class should have an addProperty hook iff it is a CC participant.
+  MOZ_RELEASE_ASSERT(bool(domClass->mParticipant) == bool(addProperty));
+
+  if (!addProperty) {
+    return true;
+  }
+
+  JS::Rooted<jsid> dummyId(RootingCx());
+  JS::Rooted<JS::Value> dummyValue(RootingCx());
+  return addProperty(nullptr, obj, dummyId, dummyValue);
 }
 
 // Can only be called with a DOM JSClass.
 bool
 InstanceClassHasProtoAtDepth(const js::Class* clasp,
                              uint32_t protoID, uint32_t depth)
 {
   const DOMJSClass* domClass = DOMJSClass::FromJSClass(clasp);
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1513,17 +1513,17 @@ UpdateWrapper(T* p, void*, JSObject* obj
 // Return true if we successfully preserved the wrapper, or there is no wrapper
 // to preserve. In the latter case we don't need to preserve the wrapper, because
 // the object can only be obtained by JS once, or they cannot be meaningfully
 // owned from the native side.
 //
 // This operation will return false only for non-nsISupports cycle-collected
 // objects, because we cannot determine if they are wrappercached or not.
 bool
-TryPreserveWrapper(JSObject* obj);
+TryPreserveWrapper(JS::Handle<JSObject*> obj);
 
 // Can only be called with a DOM JSClass.
 bool
 InstanceClassHasProtoAtDepth(const js::Class* clasp,
                              uint32_t protoID, uint32_t depth);
 
 // Only set allowNativeWrapper to false if you really know you need it; if in
 // doubt use true. Setting it to false disables security wrappers.
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -143,21 +143,16 @@ public:
     return CallbackPreserveColor();
   }
 
   nsIGlobalObject* IncumbentGlobalOrNull() const
   {
     return mIncumbentGlobal;
   }
 
-  void Reset()
-  {
-    ClearJSReferences();
-  }
-
   enum ExceptionHandling {
     // Report any exception and don't throw it to the caller code.
     eReportExceptions,
     // Throw an exception to the caller code if the thrown exception is a
     // binding object for a DOMException from the caller's scope, otherwise
     // report it.
     eRethrowContentExceptions,
     // Throw exceptions to the caller code, unless the caller realm is
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -97,16 +97,19 @@ def idlTypeNeedsCycleCollection(type):
                                              type)
         return False
     elif type.isDictionary():
         return CGDictionary.dictionaryNeedsCycleCollection(type.inner)
     else:
         raise CycleCollectionUnsupported("Don't know whether to cycle-collect type %s" % type)
 
 
+# TryPreserveWrapper uses the addProperty hook to preserve the wrapper of
+# non-nsISupports cycle collected objects, so if wantsAddProperty is changed
+# to not cover that case then TryPreserveWrapper will need to be changed.
 def wantsAddProperty(desc):
     return (desc.concrete and desc.wrapperCache and not desc.isGlobal())
 
 
 # We'll want to insert the indent at the beginnings of lines, but we
 # don't want to indent empty lines.  So only indent lines that have a
 # non-newline character on them.
 lineStartDetector = re.compile("^(?=[^\n#])", re.MULTILINE)
@@ -1678,16 +1681,20 @@ class CGAddPropertyHook(CGAbstractClassH
                 Argument('JS::Handle<JSObject*>', 'obj'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('JS::Handle<JS::Value>', 'val')]
         CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
                                      'bool', args)
 
     def generate_code(self):
         assert self.descriptor.wrapperCache
+        # This hook is also called by TryPreserveWrapper on non-nsISupports
+        # cycle collected objects, so if addProperty is ever changed to do
+        # anything more or less than preserve the wrapper, TryPreserveWrapper
+        # will need to be changed.
         return dedent("""
             // We don't want to preserve if we don't have a wrapper, and we
             // obviously can't preserve if we're not initialized.
             if (self && self->GetWrapperPreserveColor()) {
               PreserveWrapper(self);
             }
             return true;
             """)
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -667,21 +667,26 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
           "nestegg_packet_additional_data failed to retrieve alpha data r=%d",
           r);
       }
     }
     bool isKeyframe = false;
     if (aType == TrackInfo::kAudioTrack) {
       isKeyframe = true;
     } else if (aType == TrackInfo::kVideoTrack) {
-      if (packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED) {
+      if (packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED ||
+          packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_PARTITIONED) {
         // Packet is encrypted, can't peek, use packet info
         isKeyframe = nestegg_packet_has_keyframe(holder->Packet())
                      == NESTEGG_PACKET_HAS_KEYFRAME_TRUE;
       } else {
+        MOZ_ASSERT(packetEncryption ==
+                       NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED ||
+                     packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE,
+                   "Unencrypted packet expected");
         auto sample = MakeSpan(data, length);
         auto alphaSample = MakeSpan(alphaData, alphaLength);
 
         switch (mVideoCodec) {
         case NESTEGG_CODEC_VP8:
           isKeyframe = VPXDecoder::IsKeyframe(sample, VPXDecoder::Codec::VP8);
           if (isKeyframe && alphaLength) {
             isKeyframe =
--- a/dom/tests/mochitest/chrome/test_intlUtils_getLocaleInfo.html
+++ b/dom/tests/mochitest/chrome/test_intlUtils_getLocaleInfo.html
@@ -13,18 +13,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
 <script>
 
 const localeService =
   Cc["@mozilla.org/intl/localeservice;1"].getService(Ci.mozILocaleService);
 const mozIntl = Cc["@mozilla.org/mozintl;1"].getService(Ci.mozIMozIntl);
 
-let rpLocale = localeService.negotiateLanguages(localeService.getRegionalPrefsLocales(),
-                                                localeService.getAvailableLocales())[0];
+let rpLocale = localeService.negotiateLanguages(localeService.regionalPrefsLocales,
+                                                localeService.availableLocales)[0];
 
 let testData = [
   {
     locales: ["en-US"],
     expected: {
       locale: "en-US",
       direction: "ltr",
     }
--- a/dom/tests/mochitest/chrome/test_window_getRegionalPrefsLocales.html
+++ b/dom/tests/mochitest/chrome/test_window_getRegionalPrefsLocales.html
@@ -13,16 +13,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
 <script>
 
 const localeService =
   Cc["@mozilla.org/intl/localeservice;1"].getService(Ci.mozILocaleService);
 
 let rpLocales = localeService.negotiateLanguages(window.getRegionalPrefsLocales(),
-                                                 localeService.getAvailableLocales());
+                                                 localeService.availableLocales);
 
 ok(rpLocales.length > 0, "getRegionalPrefsLocales returns at least one locale.");
 is(rpLocales[0], "en-US", "The first regional prefs locale should resolve to en-US.");
 
 </script>
 </body>
 </html>
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -908,17 +908,17 @@ InitJSContextForWorker(WorkerPrivate* aW
 #ifdef JS_GC_ZEAL
   JS_SetGCZeal(aWorkerCx, settings.gcZeal, settings.gcZealFrequency);
 #endif
 
   return true;
 }
 
 static bool
-PreserveWrapper(JSContext *cx, JSObject *obj)
+PreserveWrapper(JSContext *cx, JS::HandleObject obj)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(obj);
     MOZ_ASSERT(mozilla::dom::IsDOMObject(obj));
 
     return mozilla::dom::TryPreserveWrapper(obj);
 }
 
--- a/dom/worklet/WorkletThread.cpp
+++ b/dom/worklet/WorkletThread.cpp
@@ -25,17 +25,17 @@ namespace {
 
 // The C stack size. We use the same stack size on all platforms for
 // consistency.
 const uint32_t kWorkletStackSize = 256 * sizeof(size_t) * 1024;
 
 // Helper functions
 
 bool
-PreserveWrapper(JSContext* aCx, JSObject* aObj)
+PreserveWrapper(JSContext* aCx, JS::HandleObject aObj)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aObj);
   MOZ_ASSERT(mozilla::dom::IsDOMObject(aObj));
   return mozilla::dom::TryPreserveWrapper(aObj);
 }
 
 void
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -52,30 +52,28 @@ InputBlockState::SetConfirmedTargetApzc(
     // confirmation, but we want to update the state internally so that we
     // can record the time for telemetry purposes.
     mTargetConfirmed = TargetConfirmationState::eTimedOutAndMainThreadResponded;
   }
   // Sometimes, bugs in compositor hit testing can lead to APZ confirming
   // a different target than the main thread. If this happens for a drag
   // block created for a scrollbar drag, the consequences can be fairly
   // user-unfriendly, such as the scrollbar not being draggable at all,
-  // or it scrolling the contents of the wrong scrollframe. In Nightly
-  // builds, we issue a diagnostic assert in this situation, so that the
+  // or it scrolling the contents of the wrong scrollframe. In debug
+  // builds, we assert in this situation, so that the
   // underlying compositor hit testing bug can be fixed. In release builds,
   // however, we just silently accept the main thread's confirmed target,
   // which will produce the expected behaviour (apart from drag events
   // received so far being dropped).
   if (AsDragBlock() && aForScrollbarDrag &&
       mTargetConfirmed == TargetConfirmationState::eConfirmed &&
       aState == TargetConfirmationState::eConfirmed &&
       mTargetApzc && aTargetApzc &&
       mTargetApzc->GetGuid() != aTargetApzc->GetGuid()) {
-#ifdef NIGHTLY_BUILD
-    MOZ_RELEASE_ASSERT(false, "APZ and main thread confirmed scrollbar drag block with different targets");
-#endif
+    MOZ_ASSERT(false, "APZ and main thread confirmed scrollbar drag block with different targets");
     UpdateTargetApzc(aTargetApzc);
     return true;
   }
 
   if (mTargetConfirmed != TargetConfirmationState::eUnconfirmed) {
     return false;
   }
   mTargetConfirmed = aState;
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1183,32 +1183,32 @@ WebRenderCommandBuilder::DoGroupingForDi
   GP("Bounds: %d %d %d %d vs %d %d %d %d\n", p.x, p.y, p.width, p.height, q.x, q.y, q.width, q.height);
   if (!group.mGroupBounds.IsEqualEdges(groupBounds) ||
       group.mAppUnitsPerDevPixel != appUnitsPerDevPixel ||
       group.mScale != scale ||
       group.mResidualOffset != residualOffset) {
     GP("Property change. Deleting blob\n");
 
     if (group.mAppUnitsPerDevPixel != appUnitsPerDevPixel) {
-      GP(" app unit change%d %d\n", group.mAppUnitsPerDevPixel, appUnitsPerDevPixel);
+      GP(" App unit change %d -> %d\n", group.mAppUnitsPerDevPixel, appUnitsPerDevPixel);
     }
     // The bounds have changed so we need to discard the old image and add all
     // the commands again.
     auto p = group.mGroupBounds;
     auto q = groupBounds;
     if (!group.mGroupBounds.IsEqualEdges(groupBounds)) {
-      GP(" Bounds change: %d %d %d %d vs %d %d %d %d\n", p.x, p.y, p.width, p.height, q.x, q.y, q.width, q.height);
+      GP(" Bounds change: %d %d %d %d -> %d %d %d %d\n", p.x, p.y, p.width, p.height, q.x, q.y, q.width, q.height);
     }
 
     if (group.mScale != scale) {
-      GP(" Scale %f %f vs %f %f\n", group.mScale.width, group.mScale.height, scale.width, scale.height);
+      GP(" Scale %f %f -> %f %f\n", group.mScale.width, group.mScale.height, scale.width, scale.height);
     }
 
     if (group.mResidualOffset != residualOffset) {
-      GP(" Residual Offset %f %f vs %f %f\n", group.mResidualOffset.x, group.mResidualOffset.y, residualOffset.x, residualOffset.y);
+      GP(" Residual Offset %f %f -> %f %f\n", group.mResidualOffset.x, group.mResidualOffset.y, residualOffset.x, residualOffset.y);
     }
 
     group.ClearItems();
     group.ClearImageKey(mManager);
   }
 
   FrameMetrics::ViewID scrollId = FrameMetrics::NULL_SCROLL_ID;
   if (const ActiveScrolledRoot* asr = aWrappingItem->GetActiveScrolledRoot()) {
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -1283,17 +1283,17 @@ gfxPlatformFontList::AppendCJKPrefLangs(
         prefLocales.AppendElement(NS_LITERAL_CSTRING("zh-HK"));
         prefLocales.AppendElement(NS_LITERAL_CSTRING("ko"));
 
         AutoTArray<nsCString,16> sysLocales;
         AutoTArray<nsCString,16> negLocales;
         if (OSPreferences::GetInstance()->GetSystemLocales(sysLocales)) {
             LocaleService::GetInstance()->NegotiateLanguages(
                 sysLocales, prefLocales, NS_LITERAL_CSTRING(""),
-                LocaleService::LangNegStrategy::Filtering, negLocales);
+                LocaleService::kLangNegStrategyFiltering, negLocales);
             for (const auto& localeStr : negLocales) {
                 Locale locale(localeStr);
 
                 if (locale.GetLanguage().Equals("ja")) {
                     AppendPrefLang(tempPrefLangs, tempLen,
                                    eFontPrefLang_Japanese);
                 } else if (locale.GetLanguage().Equals("zh")) {
                     if (locale.GetRegion().Equals("CN")) {
--- a/intl/docs/locale.rst
+++ b/intl/docs/locale.rst
@@ -328,33 +328,32 @@ localized resources for one or more lang
 
 The primary notion of which locales are available is based on which locales Gecko has
 UI localization resources for, and other datasets such as internationalization may
 carry different lists of available locales.
 
 Requested Locales
 =================
 
-The list of requested locales can be read using :js:`LocaleService::GetRequestedLocales` API,
-and set using :js:`LocaleService::SetRequestedLocales` API.
+The list of requested locales can be read and set using :js:`LocaleService::requestedLocales` API.
 
 Using the API will perform necessary sanity checks and canonicalize the values.
 
 After the sanitization, the value will be stored in a pref :js:`intl.locale.requested`.
 The pref usually will store a comma separated list of valid BCP47 locale
 codes, but it can also have two special meanings:
 
  - If the pref is not set at all, Gecko will use the default locale as the requested one.
  - If the pref is set to an empty string, Gecko will look into OS app locales as the requested.
 
 The former is the current default setting for Firefox Desktop, and the latter is the
 default setting for Firefox for Android.
 
 If the developer wants to programmatically request the app to follow OS locales,
-they can call the :js:`SetRequestedLocales` API with no argument.
+they can assign :js:`null` to :js:`requestedLocales`.
 
 Regional Preferences
 ====================
 
 Every locale comes with a set of default preferences that are specific to a culture
 and region. This contains preferences such as calendar system, way to display
 time (24h vs 12h clock), which day the week starts on, which days constitute a weekend,
 what numbering system and date time formatting a given locale uses
@@ -445,18 +444,18 @@ To check the mode the process is operati
 Mozilla Exceptions
 ==================
 
 There's currently only a single exception of the BCP47 used, and that's
 a legacy "ja-JP-mac" locale. The "mac" is a variant and BCP47 requires all variants
 to be 5-8 character long.
 
 Gecko supports the limitation by accepting the 3-letter variants in our APIs and also
-provides a special :js:`GetAppLocalesAsLangTags` method which returns this locale in that form.
-(:js:`GetAppLocalesAsBCP47` will canonicalize it and turn into `"ja-JP-macos"`).
+provides a special :js:`appLocalesAsLangTags` method which returns this locale in that form.
+(:js:`appLocalesAsBCP47` will canonicalize it and turn into `"ja-JP-macos"`).
 
 Usage of language negotiation etc. shouldn't rely on this behavior.
 
 Events
 ======
 
 :js:`LocaleService` emits two events: :js:`intl:app-locales-changed` and
 :js:`intl:requested-locales-changed` which all code can listen to.
@@ -502,41 +501,41 @@ It may look like this:
 
     fs.cache = {
       "resource://mock-addon/localization/ko-KR/test.ftl": "key = Value in Korean",
       "resource://mock-addon/localization/ar/test.ftl": "key = Value in Arabic"
     };
 
     L10nRegistry.registerSource(fs);
 
-    let availableLocales = Services.locale.getAvailableLocales();
+    let availableLocales = Services.locale.availableLocales;
 
     assert(availableLocales.includes("ko-KR"));
     assert(availableLocales.includes("ar"));
 
-    Services.locale.setRequestedLocales(["ko-KR");
+    Services.locale.requestedLocales = ["ko-KR"];
 
-    let appLocales = Services.locale.getAppLocalesAsBCP47();
+    let appLocales = Services.locale.appLocalesAsBCP47;
     assert(appLocales[0], "ko-KR");
 
 From here, a resource :js:`test.ftl` can be added to a `Localization` and for ID :js:`key`
 the correct value from the mocked cache will be returned.
 
 Testing Locale Switching
 ------------------------
 
 The second method is much more limited, as it only mocks the locale availability,
 but it is also simpler:
 
 .. code-block:: javascript
 
-    Services.locale.setAvailableLocales(["ko-KR", "ar"]);
-    Services.locale.setRequestedLocales(["ko-KR"]);
+    Services.locale.availableLocales = ["ko-KR", "ar"];
+    Services.locale.requestedLocales = ["ko-KR"];
 
-    let appLocales = Services.locale.getAppLocalesAsBCP47();
+    let appLocales = Services.locale.appLocalesAsBCP47;
     assert(appLocales[0], "ko-KR");
 
 In the future, Mozilla plans to add a third way for add-ons (`bug 1440969`_)
 to allow for either manual or automated testing purposes disconnecting its locales
 from the main application ones.
 
 Testing the outcome
 -------------------
--- a/intl/l10n/DOMLocalization.jsm
+++ b/intl/l10n/DOMLocalization.jsm
@@ -576,17 +576,17 @@ class DOMLocalization extends Localizati
     return Promise.all(
       roots.map(async root => {
         // We want to first retranslate the UI, and
         // then (potentially) flip the directionality.
         //
         // This means that the DOM alternations and directionality
         // are set in the same microtask.
         await this.translateFragment(root);
-        let primaryLocale = Services.locale.getAppLocaleAsBCP47();
+        let primaryLocale = Services.locale.appLocaleAsBCP47;
         let direction = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
         root.setAttribute("lang", primaryLocale);
         root.setAttribute(root.namespaceURI ===
           "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           ? "localedir" : "dir", direction);
       })
     );
   }
--- a/intl/l10n/L10nRegistry.jsm
+++ b/intl/l10n/L10nRegistry.jsm
@@ -116,43 +116,43 @@ const L10nRegistry = {
    *
    * @param {FileSource} source
    */
   registerSource(source) {
     if (this.sources.has(source.name)) {
       throw new Error(`Source with name "${source.name}" already registered.`);
     }
     this.sources.set(source.name, source);
-    Services.locale.setAvailableLocales(this.getAvailableLocales());
+    Services.locale.availableLocales = this.getAvailableLocales();
   },
 
   /**
    * Updates an existing source in the L10nRegistry
    *
    * That will usually happen when a new version of a source becomes
    * available (for example, an updated version of a language pack).
    *
    * @param {FileSource} source
    */
   updateSource(source) {
     if (!this.sources.has(source.name)) {
       throw new Error(`Source with name "${source.name}" is not registered.`);
     }
     this.sources.set(source.name, source);
-    Services.locale.setAvailableLocales(this.getAvailableLocales());
+    Services.locale.availableLocales = this.getAvailableLocales();
   },
 
   /**
    * Removes a source from the L10nRegistry.
    *
    * @param {String} sourceId
    */
   removeSource(sourceName) {
     this.sources.delete(sourceName);
-    Services.locale.setAvailableLocales(this.getAvailableLocales());
+    Services.locale.availableLocales = this.getAvailableLocales();
   },
 
   /**
    * Returns a list of locales for which at least one source
    * has resources.
    *
    * @returns {Array<String>}
    */
--- a/intl/l10n/Localization.jsm
+++ b/intl/l10n/Localization.jsm
@@ -130,17 +130,17 @@ class CachedAsyncIterable extends Cached
  * available in L10nRegistry, with locales requested by the user to
  * generate the iterator over MessageContexts.
  *
  * In the future, we may want to allow certain modules to override this
  * with a different negotitation strategy to allow for the module to
  * be localized into a different language - for example DevTools.
  */
 function defaultGenerateMessages(resourceIds) {
-  const appLocales = Services.locale.getAppLocalesAsBCP47();
+  const appLocales = Services.locale.appLocalesAsBCP47;
   return L10nRegistry.generateContexts(appLocales, resourceIds);
 }
 
 /**
  * The `Localization` class is a central high-level API for vanilla
  * JavaScript use of Fluent.
  * It combines language negotiation, MessageContext and I/O to
  * provide a scriptable API to format translations.
@@ -330,17 +330,17 @@ class Localization {
     this.ctxs = CachedAsyncIterable.from(
       this.generateMessages(this.resourceIds));
     if (eager) {
       // If the first app locale is the same as last fallback
       // it means that we have all resources in this locale, and
       // we want to eagerly fetch just that one.
       // Otherwise, we're in a scenario where the first locale may
       // be partial and we want to eagerly fetch a fallback as well.
-      const appLocale = Services.locale.getAppLocaleAsBCP47();
+      const appLocale = Services.locale.appLocaleAsBCP47;
       const lastFallback = Services.locale.lastFallbackLocale;
       const prefetchCount = appLocale === lastFallback ? 1 : 2;
       this.ctxs.touchNext(prefetchCount);
     }
   }
 }
 
 Localization.prototype.QueryInterface = ChromeUtils.generateQI([
--- a/intl/l10n/test/dom/test_mozdom_translateElements.html
+++ b/intl/l10n/test/dom/test_mozdom_translateElements.html
@@ -17,17 +17,17 @@
   const fs = {
     "/localization/en-US/browser/menu.ftl": `
 title = Hello World
 link =
   .title = Click me
 `,
   };
   const originalLoad = L10nRegistry.load;
-  const originalRequested = Services.locale.getRequestedLocales();
+  const originalRequested = Services.locale.requestedLocales;
 
   L10nRegistry.load = async function(url) {
     return fs.hasOwnProperty(url) ? fs[url] : false;
   };
 
   const source = new FileSource("test", ["en-US"], "/localization/{locale}");
   L10nRegistry.registerSource(source);
 
@@ -42,17 +42,17 @@ link =
     await domLocalization.translateElements([p1, link1], 2);
 
     is(p1.textContent, "Hello World");
     is(link1.getAttribute("title"), "Click me");
 
     // Cleanup
     L10nRegistry.removeSource(source.name);
     L10nRegistry.load = originalLoad;
-    Services.locale.setRequestedLocales(originalRequested);
+    Services.locale.requestedLocales = originalRequested;
 
     SimpleTest.finish();
   };
   </script>
 </head>
 <body>
   <p data-l10n-id="title" />
   <a data-l10n-id="link" />
--- a/intl/l10n/test/dom/test_mozdom_translateFragment.html
+++ b/intl/l10n/test/dom/test_mozdom_translateFragment.html
@@ -16,17 +16,17 @@
 
   const fs = {
     "/localization/en-US/browser/menu.ftl": `
 title = Hello World
 subtitle = Welcome to Fluent
 `,
   };
   const originalLoad = L10nRegistry.load;
-  const originalRequested = Services.locale.getRequestedLocales();
+  const originalRequested = Services.locale.requestedLocales;
 
   L10nRegistry.load = async function(url) {
     return fs.hasOwnProperty(url) ? fs[url] : false;
   };
 
   const source = new FileSource("test", ["en-US"], "/localization/{locale}");
   L10nRegistry.registerSource(source);
 
@@ -41,17 +41,17 @@ subtitle = Welcome to Fluent
 
     await domLocalization.translateFragment(frag);
     is(h1.textContent, "Hello World");
     is(p1.textContent, "Welcome to Fluent");
 
     // Cleanup
     L10nRegistry.removeSource(source.name);
     L10nRegistry.load = originalLoad;
-    Services.locale.setRequestedLocales(originalRequested);
+    Services.locale.requestedLocales = originalRequested;
 
     SimpleTest.finish();
   };
   </script>
 </head>
 <body>
   <div>
     <h1 data-l10n-id="title" />
--- a/intl/l10n/test/dom/test_mozdom_translateRoots.html
+++ b/intl/l10n/test/dom/test_mozdom_translateRoots.html
@@ -16,17 +16,17 @@
 
   const fs = {
     "/localization/en-US/browser/menu.ftl": `
 title = Hello World
 title2 = Hello Another World
 `,
   };
   const originalLoad = L10nRegistry.load;
-  const originalRequested = Services.locale.getRequestedLocales();
+  const originalRequested = Services.locale.requestedLocales;
 
   L10nRegistry.load = async function(url) {
     return fs.hasOwnProperty(url) ? fs[url] : false;
   };
 
   const source = new FileSource("test", ["en-US"], "/localization/{locale}");
   L10nRegistry.registerSource(source);
 
@@ -46,17 +46,17 @@ title2 = Hello Another World
     await domLocalization.translateRoots();
 
     is(h1.textContent, "Hello World");
     is(h2.textContent, "Hello Another World");
 
     // Cleanup
     L10nRegistry.removeSource(source.name);
     L10nRegistry.load = originalLoad;
-    Services.locale.setRequestedLocales(originalRequested);
+    Services.locale.requestedLocales = originalRequested;
 
     SimpleTest.finish();
   };
   </script>
 </head>
 <body>
   <div>
     <h1 data-l10n-id="title"></h1>
--- a/intl/l10n/test/test_localization.js
+++ b/intl/l10n/test/test_localization.js
@@ -15,17 +15,17 @@ add_task(async function test_methods_cal
   const { L10nRegistry, FileSource } =
     ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
 
   const fs = {
     "/localization/de/browser/menu.ftl": "key = [de] Value2",
     "/localization/en-US/browser/menu.ftl": "key = [en] Value2\nkey2 = [en] Value3",
   };
   const originalLoad = L10nRegistry.load;
-  const originalRequested = Services.locale.getRequestedLocales();
+  const originalRequested = Services.locale.requestedLocales;
 
   L10nRegistry.load = async function(url) {
     return fs[url];
   };
 
   const source = new FileSource("test", ["de", "en-US"], "/localization/{locale}");
   L10nRegistry.registerSource(source);
 
@@ -39,17 +39,17 @@ add_task(async function test_methods_cal
 
   let values = await l10n.formatValues([{id: "key"}, {id: "key2"}]);
 
   equal(values[0], "[de] Value2");
   equal(values[1], "[en] Value3");
 
   L10nRegistry.sources.clear();
   L10nRegistry.load = originalLoad;
-  Services.locale.setRequestedLocales(originalRequested);
+  Services.locale.requestedLocales = originalRequested;
 });
 
 add_task(async function test_builtins() {
   const { L10nRegistry, FileSource } =
     ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
 
   const known_platforms = {
     "linux": "linux",
@@ -96,17 +96,17 @@ add_task(async function test_add_remove_
   const { L10nRegistry, FileSource } =
     ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
 
   const fs = {
     "/localization/en-US/browser/menu.ftl": "key1 = Value1",
     "/localization/en-US/toolkit/menu.ftl": "key2 = Value2",
   };
   const originalLoad = L10nRegistry.load;
-  const originalRequested = Services.locale.getRequestedLocales();
+  const originalRequested = Services.locale.requestedLocales;
 
   L10nRegistry.load = async function(url) {
     return fs[url];
   };
 
   const source = new FileSource("test", ["en-US"], "/localization/{locale}");
   L10nRegistry.registerSource(source);
 
@@ -132,10 +132,10 @@ add_task(async function test_add_remove_
 
   values = await l10n.formatValues([{id: "key1"}, {id: "key2"}]);
 
   equal(values[0], undefined);
   equal(values[1], "Value2");
 
   L10nRegistry.sources.clear();
   L10nRegistry.load = originalLoad;
-  Services.locale.setRequestedLocales(originalRequested);
+  Services.locale.requestedLocales = originalRequested;
 });
--- a/intl/l10n/test/test_mozdomlocalization.js
+++ b/intl/l10n/test/test_mozdomlocalization.js
@@ -5,17 +5,17 @@ const domLocalization =
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
 const { L10nRegistry, FileSource } =
   ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
 
 const fs = {
   "/localization/en-US/browser/menu.ftl": "key = [en] Value",
 };
 const originalLoad = L10nRegistry.load;
-const originalRequested = Services.locale.getRequestedLocales();
+const originalRequested = Services.locale.requestedLocales;
 
 // Variable used to test for `L10nRegistry.load`
 // execution count.
 let loadCounter = 0;
 
 L10nRegistry.load = async function(url) {
   loadCounter++;
   return fs.hasOwnProperty(url) ? fs[url] : false;
@@ -87,10 +87,10 @@ add_task(async function test_format_valu
 add_task(async function test_ready() {
   await domLocalization.ready;
   equal(1, 1);
 });
 
 add_task(function cleanup() {
   L10nRegistry.sources.clear();
   L10nRegistry.load = originalLoad;
-  Services.locale.setRequestedLocales(originalRequested);
+  Services.locale.requestedLocales = originalRequested;
 });
--- a/intl/l10n/test/test_pseudo.js
+++ b/intl/l10n/test/test_pseudo.js
@@ -12,17 +12,17 @@ function addMockFileSource() {
 
   const fs = {
     "/localization/de/browser/menu.ftl": `
 key = This is a single message
     .tooltip = This is a tooltip
     .accesskey = f`,
   };
   originalValues.load = L10nRegistry.load;
-  originalValues.requested = Services.locale.getRequestedLocales();
+  originalValues.requested = Services.locale.requestedLocales;
 
   L10nRegistry.load = async function(url) {
     return fs[url];
   };
 
   const source = new FileSource("test", ["de"], "/localization/{locale}");
   L10nRegistry.registerSource(source);
 
@@ -90,17 +90,17 @@ add_task(async function test_accented_wo
 
     ok(message.value.includes("This is a single message"));
     ok(message.attributes[0].value.includes("This is a tooltip"));
     equal(message.attributes[1].value, "f");
   }
 
   L10nRegistry.sources.clear();
   L10nRegistry.load = originalValues.load;
-  Services.locale.setRequestedLocales(originalValues.requested);
+  Services.locale.requestedLocales = originalValues.requested;
 });
 
 /**
  * This test verifies that setting a bogus pseudo locale
  * strategy doesn't break anything.
  */
 add_task(async function test_unavailable_strategy_works() {
   Services.prefs.setStringPref("intl.l10n.pseudo", "");
@@ -121,10 +121,10 @@ add_task(async function test_unavailable
     ok(message.value.includes("This is a single message"));
     ok(message.attributes[0].value.includes("This is a tooltip"));
     equal(message.attributes[1].value, "f");
   }
 
   Services.prefs.setStringPref("intl.l10n.pseudo", "");
   L10nRegistry.sources.clear();
   L10nRegistry.load = originalValues.load;
-  Services.locale.setRequestedLocales(originalValues.requested);
+  Services.locale.requestedLocales = originalValues.requested;
 });
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -92,17 +92,17 @@ SplitLocaleListStringIntoArray(nsACStrin
         if (!aRetVal.Contains(locale)) {
           aRetVal.AppendElement(locale);
         }
       }
     }
   }
 }
 
-static bool
+static void
 ReadRequestedLocales(nsTArray<nsCString>& aRetVal)
 {
   nsAutoCString str;
   nsresult rv = Preferences::GetCString(REQUESTED_LOCALES_PREF, str);
 
   // We handle three scenarios here:
   //
   // 1) The pref is not set - use default locale
@@ -111,23 +111,26 @@ ReadRequestedLocales(nsTArray<nsCString>
   if (NS_SUCCEEDED(rv)) {
     if (str.Length() == 0) {
       // If the pref string is empty, we'll take requested locales
       // from the OS.
       OSPreferences::GetInstance()->GetSystemLocales(aRetVal);
     } else {
       SplitLocaleListStringIntoArray(str, aRetVal);
     }
-  } else {
+  }
+
+  // This will happen when either the pref is not set,
+  // or parsing of the pref didn't produce any usable
+  // result.
+  if (aRetVal.IsEmpty()) {
     nsAutoCString defaultLocale;
     LocaleService::GetInstance()->GetDefaultLocale(defaultLocale);
     aRetVal.AppendElement(defaultLocale);
   }
-
-  return true;
 }
 
 LocaleService::LocaleService(bool aIsServer)
   :mIsServer(aIsServer)
 {
 }
 
 /**
@@ -143,17 +146,17 @@ LocaleService::NegotiateAppLocales(nsTAr
     nsAutoCString defaultLocale;
     AutoTArray<nsCString, 100> availableLocales;
     AutoTArray<nsCString, 10> requestedLocales;
     GetDefaultLocale(defaultLocale);
     GetAvailableLocales(availableLocales);
     GetRequestedLocales(requestedLocales);
 
     NegotiateLanguages(requestedLocales, availableLocales, defaultLocale,
-                       LangNegStrategy::Filtering, aRetVal);
+                       kLangNegStrategyFiltering, aRetVal);
   }
 
   nsAutoCString lastFallbackLocale;
   GetLastFallbackLocale(lastFallbackLocale);
 
   if (!aRetVal.Contains(lastFallbackLocale)) {
     // This part is used in one of the two scenarios:
     //
@@ -198,82 +201,16 @@ LocaleService::~LocaleService()
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->RemoveObserver(this, INTL_SYSTEM_LOCALES_CHANGED);
     }
   }
 }
 
 void
-LocaleService::GetAppLocalesAsLangTags(nsTArray<nsCString>& aRetVal)
-{
-  if (mAppLocales.IsEmpty()) {
-    NegotiateAppLocales(mAppLocales);
-  }
-  for (uint32_t i = 0; i < mAppLocales.Length(); i++) {
-    nsAutoCString locale(mAppLocales[i]);
-    if (locale.LowerCaseEqualsASCII("ja-jp-macos")) {
-      aRetVal.AppendElement("ja-JP-mac");
-    } else {
-      aRetVal.AppendElement(locale);
-    }
-  }
-}
-
-void
-LocaleService::GetAppLocalesAsBCP47(nsTArray<nsCString>& aRetVal)
-{
-  if (mAppLocales.IsEmpty()) {
-    NegotiateAppLocales(mAppLocales);
-  }
-  aRetVal = mAppLocales;
-}
-
-void
-LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
-{
-  bool useOSLocales = Preferences::GetBool("intl.regional_prefs.use_os_locales", false);
-
-  // If the user specified that they want to use OS Regional Preferences locales,
-  // try to retrieve them and use.
-  if (useOSLocales) {
-    if (OSPreferences::GetInstance()->GetRegionalPrefsLocales(aRetVal)) {
-      return;
-    }
-
-    // If we fail to retrieve them, return the app locales.
-    GetAppLocalesAsBCP47(aRetVal);
-    return;
-  }
-
-  // Otherwise, fetch OS Regional Preferences locales and compare the first one
-  // to the app locale. If the language subtag matches, we can safely use
-  // the OS Regional Preferences locale.
-  //
-  // This facilitates scenarios such as Firefox in "en-US" and User sets
-  // regional prefs to "en-GB".
-  nsAutoCString appLocale;
-  AutoTArray<nsCString, 10> regionalPrefsLocales;
-  LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
-
-  if (!OSPreferences::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales)) {
-    GetAppLocalesAsBCP47(aRetVal);
-    return;
-  }
-
-  if (LocaleService::LanguagesMatch(appLocale, regionalPrefsLocales[0])) {
-    aRetVal = regionalPrefsLocales;
-    return;
-  }
-
-  // Otherwise use the app locales.
-  GetAppLocalesAsBCP47(aRetVal);
-}
-
-void
 LocaleService::AssignAppLocales(const nsTArray<nsCString>& aAppLocales)
 {
   MOZ_ASSERT(!mIsServer, "This should only be called for LocaleService in client mode.");
 
   mAppLocales = aAppLocales;
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "intl:app-locales-changed", nullptr);
@@ -287,46 +224,16 @@ LocaleService::AssignRequestedLocales(co
 
   mRequestedLocales = aRequestedLocales;
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "intl:requested-locales-changed", nullptr);
   }
 }
 
-bool
-LocaleService::GetRequestedLocales(nsTArray<nsCString>& aRetVal)
-{
-  if (mRequestedLocales.IsEmpty()) {
-    ReadRequestedLocales(mRequestedLocales);
-  }
-
-  aRetVal = mRequestedLocales;
-  return true;
-}
-
-bool
-LocaleService::GetAvailableLocales(nsTArray<nsCString>& aRetVal)
-{
-  MOZ_ASSERT(mIsServer, "This should only be called in the server mode.");
-  if (!mIsServer) {
-    return false;
-  }
-
-  if (mAvailableLocales.IsEmpty()) {
-    // If there are no available locales set, it means that L10nRegistry
-    // did not register its locale pool yet. The best course of action
-    // is to use packaged locales until that happens.
-    GetPackagedLocales(mAvailableLocales);
-  }
-
-  aRetVal = mAvailableLocales;
-  return true;
-}
-
 void
 LocaleService::RequestedLocalesChanged()
 {
   MOZ_ASSERT(mIsServer, "This should only be called in the server mode.");
 
   nsTArray<nsCString> newLocales;
   ReadRequestedLocales(newLocales);
 
@@ -363,21 +270,21 @@ LocaleService::LocalesChanged()
 }
 
 // After trying each step of the negotiation algorithm for each requested locale,
 // if a match was found we use this macro to decide whether to return immediately,
 // skip to the next requested locale, or continue searching for additional matches,
 // according to the desired negotiation strategy.
 #define HANDLE_STRATEGY \
           switch (aStrategy) { \
-            case LangNegStrategy::Lookup: \
+            case kLangNegStrategyLookup: \
               return; \
-            case LangNegStrategy::Matching: \
+            case kLangNegStrategyMatching: \
               continue; \
-            case LangNegStrategy::Filtering: \
+            case kLangNegStrategyFiltering: \
               break; \
           }
 
 /**
  * This is the raw algorithm for language negotiation based roughly
  * on RFC4647 language filtering, with changes from LDML language matching.
  *
  * The exact algorithm is custom, and consists of a 6 level strategy:
@@ -415,31 +322,30 @@ LocaleService::LocalesChanged()
  *               ^^^^^
  *               |----- replace region with range: 'en-*'
  *
  * It uses one of the strategies described in LocaleService.h.
  */
 void
 LocaleService::FilterMatches(const nsTArray<nsCString>& aRequested,
                              const nsTArray<nsCString>& aAvailable,
-                             LangNegStrategy aStrategy,
+                             int32_t aStrategy,
                              nsTArray<nsCString>& aRetVal)
 {
   // Local copy of the list of available locales, in Locale form for flexible
   // matching. We will invalidate entries in this list when they are matched
   // and the corresponding strings from aAvailable added to aRetVal, so that
   // no available locale will be found more than once.
   AutoTArray<Locale, 100> availLocales;
   for (auto& avail : aAvailable) {
     availLocales.AppendElement(Locale(avail));
   }
 
   for (auto& requested : aRequested) {
     if (requested.IsEmpty()) {
-      MOZ_ASSERT(!requested.IsEmpty(), "Locale string cannot be empty.");
       continue;
     }
 
     // 1) Try to find a simple (case-insensitive) string match for the request.
     auto matchesExactly = [&](Locale& aLoc) {
       return requested.Equals(aLoc.AsString(),
                               nsCaseInsensitiveCStringComparator());
     };
@@ -461,17 +367,17 @@ LocaleService::FilterMatches(const nsTAr
       };
       bool foundMatch = false;
       auto match = availLocales.begin();
       while ((match = std::find_if(match, availLocales.end(),
                                    matchesRange)) != availLocales.end()) {
         aRetVal.AppendElement(aAvailable[match - availLocales.begin()]);
         match->Invalidate();
         foundMatch = true;
-        if (aStrategy != LangNegStrategy::Filtering) {
+        if (aStrategy != kLangNegStrategyFiltering) {
           return true; // we only want the first match
         }
       }
       return foundMatch;
     };
 
     Locale requestedLocale = Locale(requested);
     if (findRangeMatches(requestedLocale, true, false)) {
@@ -502,53 +408,16 @@ LocaleService::FilterMatches(const nsTAr
     // 6) Try to match against a region as a range
     requestedLocale.ClearRegion();
     if (findRangeMatches(requestedLocale, true, true)) {
       HANDLE_STRATEGY;
     }
   }
 }
 
-void
-LocaleService::NegotiateLanguages(const nsTArray<nsCString>& aRequested,
-                                  const nsTArray<nsCString>& aAvailable,
-                                  const nsACString& aDefaultLocale,
-                                  LangNegStrategy aStrategy,
-                                  nsTArray<nsCString>& aRetVal)
-{
-  MOZ_ASSERT(aDefaultLocale.IsEmpty() || Locale(aDefaultLocale).IsWellFormed(),
-    "If specified, default locale must be a well-formed BCP47 language tag.");
-
-  if (aStrategy == LangNegStrategy::Lookup && aDefaultLocale.IsEmpty()) {
-    NS_WARNING("Default locale should be specified when using lookup strategy.");
-  }
-
-  FilterMatches(aRequested, aAvailable, aStrategy, aRetVal);
-
-  if (aStrategy == LangNegStrategy::Lookup) {
-    // If the strategy is Lookup and Filtering returned no matches, use
-    // the default locale.
-    if (aRetVal.Length() == 0) {
-      // If the default locale is empty, we already issued a warning, so
-      // now we will just pick up the LocaleService's defaultLocale.
-      if (aDefaultLocale.IsEmpty()) {
-        nsAutoCString defaultLocale;
-        GetDefaultLocale(defaultLocale);
-        aRetVal.AppendElement(defaultLocale);
-      } else {
-        aRetVal.AppendElement(aDefaultLocale);
-      }
-    }
-  } else if (!aDefaultLocale.IsEmpty() && !aRetVal.Contains(aDefaultLocale)) {
-    // If it's not a Lookup strategy, add the default locale only if it's
-    // set and it's not in the results already.
-    aRetVal.AppendElement(aDefaultLocale);
-  }
-}
-
 bool
 LocaleService::IsAppLocaleRTL()
 {
   nsAutoCString locale;
   GetAppLocaleAsBCP47(locale);
 
   int pref = Preferences::GetInt("intl.uidirection", -1);
   if (pref >= 0) {
@@ -588,27 +457,16 @@ LocaleService::LanguagesMatch(const nsAC
 
 
 bool
 LocaleService::IsServer()
 {
   return mIsServer;
 }
 
-static char**
-CreateOutArray(const nsTArray<nsCString>& aArray)
-{
-  uint32_t n = aArray.Length();
-  char** result = static_cast<char**>(moz_xmalloc(n * sizeof(char*)));
-  for (uint32_t i = 0; i < n; i++) {
-    result[i] = moz_xstrdup(aArray[i].get());
-  }
-  return result;
-}
-
 static bool
 GetGREFileContents(const char* aFilePath, nsCString* aOutString)
 {
   // Look for the requested file in omnijar.
   RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::GRE);
   if (zip) {
     nsZipItemPtr<char> item(zip, aFilePath);
     if (!item) {
@@ -668,25 +526,16 @@ LocaleService::InitPackagedLocales()
   // Last resort in case of broken build
   if (mPackagedLocales.IsEmpty()) {
     nsAutoCString defaultLocale;
     GetDefaultLocale(defaultLocale);
     mPackagedLocales.AppendElement(defaultLocale);
   }
 }
 
-void
-LocaleService::GetPackagedLocales(nsTArray<nsCString>& aRetVal)
-{
-  if (mPackagedLocales.IsEmpty()) {
-    InitPackagedLocales();
-  }
-  aRetVal = mPackagedLocales;
-}
-
 /**
  * mozILocaleService methods
  */
 
 NS_IMETHODIMP
 LocaleService::GetDefaultLocale(nsACString& aRetVal)
 {
   // We don't allow this to change during a session (it's set at build/package
@@ -718,35 +567,40 @@ LocaleService::GetDefaultLocale(nsACStri
 NS_IMETHODIMP
 LocaleService::GetLastFallbackLocale(nsACString& aRetVal)
 {
   aRetVal.AssignLiteral("en-US");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LocaleService::GetAppLocalesAsLangTags(uint32_t* aCount, char*** aOutArray)
-{
-  AutoTArray<nsCString, 32> locales;
-  GetAppLocalesAsLangTags(locales);
-
-  *aCount = locales.Length();
-  *aOutArray = CreateOutArray(locales);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-LocaleService::GetAppLocalesAsBCP47(uint32_t* aCount, char*** aOutArray)
+LocaleService::GetAppLocalesAsLangTags(nsTArray<nsCString>& aRetVal)
 {
   if (mAppLocales.IsEmpty()) {
     NegotiateAppLocales(mAppLocales);
   }
-  *aCount = mAppLocales.Length();
-  *aOutArray = CreateOutArray(mAppLocales);
+  for (uint32_t i = 0; i < mAppLocales.Length(); i++) {
+    nsAutoCString locale(mAppLocales[i]);
+    if (locale.LowerCaseEqualsASCII("ja-jp-macos")) {
+      aRetVal.AppendElement("ja-JP-mac");
+    } else {
+      aRetVal.AppendElement(locale);
+    }
+  }
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+LocaleService::GetAppLocalesAsBCP47(nsTArray<nsCString>& aRetVal)
+{
+  if (mAppLocales.IsEmpty()) {
+    NegotiateAppLocales(mAppLocales);
+  }
+  aRetVal = mAppLocales;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LocaleService::GetAppLocaleAsLangTag(nsACString& aRetVal)
 {
   AutoTArray<nsCString, 32> locales;
@@ -762,227 +616,205 @@ LocaleService::GetAppLocaleAsBCP47(nsACS
   if (mAppLocales.IsEmpty()) {
     NegotiateAppLocales(mAppLocales);
   }
   aRetVal = mAppLocales[0];
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LocaleService::GetRegionalPrefsLocales(uint32_t* aCount, char*** aOutArray)
+LocaleService::GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal)
 {
-  AutoTArray<nsCString,10> rgLocales;
-
-  GetRegionalPrefsLocales(rgLocales);
+  bool useOSLocales = Preferences::GetBool("intl.regional_prefs.use_os_locales", false);
 
-  *aCount = rgLocales.Length();
-  *aOutArray = static_cast<char**>(moz_xmalloc(*aCount * sizeof(char*)));
+  // If the user specified that they want to use OS Regional Preferences locales,
+  // try to retrieve them and use.
+  if (useOSLocales) {
+    if (OSPreferences::GetInstance()->GetRegionalPrefsLocales(aRetVal)) {
+      return NS_OK;
+    }
 
-  for (uint32_t i = 0; i < *aCount; i++) {
-    (*aOutArray)[i] = moz_xstrdup(rgLocales[i].get());
+    // If we fail to retrieve them, return the app locales.
+    GetAppLocalesAsBCP47(aRetVal);
+    return NS_OK;
   }
 
+  // Otherwise, fetch OS Regional Preferences locales and compare the first one
+  // to the app locale. If the language subtag matches, we can safely use
+  // the OS Regional Preferences locale.
+  //
+  // This facilitates scenarios such as Firefox in "en-US" and User sets
+  // regional prefs to "en-GB".
+  nsAutoCString appLocale;
+  AutoTArray<nsCString, 10> regionalPrefsLocales;
+  LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
+
+  if (!OSPreferences::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales)) {
+    GetAppLocalesAsBCP47(aRetVal);
+    return NS_OK;
+  }
+
+  if (LocaleService::LanguagesMatch(appLocale, regionalPrefsLocales[0])) {
+    aRetVal = regionalPrefsLocales;
+    return NS_OK;
+  }
+
+  // Otherwise use the app locales.
+  GetAppLocalesAsBCP47(aRetVal);
   return NS_OK;
 }
 
-static LocaleService::LangNegStrategy
-ToLangNegStrategy(int32_t aStrategy)
-{
-  switch (aStrategy) {
-    case 1:
-      return LocaleService::LangNegStrategy::Matching;
-    case 2:
-      return LocaleService::LangNegStrategy::Lookup;
-    default:
-      return LocaleService::LangNegStrategy::Filtering;
-  }
-}
-
 NS_IMETHODIMP
-LocaleService::NegotiateLanguages(const char** aRequested,
-                                  const char** aAvailable,
-                                  const char*  aDefaultLocale,
+LocaleService::NegotiateLanguages(const nsTArray<nsCString>& aRequested,
+                                  const nsTArray<nsCString>& aAvailable,
+                                  const nsACString& aDefaultLocale,
                                   int32_t aStrategy,
-                                  uint32_t aRequestedCount,
-                                  uint32_t aAvailableCount,
-                                  uint32_t* aCount, char*** aRetVal)
+                                  nsTArray<nsCString>& aRetVal)
 {
   if (aStrategy < 0 || aStrategy > 2) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  // Check that the given string contains only ASCII characters valid in tags
-  // (i.e. alphanumerics, plus '-' and '_'), and is non-empty.
-  auto validTagChars = [](const char* s) {
-    if (!s || !*s) {
-      return false;
-    }
-    while (*s) {
-      if (isalnum((unsigned char)*s) || *s == '-' || *s == '_' || *s == '*') {
-        s++;
+  MOZ_ASSERT(aDefaultLocale.IsEmpty() || Locale(aDefaultLocale).IsWellFormed(),
+    "If specified, default locale must be a well-formed BCP47 language tag.");
+
+  if (aStrategy == kLangNegStrategyLookup && aDefaultLocale.IsEmpty()) {
+    NS_WARNING("Default locale should be specified when using lookup strategy.");
+  }
+
+  FilterMatches(aRequested, aAvailable, aStrategy, aRetVal);
+
+  if (aStrategy == kLangNegStrategyLookup) {
+    // If the strategy is Lookup and Filtering returned no matches, use
+    // the default locale.
+    if (aRetVal.Length() == 0) {
+      // If the default locale is empty, we already issued a warning, so
+      // now we will just pick up the LocaleService's defaultLocale.
+      if (aDefaultLocale.IsEmpty()) {
+        nsAutoCString defaultLocale;
+        GetDefaultLocale(defaultLocale);
+        aRetVal.AppendElement(defaultLocale);
       } else {
-        return false;
+        aRetVal.AppendElement(aDefaultLocale);
       }
     }
-    return true;
-  };
+  } else if (!aDefaultLocale.IsEmpty() && !aRetVal.Contains(aDefaultLocale)) {
+    // If it's not a Lookup strategy, add the default locale only if it's
+    // set and it's not in the results already.
+    aRetVal.AppendElement(aDefaultLocale);
+  }
+  return NS_OK;
+}
 
-  AutoTArray<nsCString, 100> requestedLocales;
-  for (uint32_t i = 0; i < aRequestedCount; i++) {
-    if (!validTagChars(aRequested[i])) {
-      continue;
-    }
-    requestedLocales.AppendElement(aRequested[i]);
+NS_IMETHODIMP
+LocaleService::GetRequestedLocales(nsTArray<nsCString>& aRetVal)
+{
+  if (mRequestedLocales.IsEmpty()) {
+    ReadRequestedLocales(mRequestedLocales);
   }
 
-  AutoTArray<nsCString, 100> availableLocales;
-  for (uint32_t i = 0; i < aAvailableCount; i++) {
-    if (!validTagChars(aAvailable[i])) {
-      continue;
-    }
-    availableLocales.AppendElement(aAvailable[i]);
+  aRetVal = mRequestedLocales;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+LocaleService::GetRequestedLocale(nsACString& aRetVal)
+{
+  if (mRequestedLocales.IsEmpty()) {
+    ReadRequestedLocales(mRequestedLocales);
   }
 
-  nsAutoCString defaultLocale(aDefaultLocale);
-
-  LangNegStrategy strategy = ToLangNegStrategy(aStrategy);
-
-  AutoTArray<nsCString, 100> supportedLocales;
-  NegotiateLanguages(requestedLocales, availableLocales,
-                     defaultLocale, strategy, supportedLocales);
-
-  *aRetVal =
-    static_cast<char**>(moz_xmalloc(sizeof(char*) * supportedLocales.Length()));
-
-  *aCount = 0;
-  for (const auto& supported : supportedLocales) {
-    (*aRetVal)[(*aCount)++] = moz_xstrdup(supported.get());
+  if (mRequestedLocales.Length() > 0) {
+    aRetVal = mRequestedLocales[0];
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LocaleService::GetRequestedLocales(uint32_t* aCount, char*** aOutArray)
-{
-  AutoTArray<nsCString, 16> requestedLocales;
-  bool res = GetRequestedLocales(requestedLocales);
-
-  if (!res) {
-    NS_ERROR("Couldn't retrieve selected locales from prefs!");
-    return NS_ERROR_FAILURE;
-  }
-
-  *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)
+LocaleService::SetRequestedLocales(const nsTArray<nsCString>& aRequested)
 {
   MOZ_ASSERT(mIsServer, "This should only be called in the server mode.");
   if (!mIsServer) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsAutoCString str;
 
-  for (uint32_t i = 0; i < aRequestedCount; i++) {
-    nsAutoCString locale(aRequested[i]);
+  for (auto& req : aRequested) {
+    nsAutoCString locale(req);
     if (!SanitizeForBCP47(locale, true)) {
       NS_ERROR("Invalid language tag provided to SetRequestedLocales!");
       return NS_ERROR_INVALID_ARG;
     }
 
-    if (i > 0) {
+    if (!str.IsEmpty()) {
       str.AppendLiteral(",");
     }
     str.Append(locale);
   }
   Preferences::SetCString(REQUESTED_LOCALES_PREF, str);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LocaleService::GetAvailableLocales(uint32_t* aCount, char*** aOutArray)
+LocaleService::GetAvailableLocales(nsTArray<nsCString>& aRetVal)
 {
-  AutoTArray<nsCString, 100> availableLocales;
-  bool res = GetAvailableLocales(availableLocales);
-
-  if (!res) {
-    NS_ERROR("Couldn't retrieve available locales!");
-    return NS_ERROR_FAILURE;
+  MOZ_ASSERT(mIsServer, "This should only be called in the server mode.");
+  if (!mIsServer) {
+    return NS_ERROR_UNEXPECTED;
   }
 
-  *aCount = availableLocales.Length();
-  *aOutArray = CreateOutArray(availableLocales);
+  if (mAvailableLocales.IsEmpty()) {
+    // If there are no available locales set, it means that L10nRegistry
+    // did not register its locale pool yet. The best course of action
+    // is to use packaged locales until that happens.
+    GetPackagedLocales(mAvailableLocales);
+  }
+
+  aRetVal = mAvailableLocales;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LocaleService::GetIsAppLocaleRTL(bool* aRetVal)
 {
   (*aRetVal) = IsAppLocaleRTL();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LocaleService::SetAvailableLocales(const char** aAvailable,
-                                   uint32_t aAvailableCount)
+LocaleService::SetAvailableLocales(const nsTArray<nsCString>& aAvailable)
 {
   MOZ_ASSERT(mIsServer, "This should only be called in the server mode.");
   if (!mIsServer) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsTArray<nsCString> newLocales;
 
-  for (uint32_t i = 0; i < aAvailableCount; i++) {
-    nsAutoCString locale(aAvailable[i]);
+  for (auto& avail : aAvailable) {
+    nsAutoCString locale(avail);
     if (!SanitizeForBCP47(locale, true)) {
       NS_ERROR("Invalid language tag provided to SetAvailableLocales!");
       return NS_ERROR_INVALID_ARG;
     }
     newLocales.AppendElement(locale);
   }
 
   if (newLocales != mAvailableLocales) {
     mAvailableLocales = std::move(newLocales);
     LocalesChanged();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LocaleService::GetPackagedLocales(uint32_t* aCount, char*** aOutArray)
+LocaleService::GetPackagedLocales(nsTArray<nsCString>& aRetVal)
 {
   if (mPackagedLocales.IsEmpty()) {
     InitPackagedLocales();
   }
-
-  *aCount = mPackagedLocales.Length();
-  *aOutArray = CreateOutArray(mPackagedLocales);
-
+  aRetVal = mPackagedLocales;
   return NS_OK;
 }
--- a/intl/locale/LocaleService.h
+++ b/intl/locale/LocaleService.h
@@ -78,21 +78,19 @@ public:
   NS_DECL_MOZILOCALESERVICE
 
   /**
    * List of available language negotiation strategies.
    *
    * See the mozILocaleService.idl for detailed description of the
    * strategies.
    */
-  enum class LangNegStrategy {
-    Filtering,
-    Matching,
-    Lookup
-  };
+  static const int32_t kLangNegStrategyFiltering = 0;
+  static const int32_t kLangNegStrategyMatching = 1;
+  static const int32_t kLangNegStrategyLookup = 2;
 
   explicit LocaleService(bool aIsServer);
 
   /**
    * Create (if necessary) and return a raw pointer to the singleton instance.
    * Use this accessor in C++ code that just wants to call a method on the
    * instance, but does not need to hold a reference, as in
    *    nsAutoCString str;
@@ -105,169 +103,57 @@ public:
    * XPCOM constructor that exists to support usage from JS.
    */
   static already_AddRefed<LocaleService> GetInstanceAddRefed()
   {
     return RefPtr<LocaleService>(GetInstance()).forget();
   }
 
   /**
-   * Returns a list of locales that the application should be localized to.
-   *
-   * The result is a ordered list of valid locale IDs and it should be
-   * used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
-   *
-   * This API always returns at least one locale.
-   *
-   * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * Usage:
-   *   nsTArray<nsCString> appLocales;
-   *   LocaleService::GetInstance()->GetAppLocalesAsLangTags(appLocales);
-   *
-   * (See mozILocaleService.idl for a JS-callable version of this.)
-   */
-  void GetAppLocalesAsLangTags(nsTArray<nsCString>& aRetVal);
-  void GetAppLocalesAsBCP47(nsTArray<nsCString>& aRetVal);
-
-
-  /**
-   * Returns a list of locales to use for any regional specific operations
-   * like date formatting, calendars, unit formatting etc.
-   *
-   * The result is a ordered list of valid locale IDs and it should be
-   * used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
-   *
-   * This API always returns at least one locale.
-   *
-   * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * Usage:
-   *   nsTArray<nsCString> rgLocales;
-   *   LocaleService::GetInstance()->GetRegionalPrefsLocales(rgLocales);
-   *
-   * (See mozILocaleService.idl for a JS-callable version of this.)
-   */
-  void GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal);
-
-  /**
    * This method should only be called in the client mode.
    *
    * It replaces all the language negotiation and is supposed to be called
    * in order to bring the client LocaleService in sync with the server
    * LocaleService.
    *
    * Currently, it's called by the IPC code.
    */
   void AssignAppLocales(const nsTArray<nsCString>& aAppLocales);
   void AssignRequestedLocales(const nsTArray<nsCString>& aRequestedLocales);
 
   /**
-   * Returns a list of locales that the user requested the app to be
-   * localized to.
-   *
-   * The result is a sorted list of valid locale IDs and it should be
-   * used as a requestedLocales input list for languages negotiation.
-   *
-   * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * Usage:
-   *   nsTArray<nsCString> reqLocales;
-   *   LocaleService::GetInstance()->GetRequestedLocales(reqLocales);
-   *
-   * Returns a boolean indicating if the attempt to retrieve prefs
-   * was successful.
-   *
-   * (See mozILocaleService.idl for a JS-callable version of this.)
-   */
-  bool GetRequestedLocales(nsTArray<nsCString>& aRetVal);
-
-  /**
-   * Returns a list of available locales that can be used to
-   * localize the app.
-   *
-   * The result is an unsorted list of valid locale IDs and it should be
-   * used as a availableLocales input list for languages negotiation.
-   *
-   * Example: ["de", "en-US", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * Usage:
-   *   nsTArray<nsCString> availLocales;
-   *   LocaleService::GetInstance()->GetAvailableLocales(availLocales);
-   *
-   * Returns a boolean indicating if the attempt to retrieve at least
-   * one locale was successful.
-   *
-   * (See mozILocaleService.idl for a JS-callable version of this.)
-   */
-  bool GetAvailableLocales(nsTArray<nsCString>& aRetVal);
-
-  /**
-   * Returns a list of locales packaged into the app bundle.
-   *
-   * (See mozILocaleService.idl for a JS-callable version of this.)
-   */
-  void GetPackagedLocales(nsTArray<nsCString>& aRetVal);
-
-  /**
    * Those two functions allow to trigger cache invalidation on one of the
    * three cached values.
    *
    * In most cases, the functions will be called by the observer in
    * LocaleService itself, but in a couple special cases, we have the
    * other component call this manually instead of sending a global event.
    *
    * If the result differs from the previous list, it will additionally
    * trigger a corresponding event
    *
    * This code should be called only in the server mode..
    */
   void RequestedLocalesChanged();
   void LocalesChanged();
 
   /**
-   * Negotiates the best locales out of an ordered list of requested locales and
-   * a list of available locales.
-   *
-   * Internally it uses the following naming scheme:
-   *
-   *  Requested - locales requested by the user
-   *  Available - locales for which the data is available
-   *  Supported - locales negotiated by the algorithm
-   *
-   * Additionally, if defaultLocale is provided, it adds it to the end of the
-   * result list as a "last resort" locale.
-   *
-   * Strategy is one of the three strategies described at the top of this file.
-   *
-   * The result list is canonicalized and ordered according to the order
-   * of the requested locales.
-   *
-   * (See mozILocaleService.idl for a JS-callable version of this.)
-   */
-  void NegotiateLanguages(const nsTArray<nsCString>& aRequested,
-                          const nsTArray<nsCString>& aAvailable,
-                          const nsACString& aDefaultLocale,
-                          LangNegStrategy aLangNegStrategy,
-                          nsTArray<nsCString>& aRetVal);
-
-  /**
    * Returns whether the current app locale is RTL.
    */
   bool IsAppLocaleRTL();
 
   static bool LanguagesMatch(const nsACString& aRequested,
                              const nsACString& aAvailable);
 
   bool IsServer();
 
 private:
   void FilterMatches(const nsTArray<nsCString>& aRequested,
                      const nsTArray<nsCString>& aAvailable,
-                     LangNegStrategy aStrategy,
+                     int32_t aStrategy,
                      nsTArray<nsCString>& aRetVal);
 
   void NegotiateAppLocales(nsTArray<nsCString>& aRetVal);
 
   void InitPackagedLocales();
 
   virtual ~LocaleService();
 
--- a/intl/locale/mozILocaleService.idl
+++ b/intl/locale/mozILocaleService.idl
@@ -75,39 +75,32 @@ interface mozILocaleService : nsISupport
    * This API always returns at least one locale.
    *
    * When retrieving the locales for language negotiation and matching
    * to language resources, use the language tag form.
    * When retrieving the locales for Intl API or ICU locale settings,
    * use the BCP47 form.
    *
    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * (See LocaleService.h for a more C++-friendly version of this.)
    */
-  void getAppLocalesAsLangTags([optional] out unsigned long aCount,
-                               [retval, array, size_is(aCount)] out string aLocales);
-  void getAppLocalesAsBCP47([optional] out unsigned long aCount,
-                            [retval, array, size_is(aCount)] out string aLocales);
+  readonly attribute Array<ACString> appLocalesAsLangTags;
+  readonly attribute Array<ACString> appLocalesAsBCP47;
 
   /**
    * Returns a list of locales to use for any regional specific operations
    * like date formatting, calendars, unit formatting etc.
    *
    * The result is a ordered list of valid locale IDs and it should be
    * used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
    *
    * This API always returns at least one locale.
    *
    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * (See LocaleService.h for a more C++-friendly version of this.)
    */
-  void getRegionalPrefsLocales([optional] out unsigned long aCount,
-                        [retval, array, size_is(aCount)] out string aOutArray);
+  readonly attribute Array<ACString> regionalPrefsLocales;
 
   /**
    * Negotiates the best locales out of a ordered list of requested locales and
    * a list of available locales.
    *
    * Internally it uses the following naming scheme:
    *
    *  Requested - locales requested by the user
@@ -119,116 +112,72 @@ interface mozILocaleService : nsISupport
    *
    * Strategy is one of the three strategies described at the top of this file.
    *
    * The result list is canonicalized and ordered according to the order
    * of the requested locales.
    *
    * (See LocaleService.h for a more C++-friendly version of this.)
    */
-  void negotiateLanguages([array, size_is(aRequestedCount)] in string aRequested,
-                          [array, size_is(aAvailableCount)] in string aAvailable,
-                          [optional] in string aDefaultLocale,
-                          [optional] in long langNegStrategy,
-                          [optional] in unsigned long aRequestedCount,
-                          [optional] in unsigned long aAvailableCount,
-                          [optional] out unsigned long aCount,
-                          [retval, array, size_is(aCount)] out string aLocales);
+  Array<ACString> negotiateLanguages(in Array<ACString> aRequested,
+                                     in Array<ACString> aAvailable,
+                                     [optional] in ACString aDefaultLocale,
+                                     [optional] in long langNegStrategy);
 
   /**
    * Returns the best locale that the application should be localized to.
    *
    * The result is a valid locale ID and it should be
    * used for all APIs that do not handle language negotiation.
    *
    * When retrieving the locales for language negotiation and matching
    * to language resources, use the language tag form.
    * When retrieving the locales for Intl API or ICU locale settings,
    * use the BCP47 form.
    *
-   * Where possible, getAppLocales*() should be preferred over this API and
+   * Where possible, appLocales* should be preferred over this API and
    * all callsites should handle some form of "best effort" language
    * negotiation to respect user preferences in case the use case does
    * not have data for the first locale in the list.
    *
    * Example: "zh-Hans-HK"
    */
-  ACString getAppLocaleAsLangTag();
-  ACString getAppLocaleAsBCP47();
+  readonly attribute ACString appLocaleAsLangTag;
+  readonly attribute ACString appLocaleAsBCP47;
 
   /**
    * Returns a list of locales that the user requested the app to be
    * localized to.
    *
    * The result is an ordered list of locale IDs which should be
    * 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);
+  attribute Array<ACString> requestedLocales;
 
   /**
    * 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
-   * whole fallback chain.
-   *
-   * If an empty list is passed, the list of requested locales will
-   * be picked from the operating system.
-   *
-   * Example: ["de"]
-   */
-  void setRequestedLocales([array, size_is(aRequestedCount)] in string aRequested,
-                           [optional] in unsigned long aRequestedCount);
+  readonly attribute ACString requestedLocale;
 
   /**
    * Returns a list of locales that the app can be localized to.
    *
    * The result is an unordered list of locale IDs which should be
    * used as a availableLocales input list for language negotiation.
    *
    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
    */
-  void getAvailableLocales([optional] out unsigned long aCount,
-                           [retval, array, size_is(aCount)] out string aLocales);
+  attribute Array<ACString> availableLocales;
 
   /**
    * Returns whether the current app locale is RTL.
    */
   readonly attribute boolean isAppLocaleRTL;
 
   /**
-   * Sets a list of locales the application has resources to be localized into.
-   *
-   * The primary use of this function is to let L10nRegistry communicate all
-   * locale updates.
-   *
-   * The secondary use case is for testing purposes in scenarios in which the
-   * actual resources don't have to be available.
-   * It is recommended for tests to create a mock FileSource and register it in
-   * the L10nRegistry rather than using this call, in order to emulate full
-   * resource availability cycle.
-   *
-   */
-  void setAvailableLocales([array, size_is(aAvailableCount)] in string aAvailable,
-                           [optional] in unsigned long aAvailableCount);
-
-  /**
    * Returns a list of locales packaged into the app bundle.
    *
    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
-   *
-   * (See LocaleService.h for a more C++-friendly version of this.)
    */
-  void getPackagedLocales([optional] out unsigned long aCount,
-                          [retval, array, size_is(aCount)] out string aOutArray);
+  readonly attribute Array<ACString> packagedLocales;
 };
--- a/intl/locale/tests/gtest/TestLocaleServiceNegotiate.cpp
+++ b/intl/locale/tests/gtest/TestLocaleServiceNegotiate.cpp
@@ -10,18 +10,18 @@
 
 using namespace mozilla::intl;
 
 TEST(Intl_Locale_LocaleService, Negotiate) {
   nsTArray<nsCString> requestedLocales;
   nsTArray<nsCString> availableLocales;
   nsTArray<nsCString> supportedLocales;
   nsAutoCString defaultLocale("en-US");
-  LocaleService::LangNegStrategy strategy =
-    LocaleService::LangNegStrategy::Filtering;
+  int32_t strategy =
+    LocaleService::kLangNegStrategyFiltering;
 
   requestedLocales.AppendElement(NS_LITERAL_CSTRING("sr"));
 
   availableLocales.AppendElement(NS_LITERAL_CSTRING("sr-Cyrl"));
   availableLocales.AppendElement(NS_LITERAL_CSTRING("sr-Latn"));
 
   LocaleService::GetInstance()->NegotiateLanguages(
       requestedLocales, availableLocales, defaultLocale, strategy, supportedLocales);
@@ -31,18 +31,18 @@ TEST(Intl_Locale_LocaleService, Negotiat
   ASSERT_TRUE(supportedLocales[1].EqualsLiteral("en-US"));
 }
 
 TEST(Intl_Locale_LocaleService, UseLSDefaultLocale) {
   nsTArray<nsCString> requestedLocales;
   nsTArray<nsCString> availableLocales;
   nsTArray<nsCString> supportedLocales;
   nsAutoCString defaultLocale("");
-  LocaleService::LangNegStrategy strategy =
-    LocaleService::LangNegStrategy::Lookup;
+  int32_t strategy =
+    LocaleService::kLangNegStrategyLookup;
 
   requestedLocales.AppendElement(NS_LITERAL_CSTRING("sr"));
 
   availableLocales.AppendElement(NS_LITERAL_CSTRING("de"));
 
   LocaleService::GetInstance()->NegotiateLanguages(
       requestedLocales, availableLocales, defaultLocale, strategy, supportedLocales);
 
--- a/intl/locale/tests/unit/test_localeService.js
+++ b/intl/locale/tests/unit/test_localeService.js
@@ -25,59 +25,59 @@ add_test(function test_defaultLocale() {
 });
 
 add_test(function test_lastFallbackLocale() {
   const lastFallbackLocale = localeService.lastFallbackLocale;
   Assert.ok(lastFallbackLocale === "en-US", "Last fallback locale is en-US");
   run_next_test();
 });
 
-add_test(function test_getAppLocalesAsLangTags() {
-  const appLocale = localeService.getAppLocaleAsLangTag();
+add_test(function test_appLocalesAsLangTags() {
+  const appLocale = localeService.appLocaleAsLangTag;
   Assert.ok(appLocale != "", "appLocale is non-empty");
 
-  const appLocales = localeService.getAppLocalesAsLangTags();
+  const appLocales = localeService.appLocalesAsLangTags;
   Assert.ok(Array.isArray(appLocales), "appLocales returns an array");
 
   Assert.ok(appLocale == appLocales[0], "appLocale matches first entry in appLocales");
 
   const enUSLocales = appLocales.filter(loc => loc === "en-US");
   Assert.ok(enUSLocales.length == 1, "en-US is present exactly one time");
 
   run_next_test();
 });
 
 const PREF_REQUESTED_LOCALES = "intl.locale.requested";
 const REQ_LOC_CHANGE_EVENT = "intl:requested-locales-changed";
 
-add_test(function test_getRequestedLocales() {
-  const requestedLocales = localeService.getRequestedLocales();
+add_test(function test_requestedLocales() {
+  const requestedLocales = localeService.requestedLocales;
   Assert.ok(Array.isArray(requestedLocales), "requestedLocales returns an array");
 
   run_next_test();
 });
 
 /**
  * In this test we verify that after we set an observer on the LocaleService
  * event for requested locales change, it will be fired when the
  * pref for matchOS is set to true.
  *
  * Then, we test that when the matchOS is set to true, we will retrieve
- * OS locale from getRequestedLocales.
+ * OS locale from requestedLocales.
  */
-add_test(function test_getRequestedLocales_matchOS() {
+add_test(function test_requestedLocales_matchOS() {
   do_test_pending();
 
   Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "ar-IR");
 
   const observer = {
     observe: function (aSubject, aTopic, aData) {
       switch (aTopic) {
         case REQ_LOC_CHANGE_EVENT:
-          const reqLocs = localeService.getRequestedLocales();
+          const reqLocs = localeService.requestedLocales;
           Assert.ok(reqLocs[0] === osPrefs.systemLocale);
           Services.obs.removeObserver(observer, REQ_LOC_CHANGE_EVENT);
           do_test_finished();
       }
     }
   };
 
   Services.obs.addObserver(observer, REQ_LOC_CHANGE_EVENT);
@@ -86,127 +86,127 @@ add_test(function test_getRequestedLocal
   run_next_test();
 });
 
 /**
  * In this test we verify that after we set an observer on the LocaleService
  * event for requested locales change, it will be fired when the
  * pref for browser UI locale changes.
  */
-add_test(function test_getRequestedLocales_onChange() {
+add_test(function test_requestedLocales_onChange() {
   do_test_pending();
 
   Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "ar-IR");
 
   const observer = {
     observe: function (aSubject, aTopic, aData) {
       switch (aTopic) {
         case REQ_LOC_CHANGE_EVENT:
-          const reqLocs = localeService.getRequestedLocales();
+          const reqLocs = localeService.requestedLocales;
           Assert.ok(reqLocs[0] === "sr-RU");
           Services.obs.removeObserver(observer, REQ_LOC_CHANGE_EVENT);
           do_test_finished();
       }
     }
   };
 
   Services.obs.addObserver(observer, REQ_LOC_CHANGE_EVENT);
   Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "sr-RU");
 
   run_next_test();
 });
 
-add_test(function test_getRequestedLocale() {
+add_test(function test_requestedLocale() {
   Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "tlh");
 
-  let requestedLocale = localeService.getRequestedLocale();
+  let requestedLocale = localeService.requestedLocale;
   Assert.ok(requestedLocale === "tlh", "requestedLocale returns the right value");
 
   Services.prefs.clearUserPref(PREF_REQUESTED_LOCALES);
 
   run_next_test();
 });
 
-add_test(function test_setRequestedLocales() {
-  localeService.setRequestedLocales(['de-AT', 'de-DE', 'de-CH']);
+add_test(function test_requestedLocales() {
+  localeService.requestedLocales = ['de-AT', 'de-DE', 'de-CH'];
 
-  let locales = localeService.getRequestedLocales();
+  let locales = localeService.requestedLocales;
   Assert.ok(locales[0] === 'de-AT');
   Assert.ok(locales[1] === 'de-DE');
   Assert.ok(locales[2] === 'de-CH');
 
   run_next_test();
 });
 
 add_test(function test_isAppLocaleRTL() {
   Assert.ok(typeof localeService.isAppLocaleRTL === 'boolean');
 
   run_next_test();
 });
 
-add_test(function test_getPackagedLocales() {
-  const locales = localeService.getPackagedLocales();
+add_test(function test_packagedLocales() {
+  const locales = localeService.packagedLocales;
   Assert.ok(locales.length !== 0, "Packaged locales are empty");
   run_next_test();
 });
 
-add_test(function test_setAvailableLocales() {
-  const avLocales = localeService.getAvailableLocales();
-  localeService.setAvailableLocales(["und", "ar-IR"]);
+add_test(function test_availableLocales() {
+  const avLocales = localeService.availableLocales;
+  localeService.availableLocales = ["und", "ar-IR"];
 
-  let locales = localeService.getAvailableLocales();
+  let locales = localeService.availableLocales;
   Assert.ok(locales.length == 2);
   Assert.ok(locales[0] === 'und');
   Assert.ok(locales[1] === 'ar-IR');
 
-  localeService.setAvailableLocales(avLocales);
+  localeService.availableLocales = avLocales;
 
   run_next_test();
 });
 
 /**
  * This test verifies that all values coming from the pref are sanitized.
  */
-add_test(function test_getRequestedLocales_sanitize() {
+add_test(function test_requestedLocales_sanitize() {
   Services.prefs.setCharPref(PREF_REQUESTED_LOCALES, "de,2,#$@#,pl,ąó,!a2,DE-at,,;");
 
-  let locales = localeService.getRequestedLocales();
+  let locales = localeService.requestedLocales;
   Assert.equal(locales[0], "de");
   Assert.equal(locales[1], "pl");
   Assert.equal(locales[2], "de-AT");
   Assert.equal(locales[3], "und");
   Assert.equal(locales.length, 4);
 
   Services.prefs.clearUserPref(PREF_REQUESTED_LOCALES);
 
   run_next_test();
 });
 
 add_test(function test_handle_ja_JP_mac() {
-  const bkpAvLocales = localeService.getAvailableLocales();
+  const bkpAvLocales = localeService.availableLocales;
 
-  localeService.setAvailableLocales(["ja-JP-mac", "en-US"]);
+  localeService.availableLocales = ["ja-JP-mac", "en-US"];
 
-  localeService.setRequestedLocales(['ja-JP-mac']);
+  localeService.requestedLocales = ['ja-JP-mac'];
 
-  let reqLocales = localeService.getRequestedLocales();
+  let reqLocales = localeService.requestedLocales;
   Assert.equal(reqLocales[0], 'ja-JP-macos');
 
-  let avLocales = localeService.getAvailableLocales();
+  let avLocales = localeService.availableLocales;
   Assert.equal(avLocales[0], 'ja-JP-macos');
 
-  let appLocales = localeService.getAppLocalesAsBCP47();
+  let appLocales = localeService.appLocalesAsBCP47;
   Assert.equal(appLocales[0], 'ja-JP-macos');
 
-  let appLocalesAsLT = localeService.getAppLocalesAsLangTags();
+  let appLocalesAsLT = localeService.appLocalesAsLangTags;
   Assert.equal(appLocalesAsLT[0], 'ja-JP-mac');
 
-  Assert.equal(localeService.getAppLocaleAsLangTag(), "ja-JP-mac");
+  Assert.equal(localeService.appLocaleAsLangTag, "ja-JP-mac");
 
-  localeService.setAvailableLocales(bkpAvLocales);
+  localeService.availableLocales = bkpAvLocales;
 
   run_next_test();
 });
 
 
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref(PREF_REQUESTED_LOCALES);
 });
--- a/intl/locale/tests/unit/test_localeService_negotiateLanguages.js
+++ b/intl/locale/tests/unit/test_localeService_negotiateLanguages.js
@@ -77,33 +77,19 @@ const data = {
       [["fr_FR"], ["fr_FR"], ["fr_FR"]],
       [["fr-FR"], ["fr_FR"], ["fr_FR"]],
       [["fr_Cyrl_FR_macos"], ["fr_Cyrl_fr-macos"], ["fr_Cyrl_fr-macos"]],
     ],
     "should handle mozilla specific 3-letter variants": [
       [["ja-JP-mac", "de-DE"], ["ja-JP-mac", "de-DE"], ["ja-JP-mac", "de-DE"]],
     ],
     "should not crash on invalid input": [
-      [null, ["fr-FR"], []],
-      [[null], [], []],
-      [[undefined], [], []],
-      [[undefined], [null], []],
-      [[undefined], [undefined], []],
-      [[null], [null], null, null, []],
-      [undefined, ["fr-FR"], []],
-      [2, ["fr-FR"], []],
-      ["fr-FR", ["fr-FR"], []],
       [["fą-FŻ"], ["ór_Fń"], []],
-      [["fr-FR"], null, []],
-      [["fr-FR"], undefined, []],
-      [["fr-FR"], 2, []],
-      [["fr-FR"], "fr-FR", []],
       [["2"], ["ąóżł"], []],
-      [[[]], ["fr-FR"], []],
-      [[[]], [[2]], []],
+      [[[""]], ["fr-FR"], []],
     ],
   },
   "matching": {
     "should match only one per requested": [
       [
         ["fr", "en"],
         ["en-US", "fr-FR", "en", "fr"], null,
         localeService.langNegStrategyMatching, ["fr", "en"]
@@ -138,9 +124,31 @@ function run_test()
         const supported = test[test.length - 1];
 
         const result = nl(test[0], test[1], defaultLocale, strategy);
         deepEqual(result, supported,
   `\nExpected ${json(requested)} * ${json(available)} = ${json(supported)}.\n`);
       }
     }
   }
+
+  // Verify that we error out when requested or available is not an array.
+  for ([req, avail] in [
+    [null, ["fr-FR"]],
+		[undefined, ["fr-FR"]],
+		[2, ["fr-FR"]],
+		["fr-FR", ["fr-FR"]],
+		[["fr-FR"], null],
+		[["fr-FR"], undefined],
+		[["fr-FR"], 2],
+		[["fr-FR"], "fr-FR"],
+    [[null], []],
+    [[undefined], []],
+    [[undefined], [null]],
+    [[undefined], [undefined]],
+    [[null], [null]],
+    [[[]], [[2]]],
+  ]) {
+    Assert.throws(() => {
+      nl(req, avail);
+    }, err => err.result == Cr.NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY);
+  }
 }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -459,17 +459,17 @@ StopDrainingJobQueue(JSContext* cx);
 
 extern JS_FRIEND_API(void)
 RunJobs(JSContext* cx);
 
 extern JS_FRIEND_API(JS::Zone*)
 GetRealmZone(JS::Realm* realm);
 
 typedef bool
-(* PreserveWrapperCallback)(JSContext* cx, JSObject* obj);
+(* PreserveWrapperCallback)(JSContext* cx, JS::HandleObject obj);
 
 typedef enum  {
     CollectNurseryBeforeDump,
     IgnoreNurseryObjects
 } DumpHeapNurseryBehaviour;
 
  /**
   * Dump the complete object graph of heap-allocated things.
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3506,17 +3506,17 @@ DisassWithSrc(JSContext* cx, unsigned ar
     args.rval().setUndefined();
     return true;
 }
 
 #endif /* defined(DEBUG) || defined(JS_JITSPEW) */
 
 /* Pretend we can always preserve wrappers for dummy DOM objects. */
 static bool
-DummyPreserveWrapperCallback(JSContext* cx, JSObject* obj)
+DummyPreserveWrapperCallback(JSContext* cx, HandleObject obj)
 {
     return true;
 }
 
 static bool
 Intern(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2823,17 +2823,17 @@ DestroyRealm(JSFreeOp* fop, JS::Realm* r
 {
     // Get the current compartment private into an AutoPtr (which will do the
     // cleanup for us), and null out the private field.
     mozilla::UniquePtr<RealmPrivate> priv(RealmPrivate::Get(realm));
     JS::SetRealmPrivate(realm, nullptr);
 }
 
 static bool
-PreserveWrapper(JSContext* cx, JSObject* obj)
+PreserveWrapper(JSContext* cx, JS::Handle<JSObject*> obj)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(obj);
     MOZ_ASSERT(IS_WN_REFLECTOR(obj) || mozilla::dom::IsDOMObject(obj));
 
     return mozilla::dom::IsDOMObject(obj) && mozilla::dom::TryPreserveWrapper(obj);
 }
 
--- a/js/xpconnect/tests/chrome/test_paris_weakmap_keys.xul
+++ b/js/xpconnect/tests/chrome/test_paris_weakmap_keys.xul
@@ -38,41 +38,56 @@ https://bugzilla.mozilla.org/show_bug.cg
     ok(!div_fail, "Using elem.style as a weak map key should not produce an exception.");
 
     is(live_map.get(get_div_style()), 12345, "Live map should have live style with right value before GC.");
 
   }
 
   make_live_map();
 
-  // DOMPoint is a non-nsISupports refCounted class using WebIDL bindings.
+
+  // CanvasGradient is a non-nsISupports wrapper cached class using WebIDL
+  // bindings. If we used it as a key in a weak map, then it should not be
+  // removed from the weak map as long as it remains alive.
+  let doc = new DOMParser().parseFromString("", "text/html");
+  let canv = doc.createElement("canvas");
+  let ctx = canv.getContext("2d");
 
-  // non-nsISupports cycle-collected classes should fail as weak map keys.
-  let context = new DOMPoint(1, 2, 3);
-  let contextFail = false;
-  try {
-    live_map.set(context, 2);
-  } catch (e) {
-    contextFail = true;
+  let add_non_isupports2 = function () {
+    let grad = ctx.createLinearGradient(0, 0, 0, 0);
+    ctx.strokeStyle = grad;
+
+    let gradFail = false;
+    try {
+      live_map.set(grad, 23456);
+    } catch (e) {
+      gradFail = true;
+    }
+
+    ok(!gradFail, "Using a wrapper cached non-nsISupports class as a weak map key should not produce an exception.");
+
+    is(live_map.get(grad), 23456, "Live map should have live DOMPoint with right value before GC.");
   }
 
-  ok(contextFail, "Cycle collected non-nsISupports classes aren't allowed as weak map keys.");
+  add_non_isupports2();
+
 
   /* Set up for running precise GC/CC then check the results. */
 
   SimpleTest.waitForExplicitFinish();
 
   Cu.schedulePreciseGC(function () {
     SpecialPowers.DOMWindowUtils.cycleCollect();
     SpecialPowers.DOMWindowUtils.garbageCollect();
     SpecialPowers.DOMWindowUtils.garbageCollect();
 
-    is(ChromeUtils.nondeterministicGetWeakMapKeys(live_map).length, 1,
+    is(ChromeUtils.nondeterministicGetWeakMapKeys(live_map).length, 2,
        "Live nsISupports new DOM bindings wrappercached native weak map key should not be removed.");
 
     is(live_map.get(get_div_style()), 12345, "Live map should have live style with right value after GC.");
+    is(live_map.get(ctx.strokeStyle), 23456, "Live map should have live gradient with right value after GC.");
 
     SimpleTest.finish();
   });
 
   ]]>
   </script>
 </window>
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1916,63 +1916,63 @@ RestyleManager::AnimationsWithDestroyedF
         effect->ResetIsRunningOnCompositor();
       }
     }
   }
 }
 
 #ifdef DEBUG
 static bool
-IsAnonBox(const nsIFrame& aFrame)
+IsAnonBox(const nsIFrame* aFrame)
 {
-  return aFrame.Style()->IsAnonBox();
+  return aFrame->Style()->IsAnonBox();
 }
 
 static const nsIFrame*
 FirstContinuationOrPartOfIBSplit(const nsIFrame* aFrame)
 {
   if (!aFrame) {
     return nullptr;
   }
 
   return nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
 }
 
 static const nsIFrame*
-ExpectedOwnerForChild(const nsIFrame& aFrame)
+ExpectedOwnerForChild(const nsIFrame* aFrame)
 {
-  const nsIFrame* parent = aFrame.GetParent();
-  if (aFrame.IsTableFrame()) {
+  const nsIFrame* parent = aFrame->GetParent();
+  if (aFrame->IsTableFrame()) {
     MOZ_ASSERT(parent->IsTableWrapperFrame());
     parent = parent->GetParent();
   }
 
-  if (IsAnonBox(aFrame) && !aFrame.IsTextFrame()) {
+  if (IsAnonBox(aFrame) && !aFrame->IsTextFrame()) {
     if (parent->IsLineFrame()) {
       parent = parent->GetParent();
     }
     return parent->IsViewportFrame() ?
       nullptr : FirstContinuationOrPartOfIBSplit(parent);
   }
 
-  if (aFrame.IsBulletFrame()) {
+  if (aFrame->IsBulletFrame()) {
     return FirstContinuationOrPartOfIBSplit(parent);
   }
 
-  if (aFrame.IsLineFrame()) {
+  if (aFrame->IsLineFrame()) {
     // A ::first-line always ends up here via its block, which is therefore the
     // right expected owner.  That block can be an
     // anonymous box.  For example, we could have a ::first-line on a columnated
     // block; the blockframe is the column-content anonymous box in that case.
     // So we don't want to end up in the code below, which steps out of anon
     // boxes.  Just return the parent of the line frame, which is the block.
     return parent;
   }
 
-  if (aFrame.IsLetterFrame()) {
+  if (aFrame->IsLetterFrame()) {
     // Ditto for ::first-letter. A first-letter always arrives here via its
     // direct parent, except when it's parented to a ::first-line.
     if (parent->IsLineFrame()) {
       parent = parent->GetParent();
     }
     return FirstContinuationOrPartOfIBSplit(parent);
   }
 
@@ -1982,23 +1982,23 @@ ExpectedOwnerForChild(const nsIFrame& aF
     parent = parent->GetParent();
   }
 
   parent = FirstContinuationOrPartOfIBSplit(parent);
 
   // We've handled already anon boxes and bullet frames, so now we're looking at
   // a frame of a DOM element or pseudo. Hop through anon and line-boxes
   // generated by our DOM parent, and go find the owner frame for it.
-  while (parent && (IsAnonBox(*parent) || parent->IsLineFrame())) {
+  while (parent && (IsAnonBox(parent) || parent->IsLineFrame())) {
     auto* pseudo = parent->Style()->GetPseudo();
     if (pseudo == nsCSSAnonBoxes::tableWrapper()) {
       const nsIFrame* tableFrame = parent->PrincipalChildList().FirstChild();
       MOZ_ASSERT(tableFrame->IsTableFrame());
       // Handle :-moz-table and :-moz-inline-table.
-      parent = IsAnonBox(*tableFrame) ? parent->GetParent() : tableFrame;
+      parent = IsAnonBox(tableFrame) ? parent->GetParent() : tableFrame;
     } else {
       // We get the in-flow parent here so that we can handle the OOF anonymous
       // boxed to get the correct parent.
       parent = parent->GetInFlowParent();
     }
     parent = FirstContinuationOrPartOfIBSplit(parent);
   }
 
@@ -2011,35 +2011,35 @@ ServoRestyleState::AssertOwner(const Ser
   MOZ_ASSERT(mOwner);
   MOZ_ASSERT(!mOwner->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
   // We allow aParent.mOwner to be null, for cases when we're not starting at
   // the root of the tree.  We also allow aParent.mOwner to be somewhere up our
   // expected owner chain not our immediate owner, which allows us creating long
   // chains of ServoRestyleStates in some cases where it's just not worth it.
 #ifdef DEBUG
   if (aParent.mOwner) {
-    const nsIFrame* owner = ExpectedOwnerForChild(*mOwner);
+    const nsIFrame* owner = ExpectedOwnerForChild(mOwner);
     if (owner != aParent.mOwner) {
-      MOZ_ASSERT(IsAnonBox(*owner),
+      MOZ_ASSERT(IsAnonBox(owner),
                  "Should only have expected owner weirdness when anon boxes are involved");
       bool found = false;
-      for (; owner; owner = ExpectedOwnerForChild(*owner)) {
+      for (; owner; owner = ExpectedOwnerForChild(owner)) {
         if (owner == aParent.mOwner) {
           found = true;
           break;
         }
       }
       MOZ_ASSERT(found, "Must have aParent.mOwner on our expected owner chain");
     }
   }
 #endif
 }
 
 nsChangeHint
-ServoRestyleState::ChangesHandledFor(const nsIFrame& aFrame) const
+ServoRestyleState::ChangesHandledFor(const nsIFrame* aFrame) const
 {
   if (!mOwner) {
     MOZ_ASSERT(!mChangesHandled);
     return mChangesHandled;
   }
 
   MOZ_ASSERT(mOwner == ExpectedOwnerForChild(aFrame),
              "Missed some frame in the hierarchy?");
@@ -2394,17 +2394,17 @@ public:
     //
     // TODO(emilio): The above may not be true for ::first-{line,letter}, but
     // we'll cross that bridge when we support those in stylo.
     if (mShouldComputeHints) {
       mShouldComputeHints = false;
       uint32_t equalStructs;
       mComputedHint = oldStyle->CalcStyleDifference(&aNewStyle, &equalStructs);
       mComputedHint = NS_RemoveSubsumedHints(
-        mComputedHint, mParentRestyleState.ChangesHandledFor(*aTextFrame));
+        mComputedHint, mParentRestyleState.ChangesHandledFor(aTextFrame));
     }
 
     if (mComputedHint) {
       mParentRestyleState.ChangeList().AppendChange(
         aTextFrame, aContent, mComputedHint);
     }
   }
 
@@ -2510,17 +2510,17 @@ UpdateOneAdditionalComputedStyle(nsIFram
         aFrame->Style(),
         /* aPseudoElement = */ nullptr);
 
   uint32_t equalStructs; // Not used, actually.
   nsChangeHint childHint =
     aOldContext.CalcStyleDifference(newStyle, &equalStructs);
   if (!aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
     childHint = NS_RemoveSubsumedHints(
-        childHint, aRestyleState.ChangesHandledFor(*aFrame));
+        childHint, aRestyleState.ChangesHandledFor(aFrame));
   }
 
   if (childHint) {
     if (childHint & nsChangeHint_ReconstructFrame) {
       // If we generate a reconstruct here, remove any non-reconstruct hints we
       // may have already generated for this content.
       aRestyleState.ChangeList().PopChangesForContent(aFrame->GetContent());
     }
@@ -2680,17 +2680,17 @@ RestyleManager::ProcessPostTraversal(
     MOZ_ASSERT(primaryFrame);
 
     nsIFrame* maybeAnonBoxChild;
     if (isOutOfFlow) {
       maybeAnonBoxChild = primaryFrame->GetPlaceholderFrame();
     } else {
       maybeAnonBoxChild = primaryFrame;
       changeHint = NS_RemoveSubsumedHints(
-        changeHint, aRestyleState.ChangesHandledFor(*styleFrame));
+        changeHint, aRestyleState.ChangesHandledFor(styleFrame));
     }
 
     // If the parent wasn't restyled, the styles of our anon box parents won't
     // change either.
     if ((aFlags & ServoPostTraversalFlags::ParentWasRestyled) &&
         maybeAnonBoxChild->ParentIsWrapperAnonBox()) {
       aRestyleState.AddPendingWrapperRestyle(
         ServoRestyleState::TableAwareParentFor(maybeAnonBoxChild));
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -100,20 +100,20 @@ public:
                "Someone forgot to call ProcessWrapperRestyles!");
   }
 
   nsStyleChangeList& ChangeList() { return mChangeList; }
   ServoStyleSet& StyleSet() { return mStyleSet; }
 
 #ifdef DEBUG
   void AssertOwner(const ServoRestyleState& aParentState) const;
-  nsChangeHint ChangesHandledFor(const nsIFrame&) const;
+  nsChangeHint ChangesHandledFor(const nsIFrame*) const;
 #else
   void AssertOwner(const ServoRestyleState&) const {}
-  nsChangeHint ChangesHandledFor(const nsIFrame&) const
+  nsChangeHint ChangesHandledFor(const nsIFrame*) const
   {
     return mChangesHandled;
   }
 #endif
 
   // Add a pending wrapper restyle.  We don't have to do anything if the thing
   // being added is already last in the list, but otherwise we do want to add
   // it, in order for ProcessWrapperRestyles to work correctly.
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10776,17 +10776,17 @@ nsIFrame::UpdateStyleOfOwnedChildFrame(
              "a ResolveSameStructsAs call to ensure structs are cached on "
              "aNewComputedStyle");
 
   // If aChildFrame is out of flow, then aRestyleState's "changes handled by the
   // parent" doesn't apply to it, because it may have some other parent in the
   // frame tree.
   if (!aChildFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
     childHint = NS_RemoveSubsumedHints(
-      childHint, aRestyleState.ChangesHandledFor(*aChildFrame));
+      childHint, aRestyleState.ChangesHandledFor(aChildFrame));
   }
   if (childHint) {
     if (childHint & nsChangeHint_ReconstructFrame) {
       // If we generate a reconstruct here, remove any non-reconstruct hints we
       // may have already generated for this content.
       aRestyleState.ChangeList().PopChangesForContent(
         aChildFrame->GetContent());
     }
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -50,28 +50,31 @@ static std::bitset<128> GetForbiddenSdpP
   forbidden[2] = true;
   forbidden[19] = true;
   for (uint16_t i = 64; i < 96; ++i) {
     forbidden[i] = true;
   }
   return forbidden;
 }
 
-static std::string GetRandomHex()
+static std::string GetRandomHex(size_t words)
 {
-  uint32_t rand;
-  SECStatus rv =
-    PK11_GenerateRandom(reinterpret_cast<unsigned char*>(&rand), sizeof(rand));
-  if (rv != SECSuccess) {
-    MOZ_CRASH();
-    return "";
+  std::ostringstream os;
+
+  for (size_t i = 0; i < words; ++i) {
+    uint32_t rand;
+    SECStatus rv =
+      PK11_GenerateRandom(reinterpret_cast<unsigned char*>(&rand), sizeof(rand));
+    if (rv != SECSuccess) {
+      MOZ_CRASH();
+      return "";
+    }
+
+    os << std::hex << std::setfill('0') << std::setw(8) << rand;
   }
-
-  std::ostringstream os;
-  os << std::hex << std::setfill('0') << std::setw(8) << rand;
   return os.str();
 }
 
 nsresult
 JsepSessionImpl::Init()
 {
   mLastError.clear();
 
@@ -83,18 +86,18 @@ JsepSessionImpl::Init()
   SetupDefaultCodecs();
   SetupDefaultRtpExtensions();
 
   mRunRustParser = Preferences::GetBool("media.peerconnection.sdp.rust.enabled",
                                         false);
   mRunSdpComparer = Preferences::GetBool("media.peerconnection.sdp.rust.compare",
                                          false);
 
-  mIceUfrag = GetRandomHex();
-  mIcePwd = GetRandomHex();
+  mIceUfrag = GetRandomHex(1);
+  mIcePwd = GetRandomHex(4);
   return NS_OK;
 }
 
 nsresult
 JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver)
 {
   mLastError.clear();
   MOZ_MTLOG(ML_DEBUG, "[" << mName << "]: Adding transceiver.");
@@ -2385,18 +2388,18 @@ JsepSessionImpl::SetIceRestarting(bool r
   if (restarting) {
     // not restarting -> restarting
     if (!IsIceRestarting()) {
       // We don't set this more than once, so the old ufrag/pwd is preserved
       // even if we CreateOffer({iceRestart:true}) multiple times in a row.
       mOldIceUfrag = mIceUfrag;
       mOldIcePwd = mIcePwd;
     }
-    mIceUfrag = GetRandomHex();
-    mIcePwd = GetRandomHex();
+    mIceUfrag = GetRandomHex(1);
+    mIcePwd = GetRandomHex(4);
   } else if (IsIceRestarting()) {
     // restarting -> not restarting, restore old ufrag/pwd
     mIceUfrag = mOldIceUfrag;
     mIcePwd = mOldIcePwd;
     mOldIceUfrag.clear();
     mOldIcePwd.clear();
   }
 }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -391,17 +391,17 @@ var BrowserApp = {
       "Session:GetHistory",
       "Session:Navigate",
       "Session:Reload",
       "Session:Stop",
       "Telemetry:CustomTabsPing",
     ]);
 
     // Initialize the default l10n resource sources for L10nRegistry.
-    let locales = Services.locale.getPackagedLocales();
+    let locales = Services.locale.packagedLocales;
     const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
     L10nRegistry.registerSource(greSource);
 
     // Provide compatibility for add-ons like QuitNow that send "Browser:Quit"
     // as an observer notification.
     Services.obs.addObserver((subject, topic, data) =>
         this.quit(data ? JSON.parse(data) : undefined), "Browser:Quit");
 
@@ -1693,17 +1693,17 @@ var BrowserApp = {
       aBrowser.contentWindow.removeEventListener("resize", onResize);
       if (!gotResize) {
         onResize();
       }
     }, 500);
   },
 
   getUALocalePref: function () {
-    return Services.locale.getRequestedLocale() || undefined;
+    return Services.locale.requestedLocale || undefined;
   },
 
   getOSLocalePref: function () {
     try {
       return Services.prefs.getCharPref("intl.locale.os");
     } catch (e) {
       return undefined;
     }
@@ -1770,19 +1770,19 @@ var BrowserApp = {
 
         // Rebuild strings, in case we're mirroring OS locale.
         Strings.flush();
         break;
       }
 
       case "Locale:Changed": {
         if (data) {
-          Services.locale.setRequestedLocales([data.languageTag]);
+          Services.locale.requestedLocales = [data.languageTag];
         } else {
-          Services.locale.setRequestedLocales([]);
+          Services.locale.requestedLocales = [];
         }
 
         console.log("Gecko display locale: " + this.getUALocalePref());
 
         // Rebuild strings to reflect the new locale.
         Strings.flush();
 
         // Make sure we use the right Accept-Language header.
--- a/mobile/android/components/DirectoryProvider.js
+++ b/mobile/android/components/DirectoryProvider.js
@@ -101,17 +101,17 @@ DirectoryProvider.prototype = {
       array.push(commonPlugins);
 
     let localePlugins = searchPlugins.clone();
     localePlugins.append("locale");
     if (!localePlugins.exists())
       return;
 
     let curLocale = "";
-    let reqLocales = Services.locale.getRequestedLocales();
+    let reqLocales = Services.locale.requestedLocales;
     if (reqLocales.length > 0) {
       curLocale = reqLocales[0];
     }
 
     if (curLocale) {
       let curLocalePlugins = localePlugins.clone();
       curLocalePlugins.append(curLocale);
       if (curLocalePlugins.exists()) {
--- a/mobile/android/components/geckoview/GeckoViewStartup.js
+++ b/mobile/android/components/geckoview/GeckoViewStartup.js
@@ -114,23 +114,23 @@ GeckoViewStartup.prototype = {
         });
 
         // This initializes Telemetry for GeckoView only in the parent process.
         // The Telemetry initialization for the content process is performed in
         // ContentProcessSingleton.js for consistency with Desktop Telemetry.
         GeckoViewTelemetryController.setup();
 
         // Initialize the default l10n resource sources for L10nRegistry.
-        let locales = Services.locale.getPackagedLocales();
+        let locales = Services.locale.packagedLocales;
         const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
         L10nRegistry.registerSource(greSource);
 
         // Listen for global EventDispatcher messages
         EventDispatcher.instance.registerListener(
-          (aEvent, aData, aCallback) => Services.locale.setRequestedLocales([aData.languageTag]),
+          (aEvent, aData, aCallback) => Services.locale.requestedLocales = [aData.languageTag],
           "GeckoView:SetLocale");
         break;
       }
     }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GeckoViewStartup]);
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
@@ -20,14 +20,14 @@ import org.junit.runner.RunWith
 class LocaleTest : BaseSessionTest() {
 
     @Test fun setLocale() {
         sessionRule.runtime.getSettings().setLocale("en-GB");
 
         val index = sessionRule.waitForChromeJS(String.format(
                 "(function() {" +
                 "  return ChromeUtils.import('resource://gre/modules/Services.jsm', {})" +
-                "    .Services.locale.getRequestedLocales().indexOf('en-GB');" +
+                "    .Services.locale.requestedLocales.indexOf('en-GB');" +
                 "})()")) as Double;
 
         assertThat("Requested locale is found", index, greaterThanOrEqualTo(0.0));
     }
 }
--- a/testing/mozbase/mozrunner/setup.py
+++ b/testing/mozbase/mozrunner/setup.py
@@ -2,17 +2,17 @@
 # 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/.
 
 from __future__ import absolute_import
 
 from setuptools import setup, find_packages
 
 PACKAGE_NAME = 'mozrunner'
-PACKAGE_VERSION = '7.0.1'
+PACKAGE_VERSION = '7.0.2'
 
 desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)"""
 
 deps = [
     'mozdevice>=1.*',
     'mozfile==1.*',
     'mozinfo>=0.7,<2',
     'mozlog==3.*',
--- a/testing/tps/setup.py
+++ b/testing/tps/setup.py
@@ -10,17 +10,17 @@ version = '0.6'
 
 deps = ['httplib2 == 0.9.2',
         'mozfile == 1.2',
         'mozhttpd == 0.7',
         'mozinfo >= 0.10',
         'mozinstall == 1.16',
         'mozprocess == 0.26',
         'mozprofile == 2.0.0',
-        'mozrunner == 7.0.1',
+        'mozrunner == 7.0.2',
         'mozversion == 1.5',
        ]
 
 # we only support python 2.6+ right now
 assert sys.version_info[0] == 2
 assert sys.version_info[1] >= 6
 
 setup(name='tps',
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -1486,17 +1486,17 @@ class Extension extends ExtensionData {
     return StartupCache.locales.get([this.id, this.version, locale],
                                     () => super.readLocaleFile(locale))
       .then(result => {
         this.localeData.messages.set(locale, result);
       });
   }
 
   get manifestCacheKey() {
-    return [this.id, this.version, Services.locale.getAppLocaleAsLangTag()];
+    return [this.id, this.version, Services.locale.appLocaleAsLangTag];
   }
 
   get isPrivileged() {
     return (this.addonData.signedState === AddonManager.SIGNEDSTATE_PRIVILEGED ||
             this.addonData.signedState === AddonManager.SIGNEDSTATE_SYSTEM ||
             this.addonData.builtIn ||
             (AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS &&
              this.addonData.temporarilyInstalled));
@@ -1718,17 +1718,17 @@ class Extension extends ExtensionData {
   // Reads the locale file for the given Gecko-compatible locale code, or if
   // no locale is given, the available locale closest to the UI locale.
   // Sets the currently selected locale on success.
   async initLocale(locale = undefined) {
     if (locale === undefined) {
       let locales = await this.promiseLocales();
 
       let matches = Services.locale.negotiateLanguages(
-        Services.locale.getAppLocalesAsLangTags(),
+        Services.locale.appLocalesAsLangTags,
         Array.from(locales.keys()),
         this.defaultLocale);
 
       locale = matches[0];
     }
 
     return super.initLocale(locale);
   }
--- a/toolkit/components/extensions/ExtensionCommon.jsm
+++ b/toolkit/components/extensions/ExtensionCommon.jsm
@@ -1924,17 +1924,17 @@ LocaleData.prototype = {
 
   get acceptLanguages() {
     let result = Services.prefs.getComplexValue("intl.accept_languages", Ci.nsIPrefLocalizedString).data;
     return result.split(/\s*,\s*/g);
   },
 
 
   get uiLocale() {
-    return Services.locale.getAppLocaleAsBCP47();
+    return Services.locale.appLocaleAsBCP47;
   },
 };
 
 defineLazyGetter(LocaleData.prototype, "availableLocales", function() {
   return new Set([this.BUILTIN, this.selectedLocale, this.defaultLocale]
                  .filter(locale => this.messages.has(locale)));
 });
 
--- a/toolkit/components/extensions/test/xpcshell/test_ext_i18n.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_i18n.js
@@ -6,21 +6,21 @@ ChromeUtils.import("resource://gre/modul
 // to use the right timeout for content scripts executed at document_idle.
 ExtensionTestUtils.mockAppInfo();
 
 const server = createHttpServer();
 server.registerDirectory("/data/", do_get_file("data"));
 
 const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
 
-var originalReqLocales = Services.locale.getRequestedLocales();
+var originalReqLocales = Services.locale.requestedLocales;
 
 registerCleanupFunction(() => {
   Preferences.reset("intl.accept_languages");
-  Services.locale.setRequestedLocales(originalReqLocales);
+  Services.locale.requestedLocales = originalReqLocales;
 });
 
 
 add_task(async function test_i18n() {
   function runTests(assertEq) {
     let _ = browser.i18n.getMessage.bind(browser.i18n);
 
     let url = browser.runtime.getURL("/");
@@ -216,34 +216,34 @@ add_task(async function test_i18n_negoti
   };
 
   // At the moment extension language negotiation is tied to Firefox language
   // negotiation result. That means that to test an extension in `fr`, we need
   // to mock `fr` being available in Firefox and then request it.
   //
   // In the future, we should provide some way for tests to decouple their
   // language selection from that of Firefox.
-  Services.locale.setAvailableLocales(["en-US", "fr", "jp"]);
+  Services.locale.availableLocales = ["en-US", "fr", "jp"];
 
   let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
 
   for (let [lang, msg] of [["en-US", "English."], ["jp", "\u65e5\u672c\u8a9e"]]) {
-    Services.locale.setRequestedLocales([lang]);
+    Services.locale.requestedLocales = [lang];
 
     let extension = ExtensionTestUtils.loadExtension(extensionData);
     await extension.startup();
     await extension.awaitMessage("content-ready");
 
     extension.sendMessage(msg);
     await extension.awaitMessage("background-script-finished");
     await extension.awaitMessage("content-script-finished");
 
     await extension.unload();
   }
-  Services.locale.setRequestedLocales(originalReqLocales);
+  Services.locale.requestedLocales = originalReqLocales;
 
   await contentPage.close();
 });
 
 
 add_task(async function test_get_accept_languages() {
   function checkResults(source, results, expected) {
     browser.test.assertEq(
@@ -378,17 +378,17 @@ add_task(async function test_get_ui_lang
 
   extension.sendMessage(["expect-results", "en-US"]);
 
   await extension.awaitMessage("background-done");
   await extension.awaitMessage("content-done");
 
   // We don't currently have a good way to mock this.
   if (false) {
-    Services.locale.setRequestedLocales(["he"]);
+    Services.locale.requestedLocales = ["he"];
 
     extension.sendMessage(["expect-results", "he"]);
 
     await extension.awaitMessage("background-done");
     await extension.awaitMessage("content-done");
   }
 
   await contentPage.close();
--- a/toolkit/components/extensions/test/xpcshell/test_ext_i18n_css.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_i18n_css.js
@@ -124,24 +124,24 @@ async function test_i18n_css(options = {
 
   // We don't currently have a good way to mock this.
   if (false) {
     const DIR = "intl.uidirection";
 
     // We don't wind up actually switching the chrome registry locale, since we
     // don't have a chrome package for Hebrew. So just override it, and force
     // RTL directionality.
-    const origReqLocales = Services.locale.getRequestedLocales();
-    Services.locale.setRequestedLocales(["he"]);
+    const origReqLocales = Services.locale.requestedLocales;
+    Services.locale.requestedLocales = ["he"];
     Preferences.set(DIR, 1);
 
     css = await fetch(baseURL + "locale.css");
     equal(css, '* { content: "he rtl ltr right left" }', "CSS file localized in mochitest scope");
 
-    Services.locale.setRequestedLocales(origReqLocales);
+    Services.locale.requestedLocales = origReqLocales;
     Preferences.reset(DIR);
   }
 
   await extension.awaitFinish("i18n-css");
   await extension.unload();
 }
 
 add_task(async function startup() {
--- a/toolkit/components/extensions/test/xpcshell/test_ext_startup_cache.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_startup_cache.js
@@ -64,17 +64,17 @@ add_task(async function() {
   }
 
   // At the moment extension language negotiation is tied to Firefox language
   // negotiation result. That means that to test an extension in `fr`, we need
   // to mock `fr` being available in Firefox and then request it.
   //
   // In the future, we should provide some way for tests to decouple their
   // language selection from that of Firefox.
-  Services.locale.setAvailableLocales(["en-US", "fr", "jp"]);
+  Services.locale.availableLocales = ["en-US", "fr", "jp"];
 
   await extension.startup();
 
   equal(extension.version, "1.0", "Expected extension version");
   let manifest = await getManifest();
   equal(manifest.name, "en-US 1.0", "Got expected manifest name");
 
 
@@ -83,17 +83,17 @@ add_task(async function() {
   await extension.awaitStartup();
 
   equal(extension.version, "1.0", "Expected extension version");
   manifest = await getManifest();
   equal(manifest.name, "en-US 1.0", "Got expected manifest name");
 
 
   info("Change locale to 'fr' and restart");
-  Services.locale.setRequestedLocales(["fr"]);
+  Services.locale.requestedLocales = ["fr"];
   await AddonTestUtils.promiseRestartManager();
   await extension.awaitStartup();
 
   equal(extension.version, "1.0", "Expected extension version");
   manifest = await getManifest();
   equal(manifest.name, "fr 1.0", "Got expected manifest name");
 
 
@@ -101,17 +101,17 @@ add_task(async function() {
   await extension.upgrade(makeExtension({version: "1.1"}));
 
   equal(extension.version, "1.1", "Expected extension version");
   manifest = await getManifest();
   equal(manifest.name, "fr 1.1", "Got expected manifest name");
 
 
   info("Change locale to 'en-US' and restart");
-  Services.locale.setRequestedLocales(["en-US"]);
+  Services.locale.requestedLocales = ["en-US"];
   await AddonTestUtils.promiseRestartManager();
   await extension.awaitStartup();
 
   equal(extension.version, "1.1", "Expected extension version");
   manifest = await getManifest();
   equal(manifest.name, "en-US 1.1", "Got expected manifest name");
 
 
--- a/toolkit/components/mozintl/mozIntl.js
+++ b/toolkit/components/mozintl/mozIntl.js
@@ -17,17 +17,17 @@ const languageTagMatch = /^([a-z]{2,3}|[
 
 /**
  * This helper function retrives currently used app locales, allowing
  * all mozIntl APIs to use the current regional prefs locales unless
  * called with explicitly listed locales.
  */
 function getLocales(locales) {
   if (!locales) {
-    return Services.locale.getRegionalPrefsLocales();
+    return Services.locale.regionalPrefsLocales;
   }
   return locales;
 }
 
 function getDateTimePatternStyle(option) {
   switch (option) {
     case "full":
       return osPrefs.dateTimeFormatStyleFull;
--- a/toolkit/components/normandy/lib/NormandyDriver.jsm
+++ b/toolkit/components/normandy/lib/NormandyDriver.jsm
@@ -32,17 +32,17 @@ var NormandyDriver = function(sandboxMan
   }
   const {sandbox} = sandboxManager;
 
   return {
     testing: false,
 
     get locale() {
       if (Services.locale.getAppLocaleAsLangTag) {
-        return Services.locale.getAppLocaleAsLangTag();
+        return Services.locale.getAppLocaleAsLangTag;
       }
 
       return Cc["@mozilla.org/chrome/chrome-registry;1"]
         .getService(Ci.nsIXULChromeRegistry)
         .getSelectedLocale("global");
     },
 
     get userId() {
--- a/toolkit/components/reputationservice/test/unit/test_app_rep_maclinux.js
+++ b/toolkit/components/reputationservice/test/unit/test_app_rep_maclinux.js
@@ -69,24 +69,24 @@ add_task(function test_setup() {
   // Ensure safebrowsing is enabled for this test, even if the app
   // doesn't have it enabled.
   Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", true);
   Services.prefs.setBoolPref("browser.safebrowsing.downloads.enabled", true);
   // Set block table explicitly, no need for the allow table though
   Services.prefs.setCharPref("urlclassifier.downloadBlockTable",
                              "goog-badbinurl-shavar");
   // SendRemoteQueryInternal needs locale preference.
-  let originalReqLocales = Services.locale.getRequestedLocales();
-  Services.locale.setRequestedLocales(["en-US"]);
+  let originalReqLocales = Services.locale.requestedLocales;
+  Services.locale.requestedLocales = ["en-US"];
 
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("browser.safebrowsing.malware.enabled");
     Services.prefs.clearUserPref("browser.safebrowsing.downloads.enabled");
     Services.prefs.clearUserPref("urlclassifier.downloadBlockTable");
-    Services.locale.setRequestedLocales(originalReqLocales);
+    Services.locale.requestedLocales = originalReqLocales;
   });
 
   gHttpServer = new HttpServer();
   gHttpServer.registerDirectory("/", do_get_cwd());
 
   function createVerdict(aShouldBlock) {
     // We can't programmatically create a protocol buffer here, so just
     // hardcode some already serialized ones.
--- a/toolkit/components/reputationservice/test/unit/test_app_rep_windows.js
+++ b/toolkit/components/reputationservice/test/unit/test_app_rep_windows.js
@@ -158,25 +158,25 @@ add_task(async function test_setup() {
   Services.prefs.setBoolPref("browser.safebrowsing.downloads.enabled", true);
   // Set block and allow tables explicitly, since the allowlist is normally
   // disabled on comm-central.
   Services.prefs.setCharPref("urlclassifier.downloadBlockTable",
                              "goog-badbinurl-shavar");
   Services.prefs.setCharPref("urlclassifier.downloadAllowTable",
                              "goog-downloadwhite-digest256");
   // SendRemoteQueryInternal needs locale preference.
-  let originalReqLocales = Services.locale.getRequestedLocales();
-  Services.locale.setRequestedLocales(["en-US"]);
+  let originalReqLocales = Services.locale.requestedLocales;
+  Services.locale.requestedLocales = ["en-US"];
 
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("browser.safebrowsing.malware.enabled");
     Services.prefs.clearUserPref("browser.safebrowsing.downloads.enabled");
     Services.prefs.clearUserPref("urlclassifier.downloadBlockTable");
     Services.prefs.clearUserPref("urlclassifier.downloadAllowTable");
-    Services.locale.setRequestedLocales(originalReqLocales);
+    Services.locale.requestedLocales = originalReqLocales;
   });
 
   gHttpServer = new HttpServer();
   gHttpServer.registerDirectory("/", do_get_cwd());
 
   function createVerdict(aShouldBlock) {
     // We can't programmatically create a protocol buffer here, so just
     // hardcode some already serialized ones.
--- a/toolkit/components/resistfingerprinting/LanguagePrompt.jsm
+++ b/toolkit/components/resistfingerprinting/LanguagePrompt.jsm
@@ -59,17 +59,17 @@ class _LanguagePrompt {
     try {
       Services.obs.removeObserver(this, kTopicHttpOnModifyRequest);
     } catch (e) {
       // do nothing
     }
   }
 
   _shouldPromptForLanguagePref() {
-    return (Services.locale.getAppLocaleAsLangTag().substr(0, 2) !== "en")
+    return (Services.locale.appLocaleAsLangTag.substr(0, 2) !== "en")
       && (Services.prefs.getIntPref(kPrefSpoofEnglish) === 0);
   }
 
   _handlePrefChanged(data) {
     switch (data) {
       case kPrefResistFingerprinting:
         this._handleResistFingerprintingChanged();
         break;
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -795,17 +795,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() {
-  return Services.locale.getRequestedLocale();
+  return Services.locale.requestedLocale;
 }
 
 /**
  * Wrapper for nsIPrefBranch::getComplexValue.
  * @param aPrefName
  *        The name of the pref to get.
  * @returns aDefault if the requested pref doesn't exist.
  */
@@ -3436,17 +3436,17 @@ SearchService.prototype = {
       json = JSON.parse(list);
     } catch (e) {
       Cu.reportError("parseListJSON: Failed to parse list.json: " + e);
       dump("parseListJSON: Failed to parse list.json: " + e + "\n");
       return;
     }
 
     let searchSettings;
-    let locale = Services.locale.getAppLocaleAsBCP47();
+    let locale = Services.locale.appLocaleAsBCP47;
     if ("locales" in json &&
         locale in json.locales) {
       searchSettings = json.locales[locale];
     } else {
       // No locales were found, so use the JSON as is.
       // It should have a default section.
       if (!("default" in json)) {
         Cu.reportError("parseListJSON: Missing default in list.json");
--- a/toolkit/components/search/tests/xpcshell/head_search.js
+++ b/toolkit/components/search/tests/xpcshell/head_search.js
@@ -229,17 +229,17 @@ function getDefaultEngineName(isUS) {
   let chan = NetUtil.newChannel({
     uri: "resource://search-plugins/list.json",
     loadUsingSystemPrincipal: true,
   });
   let searchSettings = parseJsonFromStream(chan.open2());
   let defaultEngineName = searchSettings.default.searchDefault;
 
   if (isUS === undefined)
-    isUS = Services.locale.getRequestedLocale() == "en-US" && isUSTimezone();
+    isUS = Services.locale.requestedLocale == "en-US" && isUSTimezone();
 
   if (isUS && ("US" in searchSettings &&
                "searchDefault" in searchSettings.US)) {
     defaultEngineName = searchSettings.US.searchDefault;
   }
   return defaultEngineName;
 }
 
@@ -248,17 +248,17 @@ function getDefaultEngineList(isUS) {
   let chan = NetUtil.newChannel({
     uri: "resource://search-plugins/list.json",
     loadUsingSystemPrincipal: true,
   });
   let json = parseJsonFromStream(chan.open2());
   let visibleDefaultEngines = json.default.visibleDefaultEngines;
 
   if (isUS === undefined)
-    isUS = Services.locale.getRequestedLocale() == "en-US" && isUSTimezone();
+    isUS = Services.locale.requestedLocale == "en-US" && isUSTimezone();
 
   if (isUS) {
     let searchSettings = json.locales["en-US"];
     if ("US" in searchSettings &&
         "visibleDefaultEngines" in searchSettings.US) {
       visibleDefaultEngines = searchSettings.US.visibleDefaultEngines;
     }
     // From nsSearchService.js
--- a/toolkit/components/search/tests/xpcshell/test_list_json_locale.js
+++ b/toolkit/components/search/tests/xpcshell/test_list_json_locale.js
@@ -14,34 +14,34 @@ function run_test() {
 // Override list.json with test data from data/list.json
 // and check that different locale is working
 add_task(async function test_listJSONlocale() {
   let url = "resource://test/data/";
   let resProt = Services.io.getProtocolHandler("resource")
                         .QueryInterface(Ci.nsIResProtocolHandler);
   resProt.setSubstitution("search-plugins", Services.io.newURI(url));
 
-  Services.locale.setAvailableLocales(["de"]);
-  Services.locale.setRequestedLocales(["de"]);
+  Services.locale.availableLocales = ["de"];
+  Services.locale.requestedLocales = ["de"];
 
   await asyncInit();
 
   Assert.ok(Services.search.isInitialized, "search initialized");
 
   let sortedEngines = Services.search.getEngines();
   Assert.equal(sortedEngines.length, 1, "Should have only one engine");
 });
 
 
 // Check that switching locale switches search engines
 add_task(async function test_listJSONlocaleSwitch() {
   let promise = waitForSearchNotification("reinit-complete");
 
-  Services.locale.setAvailableLocales(["fr"]);
-  Services.locale.setRequestedLocales(["fr"]);
+  Services.locale.availableLocales = ["fr"];
+  Services.locale.requestedLocales = ["fr"];
 
   await promise;
 
   Assert.ok(Services.search.isInitialized, "search initialized");
 
   let sortedEngines = Services.search.getEngines();
   Assert.equal(sortedEngines.length, 2, "Should have two engines");
 });
--- a/toolkit/components/search/tests/xpcshell/test_paramSubstitution.js
+++ b/toolkit/components/search/tests/xpcshell/test_paramSubstitution.js
@@ -29,18 +29,18 @@ add_task(async function test_paramSubsti
   // The same parameter can be used more than once.
   check("{searchTerms}/{searchTerms}", searchTerms + "/" + searchTerms);
 
   // Optional parameters are replaced if we known them.
   check("{searchTerms?}", searchTerms);
   check("{unknownOptional?}", "");
   check("{unknownRequired}", "{unknownRequired}");
 
-  check("{language}", Services.locale.getRequestedLocale());
-  check("{language?}", Services.locale.getRequestedLocale());
+  check("{language}", Services.locale.requestedLocale);
+  check("{language?}", Services.locale.requestedLocale);
 
   engine.wrappedJSObject._queryCharset = "UTF-8";
   check("{inputEncoding}", "UTF-8");
   check("{inputEncoding?}", "UTF-8");
   check("{outputEncoding}", "UTF-8");
   check("{outputEncoding?}", "UTF-8");
 
   // 'Unsupported' parameters with hard coded values used only when the parameter is required.
@@ -58,10 +58,10 @@ add_task(async function test_paramSubsti
   engine.wrappedJSObject._loadPath = "[app]"; // This will make _isDefault return true;
   check("{moz:distributionID}", "");
   Services.prefs.setCharPref("browser.search.distributionID", "xpcshell");
   check("{moz:distributionID}", "xpcshell");
   Services.prefs.setBoolPref("browser.search.official", true);
   check("{moz:official}", "official");
   Services.prefs.setBoolPref("browser.search.official", false);
   check("{moz:official}", "unofficial");
-  check("{moz:locale}", Services.locale.getRequestedLocale());
+  check("{moz:locale}", Services.locale.requestedLocale);
 });
--- a/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
@@ -293,17 +293,17 @@ function enforceBoolean(aValue) {
 }
 
 /**
  * Get the current browser locale.
  * @return a string with the locale or null on failure.
  */
 function getBrowserLocale() {
   try {
-    return Services.locale.getAppLocaleAsLangTag();
+    return Services.locale.appLocaleAsLangTag;
   } catch (e) {
     return null;
   }
 }
 
 /**
  * Get the current OS locale.
  * @return a string with the OS locale or null on failure.
--- a/toolkit/components/urlformatter/nsURLFormatter.js
+++ b/toolkit/components/urlformatter/nsURLFormatter.js
@@ -55,17 +55,17 @@ function nsURLFormatterService() {
   });
 }
 
 nsURLFormatterService.prototype = {
   classID: Components.ID("{e6156350-2be8-11db-a98b-0800200c9a66}"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIURLFormatter]),
 
   _defaults: {
-    LOCALE:           () => Services.locale.getAppLocaleAsLangTag(),
+    LOCALE:           () => Services.locale.appLocaleAsLangTag,
     REGION() {
       try {
         // When the geoip lookup failed to identify the region, we fallback to
         // the 'ZZ' region code to mean 'unknown'.
         return Services.prefs.getCharPref("browser.search.region") || "ZZ";
       } catch (e) {
         return "ZZ";
       }
--- a/toolkit/components/urlformatter/tests/unit/test_urlformatter.js
+++ b/toolkit/components/urlformatter/tests/unit/test_urlformatter.js
@@ -1,17 +1,17 @@
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 function run_test() {
   var formatter = Services.urlFormatter;
-  var locale = Services.locale.getAppLocaleAsLangTag();
+  var locale = Services.locale.appLocaleAsLangTag;
   var OSVersion = Services.sysinfo.getProperty("name") + " " +
                   Services.sysinfo.getProperty("version");
   try {
     OSVersion += " (" + Services.sysinfo.getProperty("secondaryLibrary") + ")";
   } catch (e) {}
   OSVersion = encodeURIComponent(OSVersion);
   var abi = Services.appinfo.XPCOMABI;
 
--- a/toolkit/components/utils/ClientEnvironment.jsm
+++ b/toolkit/components/utils/ClientEnvironment.jsm
@@ -113,17 +113,17 @@ class ClientEnvironmentBase {
         const { name, description, version } = plugin;
         acc[name] = { name, description, version };
         return acc;
       }, {});
     })();
   }
 
   static get locale() {
-    return Services.locale.getAppLocaleAsLangTag();
+    return Services.locale.appLocaleAsLangTag;
   }
 
   static get doNotTrack() {
     return Services.prefs.getBoolPref("privacy.donottrackheader.enabled", false);
   }
 
   static get os() {
     function coerceToNumber(version) {
--- a/toolkit/content/widgets/datetimepopup.xml
+++ b/toolkit/content/widgets/datetimepopup.xml
@@ -105,17 +105,17 @@
           }
         ]]></body>
       </method>
       <method name="initPicker">
         <parameter name="detail"/>
         <body><![CDATA[
           // TODO: When bug 1376616 lands, replace this.setGregorian with
           //       mozIntl.Locale for setting calendar to Gregorian
-          const locale = this.setGregorian(Services.locale.getAppLocaleAsBCP47());
+          const locale = this.setGregorian(Services.locale.appLocaleAsBCP47);
           const dir = this.mozIntl.getLocaleInfo(locale).direction;
 
           switch (this.type) {
             case "time": {
               const { hour, minute } = detail.value;
               const format = detail.format || "12";
 
               this.postMessageToPicker({
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -613,20 +613,20 @@ var dataProviders = {
     });
   },
 
   intl: function intl(done) {
     const osPrefs =
       Cc["@mozilla.org/intl/ospreferences;1"].getService(Ci.mozIOSPreferences);
     done({
       localeService: {
-        requested: Services.locale.getRequestedLocales(),
-        available: Services.locale.getAvailableLocales(),
-        supported: Services.locale.getAppLocalesAsBCP47(),
-        regionalPrefs: Services.locale.getRegionalPrefsLocales(),
+        requested: Services.locale.requestedLocales,
+        available: Services.locale.availableLocales,
+        supported: Services.locale.appLocalesAsBCP47,
+        regionalPrefs: Services.locale.regionalPrefsLocales,
         defaultLocale: Services.locale.defaultLocale,
       },
       osPrefs: {
         systemLocales: osPrefs.getSystemLocales(),
         regionalPrefsLocales: osPrefs.getRegionalPrefsLocales(),
       },
     });
   },
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -233,17 +233,17 @@ async function promiseCallProvider(aProv
   }
 }
 
 /**
  * Gets the currently selected locale for display.
  * @return  the selected locale or "en-US" if none is selected
  */
 function getLocale() {
-  return Services.locale.getRequestedLocale() || "en-US";
+  return Services.locale.requestedLocale || "en-US";
 }
 
 const WEB_EXPOSED_ADDON_PROPERTIES = [ "id", "version", "type", "name",
                                        "description", "isActive" ];
 
 function webAPIForAddon(addon) {
   if (!addon) {
     return null;
--- a/toolkit/mozapps/extensions/Blocklist.jsm
+++ b/toolkit/mozapps/extensions/Blocklist.jsm
@@ -268,17 +268,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.
  *
  * @returns {string} The current requested locale.
  */
 function getLocale() {
-  return Services.locale.getRequestedLocale();
+  return Services.locale.requestedLocale;
 }
 
 /* Get the distribution pref values, from defaults only */
 function getDistributionPrefValue(aPrefName) {
   return Services.prefs.getDefaultBranch(null).getCharPref(aPrefName, "default");
 }
 
 /**
--- a/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.jsm
@@ -342,17 +342,17 @@ class AddonInternal {
     /**
      * this.locales is a list of objects that have property `locales`.
      * It's value is an array of locale codes.
      *
      * First, we reduce this nested structure to a flat list of locale codes.
      */
     const locales = [].concat(...this.locales.map(loc => loc.locales));
 
-    let requestedLocales = Services.locale.getRequestedLocales();
+    let requestedLocales = Services.locale.requestedLocales;
 
     /**
      * If en-US is not in the list, add it as the last fallback.
      */
     if (!requestedLocales.includes("en-US")) {
       requestedLocales.push("en-US");
     }
 
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -505,17 +505,17 @@ var SlightlyLessDodgyBootstrapMonitor = 
 function isNightlyChannel() {
   var channel = Services.prefs.getCharPref("app.update.channel", "default");
 
   return channel != "aurora" && channel != "beta" && channel != "release" && channel != "esr";
 }
 
 
 async function restartWithLocales(locales) {
-  Services.locale.setRequestedLocales(locales);
+  Services.locale.requestedLocales = locales;
   await promiseRestartManager();
 }
 
 /**
  * Returns a map of Addon objects for installed add-ons with the given
  * IDs. The returned map contains a key for the ID of each add-on that
  * is found. IDs for add-ons which do not exist are not present in the
  * map.
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_url_parameters.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_url_parameters.js
@@ -79,17 +79,17 @@ add_task(async function test_blocklist_d
   });
 
   // Some values have to be on the default branch to work
   var defaults = Services.prefs.QueryInterface(Ci.nsIPrefService)
                        .getDefaultBranch(null);
   defaults.setCharPref(PREF_APP_UPDATE_CHANNEL, EXPECTED.channel);
   defaults.setCharPref(PREF_APP_DISTRIBUTION, EXPECTED.distribution);
   defaults.setCharPref(PREF_APP_DISTRIBUTION_VERSION, EXPECTED.distribution_version);
-  Services.locale.setRequestedLocales([EXPECTED.locale]);
+  Services.locale.requestedLocales = [EXPECTED.locale];
 
   // This should correctly escape everything
   Services.prefs.setCharPref(PREF_BLOCKLIST_URL, "http://example.com/2?" + PARAMS);
   Services.prefs.setBoolPref(PREF_BLOCKLIST_ENABLED, true);
 
   await updateBlocklist();
   await gotRequest;
 });
--- a/toolkit/mozapps/extensions/test/xpcshell/test_manifest_locales.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_manifest_locales.js
@@ -57,17 +57,17 @@ const ADDON = {
       name: "en-CA Name",
       description: "en-CA Description",
     },
   ],
 };
 
 add_task(async function setup() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1");
-  Services.locale.setRequestedLocales(["fr-FR"]);
+  Services.locale.requestedLocales = ["fr-FR"];
 
   await promiseStartupManager();
   await promiseInstallXPI(ADDON);
 });
 
 add_task(async function test_1() {
   let addon = await AddonManager.getAddonByID(ID);
   Assert.notEqual(addon, null);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js
@@ -72,17 +72,17 @@ const XPIS = {};
 for (let [name, addon] of Object.entries(ADDONS)) {
   XPIS[name] = AddonTestUtils.createTempXPIFile(addon);
   testserver.registerFile(`/addons/${name}.xpi`, XPIS[name]);
 }
 
 add_task(async function setup() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
 
-  Services.locale.setRequestedLocales(["fr-FR"]);
+  Services.locale.requestedLocales = ["fr-FR"];
 });
 
 add_task(async function() {
   AddonTestUtils.updateReason = AddonManager.UPDATE_WHEN_USER_REQUESTED;
 
   await promiseStartupManager();
   await promiseInstallXPI({
     id: "addon1@tests.mozilla.org",
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_langpack.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_langpack.js
@@ -68,49 +68,49 @@ add_task(async function setup() {
  * the language pack registers and unregisters correct
  * languages at various stages.
  */
 add_task(async function() {
   await promiseStartupManager();
 
   // Make sure that `und` locale is not installed.
   equal(L10nRegistry.getAvailableLocales().includes("und"), false);
-  equal(Services.locale.getAvailableLocales().includes("und"), false);
+  equal(Services.locale.availableLocales.includes("und"), false);
 
   let [, {addon}] = await Promise.all([
     promiseLangpackStartup(),
     AddonTestUtils.promiseInstallXPI(ADDONS.langpack_1),
   ]);
 
   // Now make sure that `und` locale is available.
   equal(L10nRegistry.getAvailableLocales().includes("und"), true);
-  equal(Services.locale.getAvailableLocales().includes("und"), true);
+  equal(Services.locale.availableLocales.includes("und"), true);
 
   await addon.disable();
 
   // It is not available after the langpack has been disabled.
   equal(L10nRegistry.getAvailableLocales().includes("und"), false);
-  equal(Services.locale.getAvailableLocales().includes("und"), false);
+  equal(Services.locale.availableLocales.includes("und"), false);
 
   // This quirky code here allows us to handle a scenario where enabling the
   // addon is synchronous or asynchronous.
   await Promise.all([
     promiseLangpackStartup(),
     addon.enable(),
   ]);
 
   // After re-enabling it, the `und` locale is available again.
   equal(L10nRegistry.getAvailableLocales().includes("und"), true);
-  equal(Services.locale.getAvailableLocales().includes("und"), true);
+  equal(Services.locale.availableLocales.includes("und"), true);
 
   await addon.uninstall();
 
   // After the langpack has been uninstalled, no more `und` in locales.
   equal(L10nRegistry.getAvailableLocales().includes("und"), false);
-  equal(Services.locale.getAvailableLocales().includes("und"), false);
+  equal(Services.locale.availableLocales.includes("und"), false);
 });
 
 /**
  * This test verifies that registries are able to load and return
  * correct strings available in the language pack.
  */
 add_task(async function() {
   let [, {addon}] = await Promise.all([
@@ -129,36 +129,36 @@ add_task(async function() {
     // Browser string
     let ctxs = L10nRegistry.generateContexts(["und"], ["browser.ftl"]);
     let ctx0 = (await ctxs.next()).value;
     equal(ctx0.hasMessage("message-browser"), true);
   }
 
   {
     // Test chrome package
-    let reqLocs = Services.locale.getRequestedLocales();
-    Services.locale.setRequestedLocales(["und"]);
+    let reqLocs = Services.locale.requestedLocales;
+    Services.locale.requestedLocales = ["und"];
 
     let bundle = Services.strings.createBundle(
       "chrome://global/locale/test.properties"
     );
     let entry = bundle.GetStringFromName("message");
     equal(entry, "Value from .properties");
 
-    Services.locale.setRequestedLocales(reqLocs);
+    Services.locale.requestedLocales = reqLocs;
   }
 
   await addon.uninstall();
   await promiseShutdownManager();
 });
 
 add_task(async function test_amazing_disappearing_langpacks() {
   let check = (yes) => {
     equal(L10nRegistry.getAvailableLocales().includes("und"), yes);
-    equal(Services.locale.getAvailableLocales().includes("und"), yes);
+    equal(Services.locale.availableLocales.includes("und"), yes);
   };
 
   await promiseStartupManager();
 
   check(false);
 
   await Promise.all([
     promiseLangpackStartup(),
--- a/toolkit/profile/content/profileSelection.js
+++ b/toolkit/profile/content/profileSelection.js
@@ -93,34 +93,33 @@ function acceptDialog() {
   }
   gDialogParams.objects.insertElementAt(profileLock.nsIProfileLock, 0);
 
   gProfileService.selectedProfile = selectedProfile.profile;
   gProfileService.defaultProfile = selectedProfile.profile;
   updateStartupPrefs();
 
   gDialogParams.SetInt(0, 1);
+  /* Bug 257777 */
+  gDialogParams.SetInt(1, document.getElementById("offlineState").checked ? 1 : 0);
 
   gDialogParams.SetString(0, selectedProfile.profile.name);
 
   return true;
 }
 
 function exitDialog() {
   updateStartupPrefs();
 
   return true;
 }
 
 function updateStartupPrefs() {
   var autoSelectLastProfile = document.getElementById("autoSelectLastProfile");
   gProfileService.startWithLastProfile = autoSelectLastProfile.checked;
-
-  /* Bug 257777 */
-  gProfileService.startOffline = document.getElementById("offlineState").checked;
 }
 
 // handle key event on listboxes
 function onProfilesKey(aEvent) {
   switch ( aEvent.keyCode ) {
   case KeyEvent.DOM_VK_BACK_SPACE:
     if (AppConstants.platform != "macosx")
       break;
--- a/toolkit/profile/nsIToolkitProfileService.idl
+++ b/toolkit/profile/nsIToolkitProfileService.idl
@@ -9,17 +9,16 @@ interface nsISimpleEnumerator;
 interface nsIFile;
 interface nsIToolkitProfile;
 interface nsIProfileLock;
 
 [scriptable, uuid(1947899b-f369-48fa-89da-f7c37bb1e6bc)]
 interface nsIToolkitProfileService : nsISupports
 {
     attribute boolean startWithLastProfile;
-    attribute boolean startOffline;
 
     readonly attribute nsISimpleEnumerator /*nsIToolkitProfile*/ profiles;
 
     /**
      * The currently selected profile (the one used or about to be used by the
      * browser).
      */
     attribute nsIToolkitProfile selectedProfile;
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -114,18 +114,17 @@ public:
     NS_DECL_NSITOOLKITPROFILESERVICE
 
 private:
     friend class nsToolkitProfile;
     friend class nsToolkitProfileFactory;
     friend nsresult NS_NewToolkitProfileService(nsIToolkitProfileService**);
 
     nsToolkitProfileService() :
-        mStartWithLast(true),
-        mStartOffline(false)
+        mStartWithLast(true)
     {
         gService = this;
     }
     ~nsToolkitProfileService()
     {
         gService = nullptr;
     }
 
@@ -135,17 +134,16 @@ private:
 
     RefPtr<nsToolkitProfile>  mFirst;
     nsCOMPtr<nsIToolkitProfile> mChosen;
     nsCOMPtr<nsIToolkitProfile> mDefault;
     nsCOMPtr<nsIFile>           mAppData;
     nsCOMPtr<nsIFile>           mTempData;
     nsCOMPtr<nsIFile>           mListFile;
     bool mStartWithLast;
-    bool mStartOffline;
 
     static nsToolkitProfileService *gService;
 
     class ProfileEnumerator final : public nsSimpleEnumerator
     {
     public:
         NS_DECL_NSISIMPLEENUMERATOR
 
@@ -569,30 +567,16 @@ nsToolkitProfileService::SetStartWithLas
 NS_IMETHODIMP
 nsToolkitProfileService::GetStartWithLastProfile(bool *aResult)
 {
     *aResult = mStartWithLast;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsToolkitProfileService::GetStartOffline(bool *aResult)
-{
-    *aResult = mStartOffline;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsToolkitProfileService::SetStartOffline(bool aValue)
-{
-    mStartOffline = aValue;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsToolkitProfileService::GetProfiles(nsISimpleEnumerator* *aResult)
 {
     *aResult = new ProfileEnumerator(this->mFirst);
     if (!*aResult)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult);
     return NS_OK;
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -2114,16 +2114,17 @@ static ReturnAbortOnError
 ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
                    nsINativeAppSupport* aNative)
 {
   nsresult rv;
 
   nsCOMPtr<nsIFile> profD, profLD;
   char16_t* profileNamePtr;
   nsAutoCString profileName;
+  bool offline = false;
 
   {
     ScopedXPCOMStartup xpcom;
     rv = xpcom.Initialize();
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Initialize the graphics prefs, some of the paths need them before
     // any other graphics is initialized (e.g., showing the profile chooser.)
@@ -2167,16 +2168,20 @@ ShowProfileManager(nsIToolkitProfileServ
       NS_ENSURE_SUCCESS_LOG(rv, rv);
 
       aProfileSvc->Flush();
 
       int32_t dialogConfirmed;
       rv = ioParamBlock->GetInt(0, &dialogConfirmed);
       if (NS_FAILED(rv) || dialogConfirmed == 0) return NS_ERROR_ABORT;
 
+      int32_t startOffline;
+      rv = ioParamBlock->GetInt(1, &startOffline);
+      offline = NS_SUCCEEDED(rv) && startOffline == 1;
+
       nsCOMPtr<nsIProfileLock> lock;
       rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIProfileLock),
                                     getter_AddRefs(lock));
       NS_ENSURE_SUCCESS_LOG(rv, rv);
 
       rv = lock->GetDirectory(getter_AddRefs(profD));
       NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2192,18 +2197,16 @@ ShowProfileManager(nsIToolkitProfileServ
       lock->Unlock();
     }
   }
 
   SaveFileToEnv("XRE_PROFILE_PATH", profD);
   SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
   SaveWordToEnv("XRE_PROFILE_NAME", profileName);
 
-  bool offline = false;
-  aProfileSvc->GetStartOffline(&offline);
   if (offline) {
     SaveToEnv("XRE_START_OFFLINE=1");
   }
   if (gRestartedByOS) {
     // Re-add this argument when actually starting the application.
     char** newArgv = (char**) realloc(gRestartArgv, sizeof(char*) * (gRestartArgc + 2));
     NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY);
     gRestartArgv = newArgv;
--- a/uriloader/exthandler/HandlerService.js
+++ b/uriloader/exthandler/HandlerService.js
@@ -83,17 +83,17 @@ HandlerService.prototype = {
         // This platform does not have any default protocol handlers configured.
         return;
       }
       throw ex;
     }
 
     try {
       prefsDefaultHandlersVersion = Number(prefsDefaultHandlersVersion.data);
-      let locale = Services.locale.getAppLocaleAsLangTag();
+      let locale = Services.locale.appLocaleAsLangTag;
 
       let defaultHandlersVersion =
           this._store.data.defaultHandlersVersion[locale] || 0;
       if (defaultHandlersVersion < prefsDefaultHandlersVersion) {
         this._injectDefaultProtocolHandlers();
         this._store.data.defaultHandlersVersion[locale] =
           prefsDefaultHandlersVersion;
       }
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -229,27 +229,16 @@ bool nsView::IsEffectivelyVisible()
 {
   for (nsView* v = this; v; v = v->mParent) {
     if (v->GetVisibility() == nsViewVisibility_kHide)
       return false;
   }
   return true;
 }
 
-uint32_t nsView::GetParentWindowScaleFactor()
-{
-  uint32_t scaleFactor = 1;
-  nsIWidget* parentWidget =
-    GetParent() ? GetParent()->GetNearestWidget(nullptr) : nullptr;
-  if (parentWidget) {
-    scaleFactor = parentWidget->RoundsWidgetCoordinatesTo();
-  }
-  return scaleFactor;
-}
-
 LayoutDeviceIntRect nsView::CalcWidgetBounds(nsWindowType aType)
 {
   int32_t p2a = mViewManager->AppUnitsPerDevPixel();
 
   nsRect viewBounds(mDimBounds);
 
   nsView* parent = GetParent();
   nsIWidget* parentWidget = nullptr;
@@ -326,19 +315,17 @@ void nsView::DoResetWidgetBounds(bool aM
   MOZ_ASSERT(mWindow, "Why was this called??");
 
   // Hold this ref to make sure it stays alive.
   nsCOMPtr<nsIWidget> widget = mWindow;
 
   // Stash a copy of these and use them so we can handle this being deleted (say
   // from sync painting/flushing from Show/Move/Resize on the widget).
   LayoutDeviceIntRect newBounds;
-#if !defined(MOZ_WIDGET_GTK)
   RefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
-#endif
 
   nsWindowType type = widget->WindowType();
 
   LayoutDeviceIntRect curBounds = widget->GetClientBounds();
   bool invisiblePopup = type == eWindowType_popup &&
                         ((curBounds.IsEmpty() && mDimBounds.IsEmpty()) ||
                          mVis == nsViewVisibility_kHide);
 
@@ -368,25 +355,17 @@ void nsView::DoResetWidgetBounds(bool aM
   bool changedSize = curBounds.Size() != newBounds.Size();
 
   // Child views are never attached to top level widgets, this is safe.
 
   // Coordinates are converted to desktop pixels for window Move/Resize APIs,
   // because of the potential for device-pixel coordinate spaces for mixed
   // hidpi/lodpi screens to overlap each other and result in bad placement
   // (bug 814434).
-#if defined(MOZ_WIDGET_GTK)
-  // The GetDesktopToDeviceScale does not work under Wayland because we
-  // don't know the absolute position of the window in Wayland. We can
-  // use the same for X11, because it always returns 1 for both calls.
-  DesktopToLayoutDeviceScale scale = mozilla::DesktopToLayoutDeviceScale(
-    GetParentWindowScaleFactor());
-#else
   DesktopToLayoutDeviceScale scale = dx->GetDesktopToDeviceScale();
-#endif
 
   DesktopRect deskRect = newBounds / scale;
   if (changedPos) {
     if (changedSize && !aMoveOnly) {
       widget->ResizeClient(deskRect.X(), deskRect.Y(),
                            deskRect.Width(), deskRect.Height(),
                            aInvalidateChangedSize);
     } else {
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -457,19 +457,16 @@ private:
 
   void ResetWidgetBounds(bool aRecurse, bool aForceSync);
   void AssertNoWindow();
 
   void NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible);
 
   // Update the cached RootViewManager for all view manager descendents.
   void InvalidateHierarchy();
-  // Return current scale factor of the monitor where the parent window of the popup
-  // is mostly located.
-  uint32_t GetParentWindowScaleFactor();
 
   nsViewManager    *mViewManager;
   nsView           *mParent;
   nsCOMPtr<nsIWidget> mWindow;
   nsCOMPtr<nsIWidget> mPreviousWindow;
   nsView           *mNextSibling;
   nsView           *mFirstChild;
   nsIFrame         *mFrame;
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -222,22 +222,16 @@ protected:
   virtual void Run(AutoSlowOperation& aAso) override
   {
     JSObject* callback = mCallback->CallbackPreserveColor();
     nsIGlobalObject* global = callback ? xpc::NativeGlobal(callback) : nullptr;
     if (global && !global->IsDying()) {
       mCallback->Call("promise callback");
       aAso.CheckForInterrupt();
     }
-    // Now that mCallback is no longer needed, clear any pointers it contains to
-    // JS GC things. This removes any storebuffer entries associated with those
-    // pointers, which can cause problems by taking up memory and by triggering
-    // minor GCs. This otherwise would not happen until the next minor GC or
-    // cycle collection.
-    mCallback->Reset();
   }
 
   virtual bool Suppressed() override
   {
     nsIGlobalObject* global =
       xpc::NativeGlobal(mCallback->CallbackPreserveColor());
     return global && global->IsInSyncOperation();
   }