Bug 1166965 - Support non-<form> elements in onFormSubmit. r=dolske

--HG--
rename : toolkit/components/passwordmgr/test/test_recipe_login_fields.html => toolkit/components/passwordmgr/test/test_formless_submit.html
This commit is contained in:
Matthew Noorenberghe 2015-06-02 00:27:43 -07:00
Родитель 32f44f262c
Коммит bc585a43ed
6 изменённых файлов: 198 добавлений и 17 удалений

Просмотреть файл

@ -64,9 +64,11 @@ var observer = {
// can grab form data before it might be modified (see bug 257781).
try {
LoginManagerContent._onFormSubmit(formElement);
let formLike = FormLikeFactory.createFromForm(formElement);
LoginManagerContent._onFormSubmit(formLike);
} catch (e) {
log("Caught error in onFormSubmit(", e.lineNumber, "):", e.message);
Cu.reportError(e);
}
return true; // Always return true, or form submit will be canceled.
@ -638,18 +640,12 @@ var LoginManagerContent = {
},
/*
* _isAutoCompleteDisabled
*
* Returns true if the page requests autocomplete be disabled for the
* specified form input.
/**
* @return true if the page requests autocomplete be disabled for the
* specified element.
*/
_isAutocompleteDisabled : function (element) {
if (element && element.hasAttribute("autocomplete") &&
element.getAttribute("autocomplete").toLowerCase() == "off")
return true;
return false;
_isAutocompleteDisabled(element) {
return element && element.autocomplete == "off";
},
/**
@ -657,8 +653,10 @@ var LoginManagerContent = {
* [Note that this happens before any DOM onsubmit handlers are invoked.]
* Looks for a password change in the submitted form, so we can update
* our stored password.
*
* @param {FormLike} form
*/
_onFormSubmit : function (form) {
_onFormSubmit(form) {
var doc = form.ownerDocument;
var win = doc.defaultView;
@ -1096,8 +1094,8 @@ UserAutoCompleteResult.prototype = {
*/
let FormLikeFactory = {
_propsFromForm: [
"action",
"autocomplete",
"autocomplete",
"ownerDocument",
],
/**
@ -1113,8 +1111,8 @@ let FormLikeFactory = {
}
let formLike = {
action: LoginUtils._getActionOrigin(aForm),
elements: [...aForm.elements],
ownerDocument: aForm.ownerDocument,
rootElement: aForm,
};
@ -1152,7 +1150,7 @@ let FormLikeFactory = {
let doc = aPasswordField.ownerDocument;
log("Created non-form FormLike for rootElement:", doc.documentElement);
return {
action: "",
action: LoginUtils._getPasswordOrigin(doc.baseURI),
autocomplete: "on",
// Exclude elements inside the rootElement that are already in a <form> as
// they will be handled by their own FormLike.

Просмотреть файл

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
</body>
</html>

Просмотреть файл

@ -5,6 +5,7 @@ support-files =
notification_common.js
pwmgr_common.js
[test_formless_submit.html]
[test_privbrowsing_perwindowpb.html]
# Too many intermittent failures (bug 919016)
skip-if = true

Просмотреть файл

@ -2,6 +2,7 @@
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || e10s
support-files =
authenticate.sjs
blank.html
formsubmit.sjs
notification_common.js
privbrowsing_perwindowpb_iframe.html

Просмотреть файл

@ -273,10 +273,16 @@ if (this.addMessageListener) {
commonInit(true);
sendAsyncMessage("doneSetup");
});
addMessageListener("loadRecipes", Task.async(function* loadRecipes(recipes) {
var { LoginManagerParent } = Cu.import("resource://gre/modules/LoginManagerParent.jsm", {});
var recipeParent = yield LoginManagerParent.recipeParentPromise;
yield recipeParent.load(recipes);
sendAsyncMessage("loadedRecipes", recipes);
}));
var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
globalMM.addMessageListener("RemoteLogins:onFormSubmit", function onFormSubmit(message) {
sendAsyncMessage("formSubmissionProcessed", message.data, message.objects);
});
}

Просмотреть файл

@ -0,0 +1,167 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test capturing of fields outside of a form</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<script type="application/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
Cu.import("resource://gre/modules/Task.jsm");
const LMCBackstagePass = Cu.import("resource://gre/modules/LoginManagerContent.jsm");
const { LoginManagerContent, FormLikeFactory } = LMCBackstagePass;
SpecialPowers.Services.prefs.setBoolPref("signon.debug", true);
let parentScriptURL = SimpleTest.getTestFileURL("pwmgr_common.js");
let mm = SpecialPowers.loadChromeScript(parentScriptURL);
document.addEventListener("DOMContentLoaded", () => {
document.getElementById("loginFrame").addEventListener("load", (evt) => {
// Tell the parent to setup test logins.
mm.sendAsyncMessage("setupParent");
});
});
// When the setup is done, load a recipe for this test.
mm.addMessageListener("doneSetup", function doneSetup() {
mm.sendAsyncMessage("loadRecipes", {
siteRecipes: [{
hosts: ["mochi.test:8888"],
usernameSelector: "input[name='uname1']",
passwordSelector: "input[name='pword2']",
}],
});
});
mm.addMessageListener("loadedRecipes", () => runTest());
const DEFAULT_ORIGIN = "http://mochi.test:8888";
const TESTCASES = [
{
// Inputs
document: `<input type=password value="pass1">`,
//documentURL: DEFAULT_ORIGIN,
inputIndexForFormLike: 0,
// Expected outputs similar to RemoteLogins:onFormSubmit
hostname: DEFAULT_ORIGIN,
formSubmitURL: DEFAULT_ORIGIN,
usernameFieldValue: null,
newPasswordFieldValue: "pass1",
oldPasswordFieldValue: null,
},
{
document: `<input value="user1">
<input type=password value="pass1">`,
inputIndexForFormLike: 1,
hostname: DEFAULT_ORIGIN,
formSubmitURL: DEFAULT_ORIGIN,
usernameFieldValue: "user1",
newPasswordFieldValue: "pass1",
oldPasswordFieldValue: null,
},
{
document: `<input value="user1">
<input type=password value="pass1">
<input type=password value="pass2">`,
inputIndexForFormLike: 2,
hostname: DEFAULT_ORIGIN,
formSubmitURL: DEFAULT_ORIGIN,
usernameFieldValue: "user1",
newPasswordFieldValue: "pass2",
oldPasswordFieldValue: "pass1",
},
{
document: `<input value="user1">
<input type=password value="pass1">
<input type=password value="pass2">
<input type=password value="pass2">`,
inputIndexForFormLike: 3,
hostname: DEFAULT_ORIGIN,
formSubmitURL: DEFAULT_ORIGIN,
usernameFieldValue: "user1",
newPasswordFieldValue: "pass2",
oldPasswordFieldValue: "pass1",
},
{
document: `<input value="user1">
<input type=password value="user2" form="form1">
<input type=password value="pass1">
<form id="form1">
<input value="user3">
<input type=password value="pass2">
</form>`,
inputIndexForFormLike: 2,
hostname: DEFAULT_ORIGIN,
formSubmitURL: DEFAULT_ORIGIN,
usernameFieldValue: "user1",
newPasswordFieldValue: "pass1",
oldPasswordFieldValue: null,
},
];
function getSubmitMessage() {
info("getSubmitMessage");
return new Promise((resolve, reject) => {
mm.addMessageListener("formSubmissionProcessed", function processed(...args) {
info("got formSubmissionProcessed");
mm.removeMessageListener("formSubmissionProcessed", processed);
resolve(...args);
});
});
}
let runTest = Task.async(function*() {
let loginFrame = document.getElementById("loginFrame");
let frameDoc = loginFrame.contentWindow.document;
for (let tc of TESTCASES) {
info("Starting testcase: " + JSON.stringify(tc));
frameDoc.documentElement.innerHTML = tc.document;
let inputForFormLike = frameDoc.querySelectorAll("input")[tc.inputIndexForFormLike];
let formLike = FormLikeFactory.createFromPasswordField(inputForFormLike);
info("Calling _onFormSubmit with FormLike");
let processedPromise = getSubmitMessage();
LoginManagerContent._onFormSubmit(formLike);
let submittedResult = yield processedPromise;
// Check data sent via RemoteLogins:onFormSubmit
is(submittedResult.hostname, tc.hostname, "Check hostname");
is(submittedResult.formSubmitURL, tc.formSubmitURL, "Check formSubmitURL");
if (tc.usernameFieldValue === null) {
is(submittedResult.usernameField, tc.usernameFieldValue, "Check usernameField");
} else {
is(submittedResult.usernameField.value, tc.usernameFieldValue, "Check usernameField");
}
is(submittedResult.newPasswordField.value, tc.newPasswordFieldValue, "Check newPasswordFieldValue");
if (tc.oldPasswordFieldValue === null) {
is(submittedResult.oldPasswordField, tc.oldPasswordFieldValue, "Check oldPasswordFieldValue");
} else {
is(submittedResult.oldPasswordField.value, tc.oldPasswordFieldValue, "Check oldPasswordFieldValue");
}
}
SimpleTest.finish();
});
</script>
<p id="display"></p>
<div id="content">
<iframe id="loginFrame" src="http://mochi.test:8888/tests/toolkit/components/passwordmgr/test/blank.html"></iframe>
</div>
<pre id="test"></pre>
</body>
</html>