Bug 1654454 - [marionette] Port WebDriver:FindElement and WebDriver:FindElements to JSWindowActor. r=marionette-reviewers,maja_zf

Differential Revision: https://phabricator.services.mozilla.com/D84568
This commit is contained in:
Henrik Skupin 2020-07-23 14:22:07 +00:00
Родитель 3f547b9d29
Коммит 201cbd12be
3 изменённых файлов: 142 добавлений и 12 удалений

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

@ -10,11 +10,28 @@ const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { element } = ChromeUtils.import(
"chrome://marionette/content/element.js"
);
const { error } = ChromeUtils.import("chrome://marionette/content/error.js");
const { evaluate } = ChromeUtils.import(
"chrome://marionette/content/evaluate.js"
);
const { Log } = ChromeUtils.import("chrome://marionette/content/log.js");
XPCOMUtils.defineLazyGetter(this, "logger", Log.get);
class MarionetteFrameChild extends JSWindowActorChild {
constructor() {
super();
this.seenEls = new element.Store();
}
get content() {
return this.docShell.domWindow;
}
get id() {
return this.browsingContext.id;
}
@ -43,4 +60,65 @@ class MarionetteFrameChild extends JSWindowActorChild {
break;
}
}
async receiveMessage(msg) {
const { name, data: serializedData } = msg;
const data = evaluate.fromJSON(serializedData);
try {
let result;
switch (name) {
case "MarionetteFrameParent:findElement":
result = await this.findElement(data);
break;
case "MarionetteFrameParent:findElements":
result = await this.findElements(data);
break;
}
return { data: evaluate.toJSON(result) };
} catch (e) {
// Always wrap errors as WebDriverError
return { error: error.wrap(e).toJSON() };
}
}
// Implementation of WebDriver commands
/**
* Find an element in the current browsing context's document using the
* given search strategy.
*/
async findElement(options = {}) {
const { strategy, selector, opts } = options;
opts.all = false;
if (opts.startNode) {
opts.startNode = this.seenEls.get(opts.startNode);
}
const container = { frame: this.content };
const el = await element.find(container, strategy, selector, opts);
return this.seenEls.add(el);
}
/**
* Find elements in the current browsing context's document using the
* given search strategy.
*/
async findElements(options = {}) {
const { strategy, selector, opts } = options;
opts.all = true;
if (opts.startNode) {
opts.startNode = this.seenEls.get(opts.startNode);
}
const container = { frame: this.content };
const el = await element.find(container, strategy, selector, opts);
return this.seenEls.addAll(el);
}
}

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

@ -2,7 +2,7 @@
* 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/. */
"use strict";
("use strict");
const EXPORTED_SYMBOLS = ["MarionetteFrameParent"];
@ -14,6 +14,12 @@ const { EventEmitter } = ChromeUtils.import(
"resource://gre/modules/EventEmitter.jsm"
);
const { WebDriverError } = ChromeUtils.import(
"chrome://marionette/content/error.js"
);
const { evaluate } = ChromeUtils.import(
"chrome://marionette/content/evaluate.js"
);
const { Log } = ChromeUtils.import("chrome://marionette/content/log.js");
XPCOMUtils.defineLazyGetter(this, "logger", Log.get);
@ -29,11 +35,43 @@ class MarionetteFrameParent extends JSWindowActorParent {
logger.trace(`[${this.browsingContext.id}] Parent actor created`);
}
receiveMessage({ name, data }) {
receiveMessage(msg) {
const { name, data } = msg;
switch (name) {
case "MarionetteFrameChild:PageLoadEvent":
this.emit("page-load-event", data);
break;
}
}
async sendQuery(name, data) {
const serializedData = evaluate.toJSON(data);
const result = await super.sendQuery(name, serializedData);
if ("error" in result) {
throw WebDriverError.fromJSON(result.error);
} else {
return evaluate.fromJSON(result.data);
}
}
// Proxying methods for WebDriver commands
// TODO: Maybe using a proxy class instead similar to proxy.js
findElement(strategy, selector, opts) {
return this.sendQuery("MarionetteFrameParent:findElement", {
strategy,
selector,
opts,
});
}
findElements(strategy, selector, opts) {
return this.sendQuery("MarionetteFrameParent:findElements", {
strategy,
selector,
opts,
});
}
}

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

@ -2053,16 +2053,18 @@ GeckoDriver.prototype.multiAction = async function(cmd) {
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.findElement = async function(cmd) {
const win = assert.open(this.getCurrentWindow());
await this._handleUserPrompts();
const { element: el, using, value } = cmd.parameters;
let { using, value } = cmd.parameters;
if (!SUPPORTED_STRATEGIES.has(using)) {
throw new InvalidSelectorError(`Strategy not supported: ${using}`);
}
const win = assert.open(this.getCurrentWindow());
await this._handleUserPrompts();
let startNode;
if (typeof cmd.parameters.element != "undefined") {
startNode = WebElement.fromUUID(cmd.parameters.element, this.context);
if (typeof el != "undefined") {
startNode = WebElement.fromUUID(el, this.context);
}
let opts = {
@ -2071,6 +2073,11 @@ GeckoDriver.prototype.findElement = async function(cmd) {
all: false,
};
if (MarionettePrefs.useActors) {
const actor = await this.getActor();
return actor.findElement(using, value, opts);
}
switch (this.context) {
case Context.Chrome:
let container = { frame: win };
@ -2097,16 +2104,18 @@ GeckoDriver.prototype.findElement = async function(cmd) {
* Value the client is looking for.
*/
GeckoDriver.prototype.findElements = async function(cmd) {
const win = assert.open(this.getCurrentWindow());
await this._handleUserPrompts();
const { element: el, using, value } = cmd.parameters;
let { using, value } = cmd.parameters;
if (!SUPPORTED_STRATEGIES.has(using)) {
throw new InvalidSelectorError(`Strategy not supported: ${using}`);
}
const win = assert.open(this.getCurrentWindow());
await this._handleUserPrompts();
let startNode;
if (typeof cmd.parameters.element != "undefined") {
startNode = WebElement.fromUUID(cmd.parameters.element, this.context);
if (typeof el != "undefined") {
startNode = WebElement.fromUUID(el, this.context);
}
let opts = {
@ -2115,6 +2124,11 @@ GeckoDriver.prototype.findElements = async function(cmd) {
all: true,
};
if (MarionettePrefs.useActors) {
const actor = await this.getActor();
return actor.findElements(using, value, opts);
}
switch (this.context) {
case Context.Chrome:
let container = { frame: win };