mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1091287: Switch to the right browser before displaying a login prompt. r=mrbkap
This commit is contained in:
parent
544e2bacbb
commit
dadb2c6ca9
@ -123,7 +123,7 @@ LoginManagerPrompter.prototype = {
|
||||
},
|
||||
|
||||
|
||||
setE10sData : function (aBrowser) {
|
||||
setE10sData : function (aBrowser, aOpener) {
|
||||
// XXX Implement me!
|
||||
throw new Error("Not Yet Implemented");
|
||||
},
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include "nsAuthInformationHolder.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsILoginManagerPrompter.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::dom;
|
||||
@ -1880,8 +1881,18 @@ TabParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
|
||||
|
||||
// Get an auth prompter for our window so that the parenting
|
||||
// of the dialogs works as it should when using tabs.
|
||||
return wwatch->GetPrompt(window, iid,
|
||||
reinterpret_cast<void**>(aResult));
|
||||
nsCOMPtr<nsISupports> prompt;
|
||||
rv = wwatch->GetPrompt(window, iid, getter_AddRefs(prompt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsILoginManagerPrompter> prompter = do_QueryInterface(prompt);
|
||||
if (prompter) {
|
||||
nsCOMPtr<nsIDOMElement> browser = do_QueryInterface(mFrameElement);
|
||||
prompter->SetE10sData(browser, nullptr);
|
||||
}
|
||||
|
||||
*aResult = prompt.forget().take();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PColorPickerParent*
|
||||
|
@ -108,7 +108,7 @@ LoginManagerPrompter.prototype = {
|
||||
this.log("===== initialized =====");
|
||||
},
|
||||
|
||||
setE10sData : function (aBrowser) {
|
||||
setE10sData : function (aBrowser, aOpener) {
|
||||
throw new Error("This should be filled in when Android is multiprocess");
|
||||
},
|
||||
|
||||
|
@ -216,7 +216,7 @@ var LoginManagerParent = {
|
||||
target.ownerDocument.defaultView :
|
||||
target.contentWindow);
|
||||
if (target.isRemoteBrowser)
|
||||
prompterSvc.setE10sData({ browser: target, opener: opener });
|
||||
prompterSvc.setE10sData(target, opener);
|
||||
return prompterSvc;
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,10 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILoginInfo;
|
||||
interface nsIDOMElement;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(88b75787-a78c-43aa-bfe8-52c3248b8dfd)]
|
||||
[scriptable, uuid(425f73b9-b2db-4e8a-88c5-9ac2512934ce)]
|
||||
interface nsILoginManagerPrompter : nsISupports {
|
||||
/**
|
||||
* Initialize the prompter. Must be called before using other interfaces.
|
||||
@ -27,8 +28,9 @@ interface nsILoginManagerPrompter : nsISupports {
|
||||
* window passed to init.
|
||||
*
|
||||
* @param aBrowser the <browser> to use for this prompter.
|
||||
* @param aOpener the opener to use for this prompter.
|
||||
*/
|
||||
void setE10sData(in jsval aData);
|
||||
void setE10sData(in nsIDOMElement aBrowser, in nsIDOMWindow aOpener);
|
||||
|
||||
/**
|
||||
* Ask the user if they want to save a login (Yes, Never, Not Now)
|
||||
|
@ -11,6 +11,7 @@ const Cr = Components.results;
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/SharedPromptUtils.jsm");
|
||||
|
||||
/*
|
||||
* LoginManagerPromptFactory
|
||||
@ -577,10 +578,14 @@ LoginManagerPrompter.prototype = {
|
||||
"Epic fail in promptAuth: " + e + "\n");
|
||||
}
|
||||
|
||||
var ok = canAutologin ||
|
||||
this._promptService.promptAuth(this._window,
|
||||
aChannel, aLevel, aAuthInfo,
|
||||
checkboxLabel, checkbox);
|
||||
var ok = canAutologin;
|
||||
if (!ok) {
|
||||
if (this._window)
|
||||
PromptUtils.fireDialogEvent(this._window, "DOMWillOpenModalDialog", this._browser);
|
||||
ok = this._promptService.promptAuth(this._window,
|
||||
aChannel, aLevel, aAuthInfo,
|
||||
checkboxLabel, checkbox);
|
||||
}
|
||||
|
||||
// If there's a notification box, use it to allow the user to
|
||||
// determine if the login should be saved. If there isn't a
|
||||
@ -713,11 +718,11 @@ LoginManagerPrompter.prototype = {
|
||||
this.log("===== initialized =====");
|
||||
},
|
||||
|
||||
setE10sData : function (aData) {
|
||||
setE10sData : function (aBrowser, aOpener) {
|
||||
if (!(this._window instanceof Ci.nsIDOMChromeWindow))
|
||||
throw new Error("Unexpected call");
|
||||
this._browser = aData.browser;
|
||||
this._opener = aData.opener;
|
||||
this._browser = aBrowser;
|
||||
this._opener = aOpener;
|
||||
},
|
||||
|
||||
|
||||
@ -1224,7 +1229,7 @@ LoginManagerPrompter.prototype = {
|
||||
}
|
||||
|
||||
let browser;
|
||||
if (useOpener && isE10s) {
|
||||
if (useOpener && this._opener && isE10s) {
|
||||
// In e10s, we have to reconstruct the opener browser from
|
||||
// the CPOW passed in the message (and then passed to us in
|
||||
// setE10sData).
|
||||
|
110
toolkit/components/passwordmgr/test/browser/authenticate.sjs
Normal file
110
toolkit/components/passwordmgr/test/browser/authenticate.sjs
Normal file
@ -0,0 +1,110 @@
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var match;
|
||||
var requestAuth = true;
|
||||
|
||||
// Allow the caller to drive how authentication is processed via the query.
|
||||
// Eg, http://localhost:8888/authenticate.sjs?user=foo&realm=bar
|
||||
// The extra ? allows the user/pass/realm checks to succeed if the name is
|
||||
// at the beginning of the query string.
|
||||
var query = "?" + request.queryString;
|
||||
|
||||
var expected_user = "test", expected_pass = "testpass", realm = "mochitest";
|
||||
|
||||
// Look for an authentication header, if any, in the request.
|
||||
//
|
||||
// EG: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
||||
//
|
||||
// This test only supports Basic auth. The value sent by the client is
|
||||
// "username:password", obscured with base64 encoding.
|
||||
|
||||
var actual_user = "", actual_pass = "", authHeader, authPresent = false;
|
||||
if (request.hasHeader("Authorization")) {
|
||||
authPresent = true;
|
||||
authHeader = request.getHeader("Authorization");
|
||||
match = /Basic (.+)/.exec(authHeader);
|
||||
if (match.length != 2)
|
||||
throw "Couldn't parse auth header: " + authHeader;
|
||||
|
||||
var userpass = base64ToString(match[1]); // no atob() :-(
|
||||
match = /(.*):(.*)/.exec(userpass);
|
||||
if (match.length != 3)
|
||||
throw "Couldn't decode auth header: " + userpass;
|
||||
actual_user = match[1];
|
||||
actual_pass = match[2];
|
||||
}
|
||||
|
||||
// Don't request authentication if the credentials we got were what we
|
||||
// expected.
|
||||
if (expected_user == actual_user &&
|
||||
expected_pass == actual_pass) {
|
||||
requestAuth = false;
|
||||
}
|
||||
|
||||
if (requestAuth) {
|
||||
response.setStatusLine("1.0", 401, "Authentication required");
|
||||
response.setHeader("WWW-Authenticate", "basic realm=\"" + realm + "\"", true);
|
||||
} else {
|
||||
response.setStatusLine("1.0", 200, "OK");
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "application/xhtml+xml", false);
|
||||
response.write("<html xmlns='http://www.w3.org/1999/xhtml'>");
|
||||
response.write("<p>Login: <span id='ok'>" + (requestAuth ? "FAIL" : "PASS") + "</span></p>\n");
|
||||
response.write("<p>Auth: <span id='auth'>" + authHeader + "</span></p>\n");
|
||||
response.write("<p>User: <span id='user'>" + actual_user + "</span></p>\n");
|
||||
response.write("<p>Pass: <span id='pass'>" + actual_pass + "</span></p>\n");
|
||||
response.write("</html>");
|
||||
}
|
||||
|
||||
|
||||
// base64 decoder
|
||||
//
|
||||
// Yoinked from extensions/xml-rpc/src/nsXmlRpcClient.js because btoa()
|
||||
// doesn't seem to exist. :-(
|
||||
/* Convert Base64 data to a string */
|
||||
const toBinaryTable = [
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||||
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||||
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
||||
];
|
||||
const base64Pad = '=';
|
||||
|
||||
function base64ToString(data) {
|
||||
|
||||
var result = '';
|
||||
var leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
var leftdata = 0; // bits decoded, but yet to be appended
|
||||
|
||||
// Convert one by one.
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
var padding = (data[i] == base64Pad);
|
||||
// Skip illegal characters and whitespace
|
||||
if (c == -1) continue;
|
||||
|
||||
// Collect data into leftdata, update bitcount
|
||||
leftdata = (leftdata << 6) | c;
|
||||
leftbits += 6;
|
||||
|
||||
// If we have 8 or more bits, append 8 bits to the result
|
||||
if (leftbits >= 8) {
|
||||
leftbits -= 8;
|
||||
// Append if not padding.
|
||||
if (!padding)
|
||||
result += String.fromCharCode((leftdata >> leftbits) & 0xff);
|
||||
leftdata &= (1 << leftbits) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any bits left, the base64 string was corrupted
|
||||
if (leftbits)
|
||||
throw Components.Exception('Corrupted base64 string');
|
||||
|
||||
return result;
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
authenticate.sjs
|
||||
|
||||
[browser_passwordmgr_fields.js]
|
||||
[browser_passwordmgr_observers.js]
|
||||
[browser_passwordmgr_sort.js]
|
||||
[browser_passwordmgr_switchtab.js]
|
||||
[browser_passwordmgrcopypwd.js]
|
||||
[browser_passwordmgrdlg.js]
|
||||
|
@ -0,0 +1,42 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const PROMPT_URL = "chrome://global/content/commonDialog.xul";
|
||||
const { interfaces: Ci } = Components;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab = gBrowser.addTab();
|
||||
isnot(tab, gBrowser.selectedTab, "New tab shouldn't be selected");
|
||||
|
||||
let listener = {
|
||||
onOpenWindow: function(window) {
|
||||
var domwindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
waitForFocus(() => {
|
||||
is(domwindow.document.location.href, PROMPT_URL, "Should have seen a prompt window");
|
||||
is(domwindow.args.promptType, "promptUserAndPass", "Should be an authenticate prompt");
|
||||
|
||||
is(gBrowser.selectedTab, tab, "Should have selected the new tab");
|
||||
|
||||
domwindow.document.documentElement.cancelDialog()
|
||||
}, domwindow);
|
||||
},
|
||||
|
||||
onCloseWindow: function() {
|
||||
}
|
||||
}
|
||||
|
||||
Services.wm.addListener(listener);
|
||||
registerCleanupFunction(() => {
|
||||
Services.wm.removeListener(listener);
|
||||
gBrowser.removeTab(tab);
|
||||
})
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", () => {
|
||||
finish();
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI("http://example.com/browser/toolkit/components/passwordmgr/test/browser/authenticate.sjs");
|
||||
}
|
Loading…
Reference in New Issue
Block a user