mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1792529 - [marionette] Remove "Marionette:SingleTap" and legacy actions module. r=webdriver-reviewers,jgraham
Differential Revision: https://phabricator.services.mozilla.com/D158191
This commit is contained in:
parent
3a0c1ccb2f
commit
7ebedfced8
@ -17,7 +17,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
evaluate: "chrome://remote/content/marionette/evaluate.sys.mjs",
|
||||
interaction: "chrome://remote/content/marionette/interaction.sys.mjs",
|
||||
json: "chrome://remote/content/marionette/json.sys.mjs",
|
||||
legacyaction: "chrome://remote/content/marionette/legacyaction.sys.mjs",
|
||||
Log: "chrome://remote/content/shared/Log.sys.mjs",
|
||||
sandbox: "chrome://remote/content/marionette/evaluate.sys.mjs",
|
||||
Sandboxes: "chrome://remote/content/marionette/evaluate.sys.mjs",
|
||||
@ -47,17 +46,6 @@ export class MarionetteCommandsChild extends JSWindowActorChild {
|
||||
return this.manager.innerWindowId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy getter to create a legacyaction Chain instance for touch events.
|
||||
*/
|
||||
get legacyactions() {
|
||||
if (!this._legacyactions) {
|
||||
this._legacyactions = new lazy.legacyaction.Chain();
|
||||
}
|
||||
|
||||
return this._legacyactions;
|
||||
}
|
||||
|
||||
actorCreated() {
|
||||
lazy.logger.trace(
|
||||
`[${this.browsingContext.id}] MarionetteCommands actor created ` +
|
||||
@ -164,10 +152,6 @@ export class MarionetteCommandsChild extends JSWindowActorChild {
|
||||
result = await this.sendKeysToElement(data);
|
||||
waitForNextTick = true;
|
||||
break;
|
||||
case "MarionetteCommandsParent:singleTap":
|
||||
result = await this.singleTap(data);
|
||||
waitForNextTick = true;
|
||||
break;
|
||||
case "MarionetteCommandsParent:switchToFrame":
|
||||
result = await this.switchToFrame(data);
|
||||
waitForNextTick = true;
|
||||
@ -551,14 +535,6 @@ export class MarionetteCommandsChild extends JSWindowActorChild {
|
||||
return lazy.interaction.sendKeysToElement(elem, text, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a single tap.
|
||||
*/
|
||||
async singleTap(options = {}) {
|
||||
const { capabilities, elem, x, y } = options;
|
||||
return this.legacyactions.singleTap(elem, x, y, capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to the specified frame.
|
||||
*
|
||||
|
@ -249,15 +249,6 @@ export class MarionetteCommandsParent extends JSWindowActorParent {
|
||||
return this.sendQuery("MarionetteCommandsParent:releaseActions");
|
||||
}
|
||||
|
||||
async singleTap(webEl, x, y, capabilities) {
|
||||
return this.sendQuery("MarionetteCommandsParent:singleTap", {
|
||||
capabilities: capabilities.toJSON(),
|
||||
elem: webEl,
|
||||
x,
|
||||
y,
|
||||
});
|
||||
}
|
||||
|
||||
async switchToFrame(id) {
|
||||
const { browsingContextId } = await this.sendQuery(
|
||||
"MarionetteCommandsParent:switchToFrame",
|
||||
@ -339,7 +330,6 @@ export function getMarionetteCommandsActorProxy(browsingContextFn) {
|
||||
"performActions",
|
||||
"releaseActions",
|
||||
"sendKeysToElement",
|
||||
"singleTap",
|
||||
];
|
||||
|
||||
return new Proxy(
|
||||
|
@ -1410,21 +1410,6 @@ GeckoDriver.prototype.setTimeouts = function (cmd) {
|
||||
this.currentSession.timeouts = lazy.Timeouts.fromJSON(merged);
|
||||
};
|
||||
|
||||
/** Single tap. */
|
||||
GeckoDriver.prototype.singleTap = async function (cmd) {
|
||||
lazy.assert.open(this.getBrowsingContext());
|
||||
|
||||
let { id, x, y } = cmd.parameters;
|
||||
let webEl = lazy.WebElement.fromUUID(id).toJSON();
|
||||
|
||||
await this.getActor().singleTap(
|
||||
webEl,
|
||||
x,
|
||||
y,
|
||||
this.currentSession.capabilities
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform a series of grouped actions at the specified points in time.
|
||||
*
|
||||
@ -3299,7 +3284,6 @@ GeckoDriver.prototype.commands = {
|
||||
"Marionette:Quit": GeckoDriver.prototype.quit,
|
||||
"Marionette:SetContext": GeckoDriver.prototype.setContext,
|
||||
"Marionette:SetScreenOrientation": GeckoDriver.prototype.setScreenOrientation,
|
||||
"Marionette:SingleTap": GeckoDriver.prototype.singleTap,
|
||||
|
||||
// Addon service
|
||||
"Addon:Install": GeckoDriver.prototype.installAddon,
|
||||
|
@ -96,11 +96,6 @@ event.DoubleClickTracker = {
|
||||
},
|
||||
};
|
||||
|
||||
// Only used by legacyactions.js
|
||||
event.parseModifiers_ = function (modifiers, win) {
|
||||
return _getEventUtils(win)._parseModifiers(modifiers);
|
||||
};
|
||||
|
||||
/**
|
||||
* Synthesise a mouse event at a point.
|
||||
*
|
||||
|
@ -22,7 +22,6 @@ remote.jar:
|
||||
content/marionette/interaction.sys.mjs (interaction.sys.mjs)
|
||||
content/marionette/json.sys.mjs (json.sys.mjs)
|
||||
content/marionette/l10n.sys.mjs (l10n.sys.mjs)
|
||||
content/marionette/legacyaction.sys.mjs (legacyaction.sys.mjs)
|
||||
content/marionette/message.sys.mjs (message.sys.mjs)
|
||||
content/marionette/modal.sys.mjs (modal.sys.mjs)
|
||||
content/marionette/navigate.sys.mjs (navigate.sys.mjs)
|
||||
|
@ -1,640 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
/* eslint-disable no-restricted-globals */
|
||||
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
Preferences: "resource://gre/modules/Preferences.sys.mjs",
|
||||
|
||||
accessibility: "chrome://remote/content/marionette/accessibility.sys.mjs",
|
||||
dom: "chrome://remote/content/shared/DOM.sys.mjs",
|
||||
error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
|
||||
json: "chrome://remote/content/marionette/json.sys.mjs",
|
||||
event: "chrome://remote/content/marionette/event.sys.mjs",
|
||||
Log: "chrome://remote/content/shared/Log.sys.mjs",
|
||||
WebElement: "chrome://remote/content/marionette/web-reference.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(lazy, "logger", () =>
|
||||
lazy.Log.get(lazy.Log.TYPES.MARIONETTE)
|
||||
);
|
||||
|
||||
const CONTEXT_MENU_DELAY_PREF = "ui.click_hold_context_menus.delay";
|
||||
const DEFAULT_CONTEXT_MENU_DELAY = 750; // ms
|
||||
|
||||
/** @namespace */
|
||||
export const legacyaction = {};
|
||||
|
||||
const action = legacyaction;
|
||||
|
||||
/**
|
||||
* Functionality for (single finger) action chains.
|
||||
*/
|
||||
action.Chain = function () {
|
||||
// for assigning unique ids to all touches
|
||||
this.nextTouchId = 1000;
|
||||
// keep track of active Touches
|
||||
this.touchIds = {};
|
||||
// last touch for each fingerId
|
||||
this.lastCoordinates = null;
|
||||
this.isTap = false;
|
||||
this.scrolling = false;
|
||||
// whether to send mouse event
|
||||
this.mouseEventsOnly = false;
|
||||
this.checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
|
||||
// determines if we create touch events
|
||||
this.inputSource = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a touch based event.
|
||||
*
|
||||
* @param {Element} elem
|
||||
* The Element on which the touch event should be created.
|
||||
* @param {number} x
|
||||
* x coordinate relative to the viewport.
|
||||
* @param {number} y
|
||||
* y coordinate relative to the viewport.
|
||||
* @param {number} touchId
|
||||
* Touch event id used by legacyactions.
|
||||
*/
|
||||
action.Chain.prototype.createATouch = function (elem, x, y, touchId) {
|
||||
const doc = elem.ownerDocument;
|
||||
const win = doc.defaultView;
|
||||
const [clientX, clientY, pageX, pageY, screenX, screenY] =
|
||||
this.getCoordinateInfo(elem, x, y);
|
||||
const atouch = doc.createTouch(
|
||||
win,
|
||||
elem,
|
||||
touchId,
|
||||
pageX,
|
||||
pageY,
|
||||
screenX,
|
||||
screenY,
|
||||
clientX,
|
||||
clientY
|
||||
);
|
||||
return atouch;
|
||||
};
|
||||
|
||||
action.Chain.prototype.dispatchActions = function (
|
||||
args,
|
||||
touchId,
|
||||
container,
|
||||
seenEls
|
||||
) {
|
||||
this.seenEls = seenEls;
|
||||
this.container = container;
|
||||
let commandArray = lazy.json.deserialize(args, seenEls, container.frame);
|
||||
|
||||
if (touchId == null) {
|
||||
touchId = this.nextTSouchId++;
|
||||
}
|
||||
|
||||
if (!container.frame.document.createTouch) {
|
||||
this.mouseEventsOnly = true;
|
||||
}
|
||||
|
||||
let keyModifiers = {
|
||||
shiftKey: false,
|
||||
ctrlKey: false,
|
||||
altKey: false,
|
||||
metaKey: false,
|
||||
};
|
||||
|
||||
return new Promise(resolve => {
|
||||
this.actions(commandArray, touchId, 0, keyModifiers, resolve);
|
||||
}).catch(this.resetValues.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* This function emit mouse event.
|
||||
*
|
||||
* @param {Document} doc
|
||||
* Current document.
|
||||
* @param {string} type
|
||||
* Type of event to dispatch.
|
||||
* @param {number} elClientX
|
||||
* X coordinate of the mouse relative to the viewport.
|
||||
* @param {number} elClientY
|
||||
* Y coordinate of the mouse relative to the viewport.
|
||||
* @param {number} button
|
||||
* The button number.
|
||||
* @param {number} clickCount
|
||||
* Number of clicks, button notes the mouse button.
|
||||
* @param {object} modifiers
|
||||
* An object of modifier keys present.
|
||||
*/
|
||||
action.Chain.prototype.emitMouseEvent = function (
|
||||
doc,
|
||||
type,
|
||||
elClientX,
|
||||
elClientY,
|
||||
button,
|
||||
clickCount,
|
||||
modifiers
|
||||
) {
|
||||
lazy.logger.debug(
|
||||
`Emitting ${type} mouse event ` +
|
||||
`at coordinates (${elClientX}, ${elClientY}) ` +
|
||||
`relative to the viewport, ` +
|
||||
`button: ${button}, ` +
|
||||
`clickCount: ${clickCount}`
|
||||
);
|
||||
|
||||
let win = doc.defaultView;
|
||||
let domUtils = win.windowUtils;
|
||||
|
||||
let mods;
|
||||
if (typeof modifiers != "undefined") {
|
||||
mods = lazy.event.parseModifiers_(modifiers, win);
|
||||
} else {
|
||||
mods = 0;
|
||||
}
|
||||
|
||||
domUtils.sendMouseEvent(
|
||||
type,
|
||||
elClientX,
|
||||
elClientY,
|
||||
button || 0,
|
||||
clickCount || 1,
|
||||
mods,
|
||||
false,
|
||||
0,
|
||||
this.inputSource
|
||||
);
|
||||
};
|
||||
|
||||
action.Chain.prototype.emitTouchEvent = function (doc, type, touch) {
|
||||
lazy.logger.info(
|
||||
`Emitting Touch event of type ${type} ` +
|
||||
`to element with id: ${touch.target.id} ` +
|
||||
`and tag name: ${touch.target.tagName} ` +
|
||||
`at coordinates (${touch.clientX}), ` +
|
||||
`${touch.clientY}) relative to the viewport`
|
||||
);
|
||||
|
||||
const win = doc.defaultView;
|
||||
if (win.docShell.asyncPanZoomEnabled && this.scrolling) {
|
||||
lazy.logger.debug(
|
||||
`Cannot emit touch event with asyncPanZoomEnabled and legacyactions.scrolling`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// we get here if we're not in asyncPacZoomEnabled land, or if we're
|
||||
// the main process
|
||||
win.windowUtils.sendTouchEvent(
|
||||
type,
|
||||
[touch.identifier],
|
||||
[touch.clientX],
|
||||
[touch.clientY],
|
||||
[touch.radiusX],
|
||||
[touch.radiusY],
|
||||
[touch.rotationAngle],
|
||||
[touch.force],
|
||||
[0],
|
||||
[0],
|
||||
[0],
|
||||
0
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset any persisted values after a command completes.
|
||||
*/
|
||||
action.Chain.prototype.resetValues = function () {
|
||||
this.container = null;
|
||||
this.seenEls = null;
|
||||
this.mouseEventsOnly = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that performs a single tap.
|
||||
*/
|
||||
action.Chain.prototype.singleTap = async function (
|
||||
el,
|
||||
corx,
|
||||
cory,
|
||||
capabilities
|
||||
) {
|
||||
const doc = el.ownerDocument;
|
||||
// after this block, the element will be scrolled into view
|
||||
let visible = lazy.dom.isVisible(el, corx, cory);
|
||||
if (!visible) {
|
||||
throw new lazy.error.ElementNotInteractableError(
|
||||
"Element is not currently visible and may not be manipulated"
|
||||
);
|
||||
}
|
||||
|
||||
let a11y = lazy.accessibility.get(capabilities["moz:accessibilityChecks"]);
|
||||
let acc = await a11y.assertAccessible(el, true);
|
||||
a11y.assertVisible(acc, el, visible);
|
||||
a11y.assertActionable(acc, el);
|
||||
if (!doc.createTouch) {
|
||||
this.mouseEventsOnly = true;
|
||||
}
|
||||
let c = lazy.dom.coordinates(el, corx, cory);
|
||||
if (!this.mouseEventsOnly) {
|
||||
let touchId = this.nextTouchId++;
|
||||
let touch = this.createATouch(el, c.x, c.y, touchId);
|
||||
this.emitTouchEvent(doc, "touchstart", touch);
|
||||
this.emitTouchEvent(doc, "touchend", touch);
|
||||
}
|
||||
this.mouseTap(doc, c.x, c.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Emit events for each action in the provided chain.
|
||||
*
|
||||
* To emit touch events for each finger, one might send a [["press", id],
|
||||
* ["wait", 5], ["release"]] chain.
|
||||
*
|
||||
* @param {Array.<Array<?>>} chain
|
||||
* A multi-dimensional array of actions.
|
||||
* @param {Object<string, number>} touchId
|
||||
* Represents the finger ID.
|
||||
* @param {number} i
|
||||
* Keeps track of the current action of the chain.
|
||||
* @param {Object<string, boolean>} keyModifiers
|
||||
* Keeps track of keyDown/keyUp pairs through an action chain.
|
||||
* @param {function(?)} cb
|
||||
* Called on success.
|
||||
*
|
||||
* @returns {Object<string, number>}
|
||||
* Last finger ID, or an empty object.
|
||||
*/
|
||||
action.Chain.prototype.actions = function (
|
||||
chain,
|
||||
touchId,
|
||||
i,
|
||||
keyModifiers,
|
||||
cb
|
||||
) {
|
||||
if (i == chain.length) {
|
||||
cb(touchId || null);
|
||||
this.resetValues();
|
||||
return;
|
||||
}
|
||||
|
||||
let pack = chain[i];
|
||||
let command = pack[0];
|
||||
let webEl;
|
||||
let el;
|
||||
let c;
|
||||
i++;
|
||||
|
||||
if (!["press", "wait", "keyDown", "keyUp", "click"].includes(command)) {
|
||||
// if mouseEventsOnly, then touchIds isn't used
|
||||
if (!(touchId in this.touchIds) && !this.mouseEventsOnly) {
|
||||
this.resetValues();
|
||||
throw new lazy.error.WebDriverError("Element has not been pressed");
|
||||
}
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case "keyDown":
|
||||
lazy.event.sendKeyDown(pack[1], keyModifiers, this.container.frame);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
|
||||
case "keyUp":
|
||||
lazy.event.sendKeyUp(pack[1], keyModifiers, this.container.frame);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
|
||||
case "click":
|
||||
webEl = lazy.WebElement.fromUUID(pack[1]);
|
||||
el = this.seenEls.get(webEl);
|
||||
let button = pack[2];
|
||||
let clickCount = pack[3];
|
||||
c = lazy.dom.coordinates(el);
|
||||
this.mouseTap(
|
||||
el.ownerDocument,
|
||||
c.x,
|
||||
c.y,
|
||||
button,
|
||||
clickCount,
|
||||
keyModifiers
|
||||
);
|
||||
if (button == 2) {
|
||||
this.emitMouseEvent(
|
||||
el.ownerDocument,
|
||||
"contextmenu",
|
||||
c.x,
|
||||
c.y,
|
||||
button,
|
||||
clickCount,
|
||||
keyModifiers
|
||||
);
|
||||
}
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
|
||||
case "press":
|
||||
if (this.lastCoordinates) {
|
||||
this.generateEvents(
|
||||
"cancel",
|
||||
this.lastCoordinates[0],
|
||||
this.lastCoordinates[1],
|
||||
touchId,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
this.resetValues();
|
||||
throw new lazy.error.WebDriverError(
|
||||
"Invalid Command: press cannot follow an active touch event"
|
||||
);
|
||||
}
|
||||
|
||||
// look ahead to check if we're scrolling,
|
||||
// needed for APZ touch dispatching
|
||||
if (i != chain.length && chain[i][0].includes("move")) {
|
||||
this.scrolling = true;
|
||||
}
|
||||
webEl = lazy.WebElement.fromUUID(pack[1]);
|
||||
el = this.seenEls.get(webEl);
|
||||
c = lazy.dom.coordinates(el, pack[2], pack[3]);
|
||||
touchId = this.generateEvents("press", c.x, c.y, null, el, keyModifiers);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
|
||||
case "release":
|
||||
this.generateEvents(
|
||||
"release",
|
||||
this.lastCoordinates[0],
|
||||
this.lastCoordinates[1],
|
||||
touchId,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
this.actions(chain, null, i, keyModifiers, cb);
|
||||
this.scrolling = false;
|
||||
break;
|
||||
|
||||
case "move":
|
||||
webEl = lazy.WebElement.fromUUID(pack[1]);
|
||||
el = this.seenEls.get(webEl);
|
||||
c = lazy.dom.coordinates(el);
|
||||
this.generateEvents("move", c.x, c.y, touchId, null, keyModifiers);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
|
||||
case "moveByOffset":
|
||||
this.generateEvents(
|
||||
"move",
|
||||
this.lastCoordinates[0] + pack[1],
|
||||
this.lastCoordinates[1] + pack[2],
|
||||
touchId,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
|
||||
case "wait":
|
||||
if (pack[1] != null) {
|
||||
let time = pack[1] * 1000;
|
||||
|
||||
// standard waiting time to fire contextmenu
|
||||
let standard = lazy.Preferences.get(
|
||||
CONTEXT_MENU_DELAY_PREF,
|
||||
DEFAULT_CONTEXT_MENU_DELAY
|
||||
);
|
||||
|
||||
if (time >= standard && this.isTap) {
|
||||
chain.splice(i, 0, ["longPress"], ["wait", (time - standard) / 1000]);
|
||||
time = standard;
|
||||
}
|
||||
this.checkTimer.initWithCallback(
|
||||
() => this.actions(chain, touchId, i, keyModifiers, cb),
|
||||
time,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT
|
||||
);
|
||||
} else {
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
}
|
||||
break;
|
||||
|
||||
case "cancel":
|
||||
this.generateEvents(
|
||||
"cancel",
|
||||
this.lastCoordinates[0],
|
||||
this.lastCoordinates[1],
|
||||
touchId,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
this.scrolling = false;
|
||||
break;
|
||||
|
||||
case "longPress":
|
||||
this.generateEvents(
|
||||
"contextmenu",
|
||||
this.lastCoordinates[0],
|
||||
this.lastCoordinates[1],
|
||||
touchId,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
this.actions(chain, touchId, i, keyModifiers, cb);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an element and a pair of coordinates, returns an array of the
|
||||
* form [clientX, clientY, pageX, pageY, screenX, screenY].
|
||||
*/
|
||||
action.Chain.prototype.getCoordinateInfo = function (el, corx, cory) {
|
||||
let win = el.ownerGlobal;
|
||||
return [
|
||||
corx, // clientX
|
||||
cory, // clientY
|
||||
corx + win.pageXOffset, // pageX
|
||||
cory + win.pageYOffset, // pageY
|
||||
corx + win.mozInnerScreenX, // screenX
|
||||
cory + win.mozInnerScreenY, // screenY
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} type
|
||||
* The event type (eg "tap", "press", ...).
|
||||
* @param {number} x
|
||||
* X coordinate of the location to generate the event that is relative
|
||||
* to the viewport.
|
||||
* @param {number} y
|
||||
* Y coordinate of the location to generate the event that is relative
|
||||
* to the viewport.
|
||||
* @param {number} touchId
|
||||
* The current touch id.
|
||||
* @param {Element} target
|
||||
* The Element on which the events should be created.
|
||||
*/
|
||||
action.Chain.prototype.generateEvents = function (
|
||||
type,
|
||||
x,
|
||||
y,
|
||||
touchId,
|
||||
target,
|
||||
keyModifiers
|
||||
) {
|
||||
this.lastCoordinates = [x, y];
|
||||
let doc = this.container.frame.document;
|
||||
|
||||
switch (type) {
|
||||
case "tap":
|
||||
if (this.mouseEventsOnly) {
|
||||
let touch = this.createATouch(target, x, y, touchId);
|
||||
this.mouseTap(
|
||||
touch.target.ownerDocument,
|
||||
touch.clientX,
|
||||
touch.clientY,
|
||||
null,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
} else {
|
||||
touchId = this.nextTouchId++;
|
||||
let touch = this.createATouch(target, x, y, touchId);
|
||||
this.emitTouchEvent(doc, "touchstart", touch);
|
||||
this.emitTouchEvent(doc, "touchend", touch);
|
||||
this.mouseTap(
|
||||
touch.target.ownerDocument,
|
||||
touch.clientX,
|
||||
touch.clientY,
|
||||
null,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
}
|
||||
this.lastCoordinates = null;
|
||||
break;
|
||||
|
||||
case "press":
|
||||
this.isTap = true;
|
||||
if (this.mouseEventsOnly) {
|
||||
this.emitMouseEvent(doc, "mousemove", x, y, null, null, keyModifiers);
|
||||
this.emitMouseEvent(doc, "mousedown", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
touchId = this.nextTouchId++;
|
||||
let touch = this.createATouch(target, x, y, touchId);
|
||||
this.emitTouchEvent(doc, "touchstart", touch);
|
||||
this.touchIds[touchId] = touch;
|
||||
return touchId;
|
||||
}
|
||||
break;
|
||||
|
||||
case "release":
|
||||
if (this.mouseEventsOnly) {
|
||||
let [x, y] = this.lastCoordinates;
|
||||
this.emitMouseEvent(doc, "mouseup", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
let touch = this.touchIds[touchId];
|
||||
let [x, y] = this.lastCoordinates;
|
||||
|
||||
touch = this.createATouch(touch.target, x, y, touchId);
|
||||
this.emitTouchEvent(doc, "touchend", touch);
|
||||
|
||||
if (this.isTap) {
|
||||
this.mouseTap(
|
||||
touch.target.ownerDocument,
|
||||
touch.clientX,
|
||||
touch.clientY,
|
||||
null,
|
||||
null,
|
||||
keyModifiers
|
||||
);
|
||||
}
|
||||
delete this.touchIds[touchId];
|
||||
}
|
||||
|
||||
this.isTap = false;
|
||||
this.lastCoordinates = null;
|
||||
break;
|
||||
|
||||
case "cancel":
|
||||
this.isTap = false;
|
||||
if (this.mouseEventsOnly) {
|
||||
let [x, y] = this.lastCoordinates;
|
||||
this.emitMouseEvent(doc, "mouseup", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
this.emitTouchEvent(doc, "touchcancel", this.touchIds[touchId]);
|
||||
delete this.touchIds[touchId];
|
||||
}
|
||||
this.lastCoordinates = null;
|
||||
break;
|
||||
|
||||
case "move":
|
||||
this.isTap = false;
|
||||
if (this.mouseEventsOnly) {
|
||||
this.emitMouseEvent(doc, "mousemove", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
let touch = this.createATouch(
|
||||
this.touchIds[touchId].target,
|
||||
x,
|
||||
y,
|
||||
touchId
|
||||
);
|
||||
this.touchIds[touchId] = touch;
|
||||
this.emitTouchEvent(doc, "touchmove", touch);
|
||||
}
|
||||
break;
|
||||
|
||||
case "contextmenu":
|
||||
this.isTap = false;
|
||||
let event = this.container.frame.document.createEvent("MouseEvents");
|
||||
if (this.mouseEventsOnly) {
|
||||
target = doc.elementFromPoint(
|
||||
this.lastCoordinates[0],
|
||||
this.lastCoordinates[1]
|
||||
);
|
||||
} else {
|
||||
target = this.touchIds[touchId].target;
|
||||
}
|
||||
|
||||
let [clientX, clientY, , , screenX, screenY] = this.getCoordinateInfo(
|
||||
target,
|
||||
x,
|
||||
y
|
||||
);
|
||||
|
||||
event.initMouseEvent(
|
||||
"contextmenu",
|
||||
true,
|
||||
true,
|
||||
target.ownerGlobal,
|
||||
1,
|
||||
screenX,
|
||||
screenY,
|
||||
clientX,
|
||||
clientY,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
null
|
||||
);
|
||||
target.dispatchEvent(event);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new lazy.error.WebDriverError("Unknown event type: " + type);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
action.Chain.prototype.mouseTap = function (doc, x, y, button, count, mod) {
|
||||
this.emitMouseEvent(doc, "mousemove", x, y, button, count, mod);
|
||||
this.emitMouseEvent(doc, "mousedown", x, y, button, count, mod);
|
||||
this.emitMouseEvent(doc, "mouseup", x, y, button, count, mod);
|
||||
};
|
@ -255,17 +255,6 @@ class HTMLElement(object):
|
||||
"""Simulates a click on the element."""
|
||||
self.marionette._send_message("WebDriver:ElementClick", {"id": self.id})
|
||||
|
||||
def tap(self, x=None, y=None):
|
||||
"""Simulates a set of tap events on the element.
|
||||
|
||||
:param x: X coordinate of tap event. If not given, default to
|
||||
the centre of the element.
|
||||
:param y: Y coordinate of tap event. If not given, default to
|
||||
the centre of the element.
|
||||
"""
|
||||
body = {"id": self.id, "x": x, "y": y}
|
||||
self.marionette._send_message("Marionette:SingleTap", body)
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
"""Returns the visible text of the element, and its child elements."""
|
||||
|
Loading…
Reference in New Issue
Block a user