Bug 1671347 - [marionette] Add proxy for MarionetteFrameActor to retry queries after an AbortError r=marionette-reviewers,whimboo,maja_zf

Differential Revision: https://phabricator.services.mozilla.com/D94086
This commit is contained in:
Julian Descottes 2020-10-27 10:03:43 +00:00
Родитель f48b48fe72
Коммит a14326cffb
2 изменённых файлов: 61 добавлений и 3 удалений

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

@ -4,7 +4,10 @@
("use strict");
const EXPORTED_SYMBOLS = ["MarionetteFrameParent"];
const EXPORTED_SYMBOLS = [
"getMarionetteFrameActorProxy",
"MarionetteFrameParent",
];
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
@ -293,3 +296,57 @@ class MarionetteFrameParent extends JSWindowActorParent {
}
}
}
/**
* Proxy that will dynamically create MarionetteFrame actors for a dynamically
* provided browsing context until the method can be fully executed by the
* JSWindowActor pair.
*
* @param {function(): BrowsingContext} browsingContextFn
* A function that returns the reference to the browsing context for which
* the query should run.
*/
function getMarionetteFrameActorProxy(browsingContextFn) {
/**
* Methods which modify the content page cannot be retried safely.
* See Bug 1673345.
*/
const NO_RETRY_METHODS = [
"clickElement",
"executeScript",
"performActions",
"releaseActions",
"sendKeysToElement",
"singleTap",
];
return new Proxy(
{},
{
get(target, methodName) {
return async (...args) => {
while (true) {
try {
// TODO: Scenarios where the window/tab got closed and
// currentWindowGlobal is null will be handled in Bug 1662808.
const actor = browsingContextFn().currentWindowGlobal.getActor(
"MarionetteFrame"
);
const result = await actor[methodName](...args);
return result;
} catch (e) {
if (e.name !== "AbortError") {
// Only AbortError(s) are retried, let any other error through.
throw e;
}
if (NO_RETRY_METHODS.includes(methodName)) {
return null;
}
}
}
};
},
}
);
}

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

@ -30,6 +30,8 @@ XPCOMUtils.defineLazyModuleGetters(this, {
element: "chrome://marionette/content/element.js",
error: "chrome://marionette/content/error.js",
evaluate: "chrome://marionette/content/evaluate.js",
getMarionetteFrameActorProxy:
"chrome://marionette/content/actors/MarionetteFrameParent.jsm",
IdlePromise: "chrome://marionette/content/sync.js",
interaction: "chrome://marionette/content/interaction.js",
l10n: "chrome://marionette/content/l10n.js",
@ -378,8 +380,7 @@ GeckoDriver.prototype.sendAsync = function(name, data, commandID) {
* The parent actor.
*/
GeckoDriver.prototype.getActor = function(options = {}) {
const browsingContext = this.getBrowsingContext(options);
return browsingContext.currentWindowGlobal.getActor("MarionetteFrame");
return getMarionetteFrameActorProxy(() => this.getBrowsingContext(options));
};
/**