Bug 1726465 - [marionette-client] Add silent restart option on MacOS to Marionette client. r=webdriver-reviewers,jdescottes

Depends on D134277

Differential Revision: https://phabricator.services.mozilla.com/D134387
This commit is contained in:
Henrik Skupin 2022-05-10 15:08:20 +00:00
Родитель 266ffea2f6
Коммит 6534c7686e
5 изменённых файлов: 99 добавлений и 19 удалений

Просмотреть файл

@ -2065,10 +2065,13 @@ GeckoDriver.prototype.close = async function() {
assert.open(this.getBrowsingContext({ context: Context.Content, top: true }));
await this._handleUserPrompts();
// If there is only one window left, do not close it. Instead return
// a faked empty array of window handles. This will instruct geckodriver
// to terminate the application.
if (TabManager.getTabCount() === 1) {
// If there is only one window left, do not close unless windowless mode is
// enabled. Instead return a faked empty array of window handles.
// This will instruct geckodriver to terminate the application.
if (
TabManager.getTabCount() === 1 &&
!this.currentSession.capabilities.get("moz:windowless")
) {
return [];
}
@ -2102,10 +2105,10 @@ GeckoDriver.prototype.closeChromeWindow = async function() {
nwins++;
}
// If there is only one window left, do not close it. Instead return
// a faked empty array of window handles. This will instruct geckodriver
// to terminate the application.
if (nwins == 1) {
// If there is only one window left, do not close unless windowless mode is
// enabled. Instead return a faked empty array of window handles.
// This will instruct geckodriver to terminate the application.
if (nwins == 1 && !this.currentSession.capabilities.get("moz:windowless")) {
return [];
}
@ -2627,6 +2630,19 @@ GeckoDriver.prototype.quit = async function(cmd) {
);
}
if (flags.includes("eSilently")) {
if (!this.currentSession.capabilities.get("moz:windowless")) {
throw new error.UnsupportedOperationError(
`Silent restarts only allowed with "moz:windowless" capability set`
);
}
if (!flags.includes("eRestart")) {
throw new error.InvalidArgumentError(
`"silently" only works with restart flag`
);
}
}
let quitSeen;
let mode = 0;
if (flags.length > 0) {

Просмотреть файл

@ -602,6 +602,13 @@ class Capabilities extends Map {
case "moz:windowless":
assert.boolean(v, pprint`Expected ${k} to be boolean, got ${v}`);
// Only supported on MacOS
if (v && !AppInfo.isMac) {
throw new error.InvalidArgumentError(
"moz:windowless only supported on MacOS"
);
}
break;
}

Просмотреть файл

@ -1050,7 +1050,9 @@ class Marionette(object):
return quit_details
@do_process_check
def restart(self, callback=None, clean=False, in_app=False, safe_mode=False):
def restart(
self, callback=None, clean=False, in_app=False, safe_mode=False, silent=False
):
"""
This will terminate the currently running instance, and spawn a new instance
with the same profile and then reuse the session id when creating a session again.
@ -1069,6 +1071,10 @@ class Marionette(object):
:param safe_mode: Optional flag to indicate that the application has to
be restarted in safe mode.
:param silent: Optional flag to indicate that the application should
not open any window after a restart. Note that this flag is only
supported on MacOS.
:returns: A dictionary containing details of the application restart.
The `cause` property reflects the reason, and `forced` indicates
that something prevented the shutdown and the application had
@ -1083,8 +1089,8 @@ class Marionette(object):
context = self._send_message("Marionette:GetContext", key="value")
restart_details = {"cause": "restart", "forced": False}
# Safe mode is only available with in_app restarts.
if safe_mode:
# Safe mode and the silent flag require in_app restarts.
if safe_mode or silent:
in_app = True
if in_app:
@ -1106,9 +1112,19 @@ class Marionette(object):
if callback is not None:
callback()
else:
restart_details = self._request_in_app_shutdown(
flags=["eRestart"], safe_mode=safe_mode
)
flags = ["eRestart"]
if silent:
flags.append("eSilently")
try:
restart_details = self._request_in_app_shutdown(
flags=flags, safe_mode=safe_mode
)
except Exception as e:
self._send_message(
"Marionette:AcceptConnections", {"value": True}
)
raise e
except IOError:
# A possible IOError should be ignored at this point, given that

Просмотреть файл

@ -127,8 +127,14 @@ class TestCapabilities(MarionetteTestCase):
"Session ID has {{}} in it: {}".format(self.marionette.session_id),
)
def test_windowless_false(self):
self.marionette.delete_session()
self.marionette.start_session({"moz:windowless": False})
caps = self.marionette.session_capabilities
self.assertFalse(caps["moz:windowless"])
@unittest.skipUnless(sys.platform.startswith("darwin"), "Only supported on MacOS")
def test_windowless(self):
def test_windowless_true(self):
self.marionette.delete_session()
self.marionette.start_session({"moz:windowless": True})
caps = self.marionette.session_capabilities

Просмотреть файл

@ -67,10 +67,6 @@ class TestServerQuitApplication(MarionetteTestCase):
with self.assertRaises(errors.InvalidArgumentException):
self.quit(("eAttemptQuit", "eForceQuit"))
def test_safe_mode_requires_restart(self):
with self.assertRaises(errors.InvalidArgumentException):
self.quit(("eAttemptQuit",), True)
def test_attempt_quit(self):
cause = self.quit(("eAttemptQuit",))
self.assertEqual("shutdown", cause)
@ -79,6 +75,15 @@ class TestServerQuitApplication(MarionetteTestCase):
cause = self.quit(("eForceQuit",))
self.assertEqual("shutdown", cause)
def test_safe_mode_requires_restart(self):
with self.assertRaises(errors.InvalidArgumentException):
self.quit(("eAttemptQuit",), True)
@unittest.skipUnless(sys.platform.startswith("darwin"), "Only supported on MacOS")
def test_silent_quit_missing_windowless_capability(self):
with self.assertRaises(errors.UnsupportedOperationException):
self.quit(("eSilently",))
class TestQuitRestart(MarionetteTestCase):
def setUp(self):
@ -297,6 +302,36 @@ class TestQuitRestart(MarionetteTestCase):
self.marionette.restart(in_app=True)
self.assertEqual(self.marionette.session.get("moz:fooBar"), True)
@unittest.skipUnless(sys.platform.startswith("darwin"), "Only supported on MacOS")
def test_in_app_silent_restart_fails_without_windowless_flag_on_mac_os(self):
self.marionette.delete_session()
self.marionette.start_session()
with self.assertRaises(errors.UnsupportedOperationException):
self.marionette.restart(silent=True)
@unittest.skipUnless(sys.platform.startswith("darwin"), "Only supported on MacOS")
def test_in_app_silent_restart_windowless_flag_on_mac_os(self):
self.marionette.delete_session()
self.marionette.start_session(capabilities={"moz:windowless": True})
self.marionette.restart(silent=True)
self.assertTrue(self.marionette.session_capabilities["moz:windowless"])
self.marionette.restart(in_app=True)
self.assertTrue(self.marionette.session_capabilities["moz:windowless"])
self.marionette.delete_session()
@unittest.skipIf(
sys.platform.startswith("darwin"), "Not supported on other platforms than MacOS"
)
def test_in_app_silent_restart_windowless_flag_unsupported_platforms(self):
self.marionette.delete_session()
with self.assertRaises(errors.SessionNotCreatedException):
self.marionette.start_session(capabilities={"moz:windowless": True})
def test_in_app_quit(self):
details = self.marionette.quit(in_app=True)