Bug 1271761 - app update patch for adding CPU features/detection to update URL. r=mhowell, a=sylvestre
authorRobert Strong <robert.bugzilla@gmail.com>
Fri, 20 May 2016 18:17:43 -0700
changeset 333274 f77d5675d8f813fcb2793aedc36c38c6b40fd62f
parent 333273 dc972d877cd697c2c8f6248534f21bb5e1dba9ae
child 333275 9b770efcfb3f0b5127446d8a17682e2d7235ff51
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmhowell, sylvestre
bugs1271761
milestone48.0a2
Bug 1271761 - app update patch for adding CPU features/detection to update URL. r=mhowell, a=sylvestre
toolkit/modules/UpdateUtils.jsm
toolkit/mozapps/update/tests/unit_aus_update/urlConstruction.js
--- a/toolkit/modules/UpdateUtils.jsm
+++ b/toolkit/modules/UpdateUtils.jsm
@@ -69,16 +69,17 @@ this.UpdateUtils = {
    * @return The formatted URL.
    */
   formatUpdateURL(url) {
     url = url.replace(/%PRODUCT%/g, Services.appinfo.name);
     url = url.replace(/%VERSION%/g, Services.appinfo.version);
     url = url.replace(/%BUILD_ID%/g, Services.appinfo.appBuildID);
     url = url.replace(/%BUILD_TARGET%/g, Services.appinfo.OS + "_" + this.ABI);
     url = url.replace(/%OS_VERSION%/g, this.OSVersion);
+    url = url.replace(/%SYSTEM_CAPABILITIES%/g, gSystemCapabilities);
     if (/%LOCALE%/.test(url)) {
       url = url.replace(/%LOCALE%/g, this.Locale);
     }
     url = url.replace(/%CHANNEL%/g, this.UpdateChannel);
     url = url.replace(/%PLATFORM_VERSION%/g, Services.appinfo.platformVersion);
     url = url.replace(/%DISTRIBUTION%/g,
                       getDistributionPrefValue(PREF_APP_DISTRIBUTION));
     url = url.replace(/%DISTRIBUTION_VERSION%/g,
@@ -145,16 +146,55 @@ XPCOMUtils.defineLazyGetter(UpdateUtils,
   }
 
   Cu.reportError(FILE_UPDATE_LOCALE + " file doesn't exist in either the " +
                  "application or GRE directories");
 
   return null;
 });
 
+/**
+ * Provides adhoc system capability information for application update.
+ */
+XPCOMUtils.defineLazyGetter(this, "gSystemCapabilities", function aus_gSC() {
+  if (AppConstants.platform == "win") {
+    const PF_MMX_INSTRUCTIONS_AVAILABLE = 3; // MMX
+    const PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; // SSE
+    const PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10; // SSE2
+    const PF_SSE3_INSTRUCTIONS_AVAILABLE = 13; // SSE3
+
+    let lib = ctypes.open("kernel32.dll");
+    let IsProcessorFeaturePresent = lib.declare("IsProcessorFeaturePresent",
+                                                ctypes.winapi_abi,
+                                                ctypes.int32_t, /* success */
+                                                ctypes.uint32_t); /* DWORD */
+    let instructionSet = "unknown";
+    try {
+      if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "SSE3";
+      } else if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "SSE2";
+      } else if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "SSE";
+      } else if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "MMX";
+      }
+    } catch (e) {
+      instructionSet = "error";
+      Cu.reportError("Error getting processor instruction set. " +
+                     "Exception: " + e);
+    }
+
+    lib.close();
+    return instructionSet;
+  }
+
+  return "NA"
+});
+
 /* Windows only getter that returns the processor architecture. */
 XPCOMUtils.defineLazyGetter(this, "gWinCPUArch", function aus_gWinCPUArch() {
   // Get processor architecture
   let arch = "unknown";
 
   const WORD = ctypes.uint16_t;
   const DWORD = ctypes.uint32_t;
 
--- a/toolkit/mozapps/update/tests/unit_aus_update/urlConstruction.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/urlConstruction.js
@@ -344,87 +344,146 @@ function check_test_pt9() {
     osVersion = encodeURIComponent(osVersion);
   }
 
   Assert.equal(getResult(gRequestURL), osVersion,
                "the url param for %OS_VERSION%" + MSG_SHOULD_EQUAL);
   run_test_pt10();
 }
 
-// url constructed with %DISTRIBUTION%
+// url constructed with %SYSTEM_CAPABILITIES%
 function run_test_pt10() {
   gCheckFunc = check_test_pt10;
+  let url = URL_PREFIX + "%SYSTEM_CAPABILITIES%/";
+  debugDump("testing url constructed with %SYSTEM_CAPABILITIES% - " + url);
+  setUpdateURLOverride(url);
+  gUpdateChecker.checkForUpdates(updateCheckListener, true);
+}
+
+/**
+ * Provides system capability information for application update though it may
+ * be used by other consumers.
+ */
+function getSystemCapabilities() {
+  if (IS_WIN) {
+    const PF_MMX_INSTRUCTIONS_AVAILABLE = 3; // MMX
+    const PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; // SSE
+    const PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10; // SSE2
+    const PF_SSE3_INSTRUCTIONS_AVAILABLE = 13; // SSE3
+
+    let lib = ctypes.open("kernel32.dll");
+    let IsProcessorFeaturePresent = lib.declare("IsProcessorFeaturePresent",
+                                                ctypes.winapi_abi,
+                                                ctypes.int32_t, /* success */
+                                                ctypes.uint32_t); /* DWORD */
+    let instructionSet = "unknown";
+    try {
+      if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "SSE3";
+      } else if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "SSE2";
+      } else if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "SSE";
+      } else if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) {
+        instructionSet = "MMX";
+      }
+    } catch (e) {
+        Cu.reportError("Error getting processor instruction set. " +
+                       "Exception: " + e);
+    }
+
+    lib.close();
+    return instructionSet;
+  }
+
+  return "NA"
+}
+
+function check_test_pt10() {
+  let systemCapabilities = "NA";
+  if (IS_WIN) {
+    systemCapabilities = getSystemCapabilities();
+  }
+
+  Assert.equal(getResult(gRequestURL), systemCapabilities,
+               "the url param for %SYSTEM_CAPABILITIES%" + MSG_SHOULD_EQUAL);
+  run_test_pt11();
+}
+
+// url constructed with %DISTRIBUTION%
+function run_test_pt11() {
+  gCheckFunc = check_test_pt11;
   let url = URL_PREFIX + "%DISTRIBUTION%/";
   debugDump("testing url constructed with %DISTRIBUTION% - " + url);
   setUpdateURLOverride(url);
   gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_ID, "test_distro");
   gUpdateChecker.checkForUpdates(updateCheckListener, true);
 }
 
