Bug 1298012 - Migrate devtools/shared to use l10n.js instead of Services.string;r=tromey draft
authorJulian Descottes <jdescottes@mozilla.com>
Thu, 25 Aug 2016 17:01:51 +0200
changeset 405521 6ec7ec372be7e24d279c87b659b60dd69f7ddec3
parent 405520 bcde76adde0f3e1f08996d7ccf11b6a7672abe58
child 405522 c3c5ae473a2e051c6436893c7c26d1504424288e
push id27511
push userjdescottes@mozilla.com
push dateThu, 25 Aug 2016 15:53:03 +0000
reviewerstromey
bugs1298012, 1297733
milestone51.0a1
Bug 1298012 - Migrate devtools/shared to use l10n.js instead of Services.string;r=tromey I explicitly did not migrate the localizations of the external properties file brand.properties. This should be handled as part of Bug 1297733. MozReview-Commit-ID: JXomOmr37xV
devtools/shared/fronts/csscoverage.js
devtools/shared/gcli/commands/highlight.js
devtools/shared/gcli/source/lib/gcli/l10n.js
devtools/shared/gcli/source/lib/gcli/util/l10n.js
devtools/shared/inspector/css-logic.js
devtools/shared/security/prompt.js
--- a/devtools/shared/fronts/csscoverage.js
+++ b/devtools/shared/fronts/csscoverage.js
@@ -1,31 +1,27 @@
 /* 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 Services = require("Services");
 const {cssUsageSpec} = require("devtools/shared/specs/csscoverage");
 const protocol = require("devtools/shared/protocol");
 const {custom} = protocol;
 
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools-shared/locale/csscoverage.properties");
+
 loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
 
 /**
  * Allow: let foo = l10n.lookup("csscoverageFoo");
  */
 const l10n = exports.l10n = {
-  _URI: "chrome://devtools-shared/locale/csscoverage.properties",
-  lookup: function (msg) {
-    if (this._stringBundle == null) {
-      this._stringBundle = Services.strings.createBundle(this._URI);
-    }
-    return this._stringBundle.GetStringFromName(msg);
-  }
+  lookup: (msg) => L10N.getStr(msg)
 };
 
 /**
  * Running more than one usage report at a time is probably bad for performance
  * and it isn't particularly useful, and it's confusing from a notification POV
  * so we only allow one.
  */
 var isRunning = false;
--- a/devtools/shared/gcli/commands/highlight.js
+++ b/devtools/shared/gcli/commands/highlight.js
@@ -1,26 +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 l10n = require("gcli/l10n");
-const Services = require("Services");
 const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
 require("devtools/server/actors/inspector");
 const {
   BoxModelHighlighter,
   HighlighterEnvironment
 } = require("devtools/server/actors/highlighters");
 
-XPCOMUtils.defineLazyGetter(this, "nodesSelected", function () {
-  return Services.strings.createBundle("chrome://devtools-shared/locale/gclicommands.properties");
-});
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools-shared/locale/gclicommands.properties");
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
 
 // How many maximum nodes can be highlighted in parallel
 const MAX_HIGHLIGHTED_ELEMENTS = 100;
 
 // Store the environment object used to create highlighters so it can be
 // destroyed later.
 var highlighterEnv;
@@ -134,17 +132,17 @@ exports.items = [
           hideInfoBar: !args.showinfobar,
           hideGuides: args.hideguides,
           showOnly: args.region
         });
         exports.highlighters.push(highlighter);
         i++;
       }
 
-      let highlightText = nodesSelected.GetStringFromName("highlightOutputConfirm2");
+      let highlightText = L10N.getStr("highlightOutputConfirm2");
       let output = PluralForm.get(args.selector.length, highlightText)
                              .replace("%1$S", args.selector.length);
       if (args.selector.length > i) {
         output = l10n.lookupFormat("highlightOutputMaxReached",
           ["" + args.selector.length, "" + i]);
       }
 
       return output;
--- a/devtools/shared/gcli/source/lib/gcli/l10n.js
+++ b/devtools/shared/gcli/source/lib/gcli/l10n.js
@@ -9,71 +9,66 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-'use strict';
+"use strict";
 
-var Cc = require('chrome').Cc;
-var Ci = require('chrome').Ci;
-var Cu = require('chrome').Cu;
+var Cc = require("chrome").Cc;
+var Ci = require("chrome").Ci;
 
-var prefSvc = Cc['@mozilla.org/preferences-service;1']
-                        .getService(Ci.nsIPrefService);
+var prefSvc = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
 var prefBranch = prefSvc.getBranch(null).QueryInterface(Ci.nsIPrefBranch);
 
