Bug 1521664 - Add About Dialog test for the otherInstanceHandlingUpdates panel ID. r=mhowell
authorRobert Strong <robert.bugzilla@gmail.com>
Tue, 22 Jan 2019 16:18:17 -0800
changeset 514932 898ad7622b617e4d425fc76f1ed36ccbd429dced
parent 514931 795a8cb833cd1c28b6e4afb65333a69c01e75938
child 514933 b9509c720efefee2df87d9fd45bced75aa7b0665
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmhowell
bugs1521664
milestone66.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
Bug 1521664 - Add About Dialog test for the otherInstanceHandlingUpdates panel ID. r=mhowell
toolkit/mozapps/update/nsUpdateService.js
toolkit/mozapps/update/tests/browser/browser.ini
toolkit/mozapps/update/tests/browser/browser_about_fc_check_otherInstance.js
toolkit/mozapps/update/tests/browser/head.js
toolkit/mozapps/update/tests/data/shared.js
toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
toolkit/mozapps/update/tests/unit_aus_update/canCheckForAndCanApplyUpdates.js
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -1801,16 +1801,25 @@ UpdateService.prototype = {
 
         this.pauseDownload();
         // Prevent leaking the downloader (bug 454964)
         this._downloader = null;
         // In case an update check is in progress.
         Cc["@mozilla.org/updates/update-checker;1"].
           createInstance(Ci.nsIUpdateChecker).stopCurrentCheck();
         break;
+      case "test-close-handle-update-mutex":
+        if (Cu.isInAutomation) {
+          if (AppConstants.platform == "win" && gUpdateMutexHandle) {
+            LOG("UpdateService:observe - closing mutex handle for testing");
+            closeHandle(gUpdateMutexHandle);
+            gUpdateMutexHandle = null;
+          }
+        }
+        break;
     }
   },
 
   /**
    * The following needs to happen during the post-update-processing
    * notification from nsUpdateServiceStub.js:
    * 1. post update processing
    * 2. resume of a download that was in progress during a previous session
--- a/toolkit/mozapps/update/tests/browser/browser.ini
+++ b/toolkit/mozapps/update/tests/browser/browser.ini
@@ -10,16 +10,19 @@ support-files =
 [browser_about_bc_downloaded_staged.js]
 skip-if = (os == "linux" && verify) || asan
 reason = Bug 1520672 and Bug 1168003
 [browser_about_fc_check_cantApply.js]
 skip-if = os != 'win'
 reason = test must be able to prevent file deletion.
 [browser_about_fc_check_malformedXML.js]
 [browser_about_fc_check_noUpdate.js]
+[browser_about_fc_check_otherInstance.js]
+skip-if = os != 'win'
+reason = Windows only feature.
 [browser_about_fc_check_unsupported.js]
 [browser_about_fc_downloadAuto.js]
 [browser_about_fc_downloadAuto_staging.js]
 skip-if = (os == "linux" && verify) || asan
 reason = Bug 1520672 and Bug 1168003
 [browser_about_fc_downloadOptIn.js]
 [browser_about_fc_downloadOptIn_staging.js]
 skip-if = (os == "linux" && verify) || asan
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_about_fc_check_otherInstance.js
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for About Dialog foreground check for updates
+// with another application instance handling updates.
+add_task(async function aboutDialog_foregroundCheck_otherInstance() {
+  setOtherInstanceHandlingUpdates();
+
+  let updateParams = "";
+  await runAboutDialogUpdateTest(updateParams, false, [
+    {
+      panelId: "otherInstanceHandlingUpdates",
+      checkActiveUpdate: null,
+      continueFile: null,
+    },
+  ]);
+});
--- a/toolkit/mozapps/update/tests/browser/head.js
+++ b/toolkit/mozapps/update/tests/browser/head.js
@@ -98,17 +98,17 @@ async function continueFileHandler(leafN
  * when the user doesn't have write access to update. Since this is only
  * possible on Windows the function throws when it is called on other platforms.
  * This uses registerCleanupFunction to remove the lock and the file when the
  * test completes.
  *
  * @throws If the function is called on a platform other than Windows.
  */
 function lockWriteTestFile() {
-  if (AppConstants.platform != "win") {
+  if (!IS_WIN) {
     throw new Error("Windows only test function called");
   }
   let file = getUpdatesRootDir();
   file.append(FILE_UPDATE_TEST);
   file.QueryInterface(Ci.nsILocalFileWin);
   // Remove the file if it exists just in case.
   if (file.exists()) {
     file.fileAttributesWin |= file.WFA_READWRITE;
@@ -120,16 +120,27 @@ function lockWriteTestFile() {
   file.fileAttributesWin &= ~file.WFA_READWRITE;
   registerCleanupFunction(() => {
     file.fileAttributesWin |= file.WFA_READWRITE;
     file.fileAttributesWin &= ~file.WFA_READONLY;
     file.remove(false);
   });
 }
 
+function setOtherInstanceHandlingUpdates() {
+  if (!IS_WIN) {
+    throw new Error("Windows only test function called");
+  }
+  gAUS.observe(null, "test-close-handle-update-mutex", "");
+  let handle = createMutex(getPerInstallationMutexName());
+  registerCleanupFunction(() => {
+    closeHandle(handle);
+  });
+}
+
 /**
  * Gets the update version info for the update url parameters to send to
  * app_update.sjs.
  *
  * @param  aAppVersion (optional)
  *         The application version for the update snippet. If not specified the
  *         current application version will be used.
  * @return The url parameters for the application and platform version to send
--- a/toolkit/mozapps/update/tests/data/shared.js
+++ b/toolkit/mozapps/update/tests/data/shared.js
@@ -2,16 +2,18 @@
  * 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/. */
 
 /* Shared code for xpcshell and mochitests-chrome */
 /* eslint-disable no-undef */
 
 ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "ctypes",
+                               "resource://gre/modules/ctypes.jsm");
 ChromeUtils.defineModuleGetter(this, "UpdateUtils",
                                "resource://gre/modules/UpdateUtils.jsm");
 
 const PREF_APP_UPDATE_AUTO                       = "app.update.auto";
 const PREF_APP_UPDATE_BACKGROUNDERRORS           = "app.update.backgroundErrors";
 const PREF_APP_UPDATE_BACKGROUNDMAXERRORS        = "app.update.backgroundMaxErrors";
 const PREF_APP_UPDATE_CANCELATIONS               = "app.update.cancelations";
 const PREF_APP_UPDATE_CHANNEL                    = "app.update.channel";
@@ -640,16 +642,100 @@ function getGREBinDir() {
  */
 function getUpdateConfigFile() {
   let configFile = getUpdatesRootDir();
   configFile.append(FILE_UPDATE_CONFIG);
   return configFile;
 }
 
 /**
+ * Gets the unique mutex name for the installation.
+ *
+ * @return Global mutex path.
+ * @throws If the function is called on a platform other than Windows.
+ */
+function getPerInstallationMutexName() {
+  if (!IS_WIN) {
+    throw new Error("Windows only function called by a different platform!");
+  }
+
+  let hasher = Cc["@mozilla.org/security/hash;1"].
+               createInstance(Ci.nsICryptoHash);
+  hasher.init(hasher.SHA1);
+
+  let exeFile = Services.dirsvc.get(XRE_EXECUTABLE_FILE, Ci.nsIFile);
+  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
+                  createInstance(Ci.nsIScriptableUnicodeConverter);
+  converter.charset = "UTF-8";
+  let data = converter.convertToByteArray(exeFile.path.toLowerCase());
+
+  hasher.update(data, data.length);
+  return "Global\\MozillaUpdateMutex-" + hasher.finish(true);
+}
+
+/**
+ * Closes a Win32 handle.
+ *
+ * @param  aHandle
+ *         The handle to close.
+ * @throws If the function is called on a platform other than Windows.
+ */
+function closeHandle(aHandle) {
+  if (!IS_WIN) {
+    throw new Error("Windows only function called by a different platform!");
+  }
+
+  let lib = ctypes.open("kernel32.dll");
+  let CloseHandle = lib.declare("CloseHandle",
+                                ctypes.winapi_abi,
+                                ctypes.int32_t, /* success */
+                                ctypes.void_t.ptr); /* handle */
+  CloseHandle(aHandle);
+  lib.close();
+}
+
+/**
+ * Creates a mutex.
+ *
+ * @param  aName
+ *         The name for the mutex.
+ * @return The Win32 handle to the mutex.
+ * @throws If the function is called on a platform other than Windows.
+ */
+function createMutex(aName) {
+  if (!IS_WIN) {
+    throw new Error("Windows only function called by a different platform!");
+  }
+
+  const INITIAL_OWN = 1;
+  const ERROR_ALREADY_EXISTS = 0xB7;
+  let lib = ctypes.open("kernel32.dll");
+  let CreateMutexW = lib.declare("CreateMutexW",
+                                 ctypes.winapi_abi,
+                                 ctypes.void_t.ptr, /* return handle */
+                                 ctypes.void_t.ptr, /* security attributes */
+                                 ctypes.int32_t, /* initial owner */
+                                 ctypes.char16_t.ptr); /* name */
+
+  let handle = CreateMutexW(null, INITIAL_OWN, aName);
+  lib.close();
+  let alreadyExists = ctypes.winLastError == ERROR_ALREADY_EXISTS;
+  if (handle && !handle.isNull() && alreadyExists) {
+    closeHandle(handle);
+    handle = null;
+  }
+
+  if (handle && handle.isNull()) {
+    handle = null;
+  }
+
+  return handle;
+}
+
+/**
  * Logs TEST-INFO messages.
  *
  * @param  aText
  *         The text to log.
  * @param  aCaller (optional)
  *         An optional Components.stack.caller. If not specified
  *         Components.stack.caller will be used.
  */
--- a/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
+++ b/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
@@ -199,18 +199,16 @@ var gDebugTestLog = false;
 var gTestsToLog = [];
 var gRealDump;
 var gFOS;
 
 const DATA_URI_SPEC = Services.io.newFileURI(do_get_file("../data", false)).spec;
 /* import-globals-from ../data/shared.js */
 Services.scriptloader.loadSubScript(DATA_URI_SPEC + "shared.js", this);
 
-ChromeUtils.defineModuleGetter(this, "ctypes",
-                               "resource://gre/modules/ctypes.jsm");
 ChromeUtils.defineModuleGetter(this, "MockRegistrar",
                                "resource://testing-common/MockRegistrar.jsm");
 
 var gTestFiles = [];
 var gTestDirs = [];
 
 // Common files for both successful and failed updates.
 var gTestFilesCommon = [
--- a/toolkit/mozapps/update/tests/unit_aus_update/canCheckForAndCanApplyUpdates.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/canCheckForAndCanApplyUpdates.js
@@ -47,90 +47,8 @@ function run_test() {
     let handle = createMutex(getPerInstallationMutexName());
 
     Assert.ok(!handle, "should not be able to create the update mutex when " +
               "the application has created the update mutex");
   }
 
   doTestFinish();
 }
-
-/**
- * Determines a unique mutex name for the installation.
- *
- * @return Global mutex path.
- */
-function getPerInstallationMutexName() {
-  if (!IS_WIN) {
-    do_throw("Windows only function called by a different platform!");
-  }
-
-  let hasher = Cc["@mozilla.org/security/hash;1"].
-               createInstance(Ci.nsICryptoHash);
-  hasher.init(hasher.SHA1);
-
-  let exeFile = Services.dirsvc.get(XRE_EXECUTABLE_FILE, Ci.nsIFile);
-
-  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
-                  createInstance(Ci.nsIScriptableUnicodeConverter);
-  converter.charset = "UTF-8";
-  let data = converter.convertToByteArray(exeFile.path.toLowerCase());
-
-  hasher.update(data, data.length);
-  return "Global\\MozillaUpdateMutex-" + hasher.finish(true);
-}
-
-/**
- * Closes a Win32 handle.
- *
- * @param  aHandle
- *         The handle to close.
- */
-function closeHandle(aHandle) {
-  if (!IS_WIN) {
-    do_throw("Windows only function called by a different platform!");
-  }
-
-  let lib = ctypes.open("kernel32.dll");
-  let CloseHandle = lib.declare("CloseHandle",
-                                ctypes.winapi_abi,
-                                ctypes.int32_t, /* success */
-                                ctypes.void_t.ptr); /* handle */
-  CloseHandle(aHandle);
-  lib.close();
-}
-
-/**
- * Creates a mutex.
- *
- * @param  aName
- *         The name for the mutex.
- * @return The Win32 handle to the mutex.
- */
-function createMutex(aName) {
-  if (!IS_WIN) {
-    do_throw("Windows only function called by a different platform!");
-  }
-
-  const INITIAL_OWN = 1;
-  const ERROR_ALREADY_EXISTS = 0xB7;
-  let lib = ctypes.open("kernel32.dll");
-  let CreateMutexW = lib.declare("CreateMutexW",
-                                 ctypes.winapi_abi,
-                                 ctypes.void_t.ptr, /* return handle */
-                                 ctypes.void_t.ptr, /* security attributes */
-                                 ctypes.int32_t, /* initial owner */
-                                 ctypes.char16_t.ptr); /* name */
-
-  let handle = CreateMutexW(null, INITIAL_OWN, aName);
-  lib.close();
-  let alreadyExists = ctypes.winLastError == ERROR_ALREADY_EXISTS;
-  if (handle && !handle.isNull() && alreadyExists) {
-    closeHandle(handle);
-    handle = null;
-  }
-
-  if (handle && handle.isNull()) {
-    handle = null;
-  }
-
-  return handle;
-}