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 const char kPrefetchAuthPage[] = "files/login/prefetch.html";
91 const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
92 const int kMultiRealmTestRealmCount = 2;
94 const char kSingleRealmTestPage[] = "files/login/single_realm.html";
96 const char* kAuthBasicPage = "auth-basic";
97 const char* kAuthDigestPage = "auth-digest";
99 base::string16 ExpectedTitleFromAuth(const base::string16& username,
100 const base::string16& password) {
101 // The TestServer sets the title to username/password on successful login.
102 return username + base::UTF8ToUTF16("/") + password;
105 // Confirm that <link rel="prefetch"> targetting an auth required
106 // resource does not provide a login dialog. These types of requests
107 // should instead just cancel the auth.
109 // Unfortunately, this test doesn't assert on anything for its
110 // correctness. Instead, it relies on the auth dialog blocking the
111 // browser, and triggering a timeout to cause failure when the
112 // prefetch resource requires authorization.
113 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
114 ASSERT_TRUE(test_server()->Start());
116 GURL test_page = test_server()->GetURL(kPrefetchAuthPage);
118 class SetPrefetchForTest {
120 explicit SetPrefetchForTest(bool prefetch)
121 : old_prerender_mode_(prerender::PrerenderManager::GetMode()) {
122 std::string exp_group = prefetch ? "ExperimentYes" : "ExperimentNo";
123 base::FieldTrialList::CreateFieldTrial("Prefetch", exp_group);
124 // Disable prerender so this is just a prefetch of the top-level page.
125 prerender::PrerenderManager::SetMode(
126 prerender::PrerenderManager::PRERENDER_MODE_DISABLED);
129 ~SetPrefetchForTest() {
130 prerender::PrerenderManager::SetMode(old_prerender_mode_);
134 prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_;
135 } set_prefetch_for_test(true);
137 content::WebContents* contents =
138 browser()->tab_strip_model()->GetActiveWebContents();
139 NavigationController* controller = &contents->GetController();
140 LoginPromptBrowserTestObserver observer;
142 observer.Register(content::Source<NavigationController>(controller));
144 WindowedLoadStopObserver load_stop_waiter(controller, 1);
145 browser()->OpenURL(OpenURLParams(
146 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
149 load_stop_waiter.Wait();
150 EXPECT_TRUE(observer.handlers().empty());
151 EXPECT_TRUE(test_server()->Stop());
154 // Test that "Basic" HTTP authentication works.
155 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestBasicAuth) {
156 ASSERT_TRUE(test_server()->Start());
157 GURL test_page = test_server()->GetURL(kAuthBasicPage);
159 content::WebContents* contents =
160 browser()->tab_strip_model()->GetActiveWebContents();
161 NavigationController* controller = &contents->GetController();
162 LoginPromptBrowserTestObserver observer;
164 observer.Register(content::Source<NavigationController>(controller));
167 WindowedAuthNeededObserver auth_needed_waiter(controller);
168 browser()->OpenURL(OpenURLParams(
169 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
171 auth_needed_waiter.Wait();
174 ASSERT_FALSE(observer.handlers().empty());
176 WindowedAuthNeededObserver auth_needed_waiter(controller);
177 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
178 LoginHandler* handler = *observer.handlers().begin();
180 ASSERT_TRUE(handler);
181 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
182 base::UTF8ToUTF16(bad_password_));
183 auth_supplied_waiter.Wait();
185 // The request should be retried after the incorrect password is
186 // supplied. This should result in a new AUTH_NEEDED notification
187 // for the same realm.
188 auth_needed_waiter.Wait();
191 ASSERT_EQ(1u, observer.handlers().size());
192 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
193 LoginHandler* handler = *observer.handlers().begin();
195 auth_supplied_waiter.Wait();
197 base::string16 expected_title =
198 ExpectedTitleFromAuth(base::ASCIIToUTF16("basicuser"),
199 base::ASCIIToUTF16("secret"));
200 content::TitleWatcher title_watcher(contents, expected_title);
201 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
204 // Test that "Digest" HTTP authentication works.
205 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestDigestAuth) {
206 ASSERT_TRUE(test_server()->Start());
207 GURL test_page = test_server()->GetURL(kAuthDigestPage);
209 content::WebContents* contents =
210 browser()->tab_strip_model()->GetActiveWebContents();
211 NavigationController* controller = &contents->GetController();
212 LoginPromptBrowserTestObserver observer;
214 observer.Register(content::Source<NavigationController>(controller));
217 WindowedAuthNeededObserver auth_needed_waiter(controller);
218 browser()->OpenURL(OpenURLParams(
219 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
221 auth_needed_waiter.Wait();
224 ASSERT_FALSE(observer.handlers().empty());
226 WindowedAuthNeededObserver auth_needed_waiter(controller);
227 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
228 LoginHandler* handler = *observer.handlers().begin();
230 ASSERT_TRUE(handler);
231 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
232 base::UTF8ToUTF16(bad_password_));
233 auth_supplied_waiter.Wait();
235 // The request should be retried after the incorrect password is
236 // supplied. This should result in a new AUTH_NEEDED notification
237 // for the same realm.
238 auth_needed_waiter.Wait();
241 ASSERT_EQ(1u, observer.handlers().size());
242 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
243 LoginHandler* handler = *observer.handlers().begin();
245 base::string16 username(base::UTF8ToUTF16(username_digest_));
246 base::string16 password(base::UTF8ToUTF16(password_));
247 handler->SetAuth(username, password);
248 auth_supplied_waiter.Wait();
250 base::string16 expected_title = ExpectedTitleFromAuth(username, password);
251 content::TitleWatcher title_watcher(contents, expected_title);
252 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
255 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestTwoAuths) {
256 ASSERT_TRUE(test_server()->Start());
258 content::WebContents* contents1 =
259 browser()->tab_strip_model()->GetActiveWebContents();
260 NavigationController* controller1 = &contents1->GetController();
261 LoginPromptBrowserTestObserver observer;
263 observer.Register(content::Source<NavigationController>(controller1));
266 ui_test_utils::NavigateToURLWithDisposition(
270 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
272 content::WebContents* contents2 =
273 browser()->tab_strip_model()->GetActiveWebContents();
274 ASSERT_NE(contents1, contents2);
275 NavigationController* controller2 = &contents2->GetController();
276 observer.Register(content::Source<NavigationController>(controller2));
279 WindowedAuthNeededObserver auth_needed_waiter(controller1);
280 contents1->OpenURL(OpenURLParams(
281 test_server()->GetURL(kAuthBasicPage), Referrer(),
282 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
283 auth_needed_waiter.Wait();
287 WindowedAuthNeededObserver auth_needed_waiter(controller2);
288 contents2->OpenURL(OpenURLParams(
289 test_server()->GetURL(kAuthDigestPage), Referrer(),
290 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
291 auth_needed_waiter.Wait();
294 ASSERT_EQ(2u, observer.handlers().size());
296 LoginHandler* handler1 = *observer.handlers().begin();
297 LoginHandler* handler2 = *(++(observer.handlers().begin()));
299 base::string16 expected_title1 = ExpectedTitleFromAuth(
300 base::UTF8ToUTF16(username_basic_), base::UTF8ToUTF16(password_));
301 base::string16 expected_title2 = ExpectedTitleFromAuth(
302 base::UTF8ToUTF16(username_digest_), base::UTF8ToUTF16(password_));
303 content::TitleWatcher title_watcher1(contents1, expected_title1);
304 content::TitleWatcher title_watcher2(contents2, expected_title2);
306 handler1->SetAuth(base::UTF8ToUTF16(username_basic_),
307 base::UTF8ToUTF16(password_));
308 handler2->SetAuth(base::UTF8ToUTF16(username_digest_),
309 base::UTF8ToUTF16(password_));
311 EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
312 EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
315 // Test login prompt cancellation.
316 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestCancelAuth) {
317 ASSERT_TRUE(test_server()->Start());
318 GURL auth_page = test_server()->GetURL(kAuthBasicPage);
319 GURL no_auth_page_1 = test_server()->GetURL("a");
320 GURL no_auth_page_2 = test_server()->GetURL("b");
321 GURL no_auth_page_3 = test_server()->GetURL("c");
323 content::WebContents* contents =
324 browser()->tab_strip_model()->GetActiveWebContents();
325 NavigationController* controller = &contents->GetController();
327 LoginPromptBrowserTestObserver observer;
328 observer.Register(content::Source<NavigationController>(controller));
330 // First navigate to an unauthenticated page so we have something to
332 ui_test_utils::NavigateToURL(browser(), no_auth_page_1);
334 // Navigating while auth is requested is the same as cancelling.
336 // We need to wait for two LOAD_STOP events. One for auth_page and one for
338 WindowedLoadStopObserver load_stop_waiter(controller, 2);
339 WindowedAuthNeededObserver auth_needed_waiter(controller);
340 browser()->OpenURL(OpenURLParams(
341 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
343 auth_needed_waiter.Wait();
344 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
345 browser()->OpenURL(OpenURLParams(
346 no_auth_page_2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
348 auth_cancelled_waiter.Wait();
349 load_stop_waiter.Wait();
350 EXPECT_TRUE(observer.handlers().empty());
353 // Try navigating backwards.
355 // As above, we wait for two LOAD_STOP events; one for each navigation.
356 WindowedLoadStopObserver load_stop_waiter(controller, 2);
357 WindowedAuthNeededObserver auth_needed_waiter(controller);
358 browser()->OpenURL(OpenURLParams(
359 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
361 auth_needed_waiter.Wait();
362 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
363 ASSERT_TRUE(chrome::CanGoBack(browser()));
364 chrome::GoBack(browser(), CURRENT_TAB);
365 auth_cancelled_waiter.Wait();
366 load_stop_waiter.Wait();
367 EXPECT_TRUE(observer.handlers().empty());
370 // Now add a page and go back, so we have something to go forward to.
371 ui_test_utils::NavigateToURL(browser(), no_auth_page_3);
373 WindowedLoadStopObserver load_stop_waiter(controller, 1);
374 chrome::GoBack(browser(), CURRENT_TAB); // Should take us to page 1
375 load_stop_waiter.Wait();
379 // We wait for two LOAD_STOP events; one for each navigation.
380 WindowedLoadStopObserver load_stop_waiter(controller, 2);
381 WindowedAuthNeededObserver auth_needed_waiter(controller);
382 browser()->OpenURL(OpenURLParams(
383 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
385 auth_needed_waiter.Wait();
386 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
387 ASSERT_TRUE(chrome::CanGoForward(browser()));
388 chrome::GoForward(browser(), CURRENT_TAB); // Should take us to page 3
389 auth_cancelled_waiter.Wait();
390 load_stop_waiter.Wait();
391 EXPECT_TRUE(observer.handlers().empty());
394 // Now test that cancelling works as expected.
396 WindowedLoadStopObserver load_stop_waiter(controller, 1);
397 WindowedAuthNeededObserver auth_needed_waiter(controller);
398 browser()->OpenURL(OpenURLParams(
399 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
401 auth_needed_waiter.Wait();
402 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
403 LoginHandler* handler = *observer.handlers().begin();
404 ASSERT_TRUE(handler);
405 handler->CancelAuth();
406 auth_cancelled_waiter.Wait();
407 load_stop_waiter.Wait();
408 EXPECT_TRUE(observer.handlers().empty());
412 // Test handling of resources that require authentication even though
413 // the page they are included on doesn't. In this case we should only
414 // present the minimal number of prompts necessary for successfully
415 // displaying the page. First we check whether cancelling works as
417 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
418 ASSERT_TRUE(test_server()->Start());
419 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
421 content::WebContents* contents =
422 browser()->tab_strip_model()->GetActiveWebContents();
423 NavigationController* controller = &contents->GetController();
424 LoginPromptBrowserTestObserver observer;
426 observer.Register(content::Source<NavigationController>(controller));
428 WindowedLoadStopObserver load_stop_waiter(controller, 1);
431 WindowedAuthNeededObserver auth_needed_waiter(controller);
432 browser()->OpenURL(OpenURLParams(
433 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
435 auth_needed_waiter.Wait();
440 while (n_handlers < kMultiRealmTestRealmCount) {
441 WindowedAuthNeededObserver auth_needed_waiter(controller);
443 while (!observer.handlers().empty()) {
444 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
445 LoginHandler* handler = *observer.handlers().begin();
447 ASSERT_TRUE(handler);
449 handler->CancelAuth();
450 auth_cancelled_waiter.Wait();
453 if (n_handlers < kMultiRealmTestRealmCount)
454 auth_needed_waiter.Wait();
457 load_stop_waiter.Wait();
459 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
460 EXPECT_EQ(0, observer.auth_supplied_count());
461 EXPECT_LT(0, observer.auth_needed_count());
462 EXPECT_LT(0, observer.auth_cancelled_count());
463 EXPECT_TRUE(test_server()->Stop());
466 // Similar to the MultipleRealmCancellation test above, but tests
467 // whether supplying credentials work as exepcted.
468 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
469 ASSERT_TRUE(test_server()->Start());
470 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
472 content::WebContents* contents =
473 browser()->tab_strip_model()->GetActiveWebContents();
474 NavigationController* controller = &contents->GetController();
475 LoginPromptBrowserTestObserver observer;
477 observer.Register(content::Source<NavigationController>(controller));
479 WindowedLoadStopObserver load_stop_waiter(controller, 1);
483 WindowedAuthNeededObserver auth_needed_waiter(controller);
485 browser()->OpenURL(OpenURLParams(
486 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
488 auth_needed_waiter.Wait();
491 while (n_handlers < kMultiRealmTestRealmCount) {
492 WindowedAuthNeededObserver auth_needed_waiter(controller);
494 while (!observer.handlers().empty()) {
495 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
496 LoginHandler* handler = *observer.handlers().begin();
498 ASSERT_TRUE(handler);
501 auth_supplied_waiter.Wait();
504 if (n_handlers < kMultiRealmTestRealmCount)
505 auth_needed_waiter.Wait();
508 load_stop_waiter.Wait();
510 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
511 EXPECT_LT(0, observer.auth_needed_count());
512 EXPECT_LT(0, observer.auth_supplied_count());
513 EXPECT_EQ(0, observer.auth_cancelled_count());
514 EXPECT_TRUE(test_server()->Stop());
517 // Testing for recovery from an incorrect password for the case where
518 // there are multiple authenticated resources.
519 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, IncorrectConfirmation) {
520 ASSERT_TRUE(test_server()->Start());
521 GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
523 content::WebContents* contents =
524 browser()->tab_strip_model()->GetActiveWebContents();
525 NavigationController* controller = &contents->GetController();
526 LoginPromptBrowserTestObserver observer;
528 observer.Register(content::Source<NavigationController>(controller));
531 WindowedAuthNeededObserver auth_needed_waiter(controller);
532 browser()->OpenURL(OpenURLParams(
533 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
535 auth_needed_waiter.Wait();
538 EXPECT_FALSE(observer.handlers().empty());
540 if (!observer.handlers().empty()) {
541 WindowedAuthNeededObserver auth_needed_waiter(controller);
542 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
543 LoginHandler* handler = *observer.handlers().begin();
545 ASSERT_TRUE(handler);
546 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
547 base::UTF8ToUTF16(bad_password_));
548 auth_supplied_waiter.Wait();
550 // The request should be retried after the incorrect password is
551 // supplied. This should result in a new AUTH_NEEDED notification
552 // for the same realm.
553 auth_needed_waiter.Wait();
558 while (n_handlers < 1) {
559 WindowedAuthNeededObserver auth_needed_waiter(controller);
561 while (!observer.handlers().empty()) {
562 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
563 LoginHandler* handler = *observer.handlers().begin();
565 ASSERT_TRUE(handler);
568 auth_supplied_waiter.Wait();
572 auth_needed_waiter.Wait();
575 // The single realm test has only one realm, and thus only one login
577 EXPECT_EQ(1, n_handlers);
578 EXPECT_LT(0, observer.auth_needed_count());
579 EXPECT_EQ(0, observer.auth_cancelled_count());
580 EXPECT_EQ(observer.auth_needed_count(), observer.auth_supplied_count());
581 EXPECT_TRUE(test_server()->Stop());
584 // If the favicon is an authenticated resource, we shouldn't prompt
585 // for credentials. The same URL, if requested elsewhere should
586 // prompt for credentials.
587 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, NoLoginPromptForFavicon) {
588 const char* kFaviconTestPage = "files/login/has_favicon.html";
589 const char* kFaviconResource = "auth-basic/favicon.gif";
591 ASSERT_TRUE(test_server()->Start());
593 content::WebContents* contents =
594 browser()->tab_strip_model()->GetActiveWebContents();
595 NavigationController* controller = &contents->GetController();
596 LoginPromptBrowserTestObserver observer;
598 observer.Register(content::Source<NavigationController>(controller));
600 // First load a page that has a favicon that requires
601 // authentication. There should be no login prompt.
603 GURL test_page = test_server()->GetURL(kFaviconTestPage);
604 WindowedLoadStopObserver load_stop_waiter(controller, 1);
605 browser()->OpenURL(OpenURLParams(
606 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
608 load_stop_waiter.Wait();
611 // Now request the same favicon, but directly as the document.
612 // There should be one login prompt.
614 GURL test_page = test_server()->GetURL(kFaviconResource);
615 WindowedLoadStopObserver load_stop_waiter(controller, 1);
616 WindowedAuthNeededObserver auth_needed_waiter(controller);
617 browser()->OpenURL(OpenURLParams(
618 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
620 auth_needed_waiter.Wait();
621 ASSERT_EQ(1u, observer.handlers().size());
623 while (!observer.handlers().empty()) {
624 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
625 LoginHandler* handler = *observer.handlers().begin();
627 ASSERT_TRUE(handler);
628 handler->CancelAuth();
629 auth_cancelled_waiter.Wait();
632 load_stop_waiter.Wait();
635 EXPECT_EQ(0, observer.auth_supplied_count());
636 EXPECT_EQ(1, observer.auth_needed_count());
637 EXPECT_EQ(1, observer.auth_cancelled_count());
638 EXPECT_TRUE(test_server()->Stop());
641 // Block crossdomain image login prompting as a phishing defense.
642 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
643 BlockCrossdomainPromptForSubresources) {
644 const char* kTestPage = "files/login/load_img_from_b.html";
646 host_resolver()->AddRule("www.a.com", "127.0.0.1");
647 host_resolver()->AddRule("www.b.com", "127.0.0.1");
648 ASSERT_TRUE(test_server()->Start());
650 content::WebContents* contents =
651 browser()->tab_strip_model()->GetActiveWebContents();
652 NavigationController* controller = &contents->GetController();
653 LoginPromptBrowserTestObserver observer;
654 observer.Register(content::Source<NavigationController>(controller));
656 // Load a page that has a cross-domain sub-resource authentication.
657 // There should be no login prompt.
659 GURL test_page = test_server()->GetURL(kTestPage);
660 ASSERT_EQ("127.0.0.1", test_page.host());
662 // Change the host from 127.0.0.1 to www.a.com so that when the
663 // page tries to load from b, it will be cross-origin.
664 std::string new_host("www.a.com");
665 GURL::Replacements replacements;
666 replacements.SetHostStr(new_host);
667 test_page = test_page.ReplaceComponents(replacements);
669 WindowedLoadStopObserver load_stop_waiter(controller, 1);
670 browser()->OpenURL(OpenURLParams(
671 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
673 load_stop_waiter.Wait();
676 EXPECT_EQ(0, observer.auth_needed_count());
678 // Now request the same page, but from the same origin.
679 // There should be one login prompt.
681 GURL test_page = test_server()->GetURL(kTestPage);
682 ASSERT_EQ("127.0.0.1", test_page.host());
684 // Change the host from 127.0.0.1 to www.b.com so that when the
685 // page tries to load from b, it will be same-origin.
686 std::string new_host("www.b.com");
687 GURL::Replacements replacements;
688 replacements.SetHostStr(new_host);
689 test_page = test_page.ReplaceComponents(replacements);
691 WindowedAuthNeededObserver auth_needed_waiter(controller);
692 browser()->OpenURL(OpenURLParams(
693 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
695 auth_needed_waiter.Wait();
696 ASSERT_EQ(1u, observer.handlers().size());
698 while (!observer.handlers().empty()) {
699 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
700 LoginHandler* handler = *observer.handlers().begin();
702 ASSERT_TRUE(handler);
703 handler->CancelAuth();
704 auth_cancelled_waiter.Wait();
708 EXPECT_EQ(1, observer.auth_needed_count());
709 EXPECT_TRUE(test_server()->Stop());
712 // Allow crossdomain iframe login prompting despite the above.
713 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
714 AllowCrossdomainPromptForSubframes) {
715 const char* kTestPage = "files/login/load_iframe_from_b.html";
717 host_resolver()->AddRule("www.a.com", "127.0.0.1");
718 host_resolver()->AddRule("www.b.com", "127.0.0.1");
719 ASSERT_TRUE(test_server()->Start());
721 content::WebContents* contents =
722 browser()->tab_strip_model()->GetActiveWebContents();
723 NavigationController* controller = &contents->GetController();
724 LoginPromptBrowserTestObserver observer;
725 observer.Register(content::Source<NavigationController>(controller));
727 // Load a page that has a cross-domain iframe authentication.
729 GURL test_page = test_server()->GetURL(kTestPage);
730 ASSERT_EQ("127.0.0.1", test_page.host());
732 // Change the host from 127.0.0.1 to www.a.com so that when the
733 // page tries to load from b, it will be cross-origin.
734 std::string new_host("www.a.com");
735 GURL::Replacements replacements;
736 replacements.SetHostStr(new_host);
737 test_page = test_page.ReplaceComponents(replacements);
739 WindowedAuthNeededObserver auth_needed_waiter(controller);
740 browser()->OpenURL(OpenURLParams(
741 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
743 auth_needed_waiter.Wait();
744 ASSERT_EQ(1u, observer.handlers().size());
746 while (!observer.handlers().empty()) {
747 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
748 LoginHandler* handler = *observer.handlers().begin();
750 ASSERT_TRUE(handler);
751 // When a cross origin iframe displays a login prompt, the blank
752 // interstitial shouldn't be displayed and the omnibox should show the
753 // main frame's url, not the iframe's.
754 EXPECT_EQ(new_host, contents->GetVisibleURL().host());
756 handler->CancelAuth();
757 auth_cancelled_waiter.Wait();
761 // Should stay on the main frame's url once the prompt the iframe is closed.
762 EXPECT_EQ("www.a.com", contents->GetVisibleURL().host());
764 EXPECT_EQ(1, observer.auth_needed_count());
765 EXPECT_TRUE(test_server()->Stop());
768 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, SupplyRedundantAuths) {
769 ASSERT_TRUE(test_server()->Start());
771 // Get NavigationController for tab 1.
772 content::WebContents* contents_1 =
773 browser()->tab_strip_model()->GetActiveWebContents();
774 NavigationController* controller_1 = &contents_1->GetController();
777 ui_test_utils::NavigateToURLWithDisposition(
781 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
783 // Get NavigationController for tab 2.
784 content::WebContents* contents_2 =
785 browser()->tab_strip_model()->GetActiveWebContents();
786 ASSERT_NE(contents_1, contents_2);
787 NavigationController* controller_2 = &contents_2->GetController();
789 LoginPromptBrowserTestObserver observer;
790 observer.Register(content::Source<NavigationController>(controller_1));
791 observer.Register(content::Source<NavigationController>(controller_2));
794 // Open different auth urls in each tab.
795 WindowedAuthNeededObserver auth_needed_waiter_1(controller_1);
796 WindowedAuthNeededObserver auth_needed_waiter_2(controller_2);
797 contents_1->OpenURL(OpenURLParams(
798 test_server()->GetURL("auth-basic/1"),
801 ui::PAGE_TRANSITION_TYPED,
803 contents_2->OpenURL(OpenURLParams(
804 test_server()->GetURL("auth-basic/2"),
807 ui::PAGE_TRANSITION_TYPED,
809 auth_needed_waiter_1.Wait();
810 auth_needed_waiter_2.Wait();
812 ASSERT_EQ(2U, observer.handlers().size());
814 // Supply auth in one of the tabs.
815 WindowedAuthSuppliedObserver auth_supplied_waiter_1(controller_1);
816 WindowedAuthSuppliedObserver auth_supplied_waiter_2(controller_2);
817 LoginHandler* handler_1 = *observer.handlers().begin();
818 ASSERT_TRUE(handler_1);
819 SetAuthFor(handler_1);
821 // Both tabs should be authenticated.
822 auth_supplied_waiter_1.Wait();
823 auth_supplied_waiter_2.Wait();
826 EXPECT_EQ(2, observer.auth_needed_count());
827 EXPECT_EQ(2, observer.auth_supplied_count());
828 EXPECT_EQ(0, observer.auth_cancelled_count());
829 EXPECT_TRUE(test_server()->Stop());
832 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, CancelRedundantAuths) {
833 ASSERT_TRUE(test_server()->Start());
835 // Get NavigationController for tab 1.
836 content::WebContents* contents_1 =
837 browser()->tab_strip_model()->GetActiveWebContents();
838 NavigationController* controller_1 = &contents_1->GetController();
841 ui_test_utils::NavigateToURLWithDisposition(
845 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
847 // Get NavigationController for tab 2.
848 content::WebContents* contents_2 =
849 browser()->tab_strip_model()->GetActiveWebContents();
850 ASSERT_NE(contents_1, contents_2);
851 NavigationController* controller_2 = &contents_2->GetController();
853 LoginPromptBrowserTestObserver observer;
854 observer.Register(content::Source<NavigationController>(controller_1));
855 observer.Register(content::Source<NavigationController>(controller_2));
858 // Open different auth urls in each tab.
859 WindowedAuthNeededObserver auth_needed_waiter_1(controller_1);
860 WindowedAuthNeededObserver auth_needed_waiter_2(controller_2);
861 contents_1->OpenURL(OpenURLParams(
862 test_server()->GetURL("auth-basic/1"),
865 ui::PAGE_TRANSITION_TYPED,
867 contents_2->OpenURL(OpenURLParams(
868 test_server()->GetURL("auth-basic/2"),
871 ui::PAGE_TRANSITION_TYPED,
873 auth_needed_waiter_1.Wait();
874 auth_needed_waiter_2.Wait();
876 ASSERT_EQ(2U, observer.handlers().size());
878 // Cancel auth in one of the tabs.
879 WindowedAuthCancelledObserver auth_cancelled_waiter_1(controller_1);
880 WindowedAuthCancelledObserver auth_cancelled_waiter_2(controller_2);
881 LoginHandler* handler_1 = *observer.handlers().begin();
882 ASSERT_TRUE(handler_1);
883 handler_1->CancelAuth();
885 // Both tabs should cancel auth.
886 auth_cancelled_waiter_1.Wait();
887 auth_cancelled_waiter_2.Wait();
890 EXPECT_EQ(2, observer.auth_needed_count());
891 EXPECT_EQ(0, observer.auth_supplied_count());
892 EXPECT_EQ(2, observer.auth_cancelled_count());
893 EXPECT_TRUE(test_server()->Stop());
896 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
897 SupplyRedundantAuthsMultiProfile) {
898 ASSERT_TRUE(test_server()->Start());
900 // Get NavigationController for regular tab.
901 content::WebContents* contents =
902 browser()->tab_strip_model()->GetActiveWebContents();
903 NavigationController* controller = &contents->GetController();
905 // Open an incognito window.
906 Browser* browser_incognito = CreateIncognitoBrowser();
908 // Get NavigationController for incognito tab.
909 content::WebContents* contents_incognito =
910 browser_incognito->tab_strip_model()->GetActiveWebContents();
911 ASSERT_NE(contents, contents_incognito);
912 NavigationController* controller_incognito =
913 &contents_incognito->GetController();
915 LoginPromptBrowserTestObserver observer;
916 observer.Register(content::Source<NavigationController>(controller));
917 LoginPromptBrowserTestObserver observer_incognito;
918 observer_incognito.Register(
919 content::Source<NavigationController>(controller_incognito));
922 // Open an auth url in each window.
923 WindowedAuthNeededObserver auth_needed_waiter(controller);
924 WindowedAuthNeededObserver auth_needed_waiter_incognito(
925 controller_incognito);
926 contents->OpenURL(OpenURLParams(
927 test_server()->GetURL("auth-basic/1"),
930 ui::PAGE_TRANSITION_TYPED,
932 contents_incognito->OpenURL(OpenURLParams(
933 test_server()->GetURL("auth-basic/2"),
936 ui::PAGE_TRANSITION_TYPED,
938 auth_needed_waiter.Wait();
939 auth_needed_waiter_incognito.Wait();
941 ASSERT_EQ(1U, observer.handlers().size());
942 ASSERT_EQ(1U, observer_incognito.handlers().size());
944 // Supply auth in regular tab.
945 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
946 LoginHandler* handler = *observer.handlers().begin();
947 ASSERT_TRUE(handler);
950 // Regular tab should be authenticated.
951 auth_supplied_waiter.Wait();
953 // There's not really a way to wait for the incognito window to "do
954 // nothing". Run anything pending in the message loop just to be sure.
955 // (This shouldn't be necessary since notifications are synchronous, but
956 // maybe it will help avoid flake someday in the future..)
957 content::RunAllPendingInMessageLoop();
960 EXPECT_EQ(1, observer.auth_needed_count());
961 EXPECT_EQ(1, observer.auth_supplied_count());
962 EXPECT_EQ(0, observer.auth_cancelled_count());
963 EXPECT_EQ(1, observer_incognito.auth_needed_count());
964 EXPECT_EQ(0, observer_incognito.auth_supplied_count());
965 EXPECT_EQ(0, observer_incognito.auth_cancelled_count());
966 EXPECT_TRUE(test_server()->Stop());
969 // If an XMLHttpRequest is made with incorrect credentials, there should be no
970 // login prompt; instead the 401 status should be returned to the script.
971 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
972 NoLoginPromptForXHRWithBadCredentials) {
973 const char* kXHRTestPage = "files/login/xhr_with_credentials.html#incorrect";
975 ASSERT_TRUE(test_server()->Start());
977 content::WebContents* contents =
978 browser()->tab_strip_model()->GetActiveWebContents();
979 NavigationController* controller = &contents->GetController();
980 LoginPromptBrowserTestObserver observer;
982 observer.Register(content::Source<NavigationController>(controller));
984 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
985 // resource with the wrong credentials. There should be no login prompt.
987 GURL test_page = test_server()->GetURL(kXHRTestPage);
988 WindowedLoadStopObserver load_stop_waiter(controller, 1);
989 browser()->OpenURL(OpenURLParams(
990 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
992 load_stop_waiter.Wait();
995 base::string16 expected_title(base::UTF8ToUTF16("status=401"));
997 EXPECT_EQ(expected_title, contents->GetTitle());
998 EXPECT_EQ(0, observer.auth_supplied_count());
999 EXPECT_EQ(0, observer.auth_needed_count());
1000 EXPECT_EQ(0, observer.auth_cancelled_count());
1001 EXPECT_TRUE(test_server()->Stop());
1004 // If an XMLHttpRequest is made with correct credentials, there should be no
1005 // login prompt either.
1006 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1007 NoLoginPromptForXHRWithGoodCredentials) {
1008 const char* kXHRTestPage = "files/login/xhr_with_credentials.html#secret";
1010 ASSERT_TRUE(test_server()->Start());
1012 content::WebContents* contents =
1013 browser()->tab_strip_model()->GetActiveWebContents();
1014 NavigationController* controller = &contents->GetController();
1015 LoginPromptBrowserTestObserver observer;
1017 observer.Register(content::Source<NavigationController>(controller));
1019 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1020 // resource with the wrong credentials. There should be no login prompt.
1022 GURL test_page = test_server()->GetURL(kXHRTestPage);
1023 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1024 browser()->OpenURL(OpenURLParams(
1025 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1027 load_stop_waiter.Wait();
1030 base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1032 EXPECT_EQ(expected_title, contents->GetTitle());
1033 EXPECT_EQ(0, observer.auth_supplied_count());
1034 EXPECT_EQ(0, observer.auth_needed_count());
1035 EXPECT_EQ(0, observer.auth_cancelled_count());
1036 EXPECT_TRUE(test_server()->Stop());
1039 // If an XMLHttpRequest is made without credentials, there should be a login
1041 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1042 LoginPromptForXHRWithoutCredentials) {
1043 const char* kXHRTestPage = "files/login/xhr_without_credentials.html";
1045 ASSERT_TRUE(test_server()->Start());
1047 content::WebContents* contents =
1048 browser()->tab_strip_model()->GetActiveWebContents();
1049 NavigationController* controller = &contents->GetController();
1050 LoginPromptBrowserTestObserver observer;
1052 observer.Register(content::Source<NavigationController>(controller));
1054 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1055 // resource with the wrong credentials. There should be no login prompt.
1057 GURL test_page = test_server()->GetURL(kXHRTestPage);
1058 WindowedAuthNeededObserver auth_needed_waiter(controller);
1059 browser()->OpenURL(OpenURLParams(
1060 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1062 auth_needed_waiter.Wait();
1065 ASSERT_FALSE(observer.handlers().empty());
1067 WindowedAuthNeededObserver auth_needed_waiter(controller);
1068 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1069 LoginHandler* handler = *observer.handlers().begin();
1071 ASSERT_TRUE(handler);
1072 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
1073 base::UTF8ToUTF16(bad_password_));
1074 auth_supplied_waiter.Wait();
1076 // The request should be retried after the incorrect password is
1077 // supplied. This should result in a new AUTH_NEEDED notification
1078 // for the same realm.
1079 auth_needed_waiter.Wait();
1082 ASSERT_EQ(1u, observer.handlers().size());
1083 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1084 LoginHandler* handler = *observer.handlers().begin();
1086 base::string16 username(base::UTF8ToUTF16(username_digest_));
1087 base::string16 password(base::UTF8ToUTF16(password_));
1088 handler->SetAuth(username, password);
1089 auth_supplied_waiter.Wait();
1091 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1092 load_stop_waiter.Wait();
1094 base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1096 EXPECT_EQ(expected_title, contents->GetTitle());
1097 EXPECT_EQ(2, observer.auth_supplied_count());
1098 EXPECT_EQ(2, observer.auth_needed_count());
1099 EXPECT_EQ(0, observer.auth_cancelled_count());
1100 EXPECT_TRUE(test_server()->Stop());
1103 // If an XMLHttpRequest is made without credentials, there should be a login
1104 // prompt. If it's cancelled, the script should get a 401 status.
1105 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1106 LoginPromptForXHRWithoutCredentialsCancelled) {
1107 const char* kXHRTestPage = "files/login/xhr_without_credentials.html";
1109 ASSERT_TRUE(test_server()->Start());
1111 content::WebContents* contents =
1112 browser()->tab_strip_model()->GetActiveWebContents();
1113 NavigationController* controller = &contents->GetController();
1114 LoginPromptBrowserTestObserver observer;
1116 observer.Register(content::Source<NavigationController>(controller));
1118 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1119 // resource with the wrong credentials. There should be no login prompt.
1121 GURL test_page = test_server()->GetURL(kXHRTestPage);
1122 WindowedAuthNeededObserver auth_needed_waiter(controller);
1123 browser()->OpenURL(OpenURLParams(
1124 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1126 auth_needed_waiter.Wait();
1129 ASSERT_EQ(1u, observer.handlers().size());
1130 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
1131 LoginHandler* handler = *observer.handlers().begin();
1133 handler->CancelAuth();
1134 auth_cancelled_waiter.Wait();
1136 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1137 load_stop_waiter.Wait();
1139 base::string16 expected_title(base::UTF8ToUTF16("status=401"));
1141 EXPECT_EQ(expected_title, contents->GetTitle());
1142 EXPECT_EQ(0, observer.auth_supplied_count());
1143 EXPECT_EQ(1, observer.auth_needed_count());
1144 EXPECT_EQ(1, observer.auth_cancelled_count());
1145 EXPECT_TRUE(test_server()->Stop());
1148 // If a cross origin navigation triggers a login prompt, the destination URL
1149 // should be shown in the omnibox.
1150 void LoginPromptBrowserTest::TestCrossOriginPrompt(
1151 const GURL& visit_url,
1152 const std::string& auth_host) const {
1153 content::WebContents* contents =
1154 browser()->tab_strip_model()->GetActiveWebContents();
1155 NavigationController* controller = &contents->GetController();
1156 LoginPromptBrowserTestObserver observer;
1158 observer.Register(content::Source<NavigationController>(controller));
1160 // Load a page which will trigger a login prompt.
1162 WindowedAuthNeededObserver auth_needed_waiter(controller);
1163 browser()->OpenURL(OpenURLParams(
1164 visit_url, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1166 ASSERT_EQ(visit_url.host(), contents->GetVisibleURL().host());
1167 auth_needed_waiter.Wait();
1168 ASSERT_EQ(1u, observer.handlers().size());
1169 content::WaitForInterstitialAttach(contents);
1171 // The omnibox should show the correct origin for the new page when the
1172 // login prompt is shown.
1173 EXPECT_EQ(auth_host, contents->GetVisibleURL().host());
1174 EXPECT_TRUE(contents->ShowingInterstitialPage());
1176 // Cancel and wait for the interstitial to detach.
1177 LoginHandler* handler = *observer.handlers().begin();
1178 content::RunTaskAndWaitForInterstitialDetach(
1179 contents, base::Bind(&LoginHandler::CancelAuth, handler));
1181 EXPECT_EQ(auth_host, contents->GetVisibleURL().host());
1182 EXPECT_FALSE(contents->ShowingInterstitialPage());
1186 // If a cross origin direct navigation triggers a login prompt, the login
1187 // interstitial should be shown.
1188 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1189 ShowCorrectUrlForCrossOriginMainFrameRequests) {
1190 ASSERT_TRUE(test_server()->Start());
1192 GURL test_page = test_server()->GetURL(kAuthBasicPage);
1193 ASSERT_EQ("127.0.0.1", test_page.host());
1194 std::string auth_host("127.0.0.1");
1195 TestCrossOriginPrompt(test_page, auth_host);
1198 // If a cross origin redirect triggers a login prompt, the destination URL
1199 // should be shown in the omnibox when the auth dialog is displayed.
1200 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1201 ShowCorrectUrlForCrossOriginMainFrameRedirects) {
1202 host_resolver()->AddRule("www.a.com", "127.0.0.1");
1203 ASSERT_TRUE(test_server()->Start());
1205 const char* kTestPage = "files/login/cross_origin.html";
1206 GURL test_page = test_server()->GetURL(kTestPage);
1207 ASSERT_EQ("127.0.0.1", test_page.host());
1208 std::string auth_host("www.a.com");
1209 TestCrossOriginPrompt(test_page, auth_host);
1212 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1213 LoginInterstitialShouldReplaceExistingInterstitial) {
1214 net::SpawnedTestServer https_server(
1215 net::SpawnedTestServer::TYPE_HTTPS,
1216 net::SpawnedTestServer::SSLOptions(
1217 net::SpawnedTestServer::SSLOptions::CERT_EXPIRED),
1219 ASSERT_TRUE(https_server.Start());
1221 content::WebContents* contents =
1222 browser()->tab_strip_model()->GetActiveWebContents();
1223 NavigationController* controller = &contents->GetController();
1224 LoginPromptBrowserTestObserver observer;
1226 observer.Register(content::Source<NavigationController>(controller));
1228 // Load a page which triggers an SSL interstitial. Proceeding through it
1229 // should show the login page with the blank interstitial.
1231 GURL test_page = https_server.GetURL(kAuthBasicPage);
1232 ASSERT_EQ("127.0.0.1", test_page.host());
1234 WindowedAuthNeededObserver auth_needed_waiter(controller);
1235 browser()->OpenURL(OpenURLParams(
1236 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1238 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1239 content::WaitForInterstitialAttach(contents);
1241 // An overrideable SSL interstitial is now being displayed. Proceed through
1242 // the interstitial to see the login prompt.
1243 contents->GetInterstitialPage()->Proceed();
1244 auth_needed_waiter.Wait();
1245 ASSERT_EQ(1u, observer.handlers().size());
1246 content::WaitForInterstitialAttach(contents);
1248 // The omnibox should show the correct origin while the login prompt is
1250 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1251 EXPECT_TRUE(contents->ShowingInterstitialPage());
1253 // Cancelling the login prompt should detach the interstitial while keeping
1254 // the correct origin.
1255 LoginHandler* handler = *observer.handlers().begin();
1256 content::RunTaskAndWaitForInterstitialDetach(
1257 contents, base::Bind(&LoginHandler::CancelAuth, handler));
1259 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1260 EXPECT_FALSE(contents->ShowingInterstitialPage());