mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Bug 1426767 - Don't autocomplete logins in documents with a null principal. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D7388 --HG-- rename : toolkit/components/passwordmgr/test/mochitest/test_insecure_form_field_autocomplete.html => toolkit/components/passwordmgr/test/mochitest/test_autocomplete_sandboxed.html extra : rebase_source : dcfbdffc9d934365850397df850233db641364a8 extra : source : 8d9d8cde6d8bfa1c13a06b3d73f987bc7267ea0f
This commit is contained in:
parent
7826571e9b
commit
a6c0ee093d
@ -10,7 +10,6 @@ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/LoginManagerContent.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "BrowserUtils",
|
||||
"resource://gre/modules/BrowserUtils.jsm");
|
||||
@ -18,6 +17,10 @@ ChromeUtils.defineModuleGetter(this, "LoginHelper",
|
||||
"resource://gre/modules/LoginHelper.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "LoginFormFactory",
|
||||
"resource://gre/modules/LoginManagerContent.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "LoginManagerContent",
|
||||
"resource://gre/modules/LoginManagerContent.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "UserAutoCompleteResult",
|
||||
"resource://gre/modules/LoginManagerContent.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "InsecurePasswordUtils",
|
||||
"resource://gre/modules/InsecurePasswordUtils.jsm");
|
||||
|
||||
@ -503,8 +506,25 @@ LoginManager.prototype = {
|
||||
// aPreviousResult is an nsIAutoCompleteResult, aElement is
|
||||
// HTMLInputElement
|
||||
|
||||
let form = LoginFormFactory.createFromField(aElement);
|
||||
let isSecure = InsecurePasswordUtils.isFormSecure(form);
|
||||
let {isNullPrincipal} = aElement.nodePrincipal;
|
||||
// Show the insecure login warning in the passwords field on null principal documents.
|
||||
let isSecure = !isNullPrincipal;
|
||||
// Avoid loading InsecurePasswordUtils.jsm in a sandboxed document (e.g. an ad. frame) if we
|
||||
// already know it has a null principal and will therefore get the insecure autocomplete
|
||||
// treatment.
|
||||
// InsecurePasswordUtils doesn't handle the null principal case as not secure because we don't
|
||||
// want the same treatment:
|
||||
// * The web console warnings will be confusing (as they're primarily about http:) and not very
|
||||
// useful if the developer intentionally sandboxed the document.
|
||||
// * The site identity insecure field warning would require LoginManagerContent being loaded and
|
||||
// listening to some of the DOM events we're ignoring in null principal documents. For memory
|
||||
// reasons it's better to not load LMC at all for these sandboxed frames. Also, if the top-
|
||||
// document is sandboxing a document, it probably doesn't want that sandboxed document to be
|
||||
// able to affect the identity icon in the address bar by adding a password field.
|
||||
if (isSecure) {
|
||||
let form = LoginFormFactory.createFromField(aElement);
|
||||
isSecure = InsecurePasswordUtils.isFormSecure(form);
|
||||
}
|
||||
let isPasswordField = aElement.type == "password";
|
||||
|
||||
let completeSearch = (autoCompleteLookupPromise, { logins, messageManager }) => {
|
||||
@ -523,6 +543,14 @@ LoginManager.prototype = {
|
||||
aCallback.onSearchCompletion(results);
|
||||
};
|
||||
|
||||
if (isNullPrincipal) {
|
||||
// Don't search login storage when the field has a null principal as we don't want to fill
|
||||
// logins for the `location` in this case.
|
||||
let acLookupPromise = this._autoCompleteLookupPromise = Promise.resolve({ logins: [] });
|
||||
acLookupPromise.then(completeSearch.bind(this, acLookupPromise));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPasswordField && aSearchString) {
|
||||
// Return empty result on password fields with password already filled.
|
||||
let acLookupPromise = this._autoCompleteLookupPromise = Promise.resolve({ logins: [] });
|
||||
|
@ -15,6 +15,9 @@ support-files =
|
||||
|
||||
[test_autocomplete_https_upgrade.html]
|
||||
skip-if = toolkit == 'android' # autocomplete
|
||||
[test_autocomplete_sandboxed.html]
|
||||
scheme = https
|
||||
skip-if = toolkit == 'android' # autocomplete
|
||||
[test_autofill_https_upgrade.html]
|
||||
skip-if = toolkit == 'android' # Bug 1259768
|
||||
[test_autofill_sandboxed.html]
|
||||
|
@ -0,0 +1,102 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test form field autocomplete in sandboxed documents (null principal)</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
|
||||
<script type="text/javascript" src="satchel_common.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var chromeScript = runChecksAfterCommonInit();
|
||||
|
||||
var setupScript = runInParent(function setup() {
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
|
||||
Ci.nsILoginInfo, "init");
|
||||
assert.ok(nsLoginInfo != null, "nsLoginInfo constructor");
|
||||
|
||||
var login1 = new nsLoginInfo("https://example.com", "", null,
|
||||
"tempuser1", "temppass1", "uname", "pword");
|
||||
|
||||
// try/catch in case someone runs the tests manually, twice.
|
||||
try {
|
||||
Services.logins.addLogin(login1);
|
||||
} catch (e) {
|
||||
assert.ok(false, "addLogin threw: " + e);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<p id="display"></p>
|
||||
|
||||
<!-- we presumably can't hide the content for this test. -->
|
||||
<div id="content">
|
||||
<iframe id="sandboxed"
|
||||
sandbox=""
|
||||
src="form_basic.html"></iframe>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: form field autocomplete in sandboxed documents (null principal) **/
|
||||
|
||||
let sandboxed = document.getElementById("sandboxed");
|
||||
let uname;
|
||||
let pword;
|
||||
|
||||
// Check for expected username/password in form.
|
||||
function checkACForm(expectedUsername, expectedPassword) {
|
||||
var formID = uname.parentNode.id;
|
||||
is(uname.value, expectedUsername, "Checking " + formID + " username is: " + expectedUsername);
|
||||
is(pword.value, expectedPassword, "Checking " + formID + " password is: " + expectedPassword);
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["security.insecure_field_warning.contextual.enabled", true],
|
||||
]});
|
||||
|
||||
let frameWindow = SpecialPowers.wrap(sandboxed).contentWindow;
|
||||
// Can't use SimpleTest.promiseFocus as it doesn't work with the sandbox.
|
||||
await SimpleTest.promiseWaitForCondition(() => {
|
||||
return frameWindow.document.readyState == "complete" && frameWindow.location.href != "about:blank";
|
||||
}, "Check frame is loaded");
|
||||
let frameDoc = SpecialPowers.wrap(sandboxed).contentDocument;
|
||||
uname = frameDoc.getElementById("form-basic-username");
|
||||
pword = frameDoc.getElementById("form-basic-password");
|
||||
});
|
||||
|
||||
add_task(async function test_no_autofill() {
|
||||
// Make sure initial form is empty as autofill shouldn't happen in the sandboxed frame.
|
||||
checkACForm("", "");
|
||||
let popupState = await getPopupState();
|
||||
is(popupState.open, false, "Check popup is initially closed");
|
||||
});
|
||||
|
||||
add_task(async function test_autocomplete_warning_no_logins() {
|
||||
pword.focus();
|
||||
let shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown"); // open the popup
|
||||
let results = await shownPromise;
|
||||
|
||||
let popupState = await getPopupState();
|
||||
is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
|
||||
|
||||
let expectedMenuItems = [
|
||||
"This connection is not secure. Logins entered here could be compromised. Learn More",
|
||||
];
|
||||
checkArrayValues(results, expectedMenuItems, "Check all menuitems are displayed correctly.");
|
||||
|
||||
checkACForm("", "");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user