1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/metrics/field_trial.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/prerender/prerender_manager.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_commands.h"
15 #include "chrome/browser/ui/login/login_prompt.h"
16 #include "chrome/browser/ui/login/login_prompt_test_utils.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/interstitial_page.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_source.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "content/public/test/test_navigation_observer.h"
26 #include "net/base/auth.h"
27 #include "net/dns/mock_host_resolver.h"
28 #include "net/test/spawned_test_server/spawned_test_server.h"
30 using content::NavigationController;
31 using content::OpenURLParams;
32 using content::Referrer;
36 class LoginPromptBrowserTest : public InProcessBrowserTest {
38 LoginPromptBrowserTest()
39 : bad_password_("incorrect"),
40 bad_username_("nouser"),
42 username_basic_("basicuser"),
43 username_digest_("digestuser") {
44 auth_map_["foo"] = AuthInfo("testuser", "foopassword");
45 auth_map_["bar"] = AuthInfo("testuser", "barpassword");
46 auth_map_["testrealm"] = AuthInfo(username_basic_, password_);
51 std::string username_;
52 std::string password_;
56 AuthInfo(const std::string& username,
57 const std::string& password)
58 : username_(username), password_(password) {}
61 typedef std::map<std::string, AuthInfo> AuthMap;
63 void SetAuthFor(LoginHandler* handler);
65 void TestCrossOriginPrompt(const GURL& visit_url,
66 const std::string& landing_host) const;
69 std::string bad_password_;
70 std::string bad_username_;
71 std::string password_;
72 std::string username_basic_;
73 std::string username_digest_;
76 void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
77 const net::AuthChallengeInfo* challenge = handler->auth_info();
79 ASSERT_TRUE(challenge);
80 AuthMap::iterator i = auth_map_.find(challenge->realm);
81 EXPECT_TRUE(auth_map_.end() != i);
82 if (i != auth_map_.end()) {
83 const AuthInfo& info = i->second;
84 handler->SetAuth(base::UTF8ToUTF16(info.username_),
85 base::UTF8ToUTF16(info.password_));
89 class InterstitialObserver : public content::WebContentsObserver {
91 InterstitialObserver(content::WebContents* web_contents,
92 const base::Closure& attach_callback,
93 const base::Closure& detach_callback)
94 : WebContentsObserver(web_contents),
95 attach_callback_(attach_callback),
96 detach_callback_(detach_callback) {
99 virtual void DidAttachInterstitialPage() OVERRIDE {
100 attach_callback_.Run();
103 virtual void DidDetachInterstitialPage() OVERRIDE {
104 detach_callback_.Run();
108 base::Closure attach_callback_;
109 base::Closure detach_callback_;
111 DISALLOW_COPY_AND_ASSIGN(InterstitialObserver);
114 void WaitForInterstitialAttach(content::WebContents* web_contents) {
115 scoped_refptr<content::MessageLoopRunner> interstitial_attach_loop_runner(
116 new content::MessageLoopRunner);
117 InterstitialObserver observer(
119 interstitial_attach_loop_runner->QuitClosure(),
121 if (!content::InterstitialPage::GetInterstitialPage(web_contents))
122 interstitial_attach_loop_runner->Run();
125 const char kPrefetchAuthPage[] = "files/login/prefetch.html";
127 const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
128 const int kMultiRealmTestRealmCount = 2;
130 const char kSingleRealmTestPage[] = "files/login/single_realm.html";
132 const char* kAuthBasicPage = "auth-basic";
133 const char* kAuthDigestPage = "auth-digest";
135 base::string16 ExpectedTitleFromAuth(const base::string16& username,
136 const base::string16& password) {
137 // The TestServer sets the title to username/password on successful login.
138 return username + base::UTF8ToUTF16("/") + password;
141 // Confirm that <link rel="prefetch"> targetting an auth required
142 // resource does not provide a login dialog. These types of requests
143 // should instead just cancel the auth.
145 // Unfortunately, this test doesn't assert on anything for its
146 // correctness. Instead, it relies on the auth dialog blocking the
147 // browser, and triggering a timeout to cause failure when the
148 // prefetch resource requires authorization.
149 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
150 ASSERT_TRUE(test_server()->Start());
152 GURL test_page = test_server()->GetURL(kPrefetchAuthPage);
154 class SetPrefetchForTest {
156 explicit SetPrefetchForTest(bool prefetch)
157 : old_prerender_mode_(prerender::PrerenderManager::GetMode()) {
158 std::string exp_group = prefetch ? "ExperimentYes" : "ExperimentNo";
159 base::FieldTrialList::CreateFieldTrial("Prefetch", exp_group);
160 // Disable prerender so this is just a prefetch of the top-level page.
161 prerender::PrerenderManager::SetMode(
162 prerender::PrerenderManager::PRERENDER_MODE_DISABLED);
165 ~SetPrefetchForTest() {
166 prerender::PrerenderManager::SetMode(old_prerender_mode_);
170 prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_;
171 } set_prefetch_for_test(true);
173 content::WebContents* contents =
174 browser()->tab_strip_model()->GetActiveWebContents();
175 NavigationController* controller = &contents->GetController();
176 LoginPromptBrowserTestObserver observer;
178 observer.Register(content::Source<NavigationController>(controller));
180 WindowedLoadStopObserver load_stop_waiter(controller, 1);
181 browser()->OpenURL(OpenURLParams(
182 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
185 load_stop_waiter.Wait();
186 EXPECT_TRUE(observer.handlers().empty());
187 EXPECT_TRUE(test_server()->Stop());
190 // Test that "Basic" HTTP authentication works.
191 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestBasicAuth) {
192 ASSERT_TRUE(test_server()->Start());
193 GURL test_page = test_server()->GetURL(kAuthBasicPage);
195 content::WebContents* contents =
196 browser()->tab_strip_model()->GetActiveWebContents();
197 NavigationController* controller = &contents->GetController();
198 LoginPromptBrowserTestObserver observer;
200 observer.Register(content::Source<NavigationController>(controller));
203 WindowedAuthNeededObserver auth_needed_waiter(controller);
204 browser()->OpenURL(OpenURLParams(
205 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
207 auth_needed_waiter.Wait();
210 ASSERT_FALSE(observer.handlers().empty());
212 WindowedAuthNeededObserver auth_needed_waiter(controller);
213 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
214 LoginHandler* handler = *observer.handlers().begin();
216 ASSERT_TRUE(handler);
217 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
218 base::UTF8ToUTF16(bad_password_));
219 auth_supplied_waiter.Wait();
221 // The request should be retried after the incorrect password is
222 // supplied. This should result in a new AUTH_NEEDED notification
223 // for the same realm.
224 auth_needed_waiter.Wait();
227 ASSERT_EQ(1u, observer.handlers().size());
228 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
229 LoginHandler* handler = *observer.handlers().begin();
231 auth_supplied_waiter.Wait();
233 base::string16 expected_title =
234 ExpectedTitleFromAuth(base::ASCIIToUTF16("basicuser"),
235 base::ASCIIToUTF16("secret"));
236 content::TitleWatcher title_watcher(contents, expected_title);
237 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
240 // Test that "Digest" HTTP authentication works.
241 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestDigestAuth) {
242 ASSERT_TRUE(test_server()->Start());
243 GURL test_page = test_server()->GetURL(kAuthDigestPage);
245 content::WebContents* contents =
246 browser()->tab_strip_model()->GetActiveWebContents();
247 NavigationController* controller = &contents->GetController();
248 LoginPromptBrowserTestObserver observer;
250 observer.Register(content::Source<NavigationController>(controller));
253 WindowedAuthNeededObserver auth_needed_waiter(controller);
254 browser()->OpenURL(OpenURLParams(
255 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
257 auth_needed_waiter.Wait();
260 ASSERT_FALSE(observer.handlers().empty());
262 WindowedAuthNeededObserver auth_needed_waiter(controller);
263 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
264 LoginHandler* handler = *observer.handlers().begin();
266 ASSERT_TRUE(handler);
267 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
268 base::UTF8ToUTF16(bad_password_));
269 auth_supplied_waiter.Wait();
271 // The request should be retried after the incorrect password is
272 // supplied. This should result in a new AUTH_NEEDED notification
273 // for the same realm.
274 auth_needed_waiter.Wait();
277 ASSERT_EQ(1u, observer.handlers().size());
278 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
279 LoginHandler* handler = *observer.handlers().begin();
281 base::string16 username(base::UTF8ToUTF16(username_digest_));
282 base::string16 password(base::UTF8ToUTF16(password_));
283 handler->SetAuth(username, password);
284 auth_supplied_waiter.Wait();
286 base::string16 expected_title = ExpectedTitleFromAuth(username, password);
287 content::TitleWatcher title_watcher(contents, expected_title);
288 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
291 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestTwoAuths) {
292 ASSERT_TRUE(test_server()->Start());
294 content::WebContents* contents1 =
295 browser()->tab_strip_model()->GetActiveWebContents();
296 NavigationController* controller1 = &contents1->GetController();
297 LoginPromptBrowserTestObserver observer;
299 observer.Register(content::Source<NavigationController>(controller1));
302 ui_test_utils::NavigateToURLWithDisposition(
306 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
308 content::WebContents* contents2 =
309 browser()->tab_strip_model()->GetActiveWebContents();
310 ASSERT_NE(contents1, contents2);
311 NavigationController* controller2 = &contents2->GetController();
312 observer.Register(content::Source<NavigationController>(controller2));
315 WindowedAuthNeededObserver auth_needed_waiter(controller1);
316 contents1->OpenURL(OpenURLParams(
317 test_server()->GetURL(kAuthBasicPage), Referrer(),
318 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
319 auth_needed_waiter.Wait();
323 WindowedAuthNeededObserver auth_needed_waiter(controller2);
324 contents2->OpenURL(OpenURLParams(
325 test_server()->GetURL(kAuthDigestPage), Referrer(),
326 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
327 auth_needed_waiter.Wait();
330 ASSERT_EQ(2u, observer.handlers().size());
332 LoginHandler* handler1 = *observer.handlers().begin();
333 LoginHandler* handler2 = *(++(observer.handlers().begin()));
335 base::string16 expected_title1 = ExpectedTitleFromAuth(
336 base::UTF8ToUTF16(username_basic_), base::UTF8ToUTF16(password_));
337 base::string16 expected_title2 = ExpectedTitleFromAuth(
338 base::UTF8ToUTF16(username_digest_), base::UTF8ToUTF16(password_));
339 content::TitleWatcher title_watcher1(contents1, expected_title1);
340 content::TitleWatcher title_watcher2(contents2, expected_title2);
342 handler1->SetAuth(base::UTF8ToUTF16(username_basic_),
343 base::UTF8ToUTF16(password_));
344 handler2->SetAuth(base::UTF8ToUTF16(username_digest_),
345 base::UTF8ToUTF16(password_));
347 EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
348 EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
351 // Test login prompt cancellation.
352 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestCancelAuth) {
353 ASSERT_TRUE(test_server()->Start());
354 GURL auth_page = test_server()->GetURL(kAuthBasicPage);
355 GURL no_auth_page_1 = test_server()->GetURL("a");
356 GURL no_auth_page_2 = test_server()->GetURL("b");
357 GURL no_auth_page_3 = test_server()->GetURL("c");
359 content::WebContents* contents =
360 browser()->tab_strip_model()->GetActiveWebContents();
361 NavigationController* controller = &contents->GetController();
363 LoginPromptBrowserTestObserver observer;
364 observer.Register(content::Source<NavigationController>(controller));
366 // First navigate to an unauthenticated page so we have something to
368 ui_test_utils::NavigateToURL(browser(), no_auth_page_1);
370 // Navigating while auth is requested is the same as cancelling.
372 // We need to wait for two LOAD_STOP events. One for auth_page and one for
374 WindowedLoadStopObserver load_stop_waiter(controller, 2);
375 WindowedAuthNeededObserver auth_needed_waiter(controller);
376 browser()->OpenURL(OpenURLParams(
377 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
379 auth_needed_waiter.Wait();
380 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
381 browser()->OpenURL(OpenURLParams(
382 no_auth_page_2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
384 auth_cancelled_waiter.Wait();
385 load_stop_waiter.Wait();
386 EXPECT_TRUE(observer.handlers().empty());
389 // Try navigating backwards.
391 // As above, we wait for two LOAD_STOP events; one for each navigation.
392 WindowedLoadStopObserver load_stop_waiter(controller, 2);
393 WindowedAuthNeededObserver auth_needed_waiter(controller);
394 browser()->OpenURL(OpenURLParams(
395 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
397 auth_needed_waiter.Wait();
398 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
399 ASSERT_TRUE(chrome::CanGoBack(browser()));
400 chrome::GoBack(browser(), CURRENT_TAB);
401 auth_cancelled_waiter.Wait();
402 load_stop_waiter.Wait();
403 EXPECT_TRUE(observer.handlers().empty());
406 // Now add a page and go back, so we have something to go forward to.
407 ui_test_utils::NavigateToURL(browser(), no_auth_page_3);
409 WindowedLoadStopObserver load_stop_waiter(controller, 1);
410 chrome::GoBack(browser(), CURRENT_TAB); // Should take us to page 1
411 load_stop_waiter.Wait();
415 // We wait for two LOAD_STOP events; one for each navigation.
416 WindowedLoadStopObserver load_stop_waiter(controller, 2);
417 WindowedAuthNeededObserver auth_needed_waiter(controller);
418 browser()->OpenURL(OpenURLParams(
419 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
421 auth_needed_waiter.Wait();
422 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
423 ASSERT_TRUE(chrome::CanGoForward(browser()));
424 chrome::GoForward(browser(), CURRENT_TAB); // Should take us to page 3
425 auth_cancelled_waiter.Wait();
426 load_stop_waiter.Wait();
427 EXPECT_TRUE(observer.handlers().empty());
430 // Now test that cancelling works as expected.
432 WindowedLoadStopObserver load_stop_waiter(controller, 1);
433 WindowedAuthNeededObserver auth_needed_waiter(controller);
434 browser()->OpenURL(OpenURLParams(
435 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
437 auth_needed_waiter.Wait();
438 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
439 LoginHandler* handler = *observer.handlers().begin();
440 ASSERT_TRUE(handler);
441 handler->CancelAuth();
442 auth_cancelled_waiter.Wait();
443 load_stop_waiter.Wait();
444 EXPECT_TRUE(observer.handlers().empty());
448 // Test handling of resources that require authentication even though
449 // the page they are included on doesn't. In this case we should only
450 // present the minimal number of prompts necessary for successfully
451 // displaying the page. First we check whether cancelling works as
453 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
454 ASSERT_TRUE(test_server()->Start());
455 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
457 content::WebContents* contents =
458 browser()->tab_strip_model()->GetActiveWebContents();
459 NavigationController* controller = &contents->GetController();
460 LoginPromptBrowserTestObserver observer;
462 observer.Register(content::Source<NavigationController>(controller));
464 WindowedLoadStopObserver load_stop_waiter(controller, 1);
467 WindowedAuthNeededObserver auth_needed_waiter(controller);
468 browser()->OpenURL(OpenURLParams(
469 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
471 auth_needed_waiter.Wait();
476 while (n_handlers < kMultiRealmTestRealmCount) {
477 WindowedAuthNeededObserver auth_needed_waiter(controller);
479 while (!observer.handlers().empty()) {
480 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
481 LoginHandler* handler = *observer.handlers().begin();
483 ASSERT_TRUE(handler);
485 handler->CancelAuth();
486 auth_cancelled_waiter.Wait();
489 if (n_handlers < kMultiRealmTestRealmCount)
490 auth_needed_waiter.Wait();
493 load_stop_waiter.Wait();
495 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
496 EXPECT_EQ(0, observer.auth_supplied_count());
497 EXPECT_LT(0, observer.auth_needed_count());
498 EXPECT_LT(0, observer.auth_cancelled_count());
499 EXPECT_TRUE(test_server()->Stop());
502 // Similar to the MultipleRealmCancellation test above, but tests
503 // whether supplying credentials work as exepcted.
504 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
505 ASSERT_TRUE(test_server()->Start());
506 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
508 content::WebContents* contents =
509 browser()->tab_strip_model()->GetActiveWebContents();
510 NavigationController* controller = &contents->GetController();
511 LoginPromptBrowserTestObserver observer;
513 observer.Register(content::Source<NavigationController>(controller));
515 WindowedLoadStopObserver load_stop_waiter(controller, 1);
519 WindowedAuthNeededObserver auth_needed_waiter(controller);
521 browser()->OpenURL(OpenURLParams(
522 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
524 auth_needed_waiter.Wait();
527 while (n_handlers < kMultiRealmTestRealmCount) {
528 WindowedAuthNeededObserver auth_needed_waiter(controller);
530 while (!observer.handlers().empty()) {
531 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
532 LoginHandler* handler = *observer.handlers().begin();
534 ASSERT_TRUE(handler);
537 auth_supplied_waiter.Wait();
540 if (n_handlers < kMultiRealmTestRealmCount)
541 auth_needed_waiter.Wait();
544 load_stop_waiter.Wait();
546 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
547 EXPECT_LT(0, observer.auth_needed_count());
548 EXPECT_LT(0, observer.auth_supplied_count());
549 EXPECT_EQ(0, observer.auth_cancelled_count());
550 EXPECT_TRUE(test_server()->Stop());
553 // Testing for recovery from an incorrect password for the case where
554 // there are multiple authenticated resources.
555 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, IncorrectConfirmation) {
556 ASSERT_TRUE(test_server()->Start());
557 GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
559 content::WebContents* contents =
560 browser()->tab_strip_model()->GetActiveWebContents();
561 NavigationController* controller = &contents->GetController();
562 LoginPromptBrowserTestObserver observer;
564 observer.Register(content::Source<NavigationController>(controller));
567 WindowedAuthNeededObserver auth_needed_waiter(controller);
568 browser()->OpenURL(OpenURLParams(
569 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
571 auth_needed_waiter.Wait();
574 EXPECT_FALSE(observer.handlers().empty());
576 if (!observer.handlers().empty()) {
577 WindowedAuthNeededObserver auth_needed_waiter(controller);
578 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
579 LoginHandler* handler = *observer.handlers().begin();
581 ASSERT_TRUE(handler);
582 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
583 base::UTF8ToUTF16(bad_password_));
584 auth_supplied_waiter.Wait();
586 // The request should be retried after the incorrect password is
587 // supplied. This should result in a new AUTH_NEEDED notification
588 // for the same realm.
589 auth_needed_waiter.Wait();
594 while (n_handlers < 1) {
595 WindowedAuthNeededObserver auth_needed_waiter(controller);
597 while (!observer.handlers().empty()) {
598 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
599 LoginHandler* handler = *observer.handlers().begin();
601 ASSERT_TRUE(handler);
604 auth_supplied_waiter.Wait();
608 auth_needed_waiter.Wait();
611 // The single realm test has only one realm, and thus only one login
613 EXPECT_EQ(1, n_handlers);
614 EXPECT_LT(0, observer.auth_needed_count());
615 EXPECT_EQ(0, observer.auth_cancelled_count());
616 EXPECT_EQ(observer.auth_needed_count(), observer.auth_supplied_count());
617 EXPECT_TRUE(test_server()->Stop());
620 // If the favicon is an authenticated resource, we shouldn't prompt
621 // for credentials. The same URL, if requested elsewhere should
622 // prompt for credentials.
623 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, NoLoginPromptForFavicon) {
624 const char* kFaviconTestPage = "files/login/has_favicon.html";
625 const char* kFaviconResource = "auth-basic/favicon.gif";
627 ASSERT_TRUE(test_server()->Start());
629 content::WebContents* contents =
630 browser()->tab_strip_model()->GetActiveWebContents();
631 NavigationController* controller = &contents->GetController();
632 LoginPromptBrowserTestObserver observer;
634 observer.Register(content::Source<NavigationController>(controller));
636 // First load a page that has a favicon that requires
637 // authentication. There should be no login prompt.
639 GURL test_page = test_server()->GetURL(kFaviconTestPage);
640 WindowedLoadStopObserver load_stop_waiter(controller, 1);
641 browser()->OpenURL(OpenURLParams(
642 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
644 load_stop_waiter.Wait();
647 // Now request the same favicon, but directly as the document.
648 // There should be one login prompt.
650 GURL test_page = test_server()->GetURL(kFaviconResource);
651 WindowedLoadStopObserver load_stop_waiter(controller, 1);
652 WindowedAuthNeededObserver auth_needed_waiter(controller);
653 browser()->OpenURL(OpenURLParams(
654 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
656 auth_needed_waiter.Wait();
657 ASSERT_EQ(1u, observer.handlers().size());
659 while (!observer.handlers().empty()) {
660 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
661 LoginHandler* handler = *observer.handlers().begin();
663 ASSERT_TRUE(handler);
664 handler->CancelAuth();
665 auth_cancelled_waiter.Wait();
668 load_stop_waiter.Wait();
671 EXPECT_EQ(0, observer.auth_supplied_count());
672 EXPECT_EQ(1, observer.auth_needed_count());
673 EXPECT_EQ(1, observer.auth_cancelled_count());
674 EXPECT_TRUE(test_server()->Stop());
677 // Block crossdomain image login prompting as a phishing defense.
678 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
679 BlockCrossdomainPromptForSubresources) {
680 const char* kTestPage = "files/login/load_img_from_b.html";
682 host_resolver()->AddRule("www.a.com", "127.0.0.1");
683 host_resolver()->AddRule("www.b.com", "127.0.0.1");
684 ASSERT_TRUE(test_server()->Start());
686 content::WebContents* contents =
687 browser()->tab_strip_model()->GetActiveWebContents();
688 NavigationController* controller = &contents->GetController();
689 LoginPromptBrowserTestObserver observer;
690 observer.Register(content::Source<NavigationController>(controller));
692 // Load a page that has a cross-domain sub-resource authentication.
693 // There should be no login prompt.
695 GURL test_page = test_server()->GetURL(kTestPage);
696 ASSERT_EQ("127.0.0.1", test_page.host());
698 // Change the host from 127.0.0.1 to www.a.com so that when the
699 // page tries to load from b, it will be cross-origin.
700 std::string new_host("www.a.com");
701 GURL::Replacements replacements;
702 replacements.SetHostStr(new_host);
703 test_page = test_page.ReplaceComponents(replacements);
705 WindowedLoadStopObserver load_stop_waiter(controller, 1);
706 browser()->OpenURL(OpenURLParams(
707 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
709 load_stop_waiter.Wait();
712 EXPECT_EQ(0, observer.auth_needed_count());
714 // Now request the same page, but from the same origin.
715 // There should be one login prompt.
717 GURL test_page = test_server()->GetURL(kTestPage);
718 ASSERT_EQ("127.0.0.1", test_page.host());
720 // Change the host from 127.0.0.1 to www.b.com so that when the
721 // page tries to load from b, it will be same-origin.
722 std::string new_host("www.b.com");
723 GURL::Replacements replacements;
724 replacements.SetHostStr(new_host);
725 test_page = test_page.ReplaceComponents(replacements);
727 WindowedAuthNeededObserver auth_needed_waiter(controller);
728 browser()->OpenURL(OpenURLParams(
729 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
731 auth_needed_waiter.Wait();
732 ASSERT_EQ(1u, observer.handlers().size());
734 while (!observer.handlers().empty()) {
735 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
736 LoginHandler* handler = *observer.handlers().begin();
738 ASSERT_TRUE(handler);
739 handler->CancelAuth();
740 auth_cancelled_waiter.Wait();
744 EXPECT_EQ(1, observer.auth_needed_count());
745 EXPECT_TRUE(test_server()->Stop());
748 // Allow crossdomain iframe login prompting despite the above.
749 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
750 AllowCrossdomainPromptForSubframes) {
751 const char* kTestPage = "files/login/load_iframe_from_b.html";
753 host_resolver()->AddRule("www.a.com", "127.0.0.1");
754 host_resolver()->AddRule("www.b.com", "127.0.0.1");
755 ASSERT_TRUE(test_server()->Start());
757 content::WebContents* contents =
758 browser()->tab_strip_model()->GetActiveWebContents();
759 NavigationController* controller = &contents->GetController();
760 LoginPromptBrowserTestObserver observer;
761 observer.Register(content::Source<NavigationController>(controller));
763 // Load a page that has a cross-domain iframe authentication.
765 GURL test_page = test_server()->GetURL(kTestPage);
766 ASSERT_EQ("127.0.0.1", test_page.host());
768 // Change the host from 127.0.0.1 to www.a.com so that when the
769 // page tries to load from b, it will be cross-origin.
770 std::string new_host("www.a.com");
771 GURL::Replacements replacements;
772 replacements.SetHostStr(new_host);
773 test_page = test_page.ReplaceComponents(replacements);
775 WindowedAuthNeededObserver auth_needed_waiter(controller);
776 browser()->OpenURL(OpenURLParams(
777 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
779 auth_needed_waiter.Wait();
780 ASSERT_EQ(1u, observer.handlers().size());
782 while (!observer.handlers().empty()) {
783 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
784 LoginHandler* handler = *observer.handlers().begin();
786 ASSERT_TRUE(handler);
787 // When a cross origin iframe displays a login prompt, the blank
788 // interstitial shouldn't be displayed and the omnibox should show the
789 // main frame's url, not the iframe's.
790 EXPECT_EQ(new_host, contents->GetVisibleURL().host());
792 handler->CancelAuth();
793 auth_cancelled_waiter.Wait();
797 // Should stay on the main frame's url once the prompt the iframe is closed.
798 EXPECT_EQ("www.a.com", contents->GetVisibleURL().host());
800 EXPECT_EQ(1, observer.auth_needed_count());
801 EXPECT_TRUE(test_server()->Stop());
804 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, SupplyRedundantAuths) {
805 ASSERT_TRUE(test_server()->Start());
807 // Get NavigationController for tab 1.
808 content::WebContents* contents_1 =
809 browser()->tab_strip_model()->GetActiveWebContents();
810 NavigationController* controller_1 = &contents_1->GetController();
813 ui_test_utils::NavigateToURLWithDisposition(
817 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
819 // Get NavigationController for tab 2.
820 content::WebContents* contents_2 =
821 browser()->tab_strip_model()->GetActiveWebContents();
822 ASSERT_NE(contents_1, contents_2);
823 NavigationController* controller_2 = &contents_2->GetController();
825 LoginPromptBrowserTestObserver observer;
826 observer.Register(content::Source<NavigationController>(controller_1));
827 observer.Register(content::Source<NavigationController>(controller_2));
830 // Open different auth urls in each tab.
831 WindowedAuthNeededObserver auth_needed_waiter_1(controller_1);
832 WindowedAuthNeededObserver auth_needed_waiter_2(controller_2);
833 contents_1->OpenURL(OpenURLParams(
834 test_server()->GetURL("auth-basic/1"),
837 ui::PAGE_TRANSITION_TYPED,
839 contents_2->OpenURL(OpenURLParams(
840 test_server()->GetURL("auth-basic/2"),
843 ui::PAGE_TRANSITION_TYPED,
845 auth_needed_waiter_1.Wait();
846 auth_needed_waiter_2.Wait();
848 ASSERT_EQ(2U, observer.handlers().size());
850 // Supply auth in one of the tabs.
851 WindowedAuthSuppliedObserver auth_supplied_waiter_1(controller_1);
852 WindowedAuthSuppliedObserver auth_supplied_waiter_2(controller_2);
853 LoginHandler* handler_1 = *observer.handlers().begin();
854 ASSERT_TRUE(handler_1);
855 SetAuthFor(handler_1);
857 // Both tabs should be authenticated.
858 auth_supplied_waiter_1.Wait();
859 auth_supplied_waiter_2.Wait();
862 EXPECT_EQ(2, observer.auth_needed_count());
863 EXPECT_EQ(2, observer.auth_supplied_count());
864 EXPECT_EQ(0, observer.auth_cancelled_count());
865 EXPECT_TRUE(test_server()->Stop());
868 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, CancelRedundantAuths) {
869 ASSERT_TRUE(test_server()->Start());
871 // Get NavigationController for tab 1.
872 content::WebContents* contents_1 =
873 browser()->tab_strip_model()->GetActiveWebContents();
874 NavigationController* controller_1 = &contents_1->GetController();
877 ui_test_utils::NavigateToURLWithDisposition(
881 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
883 // Get NavigationController for tab 2.
884 content::WebContents* contents_2 =
885 browser()->tab_strip_model()->GetActiveWebContents();
886 ASSERT_NE(contents_1, contents_2);
887 NavigationController* controller_2 = &contents_2->GetController();
889 LoginPromptBrowserTestObserver observer;
890 observer.Register(content::Source<NavigationController>(controller_1));
891 observer.Register(content::Source<NavigationController>(controller_2));
894 // Open different auth urls in each tab.
895 WindowedAuthNeededObserver auth_needed_waiter_1(controller_1);
896 WindowedAuthNeededObserver auth_needed_waiter_2(controller_2);
897 contents_1->OpenURL(OpenURLParams(
898 test_server()->GetURL("auth-basic/1"),
901 ui::PAGE_TRANSITION_TYPED,
903 contents_2->OpenURL(OpenURLParams(
904 test_server()->GetURL("auth-basic/2"),
907 ui::PAGE_TRANSITION_TYPED,
909 auth_needed_waiter_1.Wait();
910 auth_needed_waiter_2.Wait();
912 ASSERT_EQ(2U, observer.handlers().size());
914 // Cancel auth in one of the tabs.
915 WindowedAuthCancelledObserver auth_cancelled_waiter_1(controller_1);
916 WindowedAuthCancelledObserver auth_cancelled_waiter_2(controller_2);
917 LoginHandler* handler_1 = *observer.handlers().begin();
918 ASSERT_TRUE(handler_1);
919 handler_1->CancelAuth();
921 // Both tabs should cancel auth.
922 auth_cancelled_waiter_1.Wait();
923 auth_cancelled_waiter_2.Wait();
926 EXPECT_EQ(2, observer.auth_needed_count());
927 EXPECT_EQ(0, observer.auth_supplied_count());
928 EXPECT_EQ(2, observer.auth_cancelled_count());
929 EXPECT_TRUE(test_server()->Stop());
932 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
933 SupplyRedundantAuthsMultiProfile) {
934 ASSERT_TRUE(test_server()->Start());
936 // Get NavigationController for regular tab.
937 content::WebContents* contents =
938 browser()->tab_strip_model()->GetActiveWebContents();
939 NavigationController* controller = &contents->GetController();
941 // Open an incognito window.
942 Browser* browser_incognito = CreateIncognitoBrowser();
944 // Get NavigationController for incognito tab.
945 content::WebContents* contents_incognito =
946 browser_incognito->tab_strip_model()->GetActiveWebContents();
947 ASSERT_NE(contents, contents_incognito);
948 NavigationController* controller_incognito =
949 &contents_incognito->GetController();
951 LoginPromptBrowserTestObserver observer;
952 observer.Register(content::Source<NavigationController>(controller));
953 LoginPromptBrowserTestObserver observer_incognito;
954 observer_incognito.Register(
955 content::Source<NavigationController>(controller_incognito));
958 // Open an auth url in each window.
959 WindowedAuthNeededObserver auth_needed_waiter(controller);
960 WindowedAuthNeededObserver auth_needed_waiter_incognito(
961 controller_incognito);
962 contents->OpenURL(OpenURLParams(
963 test_server()->GetURL("auth-basic/1"),
966 ui::PAGE_TRANSITION_TYPED,
968 contents_incognito->OpenURL(OpenURLParams(
969 test_server()->GetURL("auth-basic/2"),
972 ui::PAGE_TRANSITION_TYPED,
974 auth_needed_waiter.Wait();
975 auth_needed_waiter_incognito.Wait();
977 ASSERT_EQ(1U, observer.handlers().size());
978 ASSERT_EQ(1U, observer_incognito.handlers().size());
980 // Supply auth in regular tab.
981 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
982 LoginHandler* handler = *observer.handlers().begin();
983 ASSERT_TRUE(handler);
986 // Regular tab should be authenticated.
987 auth_supplied_waiter.Wait();
989 // There's not really a way to wait for the incognito window to "do
990 // nothing". Run anything pending in the message loop just to be sure.
991 // (This shouldn't be necessary since notifications are synchronous, but
992 // maybe it will help avoid flake someday in the future..)
993 content::RunAllPendingInMessageLoop();
996 EXPECT_EQ(1, observer.auth_needed_count());
997 EXPECT_EQ(1, observer.auth_supplied_count());
998 EXPECT_EQ(0, observer.auth_cancelled_count());
999 EXPECT_EQ(1, observer_incognito.auth_needed_count());
1000 EXPECT_EQ(0, observer_incognito.auth_supplied_count());
1001 EXPECT_EQ(0, observer_incognito.auth_cancelled_count());
1002 EXPECT_TRUE(test_server()->Stop());
1005 // If an XMLHttpRequest is made with incorrect credentials, there should be no
1006 // login prompt; instead the 401 status should be returned to the script.
1007 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1008 NoLoginPromptForXHRWithBadCredentials) {
1009 const char* kXHRTestPage = "files/login/xhr_with_credentials.html#incorrect";
1011 ASSERT_TRUE(test_server()->Start());
1013 content::WebContents* contents =
1014 browser()->tab_strip_model()->GetActiveWebContents();
1015 NavigationController* controller = &contents->GetController();
1016 LoginPromptBrowserTestObserver observer;
1018 observer.Register(content::Source<NavigationController>(controller));
1020 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1021 // resource with the wrong credentials. There should be no login prompt.
1023 GURL test_page = test_server()->GetURL(kXHRTestPage);
1024 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1025 browser()->OpenURL(OpenURLParams(
1026 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1028 load_stop_waiter.Wait();
1031 base::string16 expected_title(base::UTF8ToUTF16("status=401"));
1033 EXPECT_EQ(expected_title, contents->GetTitle());
1034 EXPECT_EQ(0, observer.auth_supplied_count());
1035 EXPECT_EQ(0, observer.auth_needed_count());
1036 EXPECT_EQ(0, observer.auth_cancelled_count());
1037 EXPECT_TRUE(test_server()->Stop());
1040 // If an XMLHttpRequest is made with correct credentials, there should be no
1041 // login prompt either.
1042 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1043 NoLoginPromptForXHRWithGoodCredentials) {
1044 const char* kXHRTestPage = "files/login/xhr_with_credentials.html#secret";
1046 ASSERT_TRUE(test_server()->Start());
1048 content::WebContents* contents =
1049 browser()->tab_strip_model()->GetActiveWebContents();
1050 NavigationController* controller = &contents->GetController();
1051 LoginPromptBrowserTestObserver observer;
1053 observer.Register(content::Source<NavigationController>(controller));
1055 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1056 // resource with the wrong credentials. There should be no login prompt.
1058 GURL test_page = test_server()->GetURL(kXHRTestPage);
1059 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1060 browser()->OpenURL(OpenURLParams(
1061 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1063 load_stop_waiter.Wait();
1066 base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1068 EXPECT_EQ(expected_title, contents->GetTitle());
1069 EXPECT_EQ(0, observer.auth_supplied_count());
1070 EXPECT_EQ(0, observer.auth_needed_count());
1071 EXPECT_EQ(0, observer.auth_cancelled_count());
1072 EXPECT_TRUE(test_server()->Stop());
1075 // If an XMLHttpRequest is made without credentials, there should be a login
1077 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1078 LoginPromptForXHRWithoutCredentials) {
1079 const char* kXHRTestPage = "files/login/xhr_without_credentials.html";
1081 ASSERT_TRUE(test_server()->Start());
1083 content::WebContents* contents =
1084 browser()->tab_strip_model()->GetActiveWebContents();
1085 NavigationController* controller = &contents->GetController();
1086 LoginPromptBrowserTestObserver observer;
1088 observer.Register(content::Source<NavigationController>(controller));
1090 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1091 // resource with the wrong credentials. There should be no login prompt.
1093 GURL test_page = test_server()->GetURL(kXHRTestPage);
1094 WindowedAuthNeededObserver auth_needed_waiter(controller);
1095 browser()->OpenURL(OpenURLParams(
1096 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1098 auth_needed_waiter.Wait();
1101 ASSERT_FALSE(observer.handlers().empty());
1103 WindowedAuthNeededObserver auth_needed_waiter(controller);
1104 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1105 LoginHandler* handler = *observer.handlers().begin();
1107 ASSERT_TRUE(handler);
1108 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
1109 base::UTF8ToUTF16(bad_password_));
1110 auth_supplied_waiter.Wait();
1112 // The request should be retried after the incorrect password is
1113 // supplied. This should result in a new AUTH_NEEDED notification
1114 // for the same realm.
1115 auth_needed_waiter.Wait();
1118 ASSERT_EQ(1u, observer.handlers().size());
1119 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1120 LoginHandler* handler = *observer.handlers().begin();
1122 base::string16 username(base::UTF8ToUTF16(username_digest_));
1123 base::string16 password(base::UTF8ToUTF16(password_));
1124 handler->SetAuth(username, password);
1125 auth_supplied_waiter.Wait();
1127 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1128 load_stop_waiter.Wait();
1130 base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1132 EXPECT_EQ(expected_title, contents->GetTitle());
1133 EXPECT_EQ(2, observer.auth_supplied_count());
1134 EXPECT_EQ(2, observer.auth_needed_count());
1135 EXPECT_EQ(0, observer.auth_cancelled_count());
1136 EXPECT_TRUE(test_server()->Stop());
1139 // If an XMLHttpRequest is made without credentials, there should be a login
1140 // prompt. If it's cancelled, the script should get a 401 status.
1141 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1142 LoginPromptForXHRWithoutCredentialsCancelled) {
1143 const char* kXHRTestPage = "files/login/xhr_without_credentials.html";
1145 ASSERT_TRUE(test_server()->Start());
1147 content::WebContents* contents =
1148 browser()->tab_strip_model()->GetActiveWebContents();
1149 NavigationController* controller = &contents->GetController();
1150 LoginPromptBrowserTestObserver observer;
1152 observer.Register(content::Source<NavigationController>(controller));
1154 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1155 // resource with the wrong credentials. There should be no login prompt.
1157 GURL test_page = test_server()->GetURL(kXHRTestPage);
1158 WindowedAuthNeededObserver auth_needed_waiter(controller);
1159 browser()->OpenURL(OpenURLParams(
1160 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1162 auth_needed_waiter.Wait();
1165 ASSERT_EQ(1u, observer.handlers().size());
1166 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
1167 LoginHandler* handler = *observer.handlers().begin();
1169 handler->CancelAuth();
1170 auth_cancelled_waiter.Wait();
1172 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1173 load_stop_waiter.Wait();
1175 base::string16 expected_title(base::UTF8ToUTF16("status=401"));
1177 EXPECT_EQ(expected_title, contents->GetTitle());
1178 EXPECT_EQ(0, observer.auth_supplied_count());
1179 EXPECT_EQ(1, observer.auth_needed_count());
1180 EXPECT_EQ(1, observer.auth_cancelled_count());
1181 EXPECT_TRUE(test_server()->Stop());
1184 // If a cross origin navigation triggers a login prompt, the destination URL
1185 // should be shown in the omnibox.
1186 void LoginPromptBrowserTest::TestCrossOriginPrompt(
1187 const GURL& visit_url,
1188 const std::string& auth_host) const {
1189 content::WebContents* contents =
1190 browser()->tab_strip_model()->GetActiveWebContents();
1191 NavigationController* controller = &contents->GetController();
1192 LoginPromptBrowserTestObserver observer;
1194 observer.Register(content::Source<NavigationController>(controller));
1196 // Load a page which will trigger a login prompt.
1198 WindowedAuthNeededObserver auth_needed_waiter(controller);
1199 browser()->OpenURL(OpenURLParams(
1200 visit_url, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1202 ASSERT_EQ(visit_url.host(), contents->GetVisibleURL().host());
1203 auth_needed_waiter.Wait();
1204 ASSERT_EQ(1u, observer.handlers().size());
1205 WaitForInterstitialAttach(contents);
1207 // The omnibox should show the correct origin for the new page when the
1208 // login prompt is shown.
1209 EXPECT_EQ(auth_host, contents->GetVisibleURL().host());
1210 EXPECT_TRUE(contents->ShowingInterstitialPage());
1212 // Cancel and wait for the interstitial to detach.
1213 LoginHandler* handler = *observer.handlers().begin();
1214 scoped_refptr<content::MessageLoopRunner> loop_runner(
1215 new content::MessageLoopRunner);
1216 InterstitialObserver interstitial_observer(contents,
1218 loop_runner->QuitClosure());
1219 handler->CancelAuth();
1220 if (content::InterstitialPage::GetInterstitialPage(contents))
1222 EXPECT_EQ(auth_host, contents->GetVisibleURL().host());
1223 EXPECT_FALSE(contents->ShowingInterstitialPage());
1227 // If a cross origin direct navigation triggers a login prompt, the login
1228 // interstitial should be shown.
1229 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1230 ShowCorrectUrlForCrossOriginMainFrameRequests) {
1231 ASSERT_TRUE(test_server()->Start());
1233 GURL test_page = test_server()->GetURL(kAuthBasicPage);
1234 ASSERT_EQ("127.0.0.1", test_page.host());
1235 std::string auth_host("127.0.0.1");
1236 TestCrossOriginPrompt(test_page, auth_host);
1239 // If a cross origin redirect triggers a login prompt, the destination URL
1240 // should be shown in the omnibox when the auth dialog is displayed.
1241 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1242 ShowCorrectUrlForCrossOriginMainFrameRedirects) {
1243 host_resolver()->AddRule("www.a.com", "127.0.0.1");
1244 ASSERT_TRUE(test_server()->Start());
1246 const char* kTestPage = "files/login/cross_origin.html";
1247 GURL test_page = test_server()->GetURL(kTestPage);
1248 ASSERT_EQ("127.0.0.1", test_page.host());
1249 std::string auth_host("www.a.com");
1250 TestCrossOriginPrompt(test_page, auth_host);
1253 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1254 LoginInterstitialShouldReplaceExistingInterstitial) {
1255 net::SpawnedTestServer https_server(
1256 net::SpawnedTestServer::TYPE_HTTPS,
1257 net::SpawnedTestServer::SSLOptions(
1258 net::SpawnedTestServer::SSLOptions::CERT_EXPIRED),
1260 ASSERT_TRUE(https_server.Start());
1262 content::WebContents* contents =
1263 browser()->tab_strip_model()->GetActiveWebContents();
1264 NavigationController* controller = &contents->GetController();
1265 LoginPromptBrowserTestObserver observer;
1267 observer.Register(content::Source<NavigationController>(controller));
1269 // Load a page which triggers an SSL interstitial. Proceeding through it
1270 // should show the login page with the blank interstitial.
1272 GURL test_page = https_server.GetURL(kAuthBasicPage);
1273 ASSERT_EQ("127.0.0.1", test_page.host());
1275 WindowedAuthNeededObserver auth_needed_waiter(controller);
1276 browser()->OpenURL(OpenURLParams(
1277 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1279 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1280 WaitForInterstitialAttach(contents);
1282 // An overrideable SSL interstitial is now being displayed. Proceed through
1283 // the interstitial to see the login prompt.
1284 contents->GetInterstitialPage()->Proceed();
1285 auth_needed_waiter.Wait();
1286 ASSERT_EQ(1u, observer.handlers().size());
1287 WaitForInterstitialAttach(contents);
1289 // The omnibox should show the correct origin while the login prompt is
1291 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1292 EXPECT_TRUE(contents->ShowingInterstitialPage());
1294 // Cancelling the login prompt should detach the interstitial while keeping
1295 // the correct origin.
1296 LoginHandler* handler = *observer.handlers().begin();
1297 scoped_refptr<content::MessageLoopRunner> loop_runner(
1298 new content::MessageLoopRunner);
1299 InterstitialObserver interstitial_observer(contents,
1301 loop_runner->QuitClosure());
1302 handler->CancelAuth();
1303 if (content::InterstitialPage::GetInterstitialPage(contents))
1305 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1306 EXPECT_FALSE(contents->ShowingInterstitialPage());