-function check_test_pt10() {
+function check_test_pt11() {
   Assert.equal(getResult(gRequestURL), "test_distro",
                "the url param for %DISTRIBUTION%" + MSG_SHOULD_EQUAL);
-  run_test_pt11();
+  run_test_pt12();
 }
 
 // url constructed with %DISTRIBUTION_VERSION%
-function run_test_pt11() {
-  gCheckFunc = check_test_pt11;
+function run_test_pt12() {
+  gCheckFunc = check_test_pt12;
   let url = URL_PREFIX + "%DISTRIBUTION_VERSION%/";
   debugDump("testing url constructed with %DISTRIBUTION_VERSION% - " + url);
   setUpdateURLOverride(url);
   gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_VERSION, "test_distro_version");
   gUpdateChecker.checkForUpdates(updateCheckListener, true);
 }
 
-function check_test_pt11() {
+function check_test_pt12() {
   Assert.equal(getResult(gRequestURL), "test_distro_version",
                "the url param for %DISTRIBUTION_VERSION%" + MSG_SHOULD_EQUAL);
-  run_test_pt12();
+  run_test_pt13();
 }
 
 // url with force param that doesn't already have a param - bug 454357
-function run_test_pt12() {
-  gCheckFunc = check_test_pt12;
+function run_test_pt13() {
+  gCheckFunc = check_test_pt13;
   let url = URL_PREFIX;
   debugDump("testing url with force param that doesn't already have a " +
             "param - " + url);
   setUpdateURLOverride(url);
   gUpdateChecker.checkForUpdates(updateCheckListener, true);
 }
 
-function check_test_pt12() {
+function check_test_pt13() {
   Assert.equal(getResult(gRequestURL), "?force=1",
                "the url query string for force" + MSG_SHOULD_EQUAL);
-  run_test_pt13();
+  run_test_pt14();
 }
 
 // url with force param that already has a param - bug 454357
-function run_test_pt13() {
-  gCheckFunc = check_test_pt13;
+function run_test_pt14() {
+  gCheckFunc = check_test_pt14;
   let url = URL_PREFIX + "?extra=param";
   debugDump("testing url with force param that already has a param - " + url);
   setUpdateURLOverride(url);
   gUpdateChecker.checkForUpdates(updateCheckListener, true);
 }
 
-function check_test_pt13() {
+function check_test_pt14() {
   Assert.equal(getResult(gRequestURL), "?extra=param&force=1",
                "the url query string for force with an extra string" +
                MSG_SHOULD_EQUAL);
-  run_test_pt14();
+  run_test_pt15();
 }
 
-function run_test_pt14() {
+function run_test_pt15() {
   Services.prefs.setCharPref("app.update.custom", "custom");
-  gCheckFunc = check_test_pt14;
+  gCheckFunc = check_test_pt15;
   let url = URL_PREFIX + "?custom=%CUSTOM%";
   debugDump("testing url constructed with %CUSTOM% - " + url);
   setUpdateURLOverride(url);
   gUpdateChecker.checkForUpdates(updateCheckListener, true);
 }
 
-function check_test_pt14() {
+function check_test_pt15() {
   Assert.equal(getResult(gRequestURL), "?custom=custom&force=1",
                "the url query string for force with a custom string" +
                MSG_SHOULD_EQUAL);
   doTestFinish();
 }