--- a/testing/marionette/action.js
+++ b/testing/marionette/action.js
@@ -194,17 +194,17 @@ action.Chain.prototype.actions = functio
break;
case "keyUp":
event.sendKeyUp(pack[1], keyModifiers, this.container.frame);
this.actions(chain, touchId, i, keyModifiers, cb);
break;
case "click":
- el = this.elementManager.getKnownElement(pack[1], this.container);
+ el = this.elementManager.get(pack[1], this.container);
let button = pack[2];
let clickCount = pack[3];
c = element.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);
}
@@ -225,17 +225,17 @@ action.Chain.prototype.actions = functio
"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].indexOf('move') !== -1)) {
this.scrolling = true;
}
- el = this.elementManager.getKnownElement(pack[1], this.container);
+ el = this.elementManager.get(pack[1], this.container);
c = element.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",
@@ -244,17 +244,17 @@ action.Chain.prototype.actions = functio
touchId,
null,
keyModifiers);
this.actions(chain, null, i, keyModifiers, cb);
this.scrolling = false;
break;
case "move":
- el = this.elementManager.getKnownElement(pack[1], this.container);
+ el = this.elementManager.get(pack[1], this.container);
c = element.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",
--- a/testing/marionette/browser.js
+++ b/testing/marionette/browser.js
@@ -37,21 +37,17 @@ browser.Context = class {
this.window = win;
this.driver = driver;
this.knownFrames = [];
this.startPage = "about:blank";
// used in B2G to identify the homescreen content page
this.mainContentId = null;
// used to set curFrameId upon new session
this.newSession = true;
- this.elementManager = new ElementManager([
- element.Strategy.Name,
- element.Strategy.LinkText,
- element.Strategy.PartialLinkText,
- ]);
+ this.elementManager = new element.Store();
this.setBrowser(win);
// A reference to the tab corresponding to the current window handle, if any.
this.tab = null;
this.pendingCommands = [];
// we should have one FM per BO so that we can handle modals in each Browser
this.frameManager = new frame.Manager(driver);
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -1415,68 +1415,65 @@ GeckoDriver.prototype.switchToFrame = fu
if (focus) {
this.mainFrame.focus();
}
checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
return;
}
// by element
- if (typeof element != "undefined") {
- if (this.curBrowser.elementManager.seenItems[element]) {
- // HTMLIFrameElement
- let wantedFrame = this.curBrowser.elementManager
- .getKnownElement(element, {frame: curWindow});
- // Deal with an embedded xul:browser case
- if (wantedFrame.tagName == "xul:browser" || wantedFrame.tagName == "browser") {
- curWindow = wantedFrame.contentWindow;
+ if (this.curBrowser.seenEls.has(element)) {
+ // HTMLIFrameElement
+ let wantedFrame = this.curBrowser.elementManager.get(element, {frame: curWindow});
+ // Deal with an embedded xul:browser case
+ if (wantedFrame.tagName == "xul:browser" || wantedFrame.tagName == "browser") {
+ curWindow = wantedFrame.contentWindow;
+ this.curFrame = curWindow;
+ if (focus) {
+ this.curFrame.focus();
+ }
+ checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
+ return;
+ }
+
+ // Check if the frame is XBL anonymous
+ let parent = curWindow.document.getBindingParent(wantedFrame);
+ // Shadow nodes also show up in getAnonymousNodes, we should ignore them.
+ if (parent && !(parent.shadowRoot && parent.shadowRoot.contains(wantedFrame))) {
+ let anonNodes = [...curWindow.document.getAnonymousNodes(parent) || []];
+ if (anonNodes.length > 0) {
+ let el = wantedFrame;
+ while (el) {
+ if (anonNodes.indexOf(el) > -1) {
+ curWindow = wantedFrame.contentWindow;
+ this.curFrame = curWindow;
+ if (focus) {
+ this.curFrame.focus();
+ }
+ checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
+ return;
+ }
+ el = el.parentNode;
+ }
+ }
+ }
+
+ // else, assume iframe
+ let frames = curWindow.document.getElementsByTagName("iframe");
+ let numFrames = frames.length;
+ for (let i = 0; i < numFrames; i++) {
+ if (new XPCNativeWrapper(frames[i]) == new XPCNativeWrapper(wantedFrame)) {
+ curWindow = frames[i].contentWindow;
this.curFrame = curWindow;
if (focus) {
this.curFrame.focus();
}
checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
return;
}
-
- // Check if the frame is XBL anonymous
- let parent = curWindow.document.getBindingParent(wantedFrame);
- // Shadow nodes also show up in getAnonymousNodes, we should ignore them.
- if (parent && !(parent.shadowRoot && parent.shadowRoot.contains(wantedFrame))) {
- let anonNodes = [...curWindow.document.getAnonymousNodes(parent) || []];
- if (anonNodes.length > 0) {
- let el = wantedFrame;
- while (el) {
- if (anonNodes.indexOf(el) > -1) {
- curWindow = wantedFrame.contentWindow;
- this.curFrame = curWindow;
- if (focus) {
- this.curFrame.focus();
- }
- checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
- return;
- }
- el = el.parentNode;
- }
- }
- }
-
- // else, assume iframe
- let frames = curWindow.document.getElementsByTagName("iframe");
- let numFrames = frames.length;
- for (let i = 0; i < numFrames; i++) {
- if (new XPCNativeWrapper(frames[i]) == new XPCNativeWrapper(wantedFrame)) {
- curWindow = frames[i].contentWindow;
- this.curFrame = curWindow;
- if (focus) {
- this.curFrame.focus();
- }
- checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
- return;
- }
- }
}
}
switch (typeof id) {
case "string" :
let foundById = null;
let frames = curWindow.document.getElementsByTagName("iframe");
let numFrames = frames.length;
@@ -1676,17 +1673,17 @@ GeckoDriver.prototype.findElement = func
switch (this.context) {
case Context.CHROME:
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);
}
let container = {frame: this.getCurrentWindow()};
if (opts.startNode) {
- opts.startNode = this.curBrowser.elementManager.getKnownElement(opts.startNode, container);
+ opts.startNode = this.curBrowser.elementManager.get(opts.startNode, container);
}
let el = yield element.find(container, strategy, expr, opts);
let elRef = this.curBrowser.elementManager.add(el);
let webEl = element.makeWebElement(elRef);
resp.body.value = webEl;
break;
@@ -1719,17 +1716,17 @@ GeckoDriver.prototype.findElements = fun
switch (this.context) {
case Context.CHROME:
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);
}
let container = {frame: this.getCurrentWindow()};
if (opts.startNode) {
- opts.startNode = this.curBrowser.elementManager.getKnownElement(opts.startNode, container);
+ opts.startNode = this.curBrowser.elementManager.get(opts.startNode, container);
}
let els = yield element.find(container, strategy, expr, opts);
let elRefs = this.curBrowser.elementManager.addAll(els);
let webEls = elRefs.map(element.makeWebElement);
resp.body = webEls;
break;
@@ -1754,17 +1751,17 @@ GeckoDriver.prototype.getActiveElement =
* Reference ID to the element that will be clicked.
*/
GeckoDriver.prototype.clickElement = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
yield interaction.clickElement(
el, this.sessionCapabilities.raisesAccessibilityExceptions);
break;
case Context.CONTENT:
// We need to protect against the click causing an OOP frame to close.
// This fires the mozbrowserclose event when it closes so we need to
// listen for it and then just send an error back. The person making the
@@ -1787,17 +1784,17 @@ GeckoDriver.prototype.clickElement = fun
* Value of the attribute.
*/
GeckoDriver.prototype.getElementAttribute = function*(cmd, resp) {
let {id, name} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
resp.body.value = atom.getElementAttribute(el, name, this.getCurrentWindow());
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementAttribute(id, name);
break;
}
};
@@ -1834,17 +1831,17 @@ GeckoDriver.prototype.getElementProperty
*/
GeckoDriver.prototype.getElementText = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// for chrome, we look at text nodes, and any node with a "label" field
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, { frame: win });
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
let lines = [];
this.getVisibleText(el, lines);
resp.body.value = lines.join("\n");
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementText(id);
break;
@@ -1858,17 +1855,17 @@ GeckoDriver.prototype.getElementText = f
* Reference ID to the element that will be inspected.
*/
GeckoDriver.prototype.getElementTagName = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
resp.body.value = el.tagName.toLowerCase();
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementTagName(id);
break;
}
};
@@ -1880,18 +1877,17 @@ GeckoDriver.prototype.getElementTagName
* Reference ID to the element that will be inspected.
*/
GeckoDriver.prototype.isElementDisplayed = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(
- id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
resp.body.value = yield interaction.isElementDisplayed(
el, this.sessionCapabilities.raisesAccessibilityExceptions);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.isElementDisplayed(id);
break;
}
@@ -1906,17 +1902,17 @@ GeckoDriver.prototype.isElementDisplayed
* CSS rule that is being requested.
*/
GeckoDriver.prototype.getElementValueOfCssProperty = function*(cmd, resp) {
let {id, propertyName: prop} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, { frame: win });
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
let sty = win.document.defaultView.getComputedStyle(el, null);
resp.body.value = sty.getPropertyValue(prop);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementValueOfCssProperty(id, prop);
break;
}
@@ -1930,18 +1926,17 @@ GeckoDriver.prototype.getElementValueOfC
*/
GeckoDriver.prototype.isElementEnabled = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// Selenium atom doesn't quite work here
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(
- id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
resp.body.value = yield interaction.isElementEnabled(
el, this.sessionCapabilities.raisesAccessibilityExceptions);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.isElementEnabled(id);
break;
}
@@ -1955,35 +1950,34 @@ GeckoDriver.prototype.isElementEnabled =
*/
GeckoDriver.prototype.isElementSelected = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// Selenium atom doesn't quite work here
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(
- id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
resp.body.value = yield interaction.isElementSelected(
el, this.sessionCapabilities.raisesAccessibilityExceptions);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.isElementSelected(id);
break;
}
};
GeckoDriver.prototype.getElementRect = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, { frame: win });
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
let rect = el.getBoundingClientRect();
resp.body = {
x: rect.x + win.pageXOffset,
y: rect.y + win.pageYOffset,
width: rect.width,
height: rect.height
};
break;
@@ -2007,18 +2001,17 @@ GeckoDriver.prototype.sendKeysToElement
if (!value) {
throw new InvalidArgumentError(`Expected character sequence: ${value}`);
}
switch (this.context) {
case Context.CHROME:
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(
- id, {frame: win});
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
yield interaction.sendKeysToElement(
el, value, true, this.sessionCapabilities.raisesAccessibilityExceptions);
break;
case Context.CONTENT:
let err;
let listener = function(msg) {
this.mm.removeMessageListener("Marionette:setElementValue", listener);
@@ -2068,17 +2061,17 @@ GeckoDriver.prototype.setTestName = func
*/
GeckoDriver.prototype.clearElement = function*(cmd, resp) {
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// the selenium atom doesn't work here
let win = this.getCurrentWindow();
- let el = this.curBrowser.elementManager.getKnownElement(id, { frame: win });
+ let el = this.curBrowser.elementManager.get(id, {frame: win});
if (el.nodeName == "textbox") {
el.value = "";
} else if (el.nodeName == "checkbox") {
el.checked = false;
}
break;
case Context.CONTENT:
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -54,27 +54,31 @@ element.Strategy = {
LinkText: "link text",
PartialLinkText: "partial link text",
TagName: "tag name",
XPath: "xpath",
Anon: "anon",
AnonAttribute: "anon attribute",
};
-this.ElementManager = class {
+/**
+ * Stores known/seen elements and their associated web element
+ * references.
+ *
+ * Elements are added by calling |add(el)| or |addAll(elements)|, and
+ * may be queried by their web element reference using |get(element)|.
+ */
+element.Store = class {
constructor() {
- this.seenItems = {};
+ this.els = {};
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
}
- /**
- * Reset values
- */
reset() {
- this.seenItems = {};
+ this.els = {};
}
/**
* Make a collection of elements seen.
*
* The oder of the returned web element references is guaranteed to
* match that of the collection passed in.
*
@@ -95,105 +99,136 @@ this.ElementManager = class {
*
* @param {nsIDOMElement} el
* Element to add to set of seen elements.
*
* @return {string}
* Web element reference associated with element.
*/
add(el) {
- for (let i in this.seenItems) {
+ for (let i in this.els) {
let foundEl;
try {
- foundEl = this.seenItems[i].get();
+ foundEl = this.els[i].get();
} catch (e) {}
if (foundEl) {
- if (XPCNativeWrapper(foundEl) == XPCNativeWrapper(el)) {
+ if (new XPCNativeWrapper(foundEl) == new XPCNativeWrapper(el)) {
return i;
}
+
+ // cleanup reference to gc'd element
} else {
- // cleanup reference to GC'd element
- delete this.seenItems[i];
+ delete this.els[i];
}
}
let id = element.generateUUID();
- this.seenItems[id] = Cu.getWeakReference(el);
+ this.els[id] = Cu.getWeakReference(el);
return id;
}
/**
- * Retrieve element from its unique ID
+ * Determine if the provided web element reference has been seen
+ * before/is in the element store.
+ *
+ * @param {string} uuid
+ * Element's associated web element reference.
*
- * @param String id
- * The DOM reference ID
- * @param nsIDOMWindow, ShadowRoot container
- * The window and an optional shadow root that contains the element
+ * @return {boolean}
+ * True if element is in the store, false otherwise.
+ */
+ has(uuid) {
+ return Object.keys(this.els).includes(uuid);
+ }
+
+ /**
+ * Retrieve a DOM element by its unique web element reference/UUID.
*
- * @returns nsIDOMElement
- * Returns the element or throws Exception if not found
+ * @param {string} uuid
+ * Web element reference, or UUID.
+ * @param {(nsIDOMWindow|ShadowRoot)} container
+ * Window and an optional shadow root that contains the element.
+ *
+ * @returns {nsIDOMElement}
+ * Element associated with reference.
+ *
+ * @throws {JavaScriptError}
+ * If the provided reference is unknown.
+ * @throws {StaleElementReferenceError}
+ * If element has gone stale, indicating it is no longer attached to
+ * the DOM provided in the container.
*/
- getKnownElement(id, container) {
- let el = this.seenItems[id];
+ get(uuid, container) {
+ let el = this.els[uuid];
if (!el) {
- throw new JavaScriptError(`Element has not been seen before. Id given was ${id}`);
+ throw new JavaScriptError(`Element reference not seen before: ${uuid}`);
}
+
try {
el = el.get();
- }
- catch(e) {
+ } catch (e) {
el = null;
- delete this.seenItems[id];
+ delete this.els[id];
}
- // use XPCNativeWrapper to compare elements; see bug 834266
- let wrappedFrame = XPCNativeWrapper(container.frame);
+
+ // use XPCNativeWrapper to compare elements (see bug 834266)
+ let wrappedFrame = new XPCNativeWrapper(container.frame);
let wrappedShadowRoot;
if (container.shadowRoot) {
- wrappedShadowRoot = XPCNativeWrapper(container.shadowRoot);
+ wrappedShadowRoot = new XPCNativeWrapper(container.shadowRoot);
}
+ let wrappedEl = new XPCNativeWrapper(el);
if (!el ||
- !(XPCNativeWrapper(el).ownerDocument == wrappedFrame.document) ||
- this.isDisconnected(XPCNativeWrapper(el), wrappedShadowRoot,
- wrappedFrame)) {
+ !(wrappedEl.ownerDocument == wrappedFrame.document) ||
+ this.isDisconnected(wrappedEl, wrappedFrame, wrappedShadowRoot)) {
throw new StaleElementReferenceError(
"The element reference is stale. Either the element " +
"is no longer attached to the DOM or the page has been refreshed.");
}
+
return el;
}
/**
- * Check if the element is detached from the current frame as well as the
- * optional shadow root (when inside a Shadow DOM context).
- * @param nsIDOMElement el
- * element to be checked
- * @param ShadowRoot shadowRoot
- * an optional shadow root containing an element
+ * Check if the element is detached from the current frame as well as
+ * the optional shadow root (when inside a Shadow DOM context).
+ *
+ * @param {nsIDOMElement} el
+ * Element to be checked.
* @param nsIDOMWindow frame
- * window that contains the element or the current host of the shadow
- * root.
- * @return {Boolean} a flag indicating that the element is disconnected
+ * Window object that contains the element or the current host
+ * of the shadow root.
+ * @param {ShadowRoot=} shadowRoot
+ * An optional shadow root containing an element.
+ *
+ * @return {boolean}
+ * Flag indicating that the element is disconnected.
*/
- isDisconnected(el, shadowRoot, frame) {
+ isDisconnected(el, frame, shadowRoot = undefined) {
+ // shadow dom
if (shadowRoot && frame.ShadowRoot) {
if (el.compareDocumentPosition(shadowRoot) &
- DOCUMENT_POSITION_DISCONNECTED) {
+ DOCUMENT_POSITION_DISCONNECTED) {
return true;
}
- // Looking for next possible ShadowRoot ancestor
+
+ // looking for next possible ShadowRoot ancestor
let parent = shadowRoot.host;
while (parent && !(parent instanceof frame.ShadowRoot)) {
parent = parent.parentNode;
}
return this.isDisconnected(shadowRoot.host, parent, frame);
+
+ // outside shadow dom
} else {
- return el.compareDocumentPosition(frame.document.documentElement) &
- DOCUMENT_POSITION_DISCONNECTED;
+ let docEl = frame.document.documentElement;
+ return el.compareDocumentPosition(docEl) &
+ DOCUMENT_POSITION_DISCONNECTED;
}
}
/**
* Convert values to primitives that can be transported over the
* Marionette protocol.
*
* This function implements the marshaling algorithm defined in the
@@ -283,17 +318,17 @@ this.ElementManager = class {
for (let i in args) {
converted.push(this.convertWrappedArguments(args[i], container));
}
}
else if (((typeof(args[element.LegacyKey]) === 'string') && args.hasOwnProperty(element.LegacyKey)) ||
((typeof(args[element.Key]) === 'string') &&
args.hasOwnProperty(element.Key))) {
let elementUniqueIdentifier = args[element.Key] ? args[element.Key] : args[element.LegacyKey];
- converted = this.getKnownElement(elementUniqueIdentifier, container);
+ converted = this.get(elementUniqueIdentifier, container);
if (converted == null) {
throw new WebDriverError(`Unknown element: ${elementUniqueIdentifier}`);
}
}
else {
converted = {};
for (let prop in args) {
converted[prop] = this.convertWrappedArguments(args[prop], container);
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -38,17 +38,17 @@ var isB2G = false;
var marionetteTestName;
var winUtil = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
var listenerId = null; // unique ID of this listener
var curContainer = { frame: content, shadowRoot: null };
var isRemoteBrowser = () => curContainer.frame.contentWindow !== null;
var previousContainer = null;
-var elementManager = new ElementManager();
+var elementManager = new element.Store();
var SUPPORTED_STRATEGIES = new Set([
element.Strategy.ClassName,
element.Strategy.Selector,
element.Strategy.ID,
element.Strategy.Name,
element.Strategy.LinkText,
element.Strategy.PartialLinkText,
element.Strategy.TagName,
@@ -642,17 +642,17 @@ function emitTouchEvent(type, touch) {
domWindowUtils.sendTouchEvent(type, [touch.identifier], [touch.clientX], [touch.clientY], [touch.radiusX], [touch.radiusY], [touch.rotationAngle], [touch.force], 1, 0);
}
}
/**
* Function that perform a single tap
*/
function singleTap(id, corx, cory) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
// after this block, the element will be scrolled into view
let visible = element.isVisible(el, corx, cory);
if (!visible) {
throw new ElementNotVisibleError("Element is not currently visible and may not be manipulated");
}
let a11y = accessibility.get(capabilities.raisesAccessibilityExceptions);
return a11y.getAccessible(el, true).then(acc => {
@@ -767,34 +767,34 @@ function setDispatch(batches, touches, b
batchIndex++;
for (let i = 0; i < batch.length; i++) {
pack = batch[i];
touchId = pack[0];
command = pack[1];
switch (command) {
case "press":
- el = elementManager.getKnownElement(pack[2], curContainer);
+ el = elementManager.get(pack[2], curContainer);
c = element.coordinates(el, pack[3], pack[4]);
touch = createATouch(el, c.x, c.y, touchId);
multiLast[touchId] = touch;
touches.push(touch);
emitMultiEvents("touchstart", touch, touches);
break;
case "release":
touch = multiLast[touchId];
// the index of the previous touch for the finger may change in the touches array
touchIndex = touches.indexOf(touch);
touches.splice(touchIndex, 1);
emitMultiEvents("touchend", touch, touches);
break;
case "move":
- el = elementManager.getKnownElement(pack[2], curContainer);
+ el = elementManager.get(pack[2], curContainer);
c = element.coordinates(el);
touch = createATouch(multiLast[touchId].target, c.x, c.y, touchId);
touchIndex = touches.indexOf(lastTouch);
touches[touchIndex] = touch;
multiLast[touchId] = touch;
emitMultiEvents("touchmove", touch, touches);
break;
@@ -1026,17 +1026,17 @@ function refresh(msg) {
*/
function* findElementContent(strategy, selector, opts = {}) {
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError("Strategy not supported: " + strategy);
}
opts.all = false;
if (opts.startNode) {
- opts.startNode = elementManager.getKnownElement(opts.startNode, curContainer);
+ opts.startNode = elementManager.get(opts.startNode, curContainer);
}
let el = yield element.find(curContainer, strategy, selector, opts);
let elRef = elementManager.add(el);
let webEl = element.makeWebElement(elRef);
return webEl;
}
@@ -1046,17 +1046,17 @@ function* findElementContent(strategy, s
*/
function* findElementsContent(strategy, selector, opts = {}) {
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError("Strategy not supported: " + strategy);
}
opts.all = true;
if (opts.startNode) {
- opts.startNode = elementManager.getKnownElement(opts.startNode, curContainer);
+ opts.startNode = elementManager.get(opts.startNode, curContainer);
}
let els = yield element.find(curContainer, strategy, selector, opts);
let elRefs = elementManager.addAll(els);
let webEls = elRefs.map(element.makeWebElement);
return webEls;
}
@@ -1077,77 +1077,77 @@ function getActiveElement() {
/**
* Send click event to element.
*
* @param {WebElement} id
* Reference to the web element to click.
*/
function clickElement(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return interaction.clickElement(
el,
!!capabilities.raisesAccessibilityExceptions,
capabilities.specificationLevel >= 1);
}
function getElementAttribute(id, name) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
if (element.isBooleanAttribute(el, name)) {
if (el.hasAttribute(name)) {
return "true";
} else {
return null;
}
} else {
return el.getAttribute(name);
}
}
function getElementProperty(id, name) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return el[name];
}
/**
* Get the text of this element. This includes text from child elements.
*
* @param {WebElement} id
* Reference to web element.
*
* @return {string}
* Text of element.
*/
function getElementText(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return atom.getElementText(el, curContainer.frame);
}
/**
* Get the tag name of an element.
*
* @param {WebElement} id
* Reference to web element.
*
* @return {string}
* Tag name of element.
*/
function getElementTagName(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return el.tagName.toLowerCase();
}
/**
* Determine the element displayedness of the given web element.
*
* Also performs additional accessibility checks if enabled by session
* capability.
*/
function isElementDisplayed(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return interaction.isElementDisplayed(
el, capabilities.raisesAccessibilityExceptions);
}
/**
* Retrieves the computed value of the given CSS property of the given
* web element.
*
@@ -1155,32 +1155,32 @@ function isElementDisplayed(id) {
* Web element reference.
* @param {String} prop
* The CSS property to get.
*
* @return {String}
* Effective value of the requested CSS property.
*/
function getElementValueOfCssProperty(id, prop) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
let st = curContainer.frame.document.defaultView.getComputedStyle(el, null);
return st.getPropertyValue(prop);
}
/**
* Get the position and dimensions of the element.
*
* @param {WebElement} id
* Reference to web element.
*
* @return {Object.<string, number>}
* The x, y, width, and height properties of the element.
*/
function getElementRect(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
let clientRect = el.getBoundingClientRect();
return {
x: clientRect.x + curContainer.frame.pageXOffset,
y: clientRect.y + curContainer.frame.pageYOffset,
width: clientRect.width,
height: clientRect.height
};
}
@@ -1190,41 +1190,41 @@ function getElementRect(id) {
*
* @param {WebElement} id
* Reference to web element.
*
* @return {boolean}
* True if enabled, false otherwise.
*/
function isElementEnabled(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return interaction.isElementEnabled(
el, capabilities.raisesAccessibilityExceptions);
}
/**
* Determines if the referenced element is selected or not.
*
* This operation only makes sense on input elements of the Checkbox-
* and Radio Button states, or option elements.
*/
function isElementSelected(id) {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
return interaction.isElementSelected(
el, capabilities.raisesAccessibilityExceptions);
}
/**
* Send keys to element
*/
function sendKeysToElement(msg) {
let command_id = msg.json.command_id;
let val = msg.json.value;
let id = msg.json.id;
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
if (el.type == "file") {
let p = val.join("");
fileInputElement = el;
// In e10s, we can only construct File objects in the parent process,
// so pass the filename to driver.js, which in turn passes them back
// to this frame script in receiveFiles.
sendSyncMessage("Marionette:getFiles",
@@ -1237,17 +1237,17 @@ function sendKeysToElement(msg) {
}
}
/**
* Clear the text of an element.
*/
function clearElement(id) {
try {
- let el = elementManager.getKnownElement(id, curContainer);
+ let el = elementManager.get(id, curContainer);
if (el.type == "file") {
el.value = null;
} else {
atom.clearElement(el, curContainer.frame);
}
} catch (e) {
// Bug 964738: Newer atoms contain status codes which makes wrapping
// this in an error prototype that has a status property unnecessary
@@ -1282,17 +1282,17 @@ function switchToShadowRoot(id) {
parent = parent.parentNode;
}
curContainer.shadowRoot = parent;
}
return;
}
let foundShadowRoot;
- let hostEl = elementManager.getKnownElement(id, curContainer);
+ let hostEl = elementManager.get(id, curContainer);
foundShadowRoot = hostEl.shadowRoot;
if (!foundShadowRoot) {
throw new NoSuchElementError('Unable to locate shadow root: ' + id);
}
curContainer.shadowRoot = foundShadowRoot;
}
/**
@@ -1352,48 +1352,50 @@ function switchToFrame(msg) {
curContainer.frame = content;
if(msg.json.focus == true) {
curContainer.frame.focus();
}
checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
return;
}
- if (msg.json.element != undefined) {
- if (elementManager.seenItems[msg.json.element] != undefined) {
- let wantedFrame;
- try {
- wantedFrame = elementManager.getKnownElement(msg.json.element, curContainer); //Frame Element
- } catch (e) {
- sendError(e, command_id);
- }
- if (frames.length > 0) {
- for (let i = 0; i < frames.length; i++) {
- // use XPCNativeWrapper to compare elements; see bug 834266
- if (XPCNativeWrapper(frames[i].frameElement) == XPCNativeWrapper(wantedFrame)) {
- curContainer.frame = frames[i].frameElement;
- foundFrame = i;
- }
+ let id = msg.json.element;
+ if (elementManager.has(id)) {
+ let wantedFrame;
+ try {
+ wantedFrame = elementManager.get(id, curContainer);
+ } catch (e) {
+ sendError(e, command_id);
+ }
+
+ if (frames.length > 0) {
+ for (let i = 0; i < frames.length; i++) {
+ // use XPCNativeWrapper to compare elements; see bug 834266
+ if (XPCNativeWrapper(frames[i].frameElement) == XPCNativeWrapper(wantedFrame)) {
+ curContainer.frame = frames[i].frameElement;
+ foundFrame = i;
}
}
- if (foundFrame === null) {
- // Either the frame has been removed or we have a OOP frame
- // so lets just get all the iframes and do a quick loop before
- // throwing in the towel
- let iframes = curContainer.frame.document.getElementsByTagName("iframe");
- for (var i = 0; i < iframes.length; i++) {
- if (XPCNativeWrapper(iframes[i]) == XPCNativeWrapper(wantedFrame)) {
- curContainer.frame = iframes[i];
- foundFrame = i;
- }
+ }
+
+ if (foundFrame === null) {
+ // Either the frame has been removed or we have a OOP frame
+ // so lets just get all the iframes and do a quick loop before
+ // throwing in the towel
+ let iframes = curContainer.frame.document.getElementsByTagName("iframe");
+ for (var i = 0; i < iframes.length; i++) {
+ if (XPCNativeWrapper(iframes[i]) == XPCNativeWrapper(wantedFrame)) {
+ curContainer.frame = iframes[i];
+ foundFrame = i;
}
}
}
}
+
if (foundFrame === null) {
if (typeof(msg.json.id) === 'number') {
try {
foundFrame = frames[msg.json.id].frameElement;
if (foundFrame !== null) {
curContainer.frame = foundFrame;
foundFrame = elementManager.add(curContainer.frame);
}
@@ -1562,29 +1564,29 @@ function getScreenshotHash(id, full=true
* @return {HTMLCanvasElement}
* The canvas element to be encoded or hashed.
*/
function screenshot(id, full=true, highlights=[]) {
let canvas;
let highlightEls = [];
for (let h of highlights) {
- let el = elementManager.getKnownElement(h, curContainer);
+ let el = elementManager.get(h, curContainer);
highlightEls.push(el);
}
// viewport
if (!id && !full) {
canvas = capture.viewport(curContainer.frame.document, highlightEls);
// element or full document element
} else {
let node;
if (id) {
- node = elementManager.getKnownElement(id, curContainer);
+ node = elementManager.get(id, curContainer);
} else {
node = curContainer.frame.document.documentElement;
}
canvas = capture.element(node, highlightEls);
}
return canvas;