Bug 843793 - Throw specific errors when a frame has frozen/crashed, r=mdas

This commit is contained in:
Jonathan Griffin 2013-04-08 14:12:32 -07:00
parent de29cf69bc
commit 2f1fe75231
3 changed files with 236 additions and 119 deletions

View File

@ -28,6 +28,8 @@ class ErrorCodes(object):
INVALID_XPATH_SELECTOR = 51
INVALID_XPATH_SELECTOR_RETURN_TYPER = 52
INVALID_RESPONSE = 53
FRAME_SEND_NOT_INITIALIZED_ERROR = 54
FRAME_SEND_FAILURE_ERROR = 55
MARIONETTE_ERROR = 500
class MarionetteException(Exception):
@ -100,3 +102,8 @@ class InvalidSelectorException(MarionetteException):
class MoveTargetOutOfBoundsException(MarionetteException):
pass
class FrameSendNotInitializedError(MarionetteException):
pass
class FrameSendFailureError(MarionetteException):
pass

View File

@ -372,7 +372,11 @@ class Marionette(object):
or status == ErrorCodes.INVALID_XPATH_SELECTOR_RETURN_TYPER:
raise InvalidSelectorException(message=message, status=status, stacktrace=stacktrace)
elif status == ErrorCodes.MOVE_TARGET_OUT_OF_BOUNDS:
MoveTargetOutOfBoundsException(message=message, status=status, stacktrace=stacktrace)
raise MoveTargetOutOfBoundsException(message=message, status=status, stacktrace=stacktrace)
elif status == ErrorCodes.FRAME_SEND_NOT_INITIALIZED_ERROR:
raise FrameSendNotInitializedError(message=message, status=status, stacktrace=stacktrace)
elif status == ErrorCodes.FRAME_SEND_FAILURE_ERROR:
raise FrameSendFailureError(message=message, status=status, stacktrace=stacktrace)
else:
raise MarionetteException(message=message, status=status, stacktrace=stacktrace)
raise MarionetteException(message=response, status=500)

View File

