зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1829334 - [marionette] Move browser quit logic into shared module. r=webdriver-reviewers,whimboo
Differential Revision: https://phabricator.services.mozilla.com/D181774
This commit is contained in:
Родитель
b7f4737fff
Коммит
86a079c36f
|
@ -14,6 +14,7 @@ remote.jar:
|
|||
|
||||
# shared modules (all protocols)
|
||||
content/shared/AppInfo.sys.mjs (shared/AppInfo.sys.mjs)
|
||||
content/shared/Browser.sys.mjs (shared/Browser.sys.mjs)
|
||||
content/shared/Capture.sys.mjs (shared/Capture.sys.mjs)
|
||||
content/shared/DOM.sys.mjs (shared/DOM.sys.mjs)
|
||||
content/shared/Format.sys.mjs (shared/Format.sys.mjs)
|
||||
|
|
|
@ -35,6 +35,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
permissions: "chrome://remote/content/marionette/permissions.sys.mjs",
|
||||
pprint: "chrome://remote/content/shared/Format.sys.mjs",
|
||||
print: "chrome://remote/content/shared/PDF.sys.mjs",
|
||||
quit: "chrome://remote/content/shared/Browser.sys.mjs",
|
||||
reftest: "chrome://remote/content/marionette/reftest.sys.mjs",
|
||||
registerCommandsActor:
|
||||
"chrome://remote/content/marionette/actors/MarionetteCommandsParent.sys.mjs",
|
||||
|
@ -49,7 +50,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
"chrome://remote/content/marionette/actors/MarionetteCommandsParent.sys.mjs",
|
||||
waitForInitialNavigationCompleted:
|
||||
"chrome://remote/content/shared/Navigate.sys.mjs",
|
||||
waitForObserverTopic: "chrome://remote/content/marionette/sync.sys.mjs",
|
||||
WebDriverSession: "chrome://remote/content/shared/webdriver/Session.sys.mjs",
|
||||
WebElement: "chrome://remote/content/marionette/web-reference.sys.mjs",
|
||||
windowManager: "chrome://remote/content/shared/WindowManager.sys.mjs",
|
||||
|
@ -84,6 +84,8 @@ const TIMEOUT_NO_WINDOW_MANAGER = 5000;
|
|||
|
||||
// Observer topic to wait for until the browser window is ready.
|
||||
const TOPIC_BROWSER_READY = "browser-delayed-startup-finished";
|
||||
// Observer topic to perform clean up when application quit is requested.
|
||||
const TOPIC_QUIT_APPLICATION_REQUESTED = "quit-application-requested";
|
||||
|
||||
/**
|
||||
* The Marionette WebDriver services provides a standard conforming
|
||||
|
@ -551,11 +553,18 @@ GeckoDriver.prototype.handleEvent = function ({ target, type }) {
|
|||
}
|
||||
};
|
||||
|
||||
GeckoDriver.prototype.observe = function (subject, topic, data) {
|
||||
GeckoDriver.prototype.observe = async function (subject, topic, data) {
|
||||
switch (topic) {
|
||||
case TOPIC_BROWSER_READY:
|
||||
this.registerWindow(subject);
|
||||
break;
|
||||
|
||||
case TOPIC_QUIT_APPLICATION_REQUESTED:
|
||||
// Run Marionette specific cleanup steps before allowing
|
||||
// the application to shutdown
|
||||
await this._server.setAcceptConnections(false);
|
||||
this.deleteSession();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2893,7 +2902,6 @@ GeckoDriver.prototype.acceptConnections = async function (cmd) {
|
|||
*/
|
||||
GeckoDriver.prototype.quit = async function (cmd) {
|
||||
const { flags = [], safeMode = false } = cmd.parameters;
|
||||
const quits = ["eConsiderQuit", "eAttemptQuit", "eForceQuit"];
|
||||
|
||||
lazy.assert.array(flags, `Expected "flags" to be an array`);
|
||||
lazy.assert.boolean(safeMode, `Expected "safeMode" to be a boolean`);
|
||||
|
@ -2904,70 +2912,27 @@ GeckoDriver.prototype.quit = async function (cmd) {
|
|||
);
|
||||
}
|
||||
|
||||
if (flags.includes("eSilently")) {
|
||||
if (!this.currentSession.capabilities.get("moz:windowless")) {
|
||||
throw new lazy.error.UnsupportedOperationError(
|
||||
`Silent restarts only allowed with "moz:windowless" capability set`
|
||||
);
|
||||
}
|
||||
if (!flags.includes("eRestart")) {
|
||||
throw new lazy.error.InvalidArgumentError(
|
||||
`"silently" only works with restart flag`
|
||||
);
|
||||
// Register handler to run Marionette specific shutdown code.
|
||||
Services.obs.addObserver(this, TOPIC_QUIT_APPLICATION_REQUESTED);
|
||||
|
||||
let quitApplicationResponse;
|
||||
try {
|
||||
quitApplicationResponse = await lazy.quit(
|
||||
flags,
|
||||
safeMode,
|
||||
this.currentSession.capabilities.get("moz:windowless")
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof TypeError) {
|
||||
throw new lazy.error.InvalidArgumentError(e.message);
|
||||
}
|
||||
|
||||
throw new lazy.error.UnsupportedOperationError(e.message);
|
||||
} finally {
|
||||
Services.obs.removeObserver(this, TOPIC_QUIT_APPLICATION_REQUESTED);
|
||||
}
|
||||
|
||||
let quitSeen;
|
||||
let mode = 0;
|
||||
if (flags.length) {
|
||||
for (let k of flags) {
|
||||
lazy.assert.in(k, Ci.nsIAppStartup);
|
||||
|
||||
if (quits.includes(k)) {
|
||||
if (quitSeen) {
|
||||
throw new lazy.error.InvalidArgumentError(
|
||||
`${k} cannot be combined with ${quitSeen}`
|
||||
);
|
||||
}
|
||||
quitSeen = k;
|
||||
}
|
||||
|
||||
mode |= Ci.nsIAppStartup[k];
|
||||
}
|
||||
}
|
||||
|
||||
if (!quitSeen) {
|
||||
mode |= Ci.nsIAppStartup.eAttemptQuit;
|
||||
}
|
||||
|
||||
await this._server.setAcceptConnections(false);
|
||||
this.deleteSession();
|
||||
|
||||
// Notify all windows that an application quit has been requested.
|
||||
const cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
|
||||
Ci.nsISupportsPRBool
|
||||
);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
|
||||
|
||||
// If the shutdown of the application is prevented force quit it instead.
|
||||
if (cancelQuit.data) {
|
||||
mode |= Ci.nsIAppStartup.eForceQuit;
|
||||
}
|
||||
|
||||
// delay response until the application is about to quit
|
||||
let quitApplication = lazy.waitForObserverTopic("quit-application");
|
||||
|
||||
if (safeMode) {
|
||||
Services.startup.restartInSafeMode(mode);
|
||||
} else {
|
||||
Services.startup.quit(mode);
|
||||
}
|
||||
|
||||
return {
|
||||
cause: (await quitApplication).data,
|
||||
forced: cancelQuit.data,
|
||||
in_app: true,
|
||||
};
|
||||
return quitApplicationResponse;
|
||||
};
|
||||
|
||||
GeckoDriver.prototype.installAddon = function (cmd) {
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/* 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/. */
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
pprint: "chrome://remote/content/shared/Format.sys.mjs",
|
||||
waitForObserverTopic: "chrome://remote/content/marionette/sync.sys.mjs",
|
||||
});
|
||||
|
||||
/**
|
||||
* Quits the application with the provided flags.
|
||||
*
|
||||
* Optional {@link nsIAppStartup} flags may be provided as
|
||||
* an array of masks, and these will be combined by ORing
|
||||
* them with a bitmask. The available masks are defined in
|
||||
* https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIAppStartup.
|
||||
*
|
||||
* 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.
|
||||
* @param {boolean=} safeMode
|
||||
* Optional flag to indicate that the application has to
|
||||
* be restarted in safe mode.
|
||||
* @param {boolean=} isWindowless
|
||||
* Optional flag to indicate that the browser was started in windowless mode.
|
||||
*
|
||||
* @returns {Object<string,boolean>}
|
||||
* Dictionary containing information that explains the shutdown reason.
|
||||
* The value for `cause` contains the shutdown kind like "shutdown" or
|
||||
* "restart", while `forced` will indicate if it was a normal or forced
|
||||
* shutdown of the application. "in_app" is always set to indicate that
|
||||
* it is a shutdown triggered from within the application.
|
||||
*/
|
||||
export async function quit(flags = [], safeMode = false, isWindowless = false) {
|
||||
if (flags.includes("eSilently")) {
|
||||
if (!isWindowless) {
|
||||
throw new Error(
|
||||
`Silent restarts only allowed with "moz:windowless" capability set`
|
||||
);
|
||||
}
|
||||
if (!flags.includes("eRestart")) {
|
||||
throw new TypeError(`"silently" only works with restart flag`);
|
||||
}
|
||||
}
|
||||
|
||||
const quits = ["eConsiderQuit", "eAttemptQuit", "eForceQuit"];
|
||||
|
||||
let quitSeen;
|
||||
let mode = 0;
|
||||
if (flags.length) {
|
||||
for (let k of flags) {
|
||||
if (!Ci.nsIAppStartup.hasOwnProperty(k)) {
|
||||
throw new TypeError(lazy.pprint`Expected ${k} in ${Ci.nsIAppStartup}`);
|
||||
}
|
||||
|
||||
if (quits.includes(k)) {
|
||||
if (quitSeen) {
|
||||
throw new TypeError(`${k} cannot be combined with ${quitSeen}`);
|
||||
}
|
||||
quitSeen = k;
|
||||
}
|
||||
|
||||
mode |= Ci.nsIAppStartup[k];
|
||||
}
|
||||
}
|
||||
|
||||
if (!quitSeen) {
|
||||
mode |= Ci.nsIAppStartup.eAttemptQuit;
|
||||
}
|
||||
|
||||
// Notify all windows that an application quit has been requested.
|
||||
const cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
|
||||
Ci.nsISupportsPRBool
|
||||
);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
|
||||
|
||||
// If the shutdown of the application is prevented force quit it instead.
|
||||
if (cancelQuit.data) {
|
||||
mode |= Ci.nsIAppStartup.eForceQuit;
|
||||
}
|
||||
|
||||
// Delay response until the application is about to quit.
|
||||
const quitApplication = lazy.waitForObserverTopic("quit-application");
|
||||
|
||||
if (safeMode) {
|
||||
Services.startup.restartInSafeMode(mode);
|
||||
} else {
|
||||
Services.startup.quit(mode);
|
||||
}
|
||||
|
||||
return {
|
||||
cause: (await quitApplication).data,
|
||||
forced: cancelQuit.data,
|
||||
in_app: true,
|
||||
};
|
||||
}
|
Загрузка…
Ссылка в новой задаче