summaryrefslogtreecommitdiff
path: root/toolkit/components/passwordmgr/test/test_prompt_async.html
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/passwordmgr/test/test_prompt_async.html')
-rw-r--r--toolkit/components/passwordmgr/test/test_prompt_async.html540
1 files changed, 540 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/test/test_prompt_async.html b/toolkit/components/passwordmgr/test/test_prompt_async.html
new file mode 100644
index 0000000000..38b34679aa
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_prompt_async.html
@@ -0,0 +1,540 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Async Auth Prompt</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="prompt_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <script class="testbody" type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+
+ const { NetUtil } = SpecialPowers.Cu.import('resource://gre/modules/NetUtil.jsm');
+
+ var prefs = Cc["@mozilla.org/preferences-service;1"].
+ getService(Ci.nsIPrefBranch);
+ prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
+ // Class monitoring number of open dialog windows
+ // It checks there is always open just a single dialog per application
+ function dialogMonitor() {
+ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ observerService.addObserver(this, "domwindowopened", false);
+ observerService.addObserver(this, "domwindowclosed", false);
+ }
+
+ /*
+ * As documented in Bug 718543, checking equality of objects pulled
+ * from SpecialPowers-wrapped objects is unreliable. Because of that,
+ * `dialogMonitor` now tracks the number of open windows rather than
+ * specific window objects.
+ *
+ * NB: Because the constructor (above) adds |this| directly as an observer,
+ * we need to do SpecialPowers.wrapCallbackObject directly on the prototype.
+ */
+ dialogMonitor.prototype = SpecialPowers.wrapCallbackObject({
+ windowsOpen : 0,
+ windowsRegistered : 0,
+
+ QueryInterface : function (iid) {
+ const interfaces = [Ci.nsIObserver, Ci.nsISupports];
+
+ if (!interfaces.some( function(v) { return iid.equals(v); } ))
+ throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
+ return this;
+ },
+
+ observe: function(subject, topic, data) {
+ if (topic === "domwindowopened") {
+ this.windowsOpen++;
+ this.windowsRegistered++;
+ return;
+ }
+ if (topic === "domwindowclosed") {
+ this.windowsOpen--;
+ return;
+ }
+ },
+
+ shutdown: function() {
+ var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ observerService.removeObserver(this, "domwindowopened");
+ observerService.removeObserver(this, "domwindowclosed");
+ },
+
+ reset: function() {
+ this.windowsOpen = 0;
+ this.windowsRegistered = 0;
+ }
+ });
+
+ var monitor = new dialogMonitor();
+
+ var pwmgr, logins = [];
+
+ function initLogins(pi) {
+ pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
+ .getService(Ci.nsILoginManager);
+
+ function addLogin(host, realm, user, pass) {
+ var login = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"]
+ .createInstance(Ci.nsILoginInfo);
+ login.init(host, null, realm, user, pass, "", "");
+ pwmgr.addLogin(login);
+ logins.push(login);
+ }
+
+ var mozproxy = "moz-proxy://" +
+ SpecialPowers.wrap(pi).host + ":" +
+ SpecialPowers.wrap(pi).port;
+
+ addLogin(mozproxy, "proxy_realm",
+ "proxy_user", "proxy_pass");
+ addLogin(mozproxy, "proxy_realm2",
+ "proxy_user2", "proxy_pass2");
+ addLogin(mozproxy, "proxy_realm3",
+ "proxy_user3", "proxy_pass3");
+ addLogin(mozproxy, "proxy_realm4",
+ "proxy_user4", "proxy_pass4");
+ addLogin(mozproxy, "proxy_realm5",
+ "proxy_user5", "proxy_pass5");
+ addLogin("http://example.com", "mochirealm",
+ "user1name", "user1pass");
+ addLogin("http://example.org", "mochirealm2",
+ "user2name", "user2pass");
+ addLogin("http://example.com", "mochirealm3",
+ "user3name", "user3pass");
+ addLogin("http://example.com", "mochirealm4",
+ "user4name", "user4pass");
+ addLogin("http://example.com", "mochirealm5",
+ "user5name", "user5pass");
+ addLogin("http://example.com", "mochirealm6",
+ "user6name", "user6pass");
+ }
+
+ function finishTest() {
+ ok(true, "finishTest removing testing logins...");
+ for (i in logins)
+ pwmgr.removeLogin(logins[i]);
+
+ var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1']
+ .getService(Ci.nsIHttpAuthManager);
+ authMgr.clearAll();
+
+ monitor.shutdown();
+ SimpleTest.finish();
+ }
+
+ var resolveCallback = SpecialPowers.wrapCallbackObject({
+ QueryInterface : function (iid) {
+ const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
+
+ if (!interfaces.some( function(v) { return iid.equals(v); } ))
+ throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
+ return this;
+ },
+
+ onProxyAvailable : function (req, uri, pi, status) {
+ initLogins(pi);
+ doTest(testNum);
+ }
+ });
+
+ function startup() {
+ // Need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
+ var channel = NetUtil.newChannel({
+ uri: "http://example.com",
+ loadUsingSystemPrincipal: true
+ });
+
+ var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"]
+ .getService();
+
+ pps.asyncResolve(channel, 0, resolveCallback);
+ }
+
+ // --------------- Test loop spin ----------------
+ var testNum = 1;
+ var iframe1;
+ var iframe2a;
+ var iframe2b;
+ window.onload = function () {
+ iframe1 = document.getElementById("iframe1");
+ iframe2a = document.getElementById("iframe2a");
+ iframe2b = document.getElementById("iframe2b");
+ iframe1.onload = onFrameLoad;
+ iframe2a.onload = onFrameLoad;
+ iframe2b.onload = onFrameLoad;
+
+ startup();
+ };
+
+ var expectedLoads;
+ var expectedDialogs;
+ function onFrameLoad()
+ {
+ if (--expectedLoads == 0) {
+ // All pages expected to load has loaded, continue with the next test
+ ok(true, "Expected frames loaded");
+
+ doCheck(testNum);
+ monitor.reset();
+
+ testNum++;
+ doTest(testNum);
+ }
+ }
+
+ function doTest(testNumber)
+ {
+ /*
+ * These contentDocument variables are located here,
+ * rather than in the global scope, because SpecialPowers threw
+ * errors (complaining that the objects were deleted)
+ * when these were in the global scope.
+ */
+ var iframe1Doc = SpecialPowers.wrap(iframe1).contentDocument;
+ var iframe2aDoc = SpecialPowers.wrap(iframe2a).contentDocument;
+ var iframe2bDoc = SpecialPowers.wrap(iframe2b).contentDocument;
+ var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/";
+ var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/";
+
+ switch (testNumber)
+ {
+ case 1:
+ // Load through a single proxy with authentication required 3 different
+ // pages, first with one login, other two with their own different login.
+ // We expect to show just a single dialog for proxy authentication and
+ // then two dialogs to authenticate to login 1 and then login 2.
+ ok(true, "doTest testNum 1");
+ expectedLoads = 3;
+ expectedDialogs = 3;
+ iframe1.src = exampleCom + "authenticate.sjs?" +
+ "r=1&" +
+ "user=user1name&" +
+ "pass=user1pass&" +
+ "realm=mochirealm&" +
+ "proxy_user=proxy_user&" +
+ "proxy_pass=proxy_pass&" +
+ "proxy_realm=proxy_realm";
+ iframe2a.src = exampleOrg + "authenticate.sjs?" +
+ "r=2&" +
+ "user=user2name&" +
+ "pass=user2pass&" +
+ "realm=mochirealm2&" +
+ "proxy_user=proxy_user&" +
+ "proxy_pass=proxy_pass&" +
+ "proxy_realm=proxy_realm";
+ iframe2b.src = exampleOrg + "authenticate.sjs?" +
+ "r=3&" +
+ "user=user2name&" +
+ "pass=user2pass&" +
+ "realm=mochirealm2&" +
+ "proxy_user=proxy_user&" +
+ "proxy_pass=proxy_pass&" +
+ "proxy_realm=proxy_realm";
+ break;
+
+ case 2:
+ // Load an iframe with 3 subpages all requiring the same login through
+ // anuthenticated proxy. We expect 2 dialogs, proxy authentication
+ // and web authentication.
+ ok(true, "doTest testNum 2");
+ expectedLoads = 3;
+ expectedDialogs = 2;
+ iframe1.src = exampleCom + "subtst_prompt_async.html";
+ iframe2a.src = "about:blank";
+ iframe2b.src = "about:blank";
+ break;
+
+ case 3:
+ // Load in the iframe page through unauthenticated proxy
+ // and discard the proxy authentication. We expect to see
+ // unauthenticated page content and just a single dialog.
+ ok(true, "doTest testNum 3");
+ expectedLoads = 1;
+ expectedDialogs = 1;
+ iframe1.src = exampleCom + "authenticate.sjs?" +
+ "user=user4name&" +
+ "pass=user4pass&" +
+ "realm=mochirealm4&" +
+ "proxy_user=proxy_user3&" +
+ "proxy_pass=proxy_pass3&" +
+ "proxy_realm=proxy_realm3";
+ break;
+
+ case 4:
+ // Reload the frame from previous step and pass the proxy authentication
+ // but cancel the WWW authentication. We should get the proxy=ok and WWW=fail
+ // content as a result.
+ ok(true, "doTest testNum 4");
+ expectedLoads = 1;
+ expectedDialogs = 2;
+ iframe1.src = exampleCom + "authenticate.sjs?" +
+ "user=user4name&" +
+ "pass=user4pass&" +
+ "realm=mochirealm4&" +
+ "proxy_user=proxy_user3&" +
+ "proxy_pass=proxy_pass3&" +
+ "proxy_realm=proxy_realm3";
+
+
+ break;
+
+ case 5:
+ // Same as the previous two steps but let the server generate
+ // huge content load to check http channel is capable to handle
+ // case when auth dialog is canceled or accepted before unauthenticated
+ // content data is load from the server. (This would be better to
+ // implement using delay of server response).
+ ok(true, "doTest testNum 5");
+ expectedLoads = 1;
+ expectedDialogs = 1;
+ iframe1.src = exampleCom + "authenticate.sjs?" +
+ "user=user5name&" +
+ "pass=user5pass&" +
+ "realm=mochirealm5&" +
+ "proxy_user=proxy_user4&" +
+ "proxy_pass=proxy_pass4&" +
+ "proxy_realm=proxy_realm4&" +
+ "huge=1";
+ break;
+
+ case 6:
+ // Reload the frame from the previous step and let the proxy
+ // authentication pass but WWW fail. We expect two dialogs
+ // and an unathenticated page content load.
+ ok(true, "doTest testNum 6");
+ expectedLoads = 1;
+ expectedDialogs = 2;
+ iframe1.src = exampleCom + "authenticate.sjs?" +
+ "user=user5name&" +
+ "pass=user5pass&" +
+ "realm=mochirealm5&" +
+ "proxy_user=proxy_user4&" +
+ "proxy_pass=proxy_pass4&" +
+ "proxy_realm=proxy_realm4&" +
+ "huge=1";
+ break;
+
+ case 7:
+ // Reload again and let pass all authentication dialogs.
+ // Check we get the authenticated content not broken by
+ // the unauthenticated content.
+ ok(true, "doTest testNum 7");
+ expectedLoads = 1;
+ expectedDialogs = 1;
+ iframe1Doc.location.reload();
+ break;
+
+ case 8:
+ // Check we proccess all challenges sent by server when
+ // user cancels prompts
+ ok(true, "doTest testNum 8");
+ expectedLoads = 1;
+ expectedDialogs = 5;
+ iframe1.src = exampleCom + "authenticate.sjs?" +
+ "user=user6name&" +
+ "pass=user6pass&" +
+ "realm=mochirealm6&" +
+ "proxy_user=proxy_user5&" +
+ "proxy_pass=proxy_pass5&" +
+ "proxy_realm=proxy_realm5&" +
+ "huge=1&" +
+ "multiple=3";
+ break;
+
+ case 9:
+ finishTest();
+ return;
+ }
+
+ startCallbackTimer();
+ }
+
+ function handleDialog(doc, testNumber)
+ {
+ var dialog = doc.getElementById("commonDialog");
+
+ switch (testNumber)
+ {
+ case 1:
+ case 2:
+ dialog.acceptDialog();
+ break;
+
+ case 3:
+ dialog.cancelDialog();
+ setTimeout(onFrameLoad, 10); // there are no successful frames for test 3
+ break;
+
+ case 4:
+ if (expectedDialogs == 2)
+ dialog.acceptDialog();
+ else
+ dialog.cancelDialog();
+ break;
+
+ case 5:
+ dialog.cancelDialog();
+ setTimeout(onFrameLoad, 10); // there are no successful frames for test 5
+ break;
+
+ case 6:
+ if (expectedDialogs == 2)
+ dialog.acceptDialog();
+ else
+ dialog.cancelDialog();
+ break;
+
+ case 7:
+ dialog.acceptDialog();
+ break;
+
+ case 8:
+ if (expectedDialogs == 3 || expectedDialogs == 1)
+ dialog.acceptDialog();
+ else
+ dialog.cancelDialog();
+ break;
+
+ default:
+ ok(false, "Unhandled testNum " + testNumber + " in handleDialog");
+ }
+
+ if (--expectedDialogs > 0)
+ startCallbackTimer();
+ }
+
+ function doCheck(testNumber)
+ {
+ var iframe1Doc = SpecialPowers.wrap(iframe1).contentDocument;
+ var iframe2aDoc = SpecialPowers.wrap(iframe2a).contentDocument;
+ var iframe2bDoc = SpecialPowers.wrap(iframe2b).contentDocument;
+ var authok1;
+ var proxyok1;
+ var footnote;
+ switch (testNumber)
+ {
+ case 1:
+ ok(true, "doCheck testNum 1");
+ is(monitor.windowsRegistered, 3, "Registered 3 open dialogs");
+
+ authok1 = iframe1Doc.getElementById("ok").textContent;
+ proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+
+ var authok2a = iframe2aDoc.getElementById("ok").textContent;
+ var proxyok2a = iframe2aDoc.getElementById("proxy").textContent;
+
+ var authok2b = iframe2bDoc.getElementById("ok").textContent;
+ var proxyok2b = iframe2bDoc.getElementById("proxy").textContent;
+
+ is(authok1, "PASS", "WWW Authorization OK, frame1");
+ is(authok2a, "PASS", "WWW Authorization OK, frame2a");
+ is(authok2b, "PASS", "WWW Authorization OK, frame2b");
+ is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+ is(proxyok2a, "PASS", "Proxy Authorization OK, frame2a");
+ is(proxyok2b, "PASS", "Proxy Authorization OK, frame2b");
+ break;
+
+ case 2:
+ is(monitor.windowsRegistered, 2, "Registered 2 open dialogs");
+ ok(true, "doCheck testNum 2");
+
+ function checkIframe(frame) {
+ var doc = SpecialPowers.wrap(frame).contentDocument;
+
+ var authok = doc.getElementById("ok").textContent;
+ var proxyok = doc.getElementById("proxy").textContent;
+
+ is(authok, "PASS", "WWW Authorization OK, " + frame.id);
+ is(proxyok, "PASS", "Proxy Authorization OK, " + frame.id);
+ }
+
+ checkIframe(iframe1Doc.getElementById("iframe1"));
+ checkIframe(iframe1Doc.getElementById("iframe2"));
+ checkIframe(iframe1Doc.getElementById("iframe3"));
+ break;
+
+ case 3:
+ ok(true, "doCheck testNum 3");
+ is(monitor.windowsRegistered, 1, "Registered 1 open dialog");
+
+ // ensure that the page content is not displayed on failed proxy auth
+ is(iframe1Doc.getElementById("ok"), null, "frame did not load");
+ break;
+
+ case 4:
+ ok(true, "doCheck testNum 4");
+ is(monitor.windowsRegistered, 2, "Registered 2 open dialogs");
+ authok1 = iframe1Doc.getElementById("ok").textContent;
+ proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+
+ is(authok1, "FAIL", "WWW Authorization FAILED, frame1");
+ is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+ break;
+
+ case 5:
+ ok(true, "doCheck testNum 5");
+ is(monitor.windowsRegistered, 1, "Registered 1 open dialog");
+
+ // ensure that the page content is not displayed on failed proxy auth
+ is(iframe1Doc.getElementById("footnote"), null, "frame did not load");
+ break;
+
+ case 6:
+ ok(true, "doCheck testNum 6");
+ is(monitor.windowsRegistered, 2, "Registered 2 open dialogs");
+ authok1 = iframe1Doc.getElementById("ok").textContent;
+ proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+ footnote = iframe1Doc.getElementById("footnote").textContent;
+
+ is(authok1, "FAIL", "WWW Authorization FAILED, frame1");
+ is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+ is(footnote, "This is a footnote after the huge content fill",
+ "Footnote present and loaded completely");
+ break;
+
+ case 7:
+ ok(true, "doCheck testNum 7");
+ is(monitor.windowsRegistered, 1, "Registered 1 open dialogs");
+ authok1 = iframe1Doc.getElementById("ok").textContent;
+ proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+ footnote = iframe1Doc.getElementById("footnote").textContent;
+
+ is(authok1, "PASS", "WWW Authorization OK, frame1");
+ is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+ is(footnote, "This is a footnote after the huge content fill",
+ "Footnote present and loaded completely");
+ break;
+
+ case 8:
+ ok(true, "doCheck testNum 8");
+ is(monitor.windowsRegistered, 5, "Registered 5 open dialogs");
+ authok1 = iframe1Doc.getElementById("ok").textContent;
+ proxyok1 = iframe1Doc.getElementById("proxy").textContent;
+ footnote = iframe1Doc.getElementById("footnote").textContent;
+
+ is(authok1, "PASS", "WWW Authorization OK, frame1");
+ is(proxyok1, "PASS", "Proxy Authorization OK, frame1");
+ is(footnote, "This is a footnote after the huge content fill",
+ "Footnote present and loaded completely");
+ break;
+
+ default:
+ ok(false, "Unhandled testNum " + testNumber + " in doCheck");
+ }
+ }
+
+ </script>
+</head>
+<body>
+ <iframe id="iframe1"></iframe>
+ <iframe id="iframe2a"></iframe>
+ <iframe id="iframe2b"></iframe>
+</body>
+</html>