1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/passwordmgr/test/test_prompt_async.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,529 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html> 1.6 +<head> 1.7 + <title>Test for Async Auth Prompt</title> 1.8 + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> 1.9 + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.10 + <script type="text/javascript" src="prompt_common.js"></script> 1.11 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 1.12 + 1.13 + <script class="testbody" type="text/javascript"> 1.14 + SimpleTest.waitForExplicitFinish(); 1.15 + 1.16 + // Class monitoring number of open dialog windows 1.17 + // It checks there is always open just a single dialog per application 1.18 + function dialogMonitor() { 1.19 + var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"] 1.20 + .getService(Ci.nsIObserverService); 1.21 + observerService.addObserver(this, "domwindowopened", false); 1.22 + observerService.addObserver(this, "domwindowclosed", false); 1.23 + } 1.24 + 1.25 + /* 1.26 + * As documented in Bug 718543, checking equality of objects pulled 1.27 + * from SpecialPowers-wrapped objects is unreliable. Because of that, 1.28 + * `dialogMonitor` now tracks the number of open windows rather than 1.29 + * specific window objects. 1.30 + * 1.31 + * NB: Because the constructor (above) adds |this| directly as an observer, 1.32 + * we need to do SpecialPowers.wrapCallbackObject directly on the prototype. 1.33 + */ 1.34 + dialogMonitor.prototype = SpecialPowers.wrapCallbackObject({ 1.35 + windowsOpen : 0, 1.36 + windowsRegistered : 0, 1.37 + 1.38 + QueryInterface : function (iid) { 1.39 + const interfaces = [Ci.nsIObserver, Ci.nsISupports]; 1.40 + 1.41 + if (!interfaces.some( function(v) { return iid.equals(v) } )) 1.42 + throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE; 1.43 + return this; 1.44 + }, 1.45 + 1.46 + observe: function(subject, topic, data) { 1.47 + if (topic === "domwindowopened") { 1.48 + this.windowsOpen++; 1.49 + this.windowsRegistered++; 1.50 + return; 1.51 + } 1.52 + if (topic === "domwindowclosed") { 1.53 + this.windowsOpen--; 1.54 + return; 1.55 + } 1.56 + }, 1.57 + 1.58 + shutdown: function() { 1.59 + var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"] 1.60 + .getService(Ci.nsIObserverService); 1.61 + observerService.removeObserver(this, "domwindowopened"); 1.62 + observerService.removeObserver(this, "domwindowclosed"); 1.63 + }, 1.64 + 1.65 + reset: function() { 1.66 + this.windowsOpen = 0; 1.67 + this.windowsRegistered = 0; 1.68 + } 1.69 + }); 1.70 + 1.71 + var monitor = new dialogMonitor(); 1.72 + 1.73 + var pwmgr, logins = []; 1.74 + 1.75 + function initLogins(pi) { 1.76 + pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"] 1.77 + .getService(Ci.nsILoginManager); 1.78 + 1.79 + function addLogin(host, realm, user, pass) { 1.80 + var login = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"] 1.81 + .createInstance(Ci.nsILoginInfo); 1.82 + login.init(host, null, realm, user, pass, "", ""); 1.83 + pwmgr.addLogin(login); 1.84 + logins.push(login); 1.85 + } 1.86 + 1.87 + var mozproxy = "moz-proxy://" + 1.88 + SpecialPowers.wrap(pi).host + ":" + 1.89 + SpecialPowers.wrap(pi).port; 1.90 + 1.91 + addLogin(mozproxy, "proxy_realm", 1.92 + "proxy_user", "proxy_pass"); 1.93 + addLogin(mozproxy, "proxy_realm2", 1.94 + "proxy_user2", "proxy_pass2"); 1.95 + addLogin(mozproxy, "proxy_realm3", 1.96 + "proxy_user3", "proxy_pass3"); 1.97 + addLogin(mozproxy, "proxy_realm4", 1.98 + "proxy_user4", "proxy_pass4"); 1.99 + addLogin(mozproxy, "proxy_realm5", 1.100 + "proxy_user5", "proxy_pass5"); 1.101 + addLogin("http://example.com", "mochirealm", 1.102 + "user1name", "user1pass"); 1.103 + addLogin("http://example.org", "mochirealm2", 1.104 + "user2name", "user2pass"); 1.105 + addLogin("http://example.com", "mochirealm3", 1.106 + "user3name", "user3pass"); 1.107 + addLogin("http://example.com", "mochirealm4", 1.108 + "user4name", "user4pass"); 1.109 + addLogin("http://example.com", "mochirealm5", 1.110 + "user5name", "user5pass"); 1.111 + addLogin("http://example.com", "mochirealm6", 1.112 + "user6name", "user6pass"); 1.113 + } 1.114 + 1.115 + function finishTest() { 1.116 + ok(true, "finishTest removing testing logins..."); 1.117 + for (i in logins) 1.118 + pwmgr.removeLogin(logins[i]); 1.119 + 1.120 + var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1'] 1.121 + .getService(Ci.nsIHttpAuthManager); 1.122 + authMgr.clearAll(); 1.123 + 1.124 + monitor.shutdown(); 1.125 + SimpleTest.finish(); 1.126 + } 1.127 + 1.128 + var resolveCallback = SpecialPowers.wrapCallbackObject({ 1.129 + QueryInterface : function (iid) { 1.130 + const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports]; 1.131 + 1.132 + if (!interfaces.some( function(v) { return iid.equals(v) } )) 1.133 + throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE; 1.134 + return this; 1.135 + }, 1.136 + 1.137 + onProxyAvailable : function (req, uri, pi, status) { 1.138 + initLogins(pi); 1.139 + doTest(testNum); 1.140 + } 1.141 + }); 1.142 + 1.143 + function startup() { 1.144 + //need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy. 1.145 + var ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"] 1.146 + .getService(SpecialPowers.Ci.nsIIOService); 1.147 + 1.148 + var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"] 1.149 + .getService(); 1.150 + 1.151 + var uri = ios.newURI("http://example.com", null, null); 1.152 + pps.asyncResolve(uri, 0, resolveCallback); 1.153 + } 1.154 + 1.155 + // --------------- Test loop spin ---------------- 1.156 + var testNum = 1; 1.157 + var iframe1; 1.158 + var iframe2a; 1.159 + var iframe2b; 1.160 + window.onload = function () { 1.161 + iframe1 = document.getElementById("iframe1"); 1.162 + iframe2a = document.getElementById("iframe2a"); 1.163 + iframe2b = document.getElementById("iframe2b"); 1.164 + iframe1.onload = onFrameLoad; 1.165 + iframe2a.onload = onFrameLoad; 1.166 + iframe2b.onload = onFrameLoad; 1.167 + 1.168 + startup(); 1.169 + } 1.170 + 1.171 + var expectedLoads; 1.172 + var expectedDialogs; 1.173 + function onFrameLoad() 1.174 + { 1.175 + if (--expectedLoads == 0) { 1.176 + // All pages expected to load has loaded, continue with the next test 1.177 + ok(true, "Expected frames loaded"); 1.178 + 1.179 + doCheck(testNum); 1.180 + monitor.reset(); 1.181 + 1.182 + testNum++; 1.183 + doTest(testNum); 1.184 + } 1.185 + } 1.186 + 1.187 + function doTest(testNum) 1.188 + { 1.189 + /* 1.190 + * These contentDocument variables are located here, 1.191 + * rather than in the global scope, because SpecialPowers threw 1.192 + * errors (complaining that the objects were deleted) 1.193 + * when these were in the global scope. 1.194 + */ 1.195 + var iframe1Doc = SpecialPowers.wrap(iframe1).contentDocument; 1.196 + var iframe2aDoc = SpecialPowers.wrap(iframe2a).contentDocument; 1.197 + var iframe2bDoc = SpecialPowers.wrap(iframe2b).contentDocument; 1.198 + var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/"; 1.199 + var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/"; 1.200 + 1.201 + switch (testNum) 1.202 + { 1.203 + case 1: 1.204 + // Load through a single proxy with authentication required 3 different 1.205 + // pages, first with one login, other two with their own different login. 1.206 + // We expect to show just a single dialog for proxy authentication and 1.207 + // then two dialogs to authenticate to login 1 and then login 2. 1.208 + ok(true, "doTest testNum 1"); 1.209 + expectedLoads = 3; 1.210 + expectedDialogs = 3; 1.211 + iframe1.src = exampleCom + "authenticate.sjs?"+ 1.212 + "r=1&"+ 1.213 + "user=user1name&"+ 1.214 + "pass=user1pass&"+ 1.215 + "realm=mochirealm&"+ 1.216 + "proxy_user=proxy_user&"+ 1.217 + "proxy_pass=proxy_pass&"+ 1.218 + "proxy_realm=proxy_realm"; 1.219 + iframe2a.src = exampleOrg + "authenticate.sjs?"+ 1.220 + "r=2&"+ 1.221 + "user=user2name&"+ 1.222 + "pass=user2pass&"+ 1.223 + "realm=mochirealm2&"+ 1.224 + "proxy_user=proxy_user&"+ 1.225 + "proxy_pass=proxy_pass&"+ 1.226 + "proxy_realm=proxy_realm"; 1.227 + iframe2b.src = exampleOrg + "authenticate.sjs?"+ 1.228 + "r=3&"+ 1.229 + "user=user2name&"+ 1.230 + "pass=user2pass&"+ 1.231 + "realm=mochirealm2&"+ 1.232 + "proxy_user=proxy_user&"+ 1.233 + "proxy_pass=proxy_pass&"+ 1.234 + "proxy_realm=proxy_realm"; 1.235 + break; 1.236 + 1.237 + case 2: 1.238 + // Load an iframe with 3 subpages all requiring the same login through 1.239 + // anuthenticated proxy. We expect 2 dialogs, proxy authentication 1.240 + // and web authentication. 1.241 + ok(true, "doTest testNum 2"); 1.242 + expectedLoads = 3; 1.243 + expectedDialogs = 2; 1.244 + iframe1.src = exampleCom + "subtst_prompt_async.html"; 1.245 + iframe2a.src = "about:blank"; 1.246 + iframe2b.src = "about:blank"; 1.247 + break; 1.248 + 1.249 + case 3: 1.250 + // Load in the iframe page through unauthenticated proxy 1.251 + // and discard the proxy authentication. We expect to see 1.252 + // unauthenticated page content and just a single dialog. 1.253 + ok(true, "doTest testNum 3"); 1.254 + expectedLoads = 1; 1.255 + expectedDialogs = 1; 1.256 + iframe1.src = exampleCom + "authenticate.sjs?"+ 1.257 + "user=user4name&"+ 1.258 + "pass=user4pass&"+ 1.259 + "realm=mochirealm4&"+ 1.260 + "proxy_user=proxy_user3&"+ 1.261 + "proxy_pass=proxy_pass3&"+ 1.262 + "proxy_realm=proxy_realm3"; 1.263 + break; 1.264 + 1.265 + case 4: 1.266 + // Reload the frame from previous step and pass the proxy authentication 1.267 + // but cancel the WWW authentication. We should get the proxy=ok and WWW=fail 1.268 + // content as a result. 1.269 + ok(true, "doTest testNum 4"); 1.270 + expectedLoads = 1; 1.271 + expectedDialogs = 2; 1.272 + iframe1.src = exampleCom + "authenticate.sjs?"+ 1.273 + "user=user4name&"+ 1.274 + "pass=user4pass&"+ 1.275 + "realm=mochirealm4&"+ 1.276 + "proxy_user=proxy_user3&"+ 1.277 + "proxy_pass=proxy_pass3&"+ 1.278 + "proxy_realm=proxy_realm3"; 1.279 + 1.280 + 1.281 + break; 1.282 + 1.283 + case 5: 1.284 + // Same as the previous two steps but let the server generate 1.285 + // huge content load to check http channel is capable to handle 1.286 + // case when auth dialog is canceled or accepted before unauthenticated 1.287 + // content data is load from the server. (This would be better to 1.288 + // implement using delay of server response). 1.289 + ok(true, "doTest testNum 5"); 1.290 + expectedLoads = 1; 1.291 + expectedDialogs = 1; 1.292 + iframe1.src = exampleCom + "authenticate.sjs?"+ 1.293 + "user=user5name&"+ 1.294 + "pass=user5pass&"+ 1.295 + "realm=mochirealm5&"+ 1.296 + "proxy_user=proxy_user4&"+ 1.297 + "proxy_pass=proxy_pass4&"+ 1.298 + "proxy_realm=proxy_realm4&"+ 1.299 + "huge=1"; 1.300 + break; 1.301 + 1.302 + case 6: 1.303 + // Reload the frame from the previous step and let the proxy 1.304 + // authentication pass but WWW fail. We expect two dialogs 1.305 + // and an unathenticated page content load. 1.306 + ok(true, "doTest testNum 6"); 1.307 + expectedLoads = 1; 1.308 + expectedDialogs = 2; 1.309 + iframe1.src = exampleCom + "authenticate.sjs?"+ 1.310 + "user=user5name&"+ 1.311 + "pass=user5pass&"+ 1.312 + "realm=mochirealm5&"+ 1.313 + "proxy_user=proxy_user4&"+ 1.314 + "proxy_pass=proxy_pass4&"+ 1.315 + "proxy_realm=proxy_realm4&"+ 1.316 + "huge=1"; 1.317 + break; 1.318 + 1.319 + case 7: 1.320 + // Reload again and let pass all authentication dialogs. 1.321 + // Check we get the authenticated content not broken by 1.322 + // the unauthenticated content. 1.323 + ok(true, "doTest testNum 7"); 1.324 + expectedLoads = 1; 1.325 + expectedDialogs = 1; 1.326 + iframe1Doc.location.reload(); 1.327 + break; 1.328 + 1.329 + case 8: 1.330 + // Check we proccess all challenges sent by server when 1.331 + // user cancels prompts 1.332 + ok(true, "doTest testNum 8"); 1.333 + expectedLoads = 1; 1.334 + expectedDialogs = 5; 1.335 + iframe1.src = exampleCom + "authenticate.sjs?"+ 1.336 + "user=user6name&"+ 1.337 + "pass=user6pass&"+ 1.338 + "realm=mochirealm6&"+ 1.339 + "proxy_user=proxy_user5&"+ 1.340 + "proxy_pass=proxy_pass5&"+ 1.341 + "proxy_realm=proxy_realm5&"+ 1.342 + "huge=1&"+ 1.343 + "multiple=3"; 1.344 + break; 1.345 + 1.346 + case 9: 1.347 + finishTest(); 1.348 + return; 1.349 + } 1.350 + 1.351 + startCallbackTimer(); 1.352 + } 1.353 + 1.354 + function handleDialog(doc, testNum) 1.355 + { 1.356 + var dialog = doc.getElementById("commonDialog"); 1.357 + 1.358 + switch (testNum) 1.359 + { 1.360 + case 1: 1.361 + case 2: 1.362 + dialog.acceptDialog(); 1.363 + break; 1.364 + 1.365 + case 3: 1.366 + dialog.cancelDialog(); 1.367 + setTimeout(onFrameLoad, 10); // there are no successful frames for test 3 1.368 + break; 1.369 + 1.370 + case 4: 1.371 + if (expectedDialogs == 2) 1.372 + dialog.acceptDialog(); 1.373 + else 1.374 + dialog.cancelDialog(); 1.375 + break; 1.376 + 1.377 + case 5: 1.378 + dialog.cancelDialog(); 1.379 + setTimeout(onFrameLoad, 10); // there are no successful frames for test 5 1.380 + break; 1.381 + 1.382 + case 6: 1.383 + if (expectedDialogs == 2) 1.384 + dialog.acceptDialog(); 1.385 + else 1.386 + dialog.cancelDialog(); 1.387 + break; 1.388 + 1.389 + case 7: 1.390 + dialog.acceptDialog(); 1.391 + break; 1.392 + 1.393 + case 8: 1.394 + if (expectedDialogs == 3 || expectedDialogs == 1) 1.395 + dialog.acceptDialog(); 1.396 + else 1.397 + dialog.cancelDialog(); 1.398 + break; 1.399 + 1.400 + default: 1.401 + ok(false, "Unhandled testNum "+testNum+" in handleDialog"); 1.402 + } 1.403 + 1.404 + if (--expectedDialogs > 0) 1.405 + startCallbackTimer(); 1.406 + } 1.407 + 1.408 + function doCheck(testNum) 1.409 + { 1.410 + var iframe1Doc = SpecialPowers.wrap(iframe1).contentDocument; 1.411 + var iframe2aDoc = SpecialPowers.wrap(iframe2a).contentDocument; 1.412 + var iframe2bDoc = SpecialPowers.wrap(iframe2b).contentDocument; 1.413 + switch (testNum) 1.414 + { 1.415 + case 1: 1.416 + ok(true, "doCheck testNum 1"); 1.417 + is(monitor.windowsRegistered, 3, "Registered 3 open dialogs"); 1.418 + 1.419 + var authok1 = iframe1Doc.getElementById("ok").textContent; 1.420 + var proxyok1 = iframe1Doc.getElementById("proxy").textContent; 1.421 + 1.422 + var authok2a = iframe2aDoc.getElementById("ok").textContent; 1.423 + var proxyok2a = iframe2aDoc.getElementById("proxy").textContent; 1.424 + 1.425 + var authok2b = iframe2bDoc.getElementById("ok").textContent; 1.426 + var proxyok2b = iframe2bDoc.getElementById("proxy").textContent; 1.427 + 1.428 + is(authok1, "PASS", "WWW Authorization OK, frame1"); 1.429 + is(authok2a, "PASS", "WWW Authorization OK, frame2a"); 1.430 + is(authok2b, "PASS", "WWW Authorization OK, frame2b"); 1.431 + is(proxyok1, "PASS", "Proxy Authorization OK, frame1"); 1.432 + is(proxyok2a, "PASS", "Proxy Authorization OK, frame2a"); 1.433 + is(proxyok2b, "PASS", "Proxy Authorization OK, frame2b"); 1.434 + break; 1.435 + 1.436 + case 2: 1.437 + is(monitor.windowsRegistered, 2, "Registered 2 open dialogs"); 1.438 + ok(true, "doCheck testNum 2"); 1.439 + 1.440 + function checkIframe(frame) { 1.441 + var doc = SpecialPowers.wrap(frame).contentDocument; 1.442 + 1.443 + var authok = doc.getElementById("ok").textContent; 1.444 + var proxyok = doc.getElementById("proxy").textContent; 1.445 + 1.446 + is(authok, "PASS", "WWW Authorization OK, " + frame.id); 1.447 + is(proxyok, "PASS", "Proxy Authorization OK, " + frame.id); 1.448 + } 1.449 + 1.450 + checkIframe(iframe1Doc.getElementById("iframe1")); 1.451 + checkIframe(iframe1Doc.getElementById("iframe2")); 1.452 + checkIframe(iframe1Doc.getElementById("iframe3")); 1.453 + break; 1.454 + 1.455 + case 3: 1.456 + ok(true, "doCheck testNum 3"); 1.457 + is(monitor.windowsRegistered, 1, "Registered 1 open dialog"); 1.458 + 1.459 + // ensure that the page content is not displayed on failed proxy auth 1.460 + is(iframe1Doc.getElementById("ok"), undefined, "frame did not load"); 1.461 + break; 1.462 + 1.463 + case 4: 1.464 + ok(true, "doCheck testNum 4"); 1.465 + is(monitor.windowsRegistered, 2, "Registered 2 open dialogs"); 1.466 + var authok1 = iframe1Doc.getElementById("ok").textContent; 1.467 + var proxyok1 = iframe1Doc.getElementById("proxy").textContent; 1.468 + 1.469 + is(authok1, "FAIL", "WWW Authorization FAILED, frame1"); 1.470 + is(proxyok1, "PASS", "Proxy Authorization OK, frame1"); 1.471 + break; 1.472 + 1.473 + case 5: 1.474 + ok(true, "doCheck testNum 5"); 1.475 + is(monitor.windowsRegistered, 1, "Registered 1 open dialog"); 1.476 + 1.477 + // ensure that the page content is not displayed on failed proxy auth 1.478 + is(iframe1Doc.getElementById("footnote"), undefined, "frame did not load"); 1.479 + break; 1.480 + 1.481 + case 6: 1.482 + ok(true, "doCheck testNum 6"); 1.483 + is(monitor.windowsRegistered, 2, "Registered 2 open dialogs"); 1.484 + var authok1 = iframe1Doc.getElementById("ok").textContent; 1.485 + var proxyok1 = iframe1Doc.getElementById("proxy").textContent; 1.486 + var footnote = iframe1Doc.getElementById("footnote").textContent; 1.487 + 1.488 + is(authok1, "FAIL", "WWW Authorization FAILED, frame1"); 1.489 + is(proxyok1, "PASS", "Proxy Authorization OK, frame1"); 1.490 + is(footnote, "This is a footnote after the huge content fill", 1.491 + "Footnote present and loaded completely"); 1.492 + break; 1.493 + 1.494 + case 7: 1.495 + ok(true, "doCheck testNum 7"); 1.496 + is(monitor.windowsRegistered, 1, "Registered 1 open dialogs"); 1.497 + var authok1 = iframe1Doc.getElementById("ok").textContent; 1.498 + var proxyok1 = iframe1Doc.getElementById("proxy").textContent; 1.499 + var footnote = iframe1Doc.getElementById("footnote").textContent; 1.500 + 1.501 + is(authok1, "PASS", "WWW Authorization OK, frame1"); 1.502 + is(proxyok1, "PASS", "Proxy Authorization OK, frame1"); 1.503 + is(footnote, "This is a footnote after the huge content fill", 1.504 + "Footnote present and loaded completely"); 1.505 + break; 1.506 + 1.507 + case 8: 1.508 + ok(true, "doCheck testNum 8"); 1.509 + is(monitor.windowsRegistered, 5, "Registered 5 open dialogs"); 1.510 + var authok1 = iframe1Doc.getElementById("ok").textContent; 1.511 + var proxyok1 = iframe1Doc.getElementById("proxy").textContent; 1.512 + var footnote = iframe1Doc.getElementById("footnote").textContent; 1.513 + 1.514 + is(authok1, "PASS", "WWW Authorization OK, frame1"); 1.515 + is(proxyok1, "PASS", "Proxy Authorization OK, frame1"); 1.516 + is(footnote, "This is a footnote after the huge content fill", 1.517 + "Footnote present and loaded completely"); 1.518 + break; 1.519 + 1.520 + default: 1.521 + ok(false, "Unhandled testNum "+testNum+" in doCheck"); 1.522 + } 1.523 + } 1.524 + 1.525 + </script> 1.526 +</head> 1.527 +<body> 1.528 + <iframe id="iframe1"></iframe> 1.529 + <iframe id="iframe2a"></iframe> 1.530 + <iframe id="iframe2b"></iframe> 1.531 +</body> 1.532 +</html>