summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/browser/browser_proxyAuth_prompt.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/passwordmgr/test/browser/browser_proxyAuth_prompt.js')
-rw-r--r--toolkit/components/passwordmgr/test/browser/browser_proxyAuth_prompt.js182
1 files changed, 182 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/test/browser/browser_proxyAuth_prompt.js b/toolkit/components/passwordmgr/test/browser/browser_proxyAuth_prompt.js
new file mode 100644
index 0000000000..478f204581
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/browser/browser_proxyAuth_prompt.js
@@ -0,0 +1,182 @@
+/* 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/. */
+
+"use strict";
+
+let proxyChannel;
+
+function initProxy() {
+ return new Promise(resolve => {
+ let proxyChannel;
+
+ let proxyCallback = {
+ QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyCallback"]),
+
+ onProxyAvailable(req, uri, pi, status) {
+ class ProxyChannelListener {
+ onStartRequest(request) {
+ resolve(proxyChannel);
+ }
+ onStopRequest(request, status) {}
+ }
+ // I'm cheating a bit here... We should probably do some magic foo to get
+ // something implementing nsIProxiedProtocolHandler and then call
+ // NewProxiedChannel(), so we have something that's definately a proxied
+ // channel. But Mochitests use a proxy for a number of hosts, so just
+ // requesting a normal channel will give us a channel that's proxied.
+ // The proxyChannel needs to move to at least on-modify-request to
+ // have valid ProxyInfo, but we use OnStartRequest during startup()
+ // for simplicity.
+ proxyChannel = Services.io.newChannel(
+ "http://mochi.test:8888",
+ null,
+ null,
+ null, // aLoadingNode
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ null, // aTriggeringPrincipal
+ Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
+ Ci.nsIContentPolicy.TYPE_OTHER
+ );
+ proxyChannel.asyncOpen(new ProxyChannelListener());
+ },
+ };
+
+ // Need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
+ let pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
+
+ let channel = Services.io.newChannel(
+ "https://example.com",
+ null,
+ null,
+ null, // aLoadingNode
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ null, // aTriggeringPrincipal
+ Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
+ Ci.nsIContentPolicy.TYPE_OTHER
+ );
+ pps.asyncResolve(channel, 0, proxyCallback);
+ });
+}
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ // This test relies on tab auth prompts.
+ set: [["prompts.modalType.httpAuth", Services.prompt.MODAL_TYPE_TAB]],
+ });
+ proxyChannel = await initProxy();
+});
+
+/**
+ * Create an object for consuming an nsIAuthPromptCallback.
+ * @returns result
+ * @returns {nsIAuthPromptCallback} result.callback - Callback to be passed into
+ * asyncPromptAuth.
+ * @returns {Promise} result.promise - Promise which resolves with authInfo once
+ * the callback has been called.
+ */
+function getAuthPromptCallback() {
+ let callbackResolver;
+ let promise = new Promise(resolve => {
+ callbackResolver = resolve;
+ });
+ let callback = {
+ onAuthAvailable(context, authInfo) {
+ callbackResolver(authInfo);
+ },
+ };
+ return { callback, promise };
+}
+
+/**
+ * Tests that if a window proxy auth prompt is open, subsequent auth calls with
+ * matching realm will be merged into the existing prompt. This should work even
+ * if the follwing auth call has browser parent.
+ */
+add_task(async function testProxyAuthPromptMerge() {
+ let tabA = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "https://example.com"
+ );
+ let tabB = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "https://example.org"
+ );
+
+ const promptFac = Cc[
+ "@mozilla.org/passwordmanager/authpromptfactory;1"
+ ].getService(Ci.nsIPromptFactory);
+ let prompter = promptFac.getPrompt(window, Ci.nsIAuthPrompt2);
+
+ let level = Ci.nsIAuthPrompt2.LEVEL_NONE;
+ let proxyAuthinfo = {
+ username: "",
+ password: "",
+ domain: "",
+ flags: Ci.nsIAuthInformation.AUTH_PROXY,
+ authenticationScheme: "basic",
+ realm: "",
+ };
+
+ // The next prompt call will result in window prompt, because the prompt does
+ // not have a browser set yet. The browser is used as a parent for tab
+ // prompts.
+ let promptOpened = PromptTestUtils.waitForPrompt(null, {
+ modalType: Services.prompt.MODAL_TYPE_WINDOW,
+ });
+ let cbWinPrompt = getAuthPromptCallback();
+ info("asyncPromptAuth no parent");
+ prompter.asyncPromptAuth(
+ proxyChannel,
+ cbWinPrompt.callback,
+ null,
+ level,
+ proxyAuthinfo
+ );
+ let prompt = await promptOpened;
+
+ // Set a browser so the next prompt would open as tab prompt.
+ prompter.QueryInterface(Ci.nsILoginManagerAuthPrompter).browser =
+ tabA.linkedBrowser;
+
+ // Since we already have an open window prompts, subsequent calls with
+ // matching realm should be merged into this prompt and no additional prompts
+ // must be spawned.
+ let cbNoPrompt = getAuthPromptCallback();
+ info("asyncPromptAuth tabA parent");
+ prompter.asyncPromptAuth(
+ proxyChannel,
+ cbNoPrompt.callback,
+ null,
+ level,
+ proxyAuthinfo
+ );
+
+ // Switch to the next tabs browser.
+ prompter.QueryInterface(Ci.nsILoginManagerAuthPrompter).browser =
+ tabB.linkedBrowser;
+
+ let cbNoPrompt2 = getAuthPromptCallback();
+ info("asyncPromptAuth tabB parent");
+ prompter.asyncPromptAuth(
+ proxyChannel,
+ cbNoPrompt2.callback,
+ null,
+ level,
+ proxyAuthinfo
+ );
+
+ // Accept the prompt.
+ PromptTestUtils.handlePrompt(prompt, {});
+
+ // Accepting the window prompts should complete all auth requests.
+ let authInfo1 = await cbWinPrompt.promise;
+ Assert.ok(authInfo1, "Received callback from first proxy auth call.");
+ let authInfo2 = await cbNoPrompt.promise;
+ Assert.ok(authInfo2, "Received callback from second proxy auth call.");
+ let authInfo3 = await cbNoPrompt2.promise;
+ Assert.ok(authInfo3, "Received callback from third proxy auth call.");
+
+ BrowserTestUtils.removeTab(tabA);
+ BrowserTestUtils.removeTab(tabB);
+});