Bug 1244425 - Avoid CPOW when setting file array on <input type=file>; r=automatedtester

This removes the need to use a CPOW when sending keys to <input type=file>
elements.  It was previously not possible to constructo File objects in
privileged content space, but this now appears fixed.

MozReview-Commit-ID: 8XOVsDdypwC

--HG--
extra : rebase_source : 8d4329c4c6a64ac717fc5d54dc42c8eb136f5e7f
This commit is contained in:
Andreas Tolfsen 2016-08-30 12:46:01 +01:00
parent 1aa1a59ead
commit e3a3466f75
4 changed files with 21 additions and 73 deletions

View File

@ -2022,7 +2022,7 @@ GeckoDriver.prototype.sendKeysToElement = function*(cmd, resp) {
break;
case Context.CONTENT:
yield this.listener.sendKeysToElement({id: id, value: value});
yield this.listener.sendKeysToElement(id, value);
break;
}
};
@ -2667,23 +2667,6 @@ GeckoDriver.prototype.receiveMessage = function(message) {
}
return results;
case "Marionette:getFiles":
// Generates file objects to send back to the content script
// for handling file uploads.
let val = message.json.value;
let command_id = message.json.command_id;
Cu.importGlobalProperties(["File"]);
try {
let file = new File(val);
this.sendAsync("receiveFiles",
{file: file, command_id: command_id});
} catch (e) {
let err = `File not found: ${val}`;
this.sendAsync("receiveFiles",
{error: err, command_id: command_id});
}
break;
case "Marionette:emitTouchEvent":
globalMessageManager.broadcastAsyncMessage(
"MarionetteMainListener:emitTouchEvent", message.json);

View File

