Bug 1254136 - Fix double registration for sessionstore-windows-restored. r=automatedtester, a=test-only
authorHenrik Skupin <mail@hskupin.info>
Thu, 10 Aug 2017 18:04:47 +0200
changeset 421238 fed67039c7b5313a562753da484e0489150c4e64
parent 421237 ec091b2f1998e869d4ce0e466b0c218653bcbc43
child 421239 8dbb3f787e2bcb77cc9f8dbdc4215c79431945eb
push id7634
push userryanvm@gmail.com
push dateFri, 18 Aug 2017 11:43:44 +0000
treeherdermozilla-beta@78a5c6c95ab8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersautomatedtester, test-only
bugs1254136
milestone56.0
Bug 1254136 - Fix double registration for sessionstore-windows-restored. r=automatedtester, a=test-only A missing break statement caused a double execution of the code in "profile-after-change", which leads to two instantiations of the Marionette server colliding due to the same port. MozReview-Commit-ID: Dp6fncj463j
testing/marionette/components/marionette.js
testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py
--- a/testing/marionette/components/marionette.js
+++ b/testing/marionette/components/marionette.js
@@ -190,40 +190,37 @@ MarionetteComponent.prototype.handle = f
     this.logger.info("Enabled via --marionette");
   }
 };
 
 MarionetteComponent.prototype.observe = function(subject, topic, data) {
   this.logger.debug(`Received observer notification "${topic}"`);
 
   switch (topic) {
+    case "profile-after-change":
+      Services.obs.addObserver(this, "command-line-startup");
+      Services.obs.addObserver(this, "sessionstore-windows-restored");
+
+      prefs.readFromEnvironment(ENV_PRESERVE_PREFS);
+      break;
+
+    // In safe mode the command line handlers are getting parsed after the
+    // safe mode dialog has been closed. To allow Marionette to start
+    // earlier, use the CLI startup observer notification for
+    // special-cased handlers, which gets fired before the dialog appears.
     case "command-line-startup":
       Services.obs.removeObserver(this, topic);
       this.handle(subject);
 
-    case "profile-after-change":
-      // Using sessionstore-windows-restored as the xpcom category doesn't
-      // seem to work, so we wait for that by adding an observer here.
-      Services.obs.addObserver(this, "sessionstore-windows-restored");
+      // We want to suppress the modal dialog that's shown
+      // when starting up in safe-mode to enable testing.
+      if (this.enabled && Services.appinfo.inSafeMode) {
+        Services.obs.addObserver(this, "domwindowopened");
+      }
 
-      // In safe mode the command line handlers are getting parsed after the
-      // safe mode dialog has been closed. To allow Marionette to start
-      // earlier, register the CLI startup observer notification for
-      // special-cased handlers, which gets fired before the dialog appears.
-      Services.obs.addObserver(this, "command-line-startup");
-
-      prefs.readFromEnvironment(ENV_PRESERVE_PREFS);
-
-      if (this.enabled) {
-        // We want to suppress the modal dialog that's shown
-        // when starting up in safe-mode to enable testing.
-        if (Services.appinfo.inSafeMode) {
-          Services.obs.addObserver(this, "domwindowopened");
-        }
-      }
       break;
 
     case "domwindowclosed":
       if (this.gfxWindow === null || subject === this.gfxWindow) {
         Services.obs.removeObserver(this, topic);
 
         Services.obs.addObserver(this, "xpcom-shutdown");
         this.finalUIStartup = true;
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py
@@ -1,12 +1,14 @@
 # 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/.
 
+import unittest
+
 from marionette_driver import errors
 
 from marionette_harness import MarionetteTestCase, skip
 
 
 class TestServerQuitApplication(MarionetteTestCase):
 
     def tearDown(self):
@@ -83,16 +85,24 @@ class TestQuitRestart(MarionetteTestCase
         # Ensure to restart a session if none exist for clean-up
         if self.marionette.session is None:
             self.marionette.start_session()
 
         self.marionette.clear_pref("startup.homepage_welcome_url")
 
         MarionetteTestCase.tearDown(self)
 
+    @property
+    def is_safe_mode(self):
+        with self.marionette.using_context("chrome"):
+            return self.marionette.execute_script("""
+              Cu.import("resource://gre/modules/Services.jsm");
+              return Services.appinfo.inSafeMode;
+            """)
+
     def shutdown(self, restart=False):
         self.marionette.set_context("chrome")
         self.marionette.execute_script("""
             Components.utils.import("resource://gre/modules/Services.jsm");
             let flags = Ci.nsIAppStartup.eAttemptQuit;
             if (arguments[0]) {
               flags |= Ci.nsIAppStartup.eRestart;
             }
@@ -184,16 +194,42 @@ class TestQuitRestart(MarionetteTestCase
         if self.marionette.session_capabilities["platformName"] == "linux":
             self.assertEqual(self.marionette.process_id, self.pid)
         else:
             self.assertNotEqual(self.marionette.process_id, self.pid)
 
         self.assertNotEqual(self.marionette.get_pref("startup.homepage_welcome_url"),
                             "about:")
 
+    def test_in_app_restart_safe_mode(self):
+        if self.marionette.session_capabilities["moz:headless"]:
+            raise unittest.SkipTest("Bug 1390848 - Hang of Marionette client after the restart.")
+
+        def restart_in_safe_mode():
+            with self.marionette.using_context("chrome"):
+                self.marionette.execute_script("""
+                  Components.utils.import("resource://gre/modules/Services.jsm");
+
+                  let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
+                                     .createInstance(Ci.nsISupportsPRBool);
+                  Services.obs.notifyObservers(cancelQuit,
+                      "quit-application-requested", null);
+
+                  if (!cancelQuit.data) {
+                    Services.startup.restartInSafeMode(Ci.nsIAppStartup.eAttemptQuit);
+                  }
+                """)
+
+        try:
+            self.assertFalse(self.is_safe_mode, "Safe Mode is unexpectedly enabled")
+            self.marionette.restart(in_app=True, callback=restart_in_safe_mode)
+            self.assertTrue(self.is_safe_mode, "Safe Mode is not enabled")
+        finally:
+            self.marionette.quit(clean=True)
+
     def test_in_app_restart_with_callback_no_shutdown(self):
         try:
             timeout_startup = self.marionette.DEFAULT_STARTUP_TIMEOUT
             timeout_shutdown = self.marionette.DEFAULT_SHUTDOWN_TIMEOUT
             self.marionette.DEFAULT_SHUTDOWN_TIMEOUT = 5
             self.marionette.DEFAULT_STARTUP_TIMEOUT = 5
 
             with self.assertRaisesRegexp(IOError, "the connection to Marionette server is lost"):