-var Services = require("Services");
-var stringBundle = Services.strings.createBundle(
-        'chrome://devtools-shared/locale/gclicommands.properties');
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools-shared/locale/gclicommands.properties");
 
 /**
  * Lookup a string in the GCLI string bundle
  */
-exports.lookup = function(name) {
+exports.lookup = function (name) {
   try {
-    return stringBundle.GetStringFromName(name);
-  }
-  catch (ex) {
-    throw new Error('Failure in lookup(\'' + name + '\')');
+    return L10N.getStr(name);
+  } catch (ex) {
+    throw new Error("Failure in lookup('" + name + "')");
   }
 };
 
 /**
  * An alternative to lookup().
- * <code>l10n.lookup('BLAH') === l10n.propertyLookup.BLAH</code>
+ * <code>l10n.lookup("BLAH") === l10n.propertyLookup.BLAH</code>
  * This is particularly nice for templates because you can pass
  * <code>l10n:l10n.propertyLookup</code> in the template data and use it
  * like <code>${l10n.BLAH}</code>
  */
 exports.propertyLookup = new Proxy({}, {
-  get: function(rcvr, name) {
+  get: function (rcvr, name) {
     return exports.lookup(name);
   }
 });
 
 /**
  * Lookup a string in the GCLI string bundle
  */
-exports.lookupFormat = function(name, swaps) {
+exports.lookupFormat = function (name, swaps) {
   try {
-    return stringBundle.formatStringFromName(name, swaps, swaps.length);
-  }
-  catch (ex) {
-    throw new Error('Failure in lookupFormat(\'' + name + '\')');
+    return L10N.getFormatStr(name, ...swaps);
+  } catch (ex) {
+    throw new Error("Failure in lookupFormat('" + name + "')");
   }
 };
 
 /**
- * Allow GCLI users to be hidden by the 'devtools.chrome.enabled' pref.
+ * Allow GCLI users to be hidden by the "devtools.chrome.enabled" pref.
  * Use it in commands like this:
  * <pre>
  *   name: "somecommand",
  *   hidden: l10n.hiddenByChromePref(),
- *   exec: function(args, context) { ... }
+ *   exec: function (args, context) { ... }
  * </pre>
  */
-exports.hiddenByChromePref = function() {
-  return !prefBranch.getBoolPref('devtools.chrome.enabled');
+exports.hiddenByChromePref = function () {
+  return !prefBranch.getBoolPref("devtools.chrome.enabled");
 };
--- a/devtools/shared/gcli/source/lib/gcli/util/l10n.js
+++ b/devtools/shared/gcli/source/lib/gcli/util/l10n.js
@@ -9,81 +9,72 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-'use strict';
-
-var Cu = require('chrome').Cu;
+"use strict";
 
-var XPCOMUtils = Cu.import('resource://gre/modules/XPCOMUtils.jsm', {}).XPCOMUtils;
-var Services = require("Services");
-
-var imports = {};
-XPCOMUtils.defineLazyGetter(imports, 'stringBundle', function () {
-  return Services.strings.createBundle('chrome://devtools-shared/locale/gcli.properties');
-});
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools-shared/locale/gcli.properties");
 
 /*
- * Not supported when embedded - we're doing things the Mozilla way not the
+ * Not supported when embedded - we"re doing things the Mozilla way not the
  * require.js way.
  */
-exports.registerStringsSource = function(modulePath) {
-  throw new Error('registerStringsSource is not available in mozilla');
+exports.registerStringsSource = function (modulePath) {
+  throw new Error("registerStringsSource is not available in mozilla");
 };
 
-exports.unregisterStringsSource = function(modulePath) {
-  throw new Error('unregisterStringsSource is not available in mozilla');
+exports.unregisterStringsSource = function (modulePath) {
+  throw new Error("unregisterStringsSource is not available in mozilla");
 };
 
-exports.lookupSwap = function(key, swaps) {
-  throw new Error('lookupSwap is not available in mozilla');
+exports.lookupSwap = function (key, swaps) {
+  throw new Error("lookupSwap is not available in mozilla");
 };
 
-exports.lookupPlural = function(key, ord, swaps) {
-  throw new Error('lookupPlural is not available in mozilla');
+exports.lookupPlural = function (key, ord, swaps) {
+  throw new Error("lookupPlural is not available in mozilla");
 };
 
-exports.getPreferredLocales = function() {
-  return [ 'root' ];
+exports.getPreferredLocales = function () {
+  return [ "root" ];
 };
 
 /** @see lookup() in lib/gcli/util/l10n.js */
-exports.lookup = function(key) {
+exports.lookup = function (key) {
   try {
     // Our memory leak hunter walks reachable objects trying to work out what
     // type of thing they are using object.constructor.name. If that causes
     // problems then we can avoid the unknown-key-exception with the following:
     /*
-    if (key === 'constructor') {
-      return { name: 'l10n-mem-leak-defeat' };
+    if (key === "constructor") {
+      return { name: "l10n-mem-leak-defeat" };
     }
     */
 
-    return imports.stringBundle.GetStringFromName(key);
-  }
-  catch (ex) {
-    console.error('Failed to lookup ', key, ex);
+    return L10N.getStr(key);
+  } catch (ex) {
+    console.error("Failed to lookup ", key, ex);
     return key;
   }
 };
 
 /** @see propertyLookup in lib/gcli/util/l10n.js */
 exports.propertyLookup = new Proxy({}, {
-  get: function(rcvr, name) {
+  get: function (rcvr, name) {
     return exports.lookup(name);
   }
 });
 
 /** @see lookupFormat in lib/gcli/util/l10n.js */
-exports.lookupFormat = function(key, swaps) {
+exports.lookupFormat = function (key, swaps) {
   try {
-    return imports.stringBundle.formatStringFromName(key, swaps, swaps.length);
-  }
-  catch (ex) {
-    console.error('Failed to format ', key, ex);
+    return L10N.getFormatStr(key, ...swaps);
+  } catch (ex) {
+    console.error("Failed to format ", key, ex);
     return key;
   }
 };
--- a/devtools/shared/inspector/css-logic.js
+++ b/devtools/shared/inspector/css-logic.js
@@ -37,16 +37,18 @@
  * helps them understand:
  * - why their expectations may not have been fulfilled
  * - how browsers process CSS
  * @constructor
  */
 
 const Services = require("Services");
 const CSSLexer = require("devtools/shared/css-lexer");
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const styleInspectorL10N = new LocalizationHelper("chrome://devtools-shared/locale/styleinspector.properties");
 
 /**
  * Special values for filter, in addition to an href these values can be used
  */
 exports.FILTER = {
   // show properties for all user style sheets.
   USER: "user",
   // USER, plus user-agent (i.e. browser) style sheets
@@ -65,26 +67,23 @@ exports.STATUS = {
   BEST: 3,
   MATCHED: 2,
   PARENT_MATCH: 1,
   UNMATCHED: 0,
   UNKNOWN: -1,
 };
 
 /**
- * Memoized lookup of a l10n string from a string bundle.
- * @param {string} name The key to lookup.
- * @returns A localized version of the given key.
+ * Lookup a l10n string in the shared styleinspector string bundle.
+ *
+ * @param {String} name
+ *        The key to lookup.
+ * @returns {String} A localized version of the given key.
  */
-exports.l10n = function (name) {
-  return exports._strings.GetStringFromName(name);
-};
-
-exports._strings = Services.strings
-  .createBundle("chrome://devtools-shared/locale/styleinspector.properties");
+exports.l10n = name => styleInspectorL10N.getStr(name);
 
 /**
  * Is the given property sheet a content stylesheet?
  *
  * @param {CSSStyleSheet} sheet a stylesheet
  * @return {boolean} true if the given stylesheet is a content stylesheet,
  * false otherwise.
  */
--- a/devtools/shared/security/prompt.js
+++ b/devtools/shared/security/prompt.js
@@ -9,20 +9,18 @@
 var { Ci } = require("chrome");
 var Services = require("Services");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "DebuggerSocket",
   "devtools/shared/security/socket", true);
 loader.lazyRequireGetter(this, "AuthenticationResult",
   "devtools/shared/security/auth", true);
 
-DevToolsUtils.defineLazyGetter(this, "bundle", () => {
-  const DBG_STRINGS_URI = "chrome://devtools-shared/locale/debugger.properties";
-  return Services.strings.createBundle(DBG_STRINGS_URI);
-});
+const {LocalizationHelper} = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools-shared/locale/debugger.properties");
 
 var Client = exports.Client = {};
 var Server = exports.Server = {};
 
 /**
  * During OOB_CERT authentication, a notification dialog like this is used to
  * to display a token which the user must transfer through some mechanism to the
  * server to authenticate the devices.
@@ -46,23 +44,21 @@ var Server = exports.Server = {};
  * @return object containing:
  *         * close: Function to hide the notification
  */
 Client.defaultSendOOB = ({ authResult, oob }) => {
   // Only show in the PENDING state
   if (authResult != AuthenticationResult.PENDING) {
     throw new Error("Expected PENDING result, got " + authResult);
   }
-  let title = bundle.GetStringFromName("clientSendOOBTitle");
-  let header = bundle.GetStringFromName("clientSendOOBHeader");
-  let hashMsg = bundle.formatStringFromName("clientSendOOBHash",
-                                            [oob.sha256], 1);
+  let title = L10N.getStr("clientSendOOBTitle");
+  let header = L10N.getStr("clientSendOOBHeader");
+  let hashMsg = L10N.getFormatStr("clientSendOOBHash", oob.sha256);
   let token = oob.sha256.replace(/:/g, "").toLowerCase() + oob.k;
-  let tokenMsg = bundle.formatStringFromName("clientSendOOBToken",
-                                             [token], 1);
+  let tokenMsg = L10N.getFormatStr("clientSendOOBToken", token);
   let msg = `${header}\n\n${hashMsg}\n${tokenMsg}`;
   let prompt = Services.prompt;
   let flags = prompt.BUTTON_POS_0 * prompt.BUTTON_TITLE_CANCEL;
 
   // Listen for the window our prompt opens, so we can close it programatically
   let promptWindow;
   let windowListener = {
     onOpenWindow(xulWindow) {
@@ -120,29 +116,25 @@ Client.defaultSendOOB = ({ authResult, o
  *          }
  *        }
  *        Specific authentication modes may include additional fields.  Check
  *        the different |allowConnection| methods in ./auth.js.
  * @return An AuthenticationResult value.
  *         A promise that will be resolved to the above is also allowed.
  */
 Server.defaultAllowConnection = ({ client, server }) => {
-  let title = bundle.GetStringFromName("remoteIncomingPromptTitle");
-  let header = bundle.GetStringFromName("remoteIncomingPromptHeader");
+  let title = L10N.getStr("remoteIncomingPromptTitle");
+  let header = L10N.getStr("remoteIncomingPromptHeader");
   let clientEndpoint = `${client.host}:${client.port}`;
-  let clientMsg =
-    bundle.formatStringFromName("remoteIncomingPromptClientEndpoint",
-                                [clientEndpoint], 1);
+  let clientMsg = L10N.getFormatStr("remoteIncomingPromptClientEndpoint", clientEndpoint);
   let serverEndpoint = `${server.host}:${server.port}`;
-  let serverMsg =
-    bundle.formatStringFromName("remoteIncomingPromptServerEndpoint",
-                                [serverEndpoint], 1);
-  let footer = bundle.GetStringFromName("remoteIncomingPromptFooter");
+  let serverMsg = L10N.getFormatStr("remoteIncomingPromptServerEndpoint", serverEndpoint);
+  let footer = L10N.getStr("remoteIncomingPromptFooter");
   let msg = `${header}\n\n${clientMsg}\n${serverMsg}\n\n${footer}`;
-  let disableButton = bundle.GetStringFromName("remoteIncomingPromptDisable");
+  let disableButton = L10N.getStr("remoteIncomingPromptDisable");
   let prompt = Services.prompt;
   let flags = prompt.BUTTON_POS_0 * prompt.BUTTON_TITLE_OK +
               prompt.BUTTON_POS_1 * prompt.BUTTON_TITLE_CANCEL +
               prompt.BUTTON_POS_2 * prompt.BUTTON_TITLE_IS_STRING +
               prompt.BUTTON_POS_1_DEFAULT;
   let result = prompt.confirmEx(null, title, msg, flags, null, null,
                                 disableButton, null, { value: false });
   if (result === 0) {
@@ -165,18 +157,18 @@ Server.defaultAllowConnection = ({ clien
  * convenient, such as reading a QR code.
  *
  * @return An object containing:
  *         * sha256: hash(ClientCert)
  *         * k     : K(random 128-bit number)
  *         A promise that will be resolved to the above is also allowed.
  */
 Server.defaultReceiveOOB = () => {
-  let title = bundle.GetStringFromName("serverReceiveOOBTitle");
-  let msg = bundle.GetStringFromName("serverReceiveOOBBody");
+  let title = L10N.getStr("serverReceiveOOBTitle");
+  let msg = L10N.getStr("serverReceiveOOBBody");
   let input = { value: null };
   let prompt = Services.prompt;
   let result = prompt.prompt(null, title, msg, input, null, { value: false });
   if (!result) {
     return null;
   }
   // Re-create original object from token
   input = input.value.trim();