@ -223,7 +223,6 @@ frame.Manager = class {
mm.addWeakMessageListener("Marionette:getImportedScripts", this.driver.importedScripts);
mm.addWeakMessageListener("Marionette:register", this.driver);
mm.addWeakMessageListener("Marionette:listenersAttached", this.driver);
mm.addWeakMessageListener("Marionette:getFiles", this.driver);
mm.addWeakMessageListener("MarionetteFrame:handleModal", this);
mm.addWeakMessageListener("MarionetteFrame:getCurrentFrameId", this);
mm.addWeakMessageListener("MarionetteFrame:getInterruptedState", this);
@ -252,7 +251,6 @@ frame.Manager = class {
mm.removeWeakMessageListener("Marionette:getImportedScripts", this.driver.importedScripts);
mm.removeWeakMessageListener("Marionette:listenersAttached", this.driver);
mm.removeWeakMessageListener("Marionette:register", this.driver);
mm.removeWeakMessageListener("Marionette:getFiles", this.driver);
mm.removeWeakMessageListener("MarionetteFrame:handleModal", this);
mm.removeWeakMessageListener("MarionetteFrame:getCurrentFrameId", this);
}

View File

@ -12,6 +12,8 @@ Cu.import("chrome://marionette/content/error.js");
Cu.import("chrome://marionette/content/element.js");
Cu.import("chrome://marionette/content/event.js");
Cu.importGlobalProperties(["File"]);
this.EXPORTED_SYMBOLS = ["interaction"];
/**
@ -226,10 +228,17 @@ interaction.selectOption = function(el) {
*
* @param {HTMLInputElement} el
* An <input type=file> element.
* @param {File} file
* File object to assign to |el|.
* @param {string} path
* Full path to file.
*/
interaction.uploadFile = function(el, file) {
interaction.uploadFile = function(el, path) {
let file;
try {
file = new File(path);
} catch (e) {
throw new InvalidArgumentError("File not found: " + path);
}
let fs = Array.prototype.slice.call(el.files);
fs.push(file);

View File

@ -61,10 +61,6 @@ var capabilities = {};
var actions = new action.Chain(checkForInterrupted);
// Contains the last file input element that was the target of
// sendKeysToElement.
var fileInputElement;
// the unload handler
var onunload;
@ -252,12 +248,12 @@ var deleteAllCookiesFn = dispatch(deleteAllCookies);
var executeFn = dispatch(execute);
var executeInSandboxFn = dispatch(executeInSandbox);
var executeSimpleTestFn = dispatch(executeSimpleTest);
var sendKeysToElementFn = dispatch(sendKeysToElement);
/**
* Start all message listeners
*/
function startListeners() {
addMessageListenerId("Marionette:receiveFiles", receiveFiles);
addMessageListenerId("Marionette:newSession", newSession);
addMessageListenerId("Marionette:execute", executeFn);
addMessageListenerId("Marionette:executeInSandbox", executeInSandboxFn);
@ -287,7 +283,7 @@ function startListeners() {
addMessageListenerId("Marionette:getElementRect", getElementRectFn);
addMessageListenerId("Marionette:isElementEnabled", isElementEnabledFn);
addMessageListenerId("Marionette:isElementSelected", isElementSelectedFn);
addMessageListenerId("Marionette:sendKeysToElement", sendKeysToElement);
addMessageListenerId("Marionette:sendKeysToElement", sendKeysToElementFn);
addMessageListenerId("Marionette:clearElement", clearElementFn);
addMessageListenerId("Marionette:switchToFrame", switchToFrame);
addMessageListenerId("Marionette:switchToParentFrame", switchToParentFrame);
@ -362,7 +358,6 @@ function restart(msg) {
* Removes all listeners
*/
function deleteSession(msg) {
removeMessageListenerId("Marionette:receiveFiles", receiveFiles);
removeMessageListenerId("Marionette:newSession", newSession);
removeMessageListenerId("Marionette:execute", executeFn);
removeMessageListenerId("Marionette:executeInSandbox", executeInSandboxFn);
@ -392,7 +387,7 @@ function deleteSession(msg) {
removeMessageListenerId("Marionette:getElementRect", getElementRectFn);
removeMessageListenerId("Marionette:isElementEnabled", isElementEnabledFn);
removeMessageListenerId("Marionette:isElementSelected", isElementSelectedFn);
removeMessageListenerId("Marionette:sendKeysToElement", sendKeysToElement);
removeMessageListenerId("Marionette:sendKeysToElement", sendKeysToElementFn);
removeMessageListenerId("Marionette:clearElement", clearElementFn);
removeMessageListenerId("Marionette:switchToFrame", switchToFrame);
removeMessageListenerId("Marionette:switchToParentFrame", switchToParentFrame);
@ -590,29 +585,6 @@ function setTestName(msg) {
sendOk(msg.json.command_id);
}
/**
* Receive file objects from chrome in order to complete a
* sendKeysToElement action on a file input element.
*/
function receiveFiles(msg) {
if ("error" in msg.json) {
let err = new InvalidArgumentError(msg.json.error);
sendError(err, msg.json.command_id);
return;
}
if (!fileInputElement) {
let err = new InvalidElementStateError("receiveFiles called with no valid fileInputElement");
sendError(err, msg.json.command_id);
return;
}
interaction.uploadFile(fileInputElement, msg.json.file);
fileInputElement = null;
sendOk(msg.json.command_id);
}
/**
* This function creates a touch event given a touch type and a touch
*/
@ -1308,28 +1280,14 @@ function isElementSelected(id) {
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;
function* sendKeysToElement(id, val) {
let el = seenEls.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",
{value: p, command_id: command_id});
let path = val.join("");
yield interaction.uploadFile(el, path);
} else {
let promise = interaction.sendKeysToElement(
el, val, false, capabilities.raisesAccessibilityExceptions)
.then(() => sendOk(command_id))
.catch(e => sendError(e, command_id));
yield interaction.sendKeysToElement(
el, val, false, capabilities.raisesAccessibilityExceptions);
}
}