Bug 1337743 - Return cause of quit; r?whimboo draft
authorAndreas Tolfsen <ato@mozilla.com>
Mon, 27 Mar 2017 12:49:22 +0100
changeset 551799 e4fff0f4e79a077f72ff8675c2ff3348adf1a162
parent 551798 183b28a910da31b81b7989b648c3345e1ddb1a90
child 551800 9af62e8ff71696ab967356960755567c1abf7390
child 551809 732dd2870958cf9ab021fc08239ba48478281b63
push id51152
push userbmo:ato@mozilla.com
push dateMon, 27 Mar 2017 12:36:48 +0000
reviewerswhimboo
bugs1337743
milestone55.0a1
Bug 1337743 - Return cause of quit; r?whimboo This adds a return type to the quitApplication command in Marionette, which extracts the data received by the quit-application observer. The returned cause is either "shutdown" or "restart". MozReview-Commit-ID: 85fBGaS1VeQ
testing/marionette/driver.js
testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2723,16 +2723,21 @@ GeckoDriver.prototype.acceptConnections 
  * Crucially, only one of the *Quit flags can be specified. The |eRestart|
  * flag may be bit-wise combined with one of the *Quit flags to cause
  * the application to restart after it quits.
  *
  * @param {Array.<string>=} flags
  *     Constant name of masks to pass to |Services.startup.quit|.
  *     If empty or undefined, |nsIAppStartup.eAttemptQuit| is used.
  *
+ * @return {string}
+ *     Explaining the reason why the application quit.  This can be
+ *     in response to a normal shutdown or restart, yielding "shutdown"
+ *     or "restart", respectively.
+ *
  * @throws {InvalidArgumentError}
  *     If |flags| contains unknown or incompatible flags, for example
  *     multiple Quit flags.
  */
 GeckoDriver.prototype.quitApplication = function* (cmd, resp) {
   const quits = ["eConsiderQuit", "eAttemptQuit", "eForceQuit"];
 
   let flags = [];
@@ -2762,21 +2767,28 @@ GeckoDriver.prototype.quitApplication = 
   } else {
     mode = Ci.nsIAppStartup.eAttemptQuit;
   }
 
   this._server.acceptConnections = false;
   this.deleteSession();
 
   // delay response until the application is about to quit
-  let quitApplication = new Promise(resolve =>
-      Services.obs.addObserver(resolve, "quit-application", false));
+  let quitApplication = new Promise(resolve => {
+    Services.obs.addObserver(
+        (subject, topic, data) => resolve(data),
+        "quit-application",
+        false);
+  });
 
   Services.startup.quit(mode);
-  yield quitApplication.then(() => resp.send());
+
+  yield quitApplication
+      .then(cause => resp.body.cause = cause)
+      .then(() => resp.send());
 };
 
 GeckoDriver.prototype.installAddon = function (cmd, resp) {
   assert.firefox()
 
   let path = cmd.parameters.path;
   let temp = cmd.parameters.temporary || false;
   if (typeof path == "undefined" || typeof path != "string" ||
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py
@@ -14,51 +14,59 @@ class TestServerQuitApplication(Marionet
             self.marionette.start_session()
 
     def quit(self, flags=None):
         body = None
         if flags is not None:
             body = {"flags": list(flags)}
 
         try:
-            self.marionette._send_message("quitApplication", body)
+            resp = self.marionette._send_message("quitApplication", body)
         finally:
             self.marionette.session_id = None
             self.marionette.session = None
             self.marionette.process_id = None
             self.marionette.profile = None
             self.marionette.window = None
 
+        self.assertIn("cause", resp)
+
         self.marionette.client.close()
         self.marionette.instance.runner.wait()
 
+        return resp["cause"]
+
     def test_types(self):
         for typ in [42, True, "foo", []]:
             print("testing type {}".format(type(typ)))
             with self.assertRaises(errors.InvalidArgumentException):
                 self.marionette._send_message("quitApplication", typ)
 
         with self.assertRaises(errors.InvalidArgumentException):
             self.quit("foo")
 
     def test_undefined_default(self):
-        self.quit()
+        cause = self.quit()
+        self.assertEqual("shutdown", cause)
 
     def test_empty_default(self):
-        self.quit(())
+        cause = self.quit(())
+        self.assertEqual("shutdown", cause)
 
     def test_incompatible_flags(self):
         with self.assertRaises(errors.InvalidArgumentException):
             self.quit(("eAttemptQuit", "eForceQuit"))
 
     def test_attempt_quit(self):
-        self.quit(("eAttemptQuit",))
+        cause = self.quit(("eAttemptQuit",))
+        self.assertEqual("shutdown", cause)
 
     def test_force_quit(self):
-        self.quit(("eForceQuit",))
+        cause = self.quit(("eForceQuit",))
+        self.assertEqual("shutdown", cause)
 
 
 class TestQuitRestart(MarionetteTestCase):
 
     def setUp(self):
         MarionetteTestCase.setUp(self)
 
         self.pid = self.marionette.process_id