Bug 1365891 - interpret preprocessing instructions in DevTools addon bootstrap;r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Tue, 06 Jun 2017 14:36:44 +0200
changeset 589589 e48fdf6d478ba0e5bd122b416514cc82ec1595dc
parent 589150 cad53f061da634a16ea75887558301b77f65745d
child 631942 d8cc8d942d1f4aad01866afccc34bcea55deb02d
push id62438
push userjdescottes@mozilla.com
push dateTue, 06 Jun 2017 12:41:13 +0000
reviewersbgrins
bugs1365891
milestone55.0a1
Bug 1365891 - interpret preprocessing instructions in DevTools addon bootstrap;r=bgrins MozReview-Commit-ID: Dh5yYsXLWRf
devtools/bootstrap.js
--- a/devtools/bootstrap.js
+++ b/devtools/bootstrap.js
@@ -6,16 +6,17 @@
 /* exported startup, shutdown, install, uninstall */
 
 "use strict";
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
+const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
 
 // MultiWindowKeyListener instance for Ctrl+Alt+R key
 let listener;
 // nsIURI to the addon root folder
 let resourceURI;
 
 function actionOccurred(id) {
   let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
@@ -35,20 +36,66 @@ function readURI(uri) {
     charset: "UTF-8"
   });
 
   stream.close();
 
   return data;
 }
 
+/**
+ * Interpret the processing instructions contained in a preferences file, based on a
+ * limited set of supported #if statements. After we ship as an addon, we don't want to
+ * introduce anymore processing instructions, so all unrecognized preprocessing
+ * instructions will be treated as an error.
+ *
+ * This function is mostly copied from devtools/client/inspector/webpack/prefs-loader.js
+ *
+ * @param  {String} content
+ *         The string content of a preferences file.
+ * @return {String} the content stripped of preprocessing instructions.
+ */
+function interpretPreprocessingInstructions(content) {
+  const ifMap = {
+    "#if MOZ_UPDATE_CHANNEL == beta": AppConstants.MOZ_UPDATE_CHANNEL === "beta",
+    "#if defined(NIGHTLY_BUILD)": AppConstants.NIGHTLY_BUILD,
+    "#ifdef MOZ_DEV_EDITION": AppConstants.MOZ_DEV_EDITION,
+    "#ifdef RELEASE_OR_BETA": AppConstants.RELEASE_OR_BETA,
+  };
+
+  let lines = content.split("\n");
+  let ignoring = false;
+  let newLines = [];
+  let continuation = false;
+  for (let line of lines) {
+    if (line.startsWith("#if")) {
+      if (!(line in ifMap)) {
+        throw new Error("missing line in ifMap: " + line);
+      }
+      ignoring = !ifMap[line];
+    } else if (line.startsWith("#else")) {
+      ignoring = !ignoring;
+    }
+
+    let isPrefLine = /^ *pref\("([^"]+)"/.test(line);
+    if (continuation || (!ignoring && isPrefLine)) {
+      newLines.push(line);
+
+      // The call to pref(...); might span more than one line.
+      continuation = !/\);/.test(line);
+    }
+  }
+  return newLines.join("\n");
+}
+
 // Read a preference file and set all of its defined pref as default values
 // (This replicates the behavior of preferences files from mozilla-central)
 function processPrefFile(url) {
   let content = readURI(url);
+  content = interpretPreprocessingInstructions(content);
   content.match(/pref\("[^"]+",\s*.+\s*\)/g).forEach(item => {
     let m = item.match(/pref\("([^"]+)",\s*(.+)\s*\)/);
     let name = m[1];
     let val = m[2];
 
     // Prevent overriding prefs that have been changed by the user
     if (Services.prefs.prefHasUserValue(name)) {
       return;