Backed out changeset 5c83a36d9eba (bug 1153832) for Gip(a) failures.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-04-16 12:20:48 -04:00
parent d827a7ffd1
commit a08d886394
5 changed files with 319 additions and 315 deletions

View File

@ -155,7 +155,8 @@ ListenerProxy.prototype.__noSuchMethod__ = function*(name, args) {
let okListener = () => resolve();
let valListener = msg => resolve(msg.json.value);
let errListener = msg => reject(msg.objects.error);
let errListener = msg => reject(
"error" in msg.objects ? msg.objects.error : msg.json);
let handleDialog = function(subject, topic) {
listeners.remove();
@ -2061,7 +2062,7 @@ GeckoDriver.prototype.clickElement = function(cmd, resp) {
// listen for it and then just send an error back. The person making the
// call should be aware something isnt right and handle accordingly
this.addFrameCloseListener("click");
yield this.listener.clickElement(id);
yield this.listener.clickElement({id: id});
break;
}
};
@ -2085,7 +2086,7 @@ GeckoDriver.prototype.getElementAttribute = function(cmd, resp) {
break;
case Context.CONTENT:
resp.value = yield this.listener.getElementAttribute(id, name);
resp.value = yield this.listener.getElementAttribute({id: id, name: name});
break;
}
};
@ -2111,7 +2112,7 @@ GeckoDriver.prototype.getElementText = function(cmd, resp) {
break;
case Context.CONTENT:
resp.value = yield this.listener.getElementText(id);
resp.value = yield this.listener.getElementText({id: id});
break;
}
};
@ -2133,7 +2134,7 @@ GeckoDriver.prototype.getElementTagName = function(cmd, resp) {
break;
case Context.CONTENT:
resp.value = yield this.listener.getElementTagName(id);
resp.value = yield this.listener.getElementTagName({id: id});
break;
}
};
@ -2223,7 +2224,7 @@ GeckoDriver.prototype.isElementEnabled = function(cmd, resp) {
break;
case Context.CONTENT:
resp.value = yield this.listener.isElementEnabled(id);
resp.value = yield this.listener.isElementEnabled({id: id});
break;
}
},
@ -2269,7 +2270,7 @@ GeckoDriver.prototype.getElementSize = function(cmd, resp) {
break;
case Context.CONTENT:
resp.value = yield this.listener.getElementSize(id);
resp.value = yield this.listener.getElementSize({id: id});
break;
}
};
@ -2291,7 +2292,7 @@ GeckoDriver.prototype.getElementRect = function(cmd, resp) {
break;
case Context.CONTENT:
resp.value = yield this.listener.getElementRect(id);
resp.value = yield this.listener.getElementRect({id: id});
break;
}
};

View File

