зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1423282 - Drop MarionetteFrame:getInterruptedState IPC message. r=automatedtester,maja_zf
MarionetteFrame:getInterruptedState was used in B2G to abortence if the OOP frame got interrupted by a modal dialogue. Like the MarionetteFrame:handleModal IPC message, the frame script needed chrome assistance for querying the presence of this dialogue. Today modal dialogues (known as "user prompts") are handled entirely in chrome space, and the presence of such a dialogue is indeed meant to pause script execution in the web document. This patch makes some rather questionable changes to the legacyaction module, but this is alright because we don't expect any more tests to be written using it. This patch just about makes sure the remaining body of tests keeps passing. MozReview-Commit-ID: 72g0GlYy21T --HG-- extra : rebase_source : f44ed5999554a42c67827d6935bd96cc79a8e5dd
This commit is contained in:
Родитель
79058696cd
Коммит
f42cdc3940
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
|
const {interfaces: Ci, results: Cr, utils: Cu} = Components;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
@ -51,8 +51,6 @@ frame.Manager = class {
|
||||||
this.currentRemoteFrame = null;
|
this.currentRemoteFrame = null;
|
||||||
// frame we'll need to restore once interrupt is gone
|
// frame we'll need to restore once interrupt is gone
|
||||||
this.previousRemoteFrame = null;
|
this.previousRemoteFrame = null;
|
||||||
// set to true when we have been interrupted by a modal
|
|
||||||
this.handledModal = false;
|
|
||||||
this.driver = driver;
|
this.driver = driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,32 +60,6 @@ frame.Manager = class {
|
||||||
/*eslint-disable*/
|
/*eslint-disable*/
|
||||||
receiveMessage(message) {
|
receiveMessage(message) {
|
||||||
switch (message.name) {
|
switch (message.name) {
|
||||||
case "MarionetteFrame:getInterruptedState":
|
|
||||||
// this will return true if the calling frame was interrupted by a modal dialog
|
|
||||||
if (this.previousRemoteFrame) {
|
|
||||||
// get the frame window of the interrupted frame
|
|
||||||
let interruptedFrame = Services.wm.getOuterWindowWithId(
|
|
||||||
this.previousRemoteFrame.windowId);
|
|
||||||
|
|
||||||
if (this.previousRemoteFrame.frameId !== null) {
|
|
||||||
// find OOP frame
|
|
||||||
let iframes = interruptedFrame.document.getElementsByTagName("iframe");
|
|
||||||
interruptedFrame = iframes[this.previousRemoteFrame.frameId];
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the interrupted frame is the same as the calling frame
|
|
||||||
if (interruptedFrame.src == message.target.src) {
|
|
||||||
return {value: this.handledModal};
|
|
||||||
}
|
|
||||||
|
|
||||||
// we get here if previousRemoteFrame and currentRemoteFrame are null,
|
|
||||||
// i.e. if we're in a non-OOP process, or we haven't switched into an OOP frame,
|
|
||||||
// in which case, handledModal can't be set to true
|
|
||||||
} else if (this.currentRemoteFrame === null) {
|
|
||||||
return {value: this.handledModal};
|
|
||||||
}
|
|
||||||
return {value: false};
|
|
||||||
|
|
||||||
case "MarionetteFrame:getCurrentFrameId":
|
case "MarionetteFrame:getCurrentFrameId":
|
||||||
if (this.currentRemoteFrame !== null) {
|
if (this.currentRemoteFrame !== null) {
|
||||||
return this.currentRemoteFrame.frameId;
|
return this.currentRemoteFrame.frameId;
|
||||||
|
@ -156,9 +128,7 @@ frame.Manager = class {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds message listeners to the driver, listening for
|
* Adds message listeners to the driver, listening for
|
||||||
* messages from content frame scripts. It also adds a
|
* messages from content frame scripts.
|
||||||
* MarionetteFrame:getInterruptedState message listener to the
|
|
||||||
* FrameManager, so the frame manager's state can be checked by the frame.
|
|
||||||
*
|
*
|
||||||
* @param {nsIMessageListenerManager} mm
|
* @param {nsIMessageListenerManager} mm
|
||||||
* The message manager object, typically
|
* The message manager object, typically
|
||||||
|
@ -175,14 +145,10 @@ frame.Manager = class {
|
||||||
mm.addWeakMessageListener("Marionette:listenersAttached", this.driver);
|
mm.addWeakMessageListener("Marionette:listenersAttached", this.driver);
|
||||||
mm.addWeakMessageListener("Marionette:GetLogLevel", this.driver);
|
mm.addWeakMessageListener("Marionette:GetLogLevel", this.driver);
|
||||||
mm.addWeakMessageListener("MarionetteFrame:getCurrentFrameId", this);
|
mm.addWeakMessageListener("MarionetteFrame:getCurrentFrameId", this);
|
||||||
mm.addWeakMessageListener("MarionetteFrame:getInterruptedState", this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes listeners for messages from content frame scripts.
|
* Removes listeners for messages from content frame scripts.
|
||||||
* We do not remove the MarionetteFrame:getInterruptedState
|
|
||||||
* message listener, because we want to allow all known frames to
|
|
||||||
* contact the frame manager so that it can check if it was interrupted.
|
|
||||||
*
|
*
|
||||||
* @param {nsIMessageListenerManager} mm
|
* @param {nsIMessageListenerManager} mm
|
||||||
* The message manager object, typically
|
* The message manager object, typically
|
||||||
|
|
|
@ -27,7 +27,7 @@ this.legacyaction = this.action = {};
|
||||||
/**
|
/**
|
||||||
* Functionality for (single finger) action chains.
|
* Functionality for (single finger) action chains.
|
||||||
*/
|
*/
|
||||||
action.Chain = function (checkForInterrupted) {
|
action.Chain = function() {
|
||||||
// for assigning unique ids to all touches
|
// for assigning unique ids to all touches
|
||||||
this.nextTouchId = 1000;
|
this.nextTouchId = 1000;
|
||||||
// keep track of active Touches
|
// keep track of active Touches
|
||||||
|
@ -40,12 +40,6 @@ action.Chain = function (checkForInterrupted) {
|
||||||
this.mouseEventsOnly = false;
|
this.mouseEventsOnly = false;
|
||||||
this.checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
this.checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
|
|
||||||
if (typeof checkForInterrupted == "function") {
|
|
||||||
this.checkForInterrupted = checkForInterrupted;
|
|
||||||
} else {
|
|
||||||
this.checkForInterrupted = () => {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// determines if we create touch events
|
// determines if we create touch events
|
||||||
this.inputSource = null;
|
this.inputSource = null;
|
||||||
};
|
};
|
||||||
|
@ -111,35 +105,33 @@ action.Chain.prototype.emitMouseEvent = function (
|
||||||
button,
|
button,
|
||||||
clickCount,
|
clickCount,
|
||||||
modifiers) {
|
modifiers) {
|
||||||
if (!this.checkForInterrupted()) {
|
logger.debug(`Emitting ${type} mouse event ` +
|
||||||
logger.debug(`Emitting ${type} mouse event ` +
|
`at coordinates (${elClientX}, ${elClientY}) ` +
|
||||||
`at coordinates (${elClientX}, ${elClientY}) ` +
|
`relative to the viewport, ` +
|
||||||
`relative to the viewport, ` +
|
`button: ${button}, ` +
|
||||||
`button: ${button}, ` +
|
`clickCount: ${clickCount}`);
|
||||||
`clickCount: ${clickCount}`);
|
|
||||||
|
|
||||||
let win = doc.defaultView;
|
let win = doc.defaultView;
|
||||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
|
||||||
let mods;
|
let mods;
|
||||||
if (typeof modifiers != "undefined") {
|
if (typeof modifiers != "undefined") {
|
||||||
mods = event.parseModifiers_(modifiers);
|
mods = event.parseModifiers_(modifiers);
|
||||||
} else {
|
} else {
|
||||||
mods = 0;
|
mods = 0;
|
||||||
}
|
|
||||||
|
|
||||||
domUtils.sendMouseEvent(
|
|
||||||
type,
|
|
||||||
elClientX,
|
|
||||||
elClientY,
|
|
||||||
button || 0,
|
|
||||||
clickCount || 1,
|
|
||||||
mods,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
this.inputSource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domUtils.sendMouseEvent(
|
||||||
|
type,
|
||||||
|
elClientX,
|
||||||
|
elClientY,
|
||||||
|
button || 0,
|
||||||
|
clickCount || 1,
|
||||||
|
mods,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
this.inputSource);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -476,7 +468,6 @@ action.Chain.prototype.generateEvents = function (
|
||||||
default:
|
default:
|
||||||
throw new WebDriverError("Unknown event type: " + type);
|
throw new WebDriverError("Unknown event type: " + type);
|
||||||
}
|
}
|
||||||
this.checkForInterrupted();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
action.Chain.prototype.mouseTap = function (doc, x, y, button, count, mod) {
|
action.Chain.prototype.mouseTap = function (doc, x, y, button, count, mod) {
|
||||||
|
|
|
@ -49,8 +49,6 @@ Cu.importGlobalProperties(["URL"]);
|
||||||
|
|
||||||
let listenerId = null; // unique ID of this listener
|
let listenerId = null; // unique ID of this listener
|
||||||
let curContainer = {frame: content, shadowRoot: null};
|
let curContainer = {frame: content, shadowRoot: null};
|
||||||
let previousContainer = null;
|
|
||||||
|
|
||||||
|
|
||||||
// Listen for click event to indicate one click has happened, so actions
|
// Listen for click event to indicate one click has happened, so actions
|
||||||
// code can send dblclick event, also resetClick and cancelTimer
|
// code can send dblclick event, also resetClick and cancelTimer
|
||||||
|
@ -73,7 +71,7 @@ const SUPPORTED_STRATEGIES = new Set([
|
||||||
|
|
||||||
let capabilities;
|
let capabilities;
|
||||||
|
|
||||||
let legacyactions = new legacyaction.Chain(checkForInterrupted);
|
let legacyactions = new legacyaction.Chain();
|
||||||
|
|
||||||
// last touch for each fingerId
|
// last touch for each fingerId
|
||||||
let multiLast = {};
|
let multiLast = {};
|
||||||
|
@ -719,30 +717,6 @@ function resetValues() {
|
||||||
action.inputsToCancel = [];
|
action.inputsToCancel = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function wasInterrupted() {
|
|
||||||
if (previousContainer) {
|
|
||||||
let element = content.document.elementFromPoint(
|
|
||||||
(content.innerWidth / 2), (content.innerHeight / 2));
|
|
||||||
if (element.id.indexOf("modal-dialog") == -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return sendSyncMessage("MarionetteFrame:getInterruptedState", {})[0].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkForInterrupted() {
|
|
||||||
if (wasInterrupted()) {
|
|
||||||
// if previousContainer is set, then we're in a single process
|
|
||||||
// environment
|
|
||||||
if (previousContainer) {
|
|
||||||
curContainer = legacyactions.container = previousContainer;
|
|
||||||
previousContainer = null;
|
|
||||||
}
|
|
||||||
sendSyncMessage("Marionette:switchedToFrame", {restorePrevious: true});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function execute(script, args, timeout, opts) {
|
async function execute(script, args, timeout, opts) {
|
||||||
opts.timeout = timeout;
|
opts.timeout = timeout;
|
||||||
let sb = sandbox.createMutable(curContainer.frame);
|
let sb = sandbox.createMutable(curContainer.frame);
|
||||||
|
@ -756,58 +730,56 @@ async function executeInSandbox(script, args, timeout, opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitTouchEvent(type, touch) {
|
function emitTouchEvent(type, touch) {
|
||||||
if (!wasInterrupted()) {
|
logger.info(`Emitting Touch event of type ${type} ` +
|
||||||
logger.info(`Emitting Touch event of type ${type} ` +
|
`to element with id: ${touch.target.id} ` +
|
||||||
`to element with id: ${touch.target.id} ` +
|
`and tag name: ${touch.target.tagName} ` +
|
||||||
`and tag name: ${touch.target.tagName} ` +
|
`at coordinates (${touch.clientX}), ` +
|
||||||
`at coordinates (${touch.clientX}), ` +
|
`${touch.clientY}) relative to the viewport`);
|
||||||
`${touch.clientY}) relative to the viewport`);
|
|
||||||
|
|
||||||
const win = curContainer.frame;
|
const win = curContainer.frame;
|
||||||
let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
.QueryInterface(Ci.nsIDocShell);
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
if (docShell.asyncPanZoomEnabled && legacyactions.scrolling) {
|
if (docShell.asyncPanZoomEnabled && legacyactions.scrolling) {
|
||||||
// if we're in APZ and we're scrolling, we must use
|
// if we're in APZ and we're scrolling, we must use
|
||||||
// sendNativeTouchPoint to dispatch our touchmove events
|
// sendNativeTouchPoint to dispatch our touchmove events
|
||||||
let index = sendSyncMessage("MarionetteFrame:getCurrentFrameId");
|
let index = sendSyncMessage("MarionetteFrame:getCurrentFrameId");
|
||||||
|
|
||||||
// only call emitTouchEventForIFrame if we're inside an iframe.
|
// only call emitTouchEventForIFrame if we're inside an iframe.
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
let ev = {
|
let ev = {
|
||||||
index,
|
index,
|
||||||
type,
|
|
||||||
id: touch.identifier,
|
|
||||||
clientX: touch.clientX,
|
|
||||||
clientY: touch.clientY,
|
|
||||||
screenX: touch.screenX,
|
|
||||||
screenY: touch.screenY,
|
|
||||||
radiusX: touch.radiusX,
|
|
||||||
radiusY: touch.radiusY,
|
|
||||||
rotation: touch.rotationAngle,
|
|
||||||
force: touch.force,
|
|
||||||
};
|
|
||||||
sendSyncMessage("Marionette:emitTouchEvent", ev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we get here if we're not in asyncPacZoomEnabled land, or if we're
|
|
||||||
// the main process
|
|
||||||
let domWindowUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
domWindowUtils.sendTouchEvent(
|
|
||||||
type,
|
type,
|
||||||
[touch.identifier],
|
id: touch.identifier,
|
||||||
[touch.clientX],
|
clientX: touch.clientX,
|
||||||
[touch.clientY],
|
clientY: touch.clientY,
|
||||||
[touch.radiusX],
|
screenX: touch.screenX,
|
||||||
[touch.radiusY],
|
screenY: touch.screenY,
|
||||||
[touch.rotationAngle],
|
radiusX: touch.radiusX,
|
||||||
[touch.force],
|
radiusY: touch.radiusY,
|
||||||
1,
|
rotation: touch.rotationAngle,
|
||||||
0);
|
force: touch.force,
|
||||||
|
};
|
||||||
|
sendSyncMessage("Marionette:emitTouchEvent", ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we get here if we're not in asyncPacZoomEnabled land, or if we're
|
||||||
|
// the main process
|
||||||
|
let domWindowUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
domWindowUtils.sendTouchEvent(
|
||||||
|
type,
|
||||||
|
[touch.identifier],
|
||||||
|
[touch.clientX],
|
||||||
|
[touch.clientY],
|
||||||
|
[touch.radiusX],
|
||||||
|
[touch.radiusY],
|
||||||
|
[touch.rotationAngle],
|
||||||
|
[touch.force],
|
||||||
|
1,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче