Bug 1230462 - Change the authentiation dialog message. r=mayhemer,dolske,margaret,tanvi

--HG--
rename : toolkit/components/prompts/test/test_bug625187.html => toolkit/components/prompts/test/test_subresources_prompts.html
extra : rebase_source : f37ed50a558040dee1958c215ccc5559637d2f84
This commit is contained in:
Dragana Damjanovic 2016-06-03 09:09:00 +02:00
parent ffad6a6151
commit 8d4a3a8b49
15 changed files with 389 additions and 114 deletions

View File

@ -826,11 +826,11 @@ mount_operation_ask_password (GMountOperation *mount_op,
if (flags & G_ASK_PASSWORD_NEED_USERNAME) {
if (!realm.IsEmpty()) {
const char16_t *strings[] = { realm.get(), dispHost.get() };
bundle->FormatStringFromName(MOZ_UTF16("EnterLoginForRealm"),
bundle->FormatStringFromName(MOZ_UTF16("EnterLoginForRealm2"),
strings, 2, getter_Copies(nsmessage));
} else {
const char16_t *strings[] = { dispHost.get() };
bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordFor"),
bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordFor2"),
strings, 1, getter_Copies(nsmessage));
}
} else {

View File

@ -676,6 +676,8 @@ var PromptUtils = {
makeDialogText: function pu_makeDialogText(aChannel, aAuthInfo) {
let isProxy = (aAuthInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY);
let isPassOnly = (aAuthInfo.flags & Ci.nsIAuthInformation.ONLY_PASSWORD);
let isCrossOrig = (aAuthInfo.flags &
Ci.nsIAuthInformation.CROSS_ORIGIN_SUB_RESOURCE);
let username = aAuthInfo.username;
let [displayHost, realm] = this.getAuthTarget(aChannel, aAuthInfo);
@ -692,14 +694,17 @@ var PromptUtils = {
}
let text;
if (isProxy)
text = this.bundle.formatStringFromName("EnterLoginForProxy", [realm, displayHost], 2);
else if (isPassOnly)
if (isProxy) {
text = this.bundle.formatStringFromName("EnterLoginForProxy2", [realm, displayHost], 2);
} else if (isPassOnly) {
text = this.bundle.formatStringFromName("EnterPasswordFor", [username, displayHost], 2);
else if (!realm)
text = this.bundle.formatStringFromName("EnterUserPasswordFor", [displayHost], 1);
else
text = this.bundle.formatStringFromName("EnterLoginForRealm", [realm, displayHost], 2);
} else if (isCrossOrig) {
text = this.bundle.formatStringFromName("EnterUserPasswordForCrossOrigin", [displayHost], 1);
} else if (!realm) {
text = this.bundle.formatStringFromName("EnterUserPasswordFor2", [displayHost], 1);
} else {
text = this.bundle.formatStringFromName("EnterLoginForRealm2", [realm, displayHost], 2);
}
return text;
},

View File

@ -54,6 +54,12 @@ interface nsIAuthInformation : nsISupports
* @see also RFC 2616, Section 10.4.2
*/
const uint32_t PREVIOUS_FAILED = 16;
/**
* A cross-origin sub-resource requests an authentication.
* The message presented to users must reflect that.
*/
const uint32_t CROSS_ORIGIN_SUB_RESOURCE = 32;
/* @} */
/**

View File

@ -40,6 +40,7 @@ namespace net {
#define HTTP_AUTH_DIALOG_TOP_LEVEL_DOC 0
#define HTTP_AUTH_DIALOG_SAME_ORIGIN_SUBRESOURCE 1
#define HTTP_AUTH_DIALOG_CROSS_ORIGIN_SUBRESOURCE 2
#define HTTP_AUTH_DIALOG_XHR 3
#define HTTP_AUTH_BASIC_INSECURE 0
#define HTTP_AUTH_BASIC_SECURE 1
@ -72,6 +73,7 @@ nsHttpChannelAuthProvider::nsHttpChannelAuthProvider()
, mTriedProxyAuth(false)
, mTriedHostAuth(false)
, mSuppressDefensiveAuth(false)
, mCrossOrigin(false)
, mHttpHandler(gHttpHandler)
{
}
@ -795,8 +797,12 @@ nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge,
// blocked for all sub-resources, blocked for cross-origin
// sub-resources, or always allowed for sub-resources.
// For more details look at the bug 647010.
// BlockPrompt will set mCrossOrigin parameter as well.
if (BlockPrompt()) {
return NS_ERROR_ABORT;
LOG(("nsHttpChannelAuthProvider::GetCredentialsForChallenge: "
"Prompt is blocked [this=%p pref=%d]\n",
this, sAuthAllowPref));
return NS_ERROR_ABORT;
}
// at this point we are forced to interact with the user to get
@ -852,61 +858,72 @@ nsHttpChannelAuthProvider::BlockPrompt()
MOZ_ASSERT(chanInternal);
if (chanInternal->GetBlockAuthPrompt()) {
LOG(("nsHttpChannelAuthProvider::BlockPrompt: Prompt is blocked "
"[this=%p channel=%p]\n", this, mAuthChannel));
return true;
}
nsCOMPtr<nsIChannel> chan = do_QueryInterface(mAuthChannel);
nsCOMPtr<nsILoadInfo> loadInfo;
chan->GetLoadInfo(getter_AddRefs(loadInfo));
if (!loadInfo) {
return false;
// We will treat loads w/o loadInfo as a top level document.
bool topDoc = true;
bool xhr = false;
if (loadInfo) {
if (loadInfo->GetExternalContentPolicyType() !=
nsIContentPolicy::TYPE_DOCUMENT) {
topDoc = false;
}
if (loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_XMLHTTPREQUEST) {
xhr = true;
}
if (!topDoc && !xhr) {
nsCOMPtr<nsIURI> topURI;
chanInternal->GetTopWindowURI(getter_AddRefs(topURI));
if (!topURI) {
// If we do not have topURI try the loadingPrincipal.
nsCOMPtr<nsIPrincipal> loadingPrinc = loadInfo->LoadingPrincipal();
if (loadingPrinc) {
loadingPrinc->GetURI(getter_AddRefs(topURI));
}
}
if (!NS_SecurityCompareURIs(topURI, mURI, true)) {
mCrossOrigin = true;
}
}
}
if (gHttpHandler->IsTelemetryEnabled()) {
if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) {
Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS,
HTTP_AUTH_DIALOG_TOP_LEVEL_DOC);
} else {
nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal();
if (loadingPrincipal) {
if (NS_SUCCEEDED(loadingPrincipal->CheckMayLoad(mURI, false, false))) {
if (topDoc) {
Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS,
HTTP_AUTH_DIALOG_SAME_ORIGIN_SUBRESOURCE);
} else {
HTTP_AUTH_DIALOG_TOP_LEVEL_DOC);
} else if (xhr) {
Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS,
HTTP_AUTH_DIALOG_CROSS_ORIGIN_SUBRESOURCE);
}
HTTP_AUTH_DIALOG_XHR);
} else if (!mCrossOrigin) {
Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS,
HTTP_AUTH_DIALOG_SAME_ORIGIN_SUBRESOURCE);
} else {
Telemetry::Accumulate(Telemetry::HTTP_AUTH_DIALOG_STATS,
HTTP_AUTH_DIALOG_CROSS_ORIGIN_SUBRESOURCE);
}
}
}
// Allow if it is the top-level document or xhr.
if ((loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) ||
(loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_XMLHTTPREQUEST)) {
return false;
}
switch (sAuthAllowPref) {
case SUBRESOURCE_AUTH_DIALOG_DISALLOW_ALL:
// Do not open the http-authentication credentials dialog for
// the sub-resources.
return true;
break;
return !topDoc && !xhr;
case SUBRESOURCE_AUTH_DIALOG_DISALLOW_CROSS_ORIGIN:
// Do not open the http-authentication credentials dialog for
// Open the http-authentication credentials dialog for
// the sub-resources only if they are not cross-origin.
{
nsCOMPtr<nsIPrincipal> loadingPrincipal =
loadInfo->LoadingPrincipal();
if (!loadingPrincipal) {
return false;
}
if (NS_FAILED(loadingPrincipal->CheckMayLoad(mURI, false, false))) {
return true;
}
}
break;
return !topDoc && !xhr && mCrossOrigin;
case SUBRESOURCE_AUTH_DIALOG_ALLOW_ALL:
// Allow the http-authentication dialog.
return false;
@ -1100,6 +1117,10 @@ nsHttpChannelAuthProvider::PromptForIdentity(uint32_t level,
if (authFlags & nsIHttpAuthenticator::IDENTITY_INCLUDES_DOMAIN)
promptFlags |= nsIAuthInformation::NEED_DOMAIN;
if (mCrossOrigin) {
promptFlags |= nsIAuthInformation::CROSS_ORIGIN_SUB_RESOURCE;
}
RefPtr<nsHTTPAuthInformation> holder =
new nsHTTPAuthInformation(promptFlags, realmU,
nsDependentCString(authType));

View File

@ -154,6 +154,10 @@ private:
uint32_t mTriedHostAuth : 1;
uint32_t mSuppressDefensiveAuth : 1;
// If a cross-origin sub-resource is being loaded, this flag will be set.
// In that case, the prompt text will be different to warn users.
uint32_t mCrossOrigin : 1;
RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive
// A variable holding the preference settings to whether to open HTTP

View File

@ -21,6 +21,7 @@ const FLAG_RETURN_FALSE = 1 << 0;
const FLAG_WRONG_PASSWORD = 1 << 1;
const FLAG_BOGUS_USER = 1 << 2;
const FLAG_PREVIOUS_FAILED = 1 << 3;
const CROSS_ORIGIN = 1 << 4;
const nsIAuthPrompt2 = Components.interfaces.nsIAuthPrompt2;
const nsIAuthInformation = Components.interfaces.nsIAuthInformation;
@ -52,8 +53,15 @@ AuthPrompt1.prototype = {
{
// Note that the realm here isn't actually the realm. it's a pw mgr key.
do_check_eq(URL + " (" + this.expectedRealm + ")", realm);
if (text.indexOf(this.expectedRealm) == -1)
do_throw("Text must indicate the realm");
if (!(this.flags & CROSS_ORIGIN)) {
if (text.indexOf(this.expectedRealm) == -1) {
do_throw("Text must indicate the realm");
}
} else {
if (text.indexOf(this.expectedRealm) != -1) {
do_throw("There should not be realm for cross origin");
}
}
if (text.indexOf("localhost") == -1)
do_throw("Text must indicate the hostname");
if (text.indexOf(String(PORT)) == -1)
@ -122,10 +130,13 @@ AuthPrompt2.prototype = {
if (this.flags & FLAG_PREVIOUS_FAILED)
expectedFlags |= nsIAuthInformation.PREVIOUS_FAILED;
if (this.flags & CROSS_ORIGIN)
expectedFlags |= nsIAuthInformation.CROSS_ORIGIN_SUB_RESOURCE;
if (isNTLM)
expectedFlags |= nsIAuthInformation.NEED_DOMAIN;
const kAllKnownFlags = 31; // Don't fail test for newly added flags
const kAllKnownFlags = 63; // Don't fail test for newly added flags
do_check_eq(expectedFlags, authInfo.flags & kAllKnownFlags);
var expectedScheme = isNTLM ? "ntlm" : isDigest ? "digest" : "basic";
@ -274,12 +285,22 @@ var listener = {
}
};
function makeChan(url) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
.QueryInterface(Components.interfaces.nsIHttpChannel);
function makeChan(url, loadingUrl) {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
var principal = ssm.createCodebasePrincipal(ios.newURI(loadingUrl, null, null), {});
return NetUtil.newChannel(
{ uri: url, loadingPrincipal: principal,
securityFlags: Ci.nsILoadInfo.SEC_NORMAL |
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
contentPolicyType: Components.interfaces.nsIContentPolicy.TYPE_OTHER
});
}
var tests = [test_noauth, test_returnfalse1, test_wrongpw1, test_prompt1,
test_prompt1CrossOrigin, test_prompt2CrossOrigin,
test_returnfalse2, test_wrongpw2, test_prompt2, test_ntlm,
test_basicrealm, test_digest_noauth, test_digest,
test_digest_bogus_user, test_large_realm, test_large_domain];
@ -304,7 +325,7 @@ function run_test() {
}
function test_noauth() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
listener.expectedCode = 401; // Unauthorized
chan.asyncOpen2(listener);
@ -313,7 +334,7 @@ function test_noauth() {
}
function test_returnfalse1() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 1);
listener.expectedCode = 401; // Unauthorized
@ -323,7 +344,7 @@ function test_returnfalse1() {
}
function test_wrongpw1() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
chan.notificationCallbacks = new Requestor(FLAG_WRONG_PASSWORD, 1);
listener.expectedCode = 200; // OK
@ -333,7 +354,7 @@ function test_wrongpw1() {
}
function test_prompt1() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
chan.notificationCallbacks = new Requestor(0, 1);
listener.expectedCode = 200; // OK
@ -342,8 +363,28 @@ function test_prompt1() {
do_test_pending();
}
function test_prompt1CrossOrigin() {
var chan = makeChan(URL + "/auth", "http://example.org");
chan.notificationCallbacks = new Requestor(16, 1);
listener.expectedCode = 200; // OK
chan.asyncOpen2(listener);
do_test_pending();
}
function test_prompt2CrossOrigin() {
var chan = makeChan(URL + "/auth", "http://example.org");
chan.notificationCallbacks = new Requestor(16, 2);
listener.expectedCode = 200; // OK
chan.asyncOpen2(listener);
do_test_pending();
}
function test_returnfalse2() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 2);
listener.expectedCode = 401; // Unauthorized
@ -353,7 +394,7 @@ function test_returnfalse2() {
}
function test_wrongpw2() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
chan.notificationCallbacks = new Requestor(FLAG_WRONG_PASSWORD, 2);
listener.expectedCode = 200; // OK
@ -363,7 +404,7 @@ function test_wrongpw2() {
}
function test_prompt2() {
var chan = makeChan(URL + "/auth");
var chan = makeChan(URL + "/auth", URL);
chan.notificationCallbacks = new Requestor(0, 2);
listener.expectedCode = 200; // OK
@ -373,7 +414,7 @@ function test_prompt2() {
}
function test_ntlm() {
var chan = makeChan(URL + "/auth/ntlm/simple");
var chan = makeChan(URL + "/auth/ntlm/simple", URL);
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 2);
listener.expectedCode = 401; // Unauthorized
@ -383,7 +424,7 @@ function test_ntlm() {
}
function test_basicrealm() {
var chan = makeChan(URL + "/auth/realm");
var chan = makeChan(URL + "/auth/realm", URL);
chan.notificationCallbacks = new RealmTestRequestor();
listener.expectedCode = 401; // Unauthorized
@ -393,7 +434,7 @@ function test_basicrealm() {
}
function test_digest_noauth() {
var chan = makeChan(URL + "/auth/digest");
var chan = makeChan(URL + "/auth/digest", URL);
//chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 2);
listener.expectedCode = 401; // Unauthorized
@ -403,7 +444,7 @@ function test_digest_noauth() {
}
function test_digest() {
var chan = makeChan(URL + "/auth/digest");
var chan = makeChan(URL + "/auth/digest", URL);
chan.notificationCallbacks = new Requestor(0, 2);
listener.expectedCode = 200; // OK
@ -413,7 +454,7 @@ function test_digest() {
}
function test_digest_bogus_user() {
var chan = makeChan(URL + "/auth/digest");
var chan = makeChan(URL + "/auth/digest", URL);
chan.notificationCallbacks = new Requestor(FLAG_BOGUS_USER, 2);
listener.expectedCode = 401; // unauthorized
chan.asyncOpen2(listener);
@ -2016,7 +2057,7 @@ function largeDomain(metadata, response) {
}
function test_large_realm() {
var chan = makeChan(URL + "/largeRealm");
var chan = makeChan(URL + "/largeRealm", URL);
listener.expectedCode = 401; // Unauthorized
chan.asyncOpen2(listener);
@ -2025,7 +2066,7 @@ function test_large_realm() {
}
function test_large_domain() {
var chan = makeChan(URL + "/largeDomain ");
var chan = makeChan(URL + "/largeDomain", URL);
listener.expectedCode = 401; // Unauthorized
chan.asyncOpen2(listener);

View File

@ -916,7 +916,7 @@ add_task(function* runTests() {
// ===== test 500 =====
state = {
msg : "A username and password are being requested by http://example.com. The site says: “some realm”",
msg : "http://example.com is requesting your username and password.\n\nThe site says: “some realm”",
title : "Authentication Required",
textValue : "inuser",
passValue : "inpass",
@ -949,7 +949,7 @@ add_task(function* runTests() {
// ===== test 501 =====
state = {
msg : "A username and password are being requested by http://example.com. The site says: “some realm”",
msg : "http://example.com is requesting your username and password.\n\nThe site says: “some realm”",
title : "Authentication Required",
textValue : "outuser",
passValue : "outpass",
@ -975,7 +975,7 @@ add_task(function* runTests() {
// ===== test 502 =====
// test filling in password-only login
state = {
msg : "A username and password are being requested by http://example.com. The site says: “http://example.com”",
msg : "http://example.com is requesting your username and password.\n\nThe site says: “http://example.com”",
title : "Authentication Required",
textValue : "",
passValue : "examplepass",
@ -1008,7 +1008,7 @@ add_task(function* runTests() {
// test filling in existing login (undetermined from multiple selection)
// user2name/user2pass would also be valid to fill here.
state = {
msg : "A username and password are being requested by http://example2.com. The site says: “http://example2.com”",
msg : "http://example2.com is requesting your username and password.\n\nThe site says: “http://example2.com”",
title : "Authentication Required",
textValue : "user1name",
passValue : "user1pass",
@ -1041,7 +1041,7 @@ add_task(function* runTests() {
// test filling in existing login (undetermined --> user1)
// user2name/user2pass would also be valid to fill here.
state = {
msg : "A username and password are being requested by http://example2.com. The site says: “http://example2.com”",
msg : "http://example2.com is requesting your username and password.\n\nThe site says: “http://example2.com”",
title : "Authentication Required",
textValue : "user1name",
passValue : "user1pass",
@ -1077,7 +1077,7 @@ add_task(function* runTests() {
// test filling in existing login (undetermined --> user2)
// user2name/user2pass would also be valid to fill here.
state = {
msg : "A username and password are being requested by http://example2.com. The site says: “http://example2.com”",
msg : "http://example2.com is requesting your username and password.\n\nThe site says: “http://example2.com”",
title : "Authentication Required",
textValue : "user1name",
passValue : "user1pass",
@ -1114,7 +1114,7 @@ add_task(function* runTests() {
// test changing a password (undetermined --> user2 w/ newpass)
// user2name/user2pass would also be valid to fill here.
state = {
msg : "A username and password are being requested by http://example2.com. The site says: “http://example2.com”",
msg : "http://example2.com is requesting your username and password.\n\nThe site says: “http://example2.com”",
title : "Authentication Required",
textValue : "user1name",
passValue : "user1pass",
@ -1151,7 +1151,7 @@ add_task(function* runTests() {
// test changing a password (undetermined --> user2 w/ origpass)
// user2name/user2pass would also be valid to fill here.
state = {
msg : "A username and password are being requested by http://example2.com. The site says: “http://example2.com”",
msg : "http://example2.com is requesting your username and password.\n\nThe site says: “http://example2.com”",
title : "Authentication Required",
textValue : "user1name",
passValue : "user1pass",
@ -1187,7 +1187,7 @@ add_task(function* runTests() {
// ===== test 508 =====
// test proxy login (default = no autologin), make sure it prompts.
state = {
msg : "The proxy moz-proxy://127.0.0.1:8888 is requesting a username and password. The site says: “Proxy Realm”",
msg : "The proxy moz-proxy://127.0.0.1:8888 is requesting a username and password.\n\nThe site says: “Proxy Realm”",
title : "Authentication Required",
textValue : "proxuser",
passValue : "proxpass",
@ -1244,7 +1244,7 @@ add_task(function* runTests() {
// ===== test 510 =====
// test proxy login (with autologin), ensure it prompts after a failed auth.
state = {
msg : "The proxy moz-proxy://127.0.0.1:8888 is requesting a username and password. The site says: “Proxy Realm”",
msg : "The proxy moz-proxy://127.0.0.1:8888 is requesting a username and password.\n\nThe site says: “Proxy Realm”",
title : "Authentication Required",
textValue : "proxuser",
passValue : "proxpass",
@ -1309,7 +1309,7 @@ add_task(function* runTests() {
// ===== test 1000 =====
state = {
msg : "A username and password are being requested by http://mochi.test:8888. The site says: “mochitest”",
msg : "http://mochi.test:8888 is requesting your username and password.\n\nThe site says: “mochitest”",
title : "Authentication Required",
textValue : "mochiuser1",
passValue : "mochipass1",
@ -1330,25 +1330,15 @@ add_task(function* runTests() {
// The following tests are driven by iframe loads
function checkEchoedAuthInfo(expectedState) {
// The server echos back the HTTP auth info it received.
let username = iframe.contentDocument.getElementById("user").textContent;
let password = iframe.contentDocument.getElementById("pass").textContent;
let authok = iframe.contentDocument.getElementById("ok").textContent;
is(authok, "PASS", "Checking for successful authentication");
is(username, expectedState.user, "Checking for echoed username");
is(password, expectedState.pass, "Checking for echoed password");
}
var iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1"});
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1"},
iframe.contentDocument);
state = {
msg : "A username and password are being requested by http://mochi.test:8888. The site says: “mochitest2”",
msg : "http://mochi.test:8888 is requesting your username and password.\n\nThe site says: “mochitest2”",
title : "Authentication Required",
textValue : "mochiuser2",
passValue : "mochipass2",
@ -1373,7 +1363,8 @@ add_task(function* runTests() {
iframe.src = "authenticate.sjs?user=mochiuser2&pass=mochipass2&realm=mochitest2";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "mochiuser2", pass: "mochipass2"});
checkEchoedAuthInfo({user: "mochiuser2", pass: "mochipass2"},
iframe.contentDocument);
// Now make a load that requests the realm from test 1000. It was
// already provided there, so auth will *not* be prompted for -- the
@ -1381,13 +1372,14 @@ add_task(function* runTests() {
iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1";
yield iframeLoaded;
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1"});
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1"},
iframe.contentDocument);
// Same realm we've already authenticated to, but with a different
// expected password (to trigger an auth prompt, and change-password
// popup notification).
state = {
msg : "A username and password are being requested by http://mochi.test:8888. The site says: “mochitest”",
msg : "http://mochi.test:8888 is requesting your username and password.\n\nThe site says: “mochitest”",
title : "Authentication Required",
textValue : "mochiuser1",
passValue : "mochipass1",
@ -1410,7 +1402,8 @@ add_task(function* runTests() {
iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1-new";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1-new"});
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1-new"},
iframe.contentDocument);
// Housekeeping: change it back
var pwchanged = new Promise(resolve => {
@ -1436,7 +1429,7 @@ add_task(function* runTests() {
// to (but have an existing saved login for, so that we'll trigger
// a change-password popup notification.
state = {
msg : "A username and password are being requested by http://mochi.test:8888. The site says: “mochitest3”",
msg : "http://mochi.test:8888 is requesting your username and password.\n\nThe site says: “mochitest3”",
title : "Authentication Required",
textValue : "mochiuser3",
passValue : "mochipass3-old",
@ -1459,7 +1452,8 @@ add_task(function* runTests() {
iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-new&realm=mochitest3";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "mochiuser3", pass: "mochipass3-new"});
checkEchoedAuthInfo({user: "mochiuser3", pass: "mochipass3-new"},
iframe.contentDocument);
// Housekeeping: change it back to the original login4. Actually,
// just delete it and we'll re-add it as the next test.
@ -1490,7 +1484,7 @@ add_task(function* runTests() {
ok(true, "authMgr cleared cached auth");
state = {
msg : "A username and password are being requested by http://mochi.test:8888. The site says: “mochitest3”",
msg : "http://mochi.test:8888 is requesting your username and password.\n\nThe site says: “mochitest3”",
title : "Authentication Required",
textValue : "",
passValue : "",
@ -1516,7 +1510,8 @@ add_task(function* runTests() {
iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "mochiuser3", pass: "mochipass3-old"});
checkEchoedAuthInfo({user: "mochiuser3", pass: "mochipass3-old"},
iframe.contentDocument);
var pwsaved = new Promise(resolve => {
function finishIt() {

View File

@ -50,6 +50,8 @@ function commonDialogOnLoad() {
Dialog = new CommonDialog(args, ui);
Dialog.onLoad(dialog);
// resize the window to the content
window.sizeToContent();
window.getAttention();
}

View File

@ -255,6 +255,8 @@ var PromptUtilsTemp = {
makeAuthMessage : function (channel, authInfo) {
let isProxy = (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY);
let isPassOnly = (authInfo.flags & Ci.nsIAuthInformation.ONLY_PASSWORD);
let isCrossOrig = (authInfo.flags &
Ci.nsIAuthInformation.CROSS_ORIGIN_SUB_RESOURCE);
let username = authInfo.username;
let [displayHost, realm] = this.getAuthTarget(channel, authInfo);
@ -271,14 +273,17 @@ var PromptUtilsTemp = {
}
let text;
if (isProxy)
text = PromptUtils.getLocalizedString("EnterLoginForProxy", [realm, displayHost]);
else if (isPassOnly)
if (isProxy) {
text = PromptUtils.getLocalizedString("EnterLoginForProxy2", [realm, displayHost]);
} else if (isPassOnly) {
text = PromptUtils.getLocalizedString("EnterPasswordFor", [username, displayHost]);
else if (!realm)
text = PromptUtils.getLocalizedString("EnterUserPasswordFor", [displayHost]);
else
text = PromptUtils.getLocalizedString("EnterLoginForRealm", [realm, displayHost]);
} else if (isCrossOrig) {
text = PromptUtils.getLocalizedString("EnterUserPasswordForCrossOrigin", [displayHost]);
} else if (!realm) {
text = PromptUtils.getLocalizedString("EnterUserPasswordFor2", [displayHost]);
} else {
text = PromptUtils.getLocalizedString("EnterLoginForRealm2", [realm, displayHost]);
}
return text;
},

View File

@ -1,6 +1,7 @@
[DEFAULT]
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
support-files =
../../passwordmgr/test/authenticate.sjs
bug619644_inner.html
bug625187_iframe.html
prompt_common.js
@ -9,7 +10,8 @@ support-files =
[test_bug619644.html]
[test_bug620145.html]
skip-if = toolkit == 'android' #TIMED_OUT
[test_bug625187.html]
[test_subresources_prompts.html]
skip-if = toolkit == 'android'
[test_dom_prompts.html]
skip-if = toolkit == 'android' #android: bug 1267092
[test_modal_prompts.html]

View File

@ -85,3 +85,14 @@ function checkPromptState(promptState, expectedState) {
is(promptState.focused, expectedState.focused, "Checking focused element");
}
}
function checkEchoedAuthInfo(expectedState, doc) {
// The server echos back the HTTP auth info it received.
let username = doc.getElementById("user").textContent;
let password = doc.getElementById("pass").textContent;
let authok = doc.getElementById("ok").textContent;
is(authok, "PASS", "Checking for successful authentication");
is(username, expectedState.user, "Checking for echoed username");
is(password, expectedState.pass, "Checking for echoed password");
}

View File

@ -982,7 +982,7 @@ function* runTests() {
// (promptAuth is only accessible from the prompt service)
info("Starting test: promptAuth with empty realm");
state = {
msg : 'Enter username and password for http://example.com',
msg : 'http://example.com is requesting your username and password.',
title : "TestTitle",
iconClass : "authentication-icon question-icon",
titleHidden : true,
@ -1020,7 +1020,7 @@ function* runTests() {
// (promptAuth is only accessible from the prompt service)
info("Starting test: promptAuth with long realm");
state = {
msg : 'A username and password are being requested by http://example.com. The site ' +
msg : 'http://example.com is requesting your username and password.\n\nThe site ' +
'says: \u201cabcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi ' +
'abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi ' +
'abcdefghi \u2026\u201d',
@ -1061,6 +1061,94 @@ function* runTests() {
yield promptDone;
}
info("Starting test: promptAuth for a cross-origin and a empty realm");
authinfo = {
username : "",
password : "",
domain : "",
flags : Ci. nsIAuthInformation.AUTH_HOST |
Ci.nsIAuthInformation.CROSS_ORIGIN_SUB_RESOURCE,
authenticationScheme : "basic",
realm : ""
}
state = {
msg : 'http://example.com is requesting your username and password.\n\n' +
'WARNING: Your password will not be sent to the website you are currently visiting!',
title : "TestTitle",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : false,
textValue : "",
passValue : "",
checkMsg : "Check me out!",
checked : false,
focused : "textField",
defButton : "button0",
};
action = {
buttonClick : "ok",
setCheckbox : false,
textField : "username",
passField : "password",
};
if (usePromptService) {
promptDone = handlePrompt(state, action);
checkVal.value = false;
isOK = prompter.promptAuth(window, channel, level, authinfo, "Check me out!", checkVal);
is(isOK, true, "checked expected retval");
is(authinfo.username, "username", "checking filled username");
is(authinfo.password, "password", "checking filled password");
is(checkVal.value, true, "expected checkbox setting");
yield promptDone;
}
info("Starting test: promptAuth for a cross-origin with realm");
authinfo = {
username : "",
password : "",
domain : "",
flags : Ci. nsIAuthInformation.AUTH_HOST | Ci.nsIAuthInformation.CROSS_ORIGIN_SUB_RESOURCE,
authenticationScheme : "basic",
realm : "Something!!!"
}
state = {
msg : 'http://example.com is requesting your username and password.\n\n' +
'WARNING: Your password will not be sent to the website you are currently visiting!',
title : "TestTitle",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : false,
textValue : "",
passValue : "",
checkMsg : "Check me out!",
checked : false,
focused : "textField",
defButton : "button0",
};
action = {
buttonClick : "ok",
setCheckbox : false,
textField : "username",
passField : "password",
};
if (usePromptService) {
promptDone = handlePrompt(state, action);
checkVal.value = false;
isOK = prompter.promptAuth(window, channel, level, authinfo, "Check me out!", checkVal);
is(isOK, true, "checked expected retval");
is(authinfo.username, "username", "checking filled username");
is(authinfo.password, "password", "checking filled password");
is(checkVal.value, true, "expected checkbox setting");
yield promptDone;
}
}
let usePromptService;

View File

@ -1,6 +1,6 @@
<html>
<head>
<title>Test for Bug 625187</title>
<title>Test subresources prompts (Bug 625187 and bug 1230462)</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
@ -17,6 +17,7 @@
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=625187">Mozilla Bug 625187</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230462">Mozilla Bug 1230462</a>
<p><button onclick="alert('hello world')">Button</button></p>
@ -24,11 +25,14 @@
<iframe id="iframe_same_origin" src="bug625187_iframe.html"></iframe>
<iframe id="iframe_prompt"></iframe>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe1Loaded = onloadPromiseFor("iframe_diff_origin");
var iframe2Loaded = onloadPromiseFor("iframe_same_origin");
var iframe_prompt = document.getElementById("iframe_prompt");
add_task(function* runTest()
{
@ -104,6 +108,96 @@ add_task(function* runTest()
yield promptDone;
});
add_task(function* runTestAuth()
{
// Following tests chack prompt message for a cross-origin and not
// cross-origin subresources load
// Force parent to not look for tab-modal prompts, as they're not
// used for auth prompts.
isTabModal = false;
state = {
msg : "http://mochi.test:8888 is requesting your username " +
"and password.\n\nThe site says: “mochitest”",
title : "Authentication Required",
textValue : "",
passValue : "",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : true,
checkMsg : "",
checked : false,
focused : "textField",
defButton : "button0",
};
if (isE10S) {
state.checkHidden = false;
state.checkMsg = "Use Password Manager to remember this password."
}
action = {
buttonClick : "ok",
setCheckbox : false,
textField : "mochiuser1",
passField : "mochipass1",
};
promptDone = handlePrompt(state, action);
var iframe3Loaded = onloadPromiseFor("iframe_prompt");
iframe_prompt.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1";
yield promptDone;
yield iframe3Loaded;
checkEchoedAuthInfo({user: "mochiuser1", pass: "mochipass1"},
iframe_prompt.contentDocument);
// Cross-origin subresourse test.
// Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
isTabModal =false;
state = {
msg : "http://example.com is requesting your username and password.\n\n" +
"WARNING: Your password will not be sent to the website you are currently visiting!",
title : "Authentication Required",
textValue : "",
passValue : "",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : true,
checkMsg : "",
checked : false,
focused : "textField",
defButton : "button0",
};
if (isE10S) {
state.checkHidden = false;
state.checkMsg = "Use Password Manager to remember this password."
}
action = {
buttonClick : "ok",
setCheckbox : false,
textField : "mochiuser2",
passField : "mochipass2",
};
promptDone = handlePrompt(state, action);
iframe3Loaded = onloadPromiseFor("iframe_prompt");
iframe_prompt.src = "http://example.com/tests/toolkit/components/prompts/test/authenticate.sjs?user=mochiuser2&pass=mochipass2&realm=mochitest";
yield promptDone;
yield iframe3Loaded;
checkEchoedAuthInfo({user: "mochiuser2", pass: "mochipass2"},
SpecialPowers.wrap(iframe_prompt.contentWindow).document);
});
function dispatchMouseEvent(target, type)
{
var win = SpecialPowers.unwrap(target.ownerDocument.defaultView);

View File

@ -1427,8 +1427,8 @@
"HTTP_AUTH_DIALOG_STATS": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values": 3,
"description": "Stats about what kind of resource requested http authentication. (0=top-level doc, 1=same origin subresources 2=cross-origin subresources)"
"n_values": 4,
"description": "Stats about what kind of resource requested http authentication. (0=top-level doc, 1=same origin subresources, 2=cross-origin subresources, 3=xhr)"
},
"HTTP_AUTH_TYPE_STATS": {
"alert_emails": ["rbarnes@mozilla.com"],

View File

@ -20,12 +20,13 @@ ScriptDlgGenericHeading=[JavaScript Application]
ScriptDlgHeading=The page at %S says:
ScriptDialogLabel=Prevent this page from creating additional dialogs
ScriptDialogPreventTitle=Confirm Dialog Preference
# LOCALIZATION NOTE (EnterLoginForRealm, EnterLoginForProxy):
# LOCALIZATION NOTE (EnterLoginForRealm2, EnterLoginForProxy2):
# %1 is an untrusted string provided by a remote server. It could try to
# take advantage of sentence structure in order to mislead the user (see
# bug 244273). %1 should be integrated into the translated sentences as
# little as possible. %2 is the url of the site being accessed.
EnterLoginForRealm=A username and password are being requested by %2$S. The site says: “%1$S”
EnterLoginForProxy=The proxy %2$S is requesting a username and password. The site says: “%1$S”
EnterUserPasswordFor=Enter username and password for %1$S
EnterLoginForRealm2=%2$S is requesting your username and password.\n\nThe site says: “%1$S”
EnterLoginForProxy2=The proxy %2$S is requesting a username and password.\n\nThe site says: “%1$S”
EnterUserPasswordFor2=%1$S is requesting your username and password.
EnterUserPasswordForCrossOrigin=%1$S is requesting your username and password.\n\nWARNING: Your password will not be sent to the website you are currently visiting!
EnterPasswordFor=Enter password for %1$S on %2$S