@ -132,6 +132,27 @@ function MarionetteRemoteFrame(windowId, frameId) {
// persistent list of remote frames that Marionette has loaded a frame script in
let remoteFrames = [];
/*
* Custom exceptions
*/
function FrameSendNotInitializedError(frame) {
this.code = 54;
this.frame = frame;
this.message = "Error sending message to frame (NS_ERROR_NOT_INITIALIZED)";
this.toString = function() {
return this.message + " " + this.frame + "; frame has closed.";
}
}
function FrameSendFailureError(frame) {
this.code = 55;
this.frame = frame;
this.message = "Error sending message to frame (NS_ERROR_FAILURE)";
this.toString = function() {
return this.message + " " + this.frame + "; frame not responding.";
}
}
/**
* This actor is responsible for all marionette API calls. It gets created
* for each connection and manages all chrome and browser based calls. It
@ -185,11 +206,7 @@ MarionetteDriverActor.prototype = {
switchToGlobalMessageManager: function MDA_switchToGlobalMM() {
if (this.currentRemoteFrame !== null) {
this.removeMessageManagerListeners(this.messageManager);
try {
// this can fail if the frame is already gone
this.sendAsync("sleepSession");
}
catch(e) {}
this.sendAsync("sleepSession", null, null, true);
}
this.messageManager = this.globalMessageManager;
this.currentRemoteFrame = null;
@ -203,15 +220,40 @@ MarionetteDriverActor.prototype = {
* @param object values
* Object to send to the listener
*/
sendAsync: function MDA_sendAsync(name, values) {
sendAsync: function MDA_sendAsync(name, values, commandId, ignoreFailure) {
let success = true;
if (values instanceof Object && commandId) {
values.command_id = commandId;
}
if (this.currentRemoteFrame !== null) {
this.messageManager.sendAsyncMessage(
"Marionette:" + name + this.currentRemoteFrame.targetFrameId, values);
try {
this.messageManager.sendAsyncMessage(
"Marionette:" + name + this.currentRemoteFrame.targetFrameId, values);
}
catch(e) {
if (!ignoreFailure) {
success = false;
let error = e;
switch(e.result) {
case Components.results.NS_ERROR_FAILURE:
error = new FrameSendFailureError(this.currentRemoteFrame);
break;
case Components.results.NS_ERROR_NOT_INITIALIZED:
error = new FrameSendNotInitializedError(this.currentRemoteFrame);
break;
default:
break;
}
code = error.hasOwnProperty('code') ? e.code : 500;
this.sendError(error.toString(), code, error.stack, commandId);
}
}
}
else {
this.messageManager.broadcastAsyncMessage(
"Marionette:" + name + this.curBrowser.curFrameId, values);
}
return success;
},
/**
@ -746,12 +788,15 @@ MarionetteDriverActor.prototype = {
aRequest.newSandbox = true;
}
if (this.context == "content") {
this.sendAsync("executeScript", {value: aRequest.value,
args: aRequest.args,
newSandbox: aRequest.newSandbox,
timeout: timeout,
command_id: command_id,
specialPowers: aRequest.specialPowers});
this.sendAsync("executeScript",
{
value: aRequest.value,
args: aRequest.args,
newSandbox: aRequest.newSandbox,
timeout: timeout,
specialPowers: aRequest.specialPowers
},
command_id);
return;
}
@ -834,13 +879,16 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("executeJSScript", { value: aRequest.value,
args: aRequest.args,
newSandbox: aRequest.newSandbox,
async: aRequest.async,
timeout: timeout,
command_id: command_id,
specialPowers: aRequest.specialPowers });
this.sendAsync("executeJSScript",
{
value: aRequest.value,
args: aRequest.args,
newSandbox: aRequest.newSandbox,
async: aRequest.async,
timeout: timeout,
specialPowers: aRequest.specialPowers
},
command_id);
}
},
@ -870,13 +918,16 @@ MarionetteDriverActor.prototype = {
}
if (this.context == "content") {
this.sendAsync("executeAsyncScript", {value: aRequest.value,
args: aRequest.args,
id: this.command_id,
newSandbox: aRequest.newSandbox,
timeout: timeout,
command_id: command_id,
specialPowers: aRequest.specialPowers});
this.sendAsync("executeAsyncScript",
{
value: aRequest.value,
args: aRequest.args,
id: this.command_id,
newSandbox: aRequest.newSandbox,
timeout: timeout,
specialPowers: aRequest.specialPowers
},
command_id);
return;
}
@ -976,7 +1027,7 @@ MarionetteDriverActor.prototype = {
if (this.context != "chrome") {
aRequest.command_id = command_id;
aRequest.pageTimeout = this.pageTimeout;
this.sendAsync("goUrl", aRequest);
this.sendAsync("goUrl", aRequest, command_id);
return;
}
@ -1013,7 +1064,7 @@ MarionetteDriverActor.prototype = {
this.sendResponse(this.getCurrentWindow().location.href, this.command_id);
}
else {
this.sendAsync("getUrl", {command_id: this.command_id});
this.sendAsync("getUrl", {}, this.command_id);
}
},
@ -1022,7 +1073,7 @@ MarionetteDriverActor.prototype = {
*/
getTitle: function MDA_getTitle() {
this.command_id = this.getCommandId();
this.sendAsync("getTitle", {command_id: this.command_id});
this.sendAsync("getTitle", {}, this.command_id);
},
/**
@ -1037,7 +1088,7 @@ MarionetteDriverActor.prototype = {
this.sendResponse(pageSource, this.command_id);
}
else {
this.sendAsync("getPageSource", {command_id: this.command_id});
this.sendAsync("getPageSource", {}, this.command_id);
}
},
@ -1046,7 +1097,7 @@ MarionetteDriverActor.prototype = {
*/
goBack: function MDA_goBack() {
this.command_id = this.getCommandId();
this.sendAsync("goBack", {command_id: this.command_id});
this.sendAsync("goBack", {}, this.command_id);
},
/**
@ -1054,7 +1105,7 @@ MarionetteDriverActor.prototype = {
*/
goForward: function MDA_goForward() {
this.command_id = this.getCommandId();
this.sendAsync("goForward", {command_id: this.command_id});
this.sendAsync("goForward", {}, this.command_id);
},
/**
@ -1062,7 +1113,7 @@ MarionetteDriverActor.prototype = {
*/
refresh: function MDA_refresh() {
this.command_id = this.getCommandId();
this.sendAsync("refresh", {command_id: this.command_id});
this.sendAsync("refresh", {}, this.command_id);
},
/**
@ -1227,7 +1278,7 @@ MarionetteDriverActor.prototype = {
this.switchToGlobalMessageManager();
}
aRequest.command_id = command_id;
this.sendAsync("switchToFrame", aRequest);
this.sendAsync("switchToFrame", aRequest, command_id);
}
},
@ -1249,8 +1300,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("setSearchTimeout", {value: aRequest.value,
command_id: this.command_id});
this.sendAsync("setSearchTimeout",
{ value: aRequest.value },
this.command_id);
}
},
@ -1300,10 +1352,13 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("singleTap", {value: serId,
corx: x,
cory: y,
command_id: this.command_id});
this.sendAsync("singleTap",
{
value: serId,
corx: x,
cory: y
},
this.command_id);
}
},
@ -1322,10 +1377,13 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("doubleTap", {value: serId,
corx: x,
cory: y,
command_id: this.command_id});
this.sendAsync("doubleTap",
{
value: serId,
corx: x,
cory: y
},
this.command_id);
}
},
@ -1344,10 +1402,13 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("press", {value: element,
corx: x,
cory: y,
command_id: this.command_id});
this.sendAsync("press",
{
value: element,
corx: x,
cory: y
},
this.command_id);
}
},
@ -1365,9 +1426,12 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("cancelTouch", {value: element,
touchId: touchId,
command_id: this.command_id});
this.sendAsync("cancelTouch",
{
value: element,
touchId: touchId
},
this.command_id);
}
},
@ -1387,11 +1451,14 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("release", {value: element,
touchId: touchId,
corx: x,
cory: y,
command_id: this.command_id});
this.sendAsync("release",
{
value: element,
touchId: touchId,
corx: x,
cory: y
},
this.command_id);
}
},
@ -1407,9 +1474,12 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("actionChain", {chain: aRequest.chain,
nextId: aRequest.nextId,
command_id: this.command_id});
this.sendAsync("actionChain",
{
chain: aRequest.chain,
nextId: aRequest.nextId
},
this.command_id);
}
},
@ -1428,9 +1498,12 @@ MarionetteDriverActor.prototype = {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("multiAction", {value: aRequest.value,
maxlen: aRequest.max_length,
command_id: this.command_id});
this.sendAsync("multiAction",
{
value: aRequest.value,
maxlen: aRequest.max_length
},
this.command_id);
}
},
@ -1462,10 +1535,13 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("findElementContent", {value: aRequest.value,
using: aRequest.using,
element: aRequest.element,
command_id: command_id});
this.sendAsync("findElementContent",
{
value: aRequest.value,
using: aRequest.using,
element: aRequest.element
},
command_id);
}
},
@ -1496,10 +1572,13 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("findElementsContent", {value: aRequest.value,
using: aRequest.using,
element: aRequest.element,
command_id: command_id});
this.sendAsync("findElementsContent",
{
value: aRequest.value,
using: aRequest.using,
element: aRequest.element
},
command_id);
}
},
@ -1508,7 +1587,7 @@ MarionetteDriverActor.prototype = {
*/
getActiveElement: function MDA_getActiveElement(){
let command_id = this.command_id = this.getCommandId();
this.sendAsync("getActiveElement", {command_id: command_id});
this.sendAsync("getActiveElement", {}, command_id);
},
/**
@ -1545,8 +1624,9 @@ MarionetteDriverActor.prototype = {
self.sendError("The frame closed during the click, recovering to allow further communications", 500, null, command_id);
};
curWindow.addEventListener('mozbrowserclose', this.mozBrowserClose, true);
this.sendAsync("clickElement", {element: aRequest.element,
command_id: command_id});
this.sendAsync("clickElement",
{ element: aRequest.element },
command_id);
}
},
@ -1572,9 +1652,12 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("getElementAttribute", {element: aRequest.element,
name: aRequest.name,
command_id: command_id});
this.sendAsync("getElementAttribute",
{
element: aRequest.element,
name: aRequest.name
},
command_id);
}
},
@ -1602,8 +1685,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("getElementText", {element: aRequest.element,
command_id: command_id});
this.sendAsync("getElementText",
{ element: aRequest.element },
command_id);
}
},
@ -1627,8 +1711,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("getElementTagName", {element: aRequest.element,
command_id: command_id});
this.sendAsync("getElementTagName",
{ element: aRequest.element },
command_id);
}
},
@ -1652,8 +1737,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("isElementDisplayed", {element:aRequest.element,
command_id: command_id});
this.sendAsync("isElementDisplayed",
{ element:aRequest.element },
command_id);
}
},
@ -1683,8 +1769,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("isElementEnabled", {element:aRequest.element,
command_id: command_id});
this.sendAsync("isElementEnabled",
{ element:aRequest.element },
command_id);
}
},
@ -1717,8 +1804,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("isElementSelected", {element:aRequest.element,
command_id: command_id});
this.sendAsync("isElementSelected",
{ element:aRequest.element },
command_id);
}
},
@ -1737,8 +1825,9 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("getElementSize", {element:aRequest.element,
command_id: command_id});
this.sendAsync("getElementSize",
{ element:aRequest.element },
command_id);
}
},
@ -1765,9 +1854,12 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("sendKeysToElement", {element:aRequest.element,
value: aRequest.value,
command_id: command_id});
this.sendAsync("sendKeysToElement",
{
element:aRequest.element,
value: aRequest.value
},
command_id);
}
},
@ -1780,8 +1872,9 @@ MarionetteDriverActor.prototype = {
this.command_id = this.getCommandId();
this.logRequest("setTestName", aRequest);
this.testName = aRequest.value;
this.sendAsync("setTestName", {value: aRequest.value,
command_id: this.command_id});
this.sendAsync("setTestName",
{ value: aRequest.value },
this.command_id);
},
/**
@ -1811,15 +1904,17 @@ MarionetteDriverActor.prototype = {
}
}
else {
this.sendAsync("clearElement", {element:aRequest.element,
command_id: command_id});
this.sendAsync("clearElement",
{ element:aRequest.element },
command_id);
}
},
getElementPosition: function MDA_getElementPosition(aRequest) {
this.command_id = this.getCommandId();
this.sendAsync("getElementPosition", {element:aRequest.element,
command_id: this.command_id});
this.sendAsync("getElementPosition",
{ element:aRequest.element },
this.command_id);
},
/**
@ -1827,8 +1922,9 @@ MarionetteDriverActor.prototype = {
*/
addCookie: function MDA_addCookie(aRequest) {
this.command_id = this.getCommandId();
this.sendAsync("addCookie", {cookie:aRequest.cookie,
command_id: this.command_id});
this.sendAsync("addCookie",
{ cookie:aRequest.cookie },
command_id);
},
/**
@ -1836,7 +1932,7 @@ MarionetteDriverActor.prototype = {
*/
getAllCookies: function MDA_getAllCookies() {
this.command_id = this.getCommandId();
this.sendAsync("getAllCookies", {command_id: this.command_id});
this.sendAsync("getAllCookies", {}, this.command_id);
},
/**
@ -1844,7 +1940,7 @@ MarionetteDriverActor.prototype = {
*/
deleteAllCookies: function MDA_deleteAllCookies() {
this.command_id = this.getCommandId();
this.sendAsync("deleteAllCookies", {command_id: this.command_id});
this.sendAsync("deleteAllCookies", {}, this.command_id);
},
/**
@ -1852,8 +1948,9 @@ MarionetteDriverActor.prototype = {
*/
deleteCookie: function MDA_deleteCookie(aRequest) {
this.command_id = this.getCommandId();
this.sendAsync("deleteCookie", {name:aRequest.name,
command_id: this.command_id});
this.sendAsync("deleteCookie",
{ name:aRequest.name },
this.command_id);
},
/**
@ -1952,7 +2049,7 @@ MarionetteDriverActor.prototype = {
*/
getAppCacheStatus: function MDA_getAppCacheStatus(aRequest) {
this.command_id = this.getCommandId();
this.sendAsync("getAppCacheStatus", {command_id: this.command_id});
this.sendAsync("getAppCacheStatus", {}, this.command_id);
},
_emu_cb_id: 0,
@ -1970,7 +2067,7 @@ MarionetteDriverActor.prototype = {
emulatorCmdResult: function emulatorCmdResult(message) {
if (this.context != "chrome") {
this.sendAsync("emulatorCmdResult", message);
this.sendAsync("emulatorCmdResult", message, -1);
return;
}
@ -2013,8 +2110,9 @@ MarionetteDriverActor.prototype = {
this.sendOk(command_id);
}
else {
this.sendAsync("importScript", {script: aRequest.script,
command_id: command_id});
this.sendAsync("importScript",
{ script: aRequest.script },
command_id);
}
},
@ -2024,9 +2122,12 @@ MarionetteDriverActor.prototype = {
*/
screenShot: function MDA_saveScreenshot(aRequest) {
this.command_id = this.getCommandId();
this.sendAsync("screenShot", {element: aRequest.element,
highlights: aRequest.highlights,
command_id: this.command_id});
this.sendAsync("screenShot",
{
element: aRequest.element,
highlights: aRequest.highlights
},
this.command_id);
},
/**
@ -2130,11 +2231,12 @@ MarionetteDriverActor.prototype = {
// XXX: Should have a better way of determining that this message
// is from a remote frame.
this.currentRemoteFrame.targetFrameId = this.generateFrameId(message.json.value);
this.sendAsync(
"setState",
{scriptTimeout: this.scriptTimeout,
searchTimeout: this.curBrowser.elementManager.searchTimeout,
command_id: this.currentRemoteFrame.command_id});
this.sendAsync("setState",
{
scriptTimeout: this.scriptTimeout,
searchTimeout: this.curBrowser.elementManager.searchTimeout
},
this.currentRemoteFrame.command_id);
}
let browserType;
@ -2151,7 +2253,11 @@ MarionetteDriverActor.prototype = {
this.curBrowser.elementManager.seenItems[reg.id] = listenerWindow; //add to seenItems
reg.importedScripts = this.importedScripts.path;
if (nullPrevious && (this.curBrowser.curFrameId != null)) {
this.sendAsync("newSession", {B2G: (appName == "B2G")});
if (!this.sendAsync("newSession",
{ B2G: (appName == "B2G") },
this.newSessionCommandId)) {
return;
}
if (this.curBrowser.newSession) {
this.sendResponse(reg.id, this.newSessionCommandId);
this.newSessionCommandId = null;