@ -1,11 +1,8 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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/. */
let {utils: Cu} = Components;
Cu.import("chrome://marionette/content/error.js");
/**
* The ElementManager manages DOM references and interactions with elements.
* According to the WebDriver spec (http://code.google.com/p/selenium/wiki/JsonWireProtocol), the
@ -31,8 +28,8 @@ this.EXPORTED_SYMBOLS = [
const DOCUMENT_POSITION_DISCONNECTED = 1;
const uuidGen = Components.classes["@mozilla.org/uuid-generator;1"]
.getService(Components.interfaces.nsIUUIDGenerator);
let uuidGen = Components.classes["@mozilla.org/uuid-generator;1"]
.getService(Components.interfaces.nsIUUIDGenerator);
this.CLASS_NAME = "class name";
this.SELECTOR = "css selector";
@ -45,6 +42,12 @@ this.XPATH = "xpath";
this.ANON= "anon";
this.ANON_ATTRIBUTE = "anon attribute";
function ElementException(msg, num, stack) {
this.message = msg;
this.code = num;
this.stack = stack;
}
this.Accessibility = function Accessibility() {
// A flag indicating whether the accessibility issue should be logged or cause
// an exception. Default: log to stdout.
@ -182,7 +185,7 @@ Accessibility.prototype = {
return;
}
if (this.strict) {
throw new ElementNotAccessibleError(message);
throw new ElementException(message, 56, null);
}
dump(Date.now() + " Marionette: " + message);
}
@ -221,17 +224,19 @@ ElementManager.prototype = {
let foundEl = null;
try {
foundEl = this.seenItems[i].get();
} catch (e) {}
}
catch(e) {}
if (foundEl) {
if (XPCNativeWrapper(foundEl) == XPCNativeWrapper(element)) {
return i;
}
} else {
// cleanup reference to GC'd element
}
else {
//cleanup reference to GC'd element
delete this.seenItems[i];
}
}
let id = uuidGen.generateUUID().toString();
var id = uuidGen.generateUUID().toString();
this.seenItems[id] = Components.utils.getWeakReference(element);
return id;
},
@ -250,7 +255,7 @@ ElementManager.prototype = {
getKnownElement: function EM_getKnownElement(id, win) {
let el = this.seenItems[id];
if (!el) {
throw new JavaScriptError("Element has not been seen before. Id given was " + id);
throw new ElementException("Element has not been seen before. Id given was " + id, 17, null);
}
try {
el = el.get();
@ -265,9 +270,8 @@ ElementManager.prototype = {
!(XPCNativeWrapper(el).ownerDocument == wrappedWin.document) ||
(XPCNativeWrapper(el).compareDocumentPosition(wrappedWin.document.documentElement) &
DOCUMENT_POSITION_DISCONNECTED)) {
throw new StaleElementReferenceError(
"The element reference is stale. Either the element " +
"is no longer attached to the DOM or the page has been refreshed.");
throw new ElementException("The element reference is stale. Either the element " +
"is no longer attached to the DOM or the page has been refreshed.", 10, null);
}
return el;
},
@ -365,9 +369,8 @@ ElementManager.prototype = {
args.hasOwnProperty(this.w3cElementKey))) {
let elementUniqueIdentifier = args[this.w3cElementKey] ? args[this.w3cElementKey] : args[this.elementKey];
converted = this.getKnownElement(elementUniqueIdentifier, win);
if (converted == null) {
throw new WebDriverError(`Unknown element: ${elementUniqueIdentifier}`);
}
if (converted == null)
throw new ElementException("Unknown element: " + elementUniqueIdentifier, 500, null);
}
else {
converted = {};
@ -440,7 +443,7 @@ ElementManager.prototype = {
let startNode = (values.element != undefined) ?
this.getKnownElement(values.element, win) : win.document;
if (this.elementStrategies.indexOf(values.using) < 0) {
throw new InvalidSelectorError(`No such strategy: ${values.using}`);
throw new ElementException("No such strategy.", 32, null);
}
let found = all ? this.findElements(values.using, values.value, win.document, startNode) :
this.findElement(values.using, values.value, win.document, startNode);
@ -458,7 +461,7 @@ ElementManager.prototype = {
} else if (values.using == ANON_ATTRIBUTE) {
message = "Unable to locate anonymous element: " + JSON.stringify(values.value);
}
on_error(new NoSuchElementError(message), command_id);
on_error({message: message, code: 7}, command_id);
}
} else {
values.time = startTime;
@ -591,7 +594,7 @@ ElementManager.prototype = {
element = rootNode.getAnonymousElementByAttribute(startNode, attr, value[attr]);
break;
default:
throw new WebDriverError("No such strategy");
throw new ElementException("No such strategy", 500, null);
}
return element;
},
@ -658,7 +661,7 @@ ElementManager.prototype = {
}
break;
default:
throw new WebDriverError("No such strategy");
throw new ElementException("No such strategy", 500, null);
}
return elements;
},

View File

@ -7,13 +7,11 @@
const {utils: Cu} = Components;
const errors = [
"ElementNotAccessibleError",
"ElementNotVisibleError",
"FrameSendFailureError",
"FrameSendNotInitializedError",
"IllegalArgumentError",
"InvalidElementStateError",
"InvalidSelectorError",
"JavaScriptError",
"NoAlertOpenError",
"NoSuchElementError",
@ -21,7 +19,6 @@ const errors = [
"NoSuchWindowError",
"ScriptTimeoutError",
"SessionNotCreatedError",
"StaleElementReferenceError",
"TimeoutError",
"UnknownCommandError",
"UnknownError",
@ -41,6 +38,11 @@ error.toJSON = function(err) {
};
};
/**
* Gets WebDriver error by its Selenium status code number.
*/
error.byCode = n => lookup.get(n);
/**
* Determines if the given status code is successful.
*/
@ -128,14 +130,6 @@ this.WebDriverError = function(msg) {
};
WebDriverError.prototype = Object.create(Error.prototype);
this.ElementNotAccessibleError = function(msg) {
WebDriverError.call(this, msg);
this.name = "ElementNotAccessibleError";
this.status = "element not accessible";
this.code = 56;
};
ElementNotAccessibleError.prototype = Object.create(WebDriverError.prototype);
this.ElementNotVisibleError = function(msg) {
WebDriverError.call(this, msg);
this.name = "ElementNotVisibleError";
@ -182,14 +176,6 @@ this.InvalidElementStateError = function(msg) {
};
InvalidElementStateError.prototype = Object.create(WebDriverError.prototype);
this.InvalidSelectorError = function(msg) {
WebDriverError.call(this, msg);
this.name = "InvalidSelectorError";
this.status = "invalid selector";
this.code = 32;
};
InvalidSelectorError.prototype = Object.create(WebDriverError.prototype);
/**
* Creates an error message for a JavaScript error thrown during
* executeScript or executeAsyncScript.
@ -284,17 +270,9 @@ this.SessionNotCreatedError = function(msg) {
this.status = "session not created";
// should be 33 to match Selenium
this.code = 71;
};
}
SessionNotCreatedError.prototype = Object.create(WebDriverError.prototype);
this.StaleElementReferenceError = function(msg) {
WebDriverError.call(this, msg);
this.name = "StaleElementReferenceError";
this.status = "stale element reference";
this.code = 10;
};
StaleElementReferenceError.prototype = Object.create(WebDriverError.prototype);
this.TimeoutError = function(msg) {
WebDriverError.call(this, msg);
this.name = "TimeoutError";
@ -326,3 +304,24 @@ this.UnsupportedOperationError = function(msg) {
this.code = 405;
};
UnsupportedOperationError.prototype = Object.create(WebDriverError.prototype);
const errorObjs = [
this.ElementNotVisibleError,
this.FrameSendFailureError,
this.FrameSendNotInitializedError,
this.IllegalArgumentError,
this.InvalidElementStateError,
this.JavaScriptError,
this.NoAlertOpenError,
this.NoSuchElementError,
this.NoSuchFrameError,
this.NoSuchWindowError,
this.ScriptTimeoutError,
this.SessionNotCreatedError,
this.TimeoutError,
this.UnknownCommandError,
this.UnknownError,
this.UnsupportedOperationError,
this.WebDriverError,
];
const lookup = new Map(errorObjs.map(err => [new err().code, err]));

View File

@ -15,7 +15,6 @@ loader.loadSubScript("chrome://marionette/content/simpletest.js");
loader.loadSubScript("chrome://marionette/content/common.js");
loader.loadSubScript("chrome://marionette/content/actions.js");
Cu.import("chrome://marionette/content/elements.js");
Cu.import("chrome://marionette/content/error.js");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -94,7 +93,7 @@ let modalHandler = function() {
* If the actor returns an ID, we start the listeners. Otherwise, nothing happens.
*/
function registerSelf() {
let msg = {value: winUtil.outerWindowID};
let msg = {value: winUtil.outerWindowID}
// register will have the ID and a boolean describing if this is the main process or not
let register = sendSyncMessage("Marionette:register", msg);
@ -147,28 +146,6 @@ function emitTouchEventForIFrame(message) {
message.force, 90);
}
function dispatch(fn) {
return function(msg) {
let id = msg.json.command_id;
try {
let rv;
if (typeof msg.json == "undefined" || msg.json instanceof Array) {
rv = fn.apply(null, msg.json);
} else {
rv = fn(msg.json);
}
if (typeof rv == "undefined") {
sendOk(id);
} else {
sendResponse({value: rv}, id);
}
} catch (e) {
sendError(e, id);
}
};
}
/**
* Add a message listener that's tied to our listenerId.
*/
@ -183,15 +160,6 @@ function removeMessageListenerId(messageName, handler) {
removeMessageListener(messageName + listenerId, handler);
}
let getElementSizeFn = dispatch(getElementSize);
let getActiveElementFn = dispatch(getActiveElement);
let clickElementFn = dispatch(clickElement);
let getElementAttributeFn = dispatch(getElementAttribute);
let getElementTextFn = dispatch(getElementText);
let getElementTagNameFn = dispatch(getElementTagName);
let getElementRectFn = dispatch(getElementRect);
let isElementEnabledFn = dispatch(isElementEnabled);
/**
* Start all message listeners
*/
@ -214,17 +182,17 @@ function startListeners() {
addMessageListenerId("Marionette:refresh", refresh);
addMessageListenerId("Marionette:findElementContent", findElementContent);
addMessageListenerId("Marionette:findElementsContent", findElementsContent);
addMessageListenerId("Marionette:getActiveElement", getActiveElementFn);
addMessageListenerId("Marionette:clickElement", clickElementFn);
addMessageListenerId("Marionette:getElementAttribute", getElementAttributeFn);
addMessageListenerId("Marionette:getElementText", getElementTextFn);
addMessageListenerId("Marionette:getElementTagName", getElementTagNameFn);
addMessageListenerId("Marionette:getActiveElement", getActiveElement);
addMessageListenerId("Marionette:clickElement", clickElement);
addMessageListenerId("Marionette:getElementAttribute", getElementAttribute);
addMessageListenerId("Marionette:getElementText", getElementText);
addMessageListenerId("Marionette:getElementTagName", getElementTagName);
addMessageListenerId("Marionette:isElementDisplayed", isElementDisplayed);
addMessageListenerId("Marionette:getElementValueOfCssProperty", getElementValueOfCssProperty);
addMessageListenerId("Marionette:submitElement", submitElement);
addMessageListenerId("Marionette:getElementSize", getElementSizeFn); // deprecated
addMessageListenerId("Marionette:getElementRect", getElementRectFn);
addMessageListenerId("Marionette:isElementEnabled", isElementEnabledFn);
addMessageListenerId("Marionette:getElementSize", getElementSize);
addMessageListenerId("Marionette:getElementRect", getElementRect);
addMessageListenerId("Marionette:isElementEnabled", isElementEnabled);
addMessageListenerId("Marionette:isElementSelected", isElementSelected);
addMessageListenerId("Marionette:sendKeysToElement", sendKeysToElement);
addMessageListenerId("Marionette:getElementLocation", getElementLocation); //deprecated
@ -319,17 +287,17 @@ function deleteSession(msg) {
removeMessageListenerId("Marionette:refresh", refresh);
removeMessageListenerId("Marionette:findElementContent", findElementContent);
removeMessageListenerId("Marionette:findElementsContent", findElementsContent);
removeMessageListenerId("Marionette:getActiveElement", getActiveElementFn);
removeMessageListenerId("Marionette:clickElement", clickElementFn);
removeMessageListenerId("Marionette:getElementAttribute", getElementAttributeFn);
removeMessageListenerId("Marionette:getElementText", getElementTextFn);
removeMessageListenerId("Marionette:getElementTagName", getElementTagNameFn);
removeMessageListenerId("Marionette:getActiveElement", getActiveElement);
removeMessageListenerId("Marionette:clickElement", clickElement);
removeMessageListenerId("Marionette:getElementAttribute", getElementAttribute);
removeMessageListenerId("Marionette:getElementText", getElementText);
removeMessageListenerId("Marionette:getElementTagName", getElementTagName);
removeMessageListenerId("Marionette:isElementDisplayed", isElementDisplayed);
removeMessageListenerId("Marionette:getElementValueOfCssProperty", getElementValueOfCssProperty);
removeMessageListenerId("Marionette:submitElement", submitElement);
removeMessageListenerId("Marionette:getElementSize", getElementSizeFn); // deprecated
removeMessageListenerId("Marionette:getElementRect", getElementRectFn);
removeMessageListenerId("Marionette:isElementEnabled", isElementEnabledFn);
removeMessageListenerId("Marionette:getElementSize", getElementSize); //deprecated
removeMessageListenerId("Marionette:getElementRect", getElementRect);
removeMessageListenerId("Marionette:isElementEnabled", isElementEnabled);
removeMessageListenerId("Marionette:isElementSelected", isElementSelected);
removeMessageListenerId("Marionette:sendKeysToElement", sendKeysToElement);
removeMessageListenerId("Marionette:getElementLocation", getElementLocation);
@ -363,42 +331,40 @@ function deleteSession(msg) {
/**
* Generic method to send a message to the server
*/
function sendToServer(name, data, objs, id) {
if (!data) {
data = {}
function sendToServer(msg, value, command_id) {
if (command_id) {
value.command_id = command_id;
}
if (id) {
data.command_id = id;
}
sendAsyncMessage(name, data, objs);
sendAsyncMessage(msg, value);
}
/**
* Send response back to server
*/
function sendResponse(value, command_id) {
sendToServer("Marionette:done", value, null, command_id);
sendToServer("Marionette:done", value, command_id);
}
/**
* Send ack back to server
*/
function sendOk(command_id) {
sendToServer("Marionette:ok", null, null, command_id);
sendToServer("Marionette:ok", {}, command_id);
}
/**
* Send log message to server
*/
function sendLog(msg) {
sendToServer("Marionette:log", {message: msg});
sendToServer("Marionette:log", { message: msg });
}
/**
* Send error message to server
*/
function sendError(err, cmdId) {
sendToServer("Marionette:error", null, {error: err}, cmdId);
function sendError(msg, code, stack, cmdId) {
let payload = {message: msg, code: code, stack: stack};
sendToServer("Marionette:error", payload, cmdId);
}
/**
@ -492,8 +458,8 @@ function createExecuteContentSandbox(aWindow, timeout) {
});
}
sandbox.asyncComplete = function(obj, id) {
if (id == asyncTestCommandId) {
sandbox.asyncComplete = function sandbox_asyncComplete(value, status, stack, commandId) {
if (commandId == asyncTestCommandId) {
curFrame.removeEventListener("unload", onunload, false);
curFrame.clearTimeout(asyncTestTimeoutId);
@ -501,19 +467,24 @@ function createExecuteContentSandbox(aWindow, timeout) {
curFrame.clearTimeout(inactivityTimeoutId);
}
sendSyncMessage("Marionette:shareData",
{log: elementManager.wrapValue(marionetteLogObj.getLogs())});
{log: elementManager.wrapValue(marionetteLogObj.getLogs())});
marionetteLogObj.clearLogs();
if (error.isError(obj)) {
sendError(obj, id);
} else {
if (status == 0){
if (Object.keys(_emu_cbs).length) {
_emu_cbs = {};
sendError(new WebDriverError("Emulator callback still pending when finish() called"), id);
} else {
sendResponse({value: elementManager.wrapValue(obj)}, id);
sendError("Emulator callback still pending when finish() called",
500, null, commandId);
}
else {
sendResponse({value: elementManager.wrapValue(value), status: status},
commandId);
}
}
else {
sendError(value, status, stack, commandId);
}
asyncTestRunning = false;
@ -524,32 +495,33 @@ function createExecuteContentSandbox(aWindow, timeout) {
};
sandbox.finish = function sandbox_finish() {
if (asyncTestRunning) {
sandbox.asyncComplete(marionette.generate_results(), sandbox.asyncTestCommandId);
sandbox.asyncComplete(marionette.generate_results(), 0, null, sandbox.asyncTestCommandId);
} else {
return marionette.generate_results();
}
};
sandbox.marionetteScriptFinished = val =>
sandbox.asyncComplete(val, sandbox.asyncTestCommandId);
sandbox.marionetteScriptFinished = function sandbox_marionetteScriptFinished(value) {
return sandbox.asyncComplete(value, 0, null, sandbox.asyncTestCommandId);
};
return sandbox;
}
/**
* Execute the given script either as a function body (executeScript)
* or directly (for mochitest like JS Marionette tests).
* or directly (for 'mochitest' like JS Marionette tests)
*/
function executeScript(msg, directInject) {
// Set up inactivity timeout.
if (msg.json.inactivityTimeout) {
let setTimer = function() {
inactivityTimeoutId = curFrame.setTimeout(function() {
sendError(new ScriptTimeoutError("timed out due to inactivity"), asyncTestCommandId);
inactivityTimeoutId = curFrame.setTimeout(function() {
sendError('timed out due to inactivity', 28, null, asyncTestCommandId);
}, msg.json.inactivityTimeout);
};
setTimer();
heartbeatCallback = function() {
heartbeatCallback = function resetInactivityTimeout() {
curFrame.clearTimeout(inactivityTimeoutId);
setTimer();
};
@ -562,10 +534,11 @@ function executeScript(msg, directInject) {
sandbox = createExecuteContentSandbox(curFrame,
msg.json.timeout);
if (!sandbox) {
sendError(new WebDriverError("Could not create sandbox!"), asyncTestCommandId);
sendError("Could not create sandbox!", 500, null, asyncTestCommandId);
return;
}
} else {
}
else {
sandbox.asyncTestCommandId = asyncTestCommandId;
}
@ -585,7 +558,7 @@ function executeScript(msg, directInject) {
marionetteLogObj.clearLogs();
if (res == undefined || res.passed == undefined) {
sendError(new JavaScriptError("Marionette.finish() not called"), asyncTestCommandId);
sendError("Marionette.finish() not called", 17, null, asyncTestCommandId);
}
else {
sendResponse({value: elementManager.wrapValue(res)}, asyncTestCommandId);
@ -595,8 +568,9 @@ function executeScript(msg, directInject) {
try {
sandbox.__marionetteParams = Cu.cloneInto(elementManager.convertWrappedArguments(
msg.json.args, curFrame), sandbox, { wrapReflectors: true });
} catch (e) {
sendError(e, asyncTestCommandId);
}
catch(e) {
sendError(e.message, e.code, e.stack, asyncTestCommandId);
return;
}
@ -616,14 +590,15 @@ function executeScript(msg, directInject) {
marionetteLogObj.clearLogs();
sendResponse({value: elementManager.wrapValue(res)}, asyncTestCommandId);
}
} catch (e) {
let err = new JavaScriptError(
e,
"execute_script",
msg.json.filename,
msg.json.line,
script);
sendError(err, asyncTestCommandId);
}
catch (e) {
// 17 = JavascriptException
let error = createStackMessage(e,
"execute_script",
msg.json.filename,
msg.json.line,
script);
sendError(error[0], 17, error[1], asyncTestCommandId);
}
}
@ -667,12 +642,12 @@ function executeWithCallback(msg, useFinish) {
if (msg.json.inactivityTimeout) {
let setTimer = function() {
inactivityTimeoutId = curFrame.setTimeout(function() {
sandbox.asyncComplete(new ScriptTimeout("timed out due to inactivity"), asyncTestCommandId);
sandbox.asyncComplete('timed out due to inactivity', 28, null, asyncTestCommandId);
}, msg.json.inactivityTimeout);
};
setTimer();
heartbeatCallback = function() {
heartbeatCallback = function resetInactivityTimeout() {
curFrame.clearTimeout(inactivityTimeoutId);
setTimer();
};
@ -682,7 +657,7 @@ function executeWithCallback(msg, useFinish) {
asyncTestCommandId = msg.json.command_id;
onunload = function() {
sendError(new JavaScriptError("unload was called"), asyncTestCommandId);
sendError("unload was called", 17, null, asyncTestCommandId);
};
curFrame.addEventListener("unload", onunload, false);
@ -690,7 +665,7 @@ function executeWithCallback(msg, useFinish) {
sandbox = createExecuteContentSandbox(curFrame,
msg.json.timeout);
if (!sandbox) {
sendError(new JavaScriptError("Could not create sandbox!"), asyncTestCommandId);
sendError("Could not create sandbox!", 17, null, asyncTestCommandId);
return;
}
}
@ -705,19 +680,19 @@ function executeWithCallback(msg, useFinish) {
// http://code.google.com/p/selenium/source/browse/trunk/javascript/firefox-driver/js/evaluate.js.
// We'll stay compatible with the Selenium code.
asyncTestTimeoutId = curFrame.setTimeout(function() {
sandbox.asyncComplete(new ScriptTimeoutError("timed out"), asyncTestCommandId);
sandbox.asyncComplete('timed out', 28, null, asyncTestCommandId);
}, msg.json.timeout);
originalOnError = curFrame.onerror;
curFrame.onerror = function errHandler(msg, url, line) {
sandbox.asyncComplete(new JavaScriptError(msg + "@" + url + ", line " + line), asyncTestCommandId);
curFrame.onerror = function errHandler(errMsg, url, line) {
sandbox.asyncComplete(errMsg, 17, "@" + url + ", line " + line, asyncTestCommandId);
curFrame.onerror = originalOnError;
};
let scriptSrc;
if (useFinish) {
if (msg.json.timeout == null || msg.json.timeout == 0) {
sendError(new TimeoutError("Please set a timeout"), asyncTestCommandId);
sendError("Please set a timeout", 21, null, asyncTestCommandId);
}
scriptSrc = script;
}
@ -725,8 +700,9 @@ function executeWithCallback(msg, useFinish) {
try {
sandbox.__marionetteParams = Cu.cloneInto(elementManager.convertWrappedArguments(
msg.json.args, curFrame), sandbox, { wrapReflectors: true });
} catch (e) {
sendError(e, asyncTestCommandId);
}
catch(e) {
sendError(e.message, e.code, e.stack, asyncTestCommandId);
return;
}
@ -747,13 +723,13 @@ function executeWithCallback(msg, useFinish) {
}
Cu.evalInSandbox(scriptSrc, sandbox, "1.8", "dummy file", 0);
} catch (e) {
let err = new JavaScriptError(
e,
"execute_async_script",
msg.json.filename,
msg.json.line,
scriptSrc);
sandbox.asyncComplete(err, asyncTestCommandId);
// 17 = JavascriptException
let error = createStackMessage(e,
"execute_async_script",
msg.json.filename,
msg.json.line,
scriptSrc);
sandbox.asyncComplete(error[0], 17, error[1], asyncTestCommandId);
}
}
@ -880,7 +856,7 @@ function singleTap(msg) {
let visible = checkVisible(el, msg.json.corx, msg.json.cory);
checkVisibleAccessibility(acc, visible);
if (!visible) {
sendError(new ElementNotVisibleError("Element is not currently visible and may not be manipulated"), command_id);
sendError("Element is not currently visible and may not be manipulated", 11, null, command_id);
return;
}
checkActionableAccessibility(acc);
@ -895,9 +871,10 @@ function singleTap(msg) {
emitTouchEvent('touchend', touch);
}
actions.mouseTap(el.ownerDocument, c.x, c.y);
sendOk(command_id);
} catch (e) {
sendError(e, command_id);
sendOk(msg.json.command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, msg.json.command_id);
}
}
@ -982,8 +959,12 @@ function actionChain(msg) {
let touchId = msg.json.nextId;
let callbacks = {};
callbacks.onSuccess = value => sendResponse(value, command_id);
callbacks.onError = err => sendError(err, command_id);
callbacks.onSuccess = (value) => {
sendResponse(value, command_id);
};
callbacks.onError = (message, code, trace) => {
sendError(message, code, trace, msg.json.command_id);
};
let touchProvider = {};
touchProvider.createATouch = createATouch;
@ -998,7 +979,7 @@ function actionChain(msg) {
callbacks,
touchProvider);
} catch (e) {
sendError(e, command_id);
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1163,8 +1144,9 @@ function multiAction(msg) {
// pendingTouches keeps track of current touches that's on the screen
let pendingTouches = [];
setDispatch(concurrentEvent, pendingTouches, command_id);
} catch (e) {
sendError(e, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, msg.json.command_id);
}
}
@ -1196,7 +1178,7 @@ function pollForReadyState(msg, start, callback) {
!curFrame.document.baseURI.startsWith(url)) {
// We have reached an error url without requesting it.
callback();
sendError(new UnknownError("Error loading page"), command_id);
sendError("Error loading page", 13, null, command_id);
} else if (curFrame.document.readyState == "interactive" &&
curFrame.document.baseURI.startsWith("about:")) {
callback();
@ -1204,9 +1186,11 @@ function pollForReadyState(msg, start, callback) {
} else {
navTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
}
} else {
}
else {
callback();
sendError(new TimeoutError("Error loading page, timed out (checkLoad)"), command_id);
sendError("Error loading page, timed out (checkLoad)", 21, null,
command_id);
}
}
checkLoad();
@ -1236,7 +1220,8 @@ function get(msg) {
function timerFunc() {
removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
sendError(new TimeoutError("Error loading page, timed out (onDOMContentLoaded)"), msg.json.command_id);
sendError("Error loading page, timed out (onDOMContentLoaded)", 21,
null, msg.json.command_id);
}
if (msg.json.pageTimeout != null) {
navTimer.initWithCallback(timerFunc, msg.json.pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
@ -1321,12 +1306,13 @@ function refresh(msg) {
function findElementContent(msg) {
let command_id = msg.json.command_id;
try {
let onSuccess = (el, id) => sendResponse({value: el}, id);
let onError = (err, id) => sendError(err, id);
let on_success = function(el, cmd_id) { sendResponse({value: el}, cmd_id) };
let on_error = function(e, cmd_id) { sendError(e.message, e.code, null, cmd_id); };
elementManager.find(curFrame, msg.json, msg.json.searchTimeout,
false /* all */, onSuccess, onError, command_id);
} catch (e) {
sendError(e, command_id);
false /* all */, on_success, on_error, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1336,90 +1322,97 @@ function findElementContent(msg) {
function findElementsContent(msg) {
let command_id = msg.json.command_id;
try {
let onSuccess = (els, id) => sendResponse({value: els}, id);
let onError = (err, id) => sendError(err, id);
let on_success = function(els, cmd_id) { sendResponse({value: els}, cmd_id); };
let on_error = function(e, cmd_id) { sendError(e.message, e.code, null, cmd_id); };
elementManager.find(curFrame, msg.json, msg.json.searchTimeout,
true /* all */, onSuccess, onError, command_id);
} catch (e) {
sendError(e, command_id);
true /* all */, on_success, on_error, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* Find and return the active element on the page.
*
* @return {WebElement}
* Reference to web element.
* Find and return the active element on the page
*/
function getActiveElement() {
let el = curFrame.document.activeElement;
return elementManager.addToKnownElements(el);
function getActiveElement(msg) {
let command_id = msg.json.command_id;
var element = curFrame.document.activeElement;
var id = elementManager.addToKnownElements(element);
sendResponse({value: id}, command_id);
}
/**
* Send click event to element.
*
* @param {WebElement} id
* Reference to the web element to click.
* Send click event to element
*/
function clickElement(id) {
let el = elementManager.getKnownElement(id, curFrame);
let acc = accessibility.getAccessibleObject(el, true);
let visible = checkVisible(el);
checkVisibleAccessibility(acc, visible);
if (!visible) {
throw new ElementNotVisibleError("Element is not visible");
function clickElement(msg) {
let command_id = msg.json.command_id;
let el;
try {
el = elementManager.getKnownElement(msg.json.id, curFrame);
let acc = accessibility.getAccessibleObject(el, true);
let visible = checkVisible(el);
checkVisibleAccessibility(acc, visible);
if (visible) {
checkActionableAccessibility(acc);
if (utils.isElementEnabled(el)) {
utils.synthesizeMouseAtCenter(el, {}, el.ownerDocument.defaultView)
}
else {
sendError("Element is not Enabled", 12, null, command_id)
}
}
else {
sendError("Element is not visible", 11, null, command_id)
}
sendOk(command_id);
}
checkActionableAccessibility(acc);
if (utils.isElementEnabled(el)) {
utils.synthesizeMouseAtCenter(el, {}, el.ownerDocument.defaultView);
} else {
throw new InvalidElementStateError("Element is not Enabled");
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* Get a given attribute of an element.
*
* @param {WebElement} id
* Reference to the web element to get the attribute of.
* @param {string} name
* Name of the attribute.
*
* @return {string}
* The value of the attribute.
* Get a given attribute of an element
*/
function getElementAttribute(id, name) {
let el = elementManager.getKnownElement(id, curFrame);
return utils.getElementAttribute(el, name);
function getElementAttribute(msg) {
let command_id = msg.json.command_id;
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
sendResponse({value: utils.getElementAttribute(el, msg.json.name)},
command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* 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, curFrame);
return utils.getElementText(el);
function getElementText(msg) {
let command_id = msg.json.command_id;
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
sendResponse({value: utils.getElementText(el)}, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* 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, curFrame);
return el.tagName.toLowerCase();
function getElementTagName(msg) {
let command_id = msg.json.command_id;
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
sendResponse({value: el.tagName.toLowerCase()}, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
@ -1432,8 +1425,9 @@ function isElementDisplayed(msg) {
let displayed = utils.isElementDisplayed(el);
checkVisibleAccessibility(accessibility.getAccessibleObject(el), displayed);
sendResponse({value: displayed}, command_id);
} catch (e) {
sendError(e, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1452,8 +1446,9 @@ function getElementValueOfCssProperty(msg){
let el = elementManager.getKnownElement(msg.json.id, curFrame);
sendResponse({value: curFrame.document.defaultView.getComputedStyle(el, null).getPropertyValue(propertyName)},
command_id);
} catch (e) {
sendError(e, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1472,63 +1467,67 @@ function submitElement (msg) {
if (el.tagName && el.tagName.toLowerCase() == 'form') {
el.submit();
sendOk(command_id);
} else {
sendError(new NoSuchElementError("Element is not a form element or in a form"), command_id);
}
} catch (e) {
sendError(e, command_id);
else {
sendError("Element is not a form element or in a form", 7, null, command_id);
}
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* Get the size of the element.
*
* @param {WebElement} id
* Web element reference.
*
* @return {Object.<string, number>}
* The width/height dimensions of th element.
* Get the size of the element and return it
*/
function getElementSize(id) {
let el = elementManager.getKnownElement(id, curFrame);
let clientRect = el.getBoundingClientRect();
return {width: clientRect.width, height: clientRect.height};
function getElementSize(msg){
let command_id = msg.json.command_id;
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
let clientRect = el.getBoundingClientRect();
sendResponse({value: {width: clientRect.width, height: clientRect.height}},
command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* Get the size of the element.
*
* @param {WebElement} id
* Reference to web element.
*
* @return {Object.<string, number>}
* The x, y, width, and height properties of the element.
* Get the size of the element and return it
*/
function getElementRect(id) {
let el = elementManager.getKnownElement(id, curFrame);
let clientRect = el.getBoundingClientRect();
return {
x: clientRect.x + curFrame.pageXOffset,
y: clientRect.y + curFrame.pageYOffset,
width: clientRect.width,
height: clientRect.height
};
function getElementRect(msg){
let command_id = msg.json.command_id;
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
let clientRect = el.getBoundingClientRect();
sendResponse({value: {x: clientRect.x + curFrame.pageXOffset,
y: clientRect.y + curFrame.pageYOffset,
width: clientRect.width,
height: clientRect.height}},
command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
* Check if element is enabled.
*
* @param {WebElement} id
* Reference to web element.
*
* @return {boolean}
* True if enabled, false otherwise.
* Check if element is enabled
*/
function isElementEnabled(id) {
let el = elementManager.getKnownElement(id, curFrame);
let enabled = utils.isElementEnabled(el);
checkEnabledStateAccessibility(accessibility.getAccessibleObject(el), enabled);
return enabled;
function isElementEnabled(msg) {
let command_id = msg.json.command_id;
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
let enabled = utils.isElementEnabled(el);
checkEnabledStateAccessibility(accessibility.getAccessibleObject(el),
enabled);
sendResponse({value: enabled}, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
/**
@ -1539,8 +1538,9 @@ function isElementSelected(msg) {
try {
let el = elementManager.getKnownElement(msg.json.id, curFrame);
sendResponse({value: utils.isElementSelected(el)}, command_id);
} catch (e) {
sendError(e, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1567,7 +1567,7 @@ function sendKeysToElement(msg) {
file = new File(p);
} catch (e) {
let err = new IllegalArgumentError(`File not found: ${val}`);
sendError(err, command_id);
sendError(err.message, err.code, err.stack, command_id);
return;
}
fs.push(file);
@ -1598,8 +1598,9 @@ function getElementLocation(msg) {
location.y = rect.top;
sendResponse({value: location}, command_id);
} catch (e) {
sendError(e, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1617,7 +1618,7 @@ function clearElement(msg) {
}
sendOk(command_id);
} catch (e) {
sendError(e, command_id);
sendError(e.message, e.code, e.stack, command_id);
}
}
@ -1632,9 +1633,9 @@ function switchToFrame(msg) {
if (curFrame.document.readyState == "complete") {
sendOk(command_id);
return;
} else if (curFrame.document.readyState == "interactive" &&
errorRegex.exec(curFrame.document.baseURI)) {
sendError(new UnknownError("Error loading page"), command_id);
}
else if (curFrame.document.readyState == "interactive" && errorRegex.exec(curFrame.document.baseURI)) {
sendError("Error loading page", 13, null, command_id);
return;
}
checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
@ -1674,8 +1675,9 @@ function switchToFrame(msg) {
let wantedFrame;
try {
wantedFrame = elementManager.getKnownElement(msg.json.element, curFrame); //Frame Element
} catch (e) {
sendError(e, command_id);
}
catch(e) {
sendError(e.message, e.code, e.stack, command_id);
}
if (frames.length > 0) {
@ -1733,9 +1735,8 @@ function switchToFrame(msg) {
}
}
}
if (foundFrame === null) {
sendError(new NoSuchFrameError("Unable to locate frame: " + (msg.json.id || msg.json.element)), command_id);
sendError("Unable to locate frame: " + (msg.json.id || msg.json.element), 8, null, command_id);
return true;
}
@ -1776,11 +1777,12 @@ function addCookie(msg) {
if (!cookie.domain) {
var location = curFrame.document.location;
cookie.domain = location.hostname;
} else {
}
else {
var currLocation = curFrame.location;
var currDomain = currLocation.host;
if (currDomain.indexOf(cookie.domain) == -1) {
sendError(new InvalidCookieDomainError("You may only set cookies for the current domain"), msg.json.command_id);
sendError("You may only set cookies for the current domain", 24, null, msg.json.command_id);
}
}
@ -1793,12 +1795,12 @@ function addCookie(msg) {
var document = curFrame.document;
if (!document || !document.contentType.match(/html/i)) {
sendError(new UnableToSetCookie("You may only set cookies on html documents"), msg.json.command_id);
sendError('You may only set cookies on html documents', 25, null, msg.json.command_id);
}
let added = sendSyncMessage("Marionette:addCookie", {value: cookie});
if (added[0] !== true) {
sendError(new UnknownError("Error setting cookie"), msg.json.command_id);
sendError("Error setting cookie", 13, null, msg.json.command_id);
return;
}
sendOk(msg.json.command_id);
@ -1839,7 +1841,7 @@ function deleteCookie(msg) {
if (cookie.name == toDelete) {
let deleted = sendSyncMessage("Marionette:deleteCookie", {value: cookie});
if (deleted[0] !== true) {
sendError(new UnknownError("Could not delete cookie: " + msg.json.name), msg.json.command_id);
sendError("Could not delete cookie: " + msg.json.name, 13, null, msg.json.command_id);
return;
}
}
@ -1856,7 +1858,7 @@ function deleteAllCookies(msg) {
for (let cookie of cookies) {
let deleted = sendSyncMessage("Marionette:deleteCookie", {value: cookie});
if (!deleted[0]) {
sendError(new UnknownError("Could not delete cookie: " + JSON.stringify(cookie)), msg.json.command_id);
sendError("Could not delete cookie: " + JSON.stringify(cookie), 13, null, msg.json.command_id);
return;
}
}
@ -1910,8 +1912,9 @@ function emulatorCmdResult(msg) {
}
try {
cb(message.result);
} catch (e) {
sendError(e, -1);
}
catch(e) {
sendError(e.message, e.code, e.stack, -1);
return;
}
}

View File

@ -17,11 +17,8 @@
*/
let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("chrome://marionette/content/error.js");
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
.getService(Ci.mozIJSSubScriptLoader);
let utils = {};
loader.loadSubScript("chrome://marionette/content/EventUtils.js", utils);
@ -141,7 +138,8 @@ function sendKeysToElement (document, element, keysToSend, successCallback, erro
sendSingleKey(c, modifiers, document);
}
successCallback(command_id);
} else {
errorCallback(new ElementNotVisibleError("Element is not visible"), command_id);
}
else {
errorCallback("Element is not visible", 11, null, command_id);
}
};