Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / login / login_prompt_browsertest.cc
bloba284438c112e559c06aae0cd86dc0fcc49d1feb5
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.
5 #include <algorithm>
6 #include <list>
7 #include <map>
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/ssl/ssl_blocking_page.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/login/login_interstitial_delegate.h"
17 #include "chrome/browser/ui/login/login_prompt.h"
18 #include "chrome/browser/ui/login/login_prompt_test_utils.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/browser/interstitial_page.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/test/browser_test_utils.h"
27 #include "content/public/test/test_navigation_observer.h"
28 #include "net/base/auth.h"
29 #include "net/dns/mock_host_resolver.h"
30 #include "net/test/spawned_test_server/spawned_test_server.h"
32 using content::NavigationController;
33 using content::OpenURLParams;
34 using content::Referrer;
36 namespace {
38 class LoginPromptBrowserTest : public InProcessBrowserTest {
39 public:
40 LoginPromptBrowserTest()
41 : bad_password_("incorrect"),
42 bad_username_("nouser"),
43 password_("secret"),
44 username_basic_("basicuser"),
45 username_digest_("digestuser") {
46 auth_map_["foo"] = AuthInfo("testuser", "foopassword");
47 auth_map_["bar"] = AuthInfo("testuser", "barpassword");
48 auth_map_["testrealm"] = AuthInfo(username_basic_, password_);
51 protected:
52 struct AuthInfo {
53 std::string username_;
54 std::string password_;
56 AuthInfo() {}
58 AuthInfo(const std::string& username,
59 const std::string& password)
60 : username_(username), password_(password) {}
63 typedef std::map<std::string, AuthInfo> AuthMap;
65 void SetAuthFor(LoginHandler* handler);
67 void TestCrossOriginPrompt(const GURL& visit_url,
68 const std::string& landing_host) const;
70 AuthMap auth_map_;
71 std::string bad_password_;
72 std::string bad_username_;
73 std::string password_;
74 std::string username_basic_;
75 std::string username_digest_;
78 void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
79 const net::AuthChallengeInfo* challenge = handler->auth_info();
81 ASSERT_TRUE(challenge);
82 AuthMap::iterator i = auth_map_.find(challenge->realm);
83 EXPECT_TRUE(auth_map_.end() != i);
84 if (i != auth_map_.end()) {
85 const AuthInfo& info = i->second;
86 handler->SetAuth(base::UTF8ToUTF16(info.username_),
87 base::UTF8ToUTF16(info.password_));
91 const char kPrefetchAuthPage[] = "files/login/prefetch.html";
93 const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
94 const int kMultiRealmTestRealmCount = 2;
96 const char kSingleRealmTestPage[] = "files/login/single_realm.html";
98 const char* kAuthBasicPage = "auth-basic";
99 const char* kAuthDigestPage = "auth-digest";
101 base::string16 ExpectedTitleFromAuth(const base::string16& username,
102 const base::string16& password) {
103 // The TestServer sets the title to username/password on successful login.
104 return username + base::UTF8ToUTF16("/") + password;
107 // Confirm that <link rel="prefetch"> targetting an auth required
108 // resource does not provide a login dialog. These types of requests
109 // should instead just cancel the auth.
111 // Unfortunately, this test doesn't assert on anything for its
112 // correctness. Instead, it relies on the auth dialog blocking the
113 // browser, and triggering a timeout to cause failure when the
114 // prefetch resource requires authorization.
115 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
116 ASSERT_TRUE(test_server()->Start());
118 GURL test_page = test_server()->GetURL(kPrefetchAuthPage);
120 class SetPrefetchForTest {
121 public:
122 explicit SetPrefetchForTest(bool prefetch)
123 : old_prerender_mode_(prerender::PrerenderManager::GetMode()) {
124 std::string exp_group = prefetch ? "ExperimentYes" : "ExperimentNo";
125 base::FieldTrialList::CreateFieldTrial("Prefetch", exp_group);
126 // Disable prerender so this is just a prefetch of the top-level page.
127 prerender::PrerenderManager::SetMode(
128 prerender::PrerenderManager::PRERENDER_MODE_DISABLED);
131 ~SetPrefetchForTest() {
132 prerender::PrerenderManager::SetMode(old_prerender_mode_);
135 private:
136 prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_;
137 } set_prefetch_for_test(true);
139 content::WebContents* contents =
140 browser()->tab_strip_model()->GetActiveWebContents();
141 NavigationController* controller = &contents->GetController();
142 LoginPromptBrowserTestObserver observer;
144 observer.Register(content::Source<NavigationController>(controller));
146 WindowedLoadStopObserver load_stop_waiter(controller, 1);
147 browser()->OpenURL(OpenURLParams(
148 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
149 false));
151 load_stop_waiter.Wait();
152 EXPECT_TRUE(observer.handlers().empty());
153 EXPECT_TRUE(test_server()->Stop());
156 // Test that "Basic" HTTP authentication works.
157 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestBasicAuth) {
158 ASSERT_TRUE(test_server()->Start());
159 GURL test_page = test_server()->GetURL(kAuthBasicPage);
161 content::WebContents* contents =
162 browser()->tab_strip_model()->GetActiveWebContents();
163 NavigationController* controller = &contents->GetController();
164 LoginPromptBrowserTestObserver observer;
166 observer.Register(content::Source<NavigationController>(controller));
169 WindowedAuthNeededObserver auth_needed_waiter(controller);
170 browser()->OpenURL(OpenURLParams(
171 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
172 false));
173 auth_needed_waiter.Wait();
176 ASSERT_FALSE(observer.handlers().empty());
178 WindowedAuthNeededObserver auth_needed_waiter(controller);
179 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
180 LoginHandler* handler = *observer.handlers().begin();
182 ASSERT_TRUE(handler);
183 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
184 base::UTF8ToUTF16(bad_password_));
185 auth_supplied_waiter.Wait();
187 // The request should be retried after the incorrect password is
188 // supplied. This should result in a new AUTH_NEEDED notification
189 // for the same realm.
190 auth_needed_waiter.Wait();
193 ASSERT_EQ(1u, observer.handlers().size());
194 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
195 LoginHandler* handler = *observer.handlers().begin();
196 SetAuthFor(handler);
197 auth_supplied_waiter.Wait();
199 base::string16 expected_title =
200 ExpectedTitleFromAuth(base::ASCIIToUTF16("basicuser"),
201 base::ASCIIToUTF16("secret"));
202 content::TitleWatcher title_watcher(contents, expected_title);
203 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
206 // Test that "Digest" HTTP authentication works.
207 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestDigestAuth) {
208 ASSERT_TRUE(test_server()->Start());
209 GURL test_page = test_server()->GetURL(kAuthDigestPage);
211 content::WebContents* contents =
212 browser()->tab_strip_model()->GetActiveWebContents();
213 NavigationController* controller = &contents->GetController();
214 LoginPromptBrowserTestObserver observer;
216 observer.Register(content::Source<NavigationController>(controller));
219 WindowedAuthNeededObserver auth_needed_waiter(controller);
220 browser()->OpenURL(OpenURLParams(
221 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
222 false));
223 auth_needed_waiter.Wait();
226 ASSERT_FALSE(observer.handlers().empty());
228 WindowedAuthNeededObserver auth_needed_waiter(controller);
229 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
230 LoginHandler* handler = *observer.handlers().begin();
232 ASSERT_TRUE(handler);
233 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
234 base::UTF8ToUTF16(bad_password_));
235 auth_supplied_waiter.Wait();
237 // The request should be retried after the incorrect password is
238 // supplied. This should result in a new AUTH_NEEDED notification
239 // for the same realm.
240 auth_needed_waiter.Wait();
243 ASSERT_EQ(1u, observer.handlers().size());
244 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
245 LoginHandler* handler = *observer.handlers().begin();
247 base::string16 username(base::UTF8ToUTF16(username_digest_));
248 base::string16 password(base::UTF8ToUTF16(password_));
249 handler->SetAuth(username, password);
250 auth_supplied_waiter.Wait();
252 base::string16 expected_title = ExpectedTitleFromAuth(username, password);
253 content::TitleWatcher title_watcher(contents, expected_title);
254 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
257 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestTwoAuths) {
258 ASSERT_TRUE(test_server()->Start());
260 content::WebContents* contents1 =
261 browser()->tab_strip_model()->GetActiveWebContents();
262 NavigationController* controller1 = &contents1->GetController();
263 LoginPromptBrowserTestObserver observer;
265 observer.Register(content::Source<NavigationController>(controller1));
267 // Open a new tab.
268 ui_test_utils::NavigateToURLWithDisposition(
269 browser(),
270 GURL("about:blank"),
271 NEW_FOREGROUND_TAB,
272 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
274 content::WebContents* contents2 =
275 browser()->tab_strip_model()->GetActiveWebContents();
276 ASSERT_NE(contents1, contents2);
277 NavigationController* controller2 = &contents2->GetController();
278 observer.Register(content::Source<NavigationController>(controller2));
281 WindowedAuthNeededObserver auth_needed_waiter(controller1);
282 contents1->OpenURL(OpenURLParams(
283 test_server()->GetURL(kAuthBasicPage), Referrer(),
284 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
285 auth_needed_waiter.Wait();
289 WindowedAuthNeededObserver auth_needed_waiter(controller2);
290 contents2->OpenURL(OpenURLParams(
291 test_server()->GetURL(kAuthDigestPage), Referrer(),
292 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
293 auth_needed_waiter.Wait();
296 ASSERT_EQ(2u, observer.handlers().size());
298 LoginHandler* handler1 = *observer.handlers().begin();
299 LoginHandler* handler2 = *(++(observer.handlers().begin()));
301 base::string16 expected_title1 = ExpectedTitleFromAuth(
302 base::UTF8ToUTF16(username_basic_), base::UTF8ToUTF16(password_));
303 base::string16 expected_title2 = ExpectedTitleFromAuth(
304 base::UTF8ToUTF16(username_digest_), base::UTF8ToUTF16(password_));
305 content::TitleWatcher title_watcher1(contents1, expected_title1);
306 content::TitleWatcher title_watcher2(contents2, expected_title2);
308 handler1->SetAuth(base::UTF8ToUTF16(username_basic_),
309 base::UTF8ToUTF16(password_));
310 handler2->SetAuth(base::UTF8ToUTF16(username_digest_),
311 base::UTF8ToUTF16(password_));
313 EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
314 EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
317 // Test login prompt cancellation.
318 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestCancelAuth) {
319 ASSERT_TRUE(test_server()->Start());
320 GURL auth_page = test_server()->GetURL(kAuthBasicPage);
321 GURL no_auth_page_1 = test_server()->GetURL("a");
322 GURL no_auth_page_2 = test_server()->GetURL("b");
323 GURL no_auth_page_3 = test_server()->GetURL("c");
325 content::WebContents* contents =
326 browser()->tab_strip_model()->GetActiveWebContents();
327 NavigationController* controller = &contents->GetController();
329 LoginPromptBrowserTestObserver observer;
330 observer.Register(content::Source<NavigationController>(controller));
332 // First navigate to an unauthenticated page so we have something to
333 // go back to.
334 ui_test_utils::NavigateToURL(browser(), no_auth_page_1);
336 // Navigating while auth is requested is the same as cancelling.
338 // We need to wait for two LOAD_STOP events. One for auth_page and one for
339 // no_auth_page_2.
340 WindowedLoadStopObserver load_stop_waiter(controller, 2);
341 WindowedAuthNeededObserver auth_needed_waiter(controller);
342 browser()->OpenURL(OpenURLParams(
343 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
344 false));
345 auth_needed_waiter.Wait();
346 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
347 browser()->OpenURL(OpenURLParams(
348 no_auth_page_2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
349 false));
350 auth_cancelled_waiter.Wait();
351 load_stop_waiter.Wait();
352 EXPECT_TRUE(observer.handlers().empty());
355 // Try navigating backwards.
357 // As above, we wait for two LOAD_STOP events; one for each navigation.
358 WindowedLoadStopObserver load_stop_waiter(controller, 2);
359 WindowedAuthNeededObserver auth_needed_waiter(controller);
360 browser()->OpenURL(OpenURLParams(
361 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
362 false));
363 auth_needed_waiter.Wait();
364 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
365 ASSERT_TRUE(chrome::CanGoBack(browser()));
366 chrome::GoBack(browser(), CURRENT_TAB);
367 auth_cancelled_waiter.Wait();
368 load_stop_waiter.Wait();
369 EXPECT_TRUE(observer.handlers().empty());
372 // Now add a page and go back, so we have something to go forward to.
373 ui_test_utils::NavigateToURL(browser(), no_auth_page_3);
375 WindowedLoadStopObserver load_stop_waiter(controller, 1);
376 chrome::GoBack(browser(), CURRENT_TAB); // Should take us to page 1
377 load_stop_waiter.Wait();
381 // We wait for two LOAD_STOP events; one for each navigation.
382 WindowedLoadStopObserver load_stop_waiter(controller, 2);
383 WindowedAuthNeededObserver auth_needed_waiter(controller);
384 browser()->OpenURL(OpenURLParams(
385 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
386 false));
387 auth_needed_waiter.Wait();
388 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
389 ASSERT_TRUE(chrome::CanGoForward(browser()));
390 chrome::GoForward(browser(), CURRENT_TAB); // Should take us to page 3
391 auth_cancelled_waiter.Wait();
392 load_stop_waiter.Wait();
393 EXPECT_TRUE(observer.handlers().empty());
396 // Now test that cancelling works as expected.
398 WindowedLoadStopObserver load_stop_waiter(controller, 1);
399 WindowedAuthNeededObserver auth_needed_waiter(controller);
400 browser()->OpenURL(OpenURLParams(
401 auth_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
402 false));
403 auth_needed_waiter.Wait();
404 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
405 LoginHandler* handler = *observer.handlers().begin();
406 ASSERT_TRUE(handler);
407 handler->CancelAuth();
408 auth_cancelled_waiter.Wait();
409 load_stop_waiter.Wait();
410 EXPECT_TRUE(observer.handlers().empty());
414 // Test handling of resources that require authentication even though
415 // the page they are included on doesn't. In this case we should only
416 // present the minimal number of prompts necessary for successfully
417 // displaying the page. First we check whether cancelling works as
418 // expected.
419 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
420 ASSERT_TRUE(test_server()->Start());
421 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
423 content::WebContents* contents =
424 browser()->tab_strip_model()->GetActiveWebContents();
425 NavigationController* controller = &contents->GetController();
426 LoginPromptBrowserTestObserver observer;
428 observer.Register(content::Source<NavigationController>(controller));
430 WindowedLoadStopObserver load_stop_waiter(controller, 1);
433 WindowedAuthNeededObserver auth_needed_waiter(controller);
434 browser()->OpenURL(OpenURLParams(
435 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
436 false));
437 auth_needed_waiter.Wait();
440 int n_handlers = 0;
442 while (n_handlers < kMultiRealmTestRealmCount) {
443 WindowedAuthNeededObserver auth_needed_waiter(controller);
445 while (!observer.handlers().empty()) {
446 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
447 LoginHandler* handler = *observer.handlers().begin();
449 ASSERT_TRUE(handler);
450 n_handlers++;
451 handler->CancelAuth();
452 auth_cancelled_waiter.Wait();
455 if (n_handlers < kMultiRealmTestRealmCount)
456 auth_needed_waiter.Wait();
459 load_stop_waiter.Wait();
461 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
462 EXPECT_EQ(0, observer.auth_supplied_count());
463 EXPECT_LT(0, observer.auth_needed_count());
464 EXPECT_LT(0, observer.auth_cancelled_count());
465 EXPECT_TRUE(test_server()->Stop());
468 // Similar to the MultipleRealmCancellation test above, but tests
469 // whether supplying credentials work as exepcted.
470 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
471 ASSERT_TRUE(test_server()->Start());
472 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
474 content::WebContents* contents =
475 browser()->tab_strip_model()->GetActiveWebContents();
476 NavigationController* controller = &contents->GetController();
477 LoginPromptBrowserTestObserver observer;
479 observer.Register(content::Source<NavigationController>(controller));
481 WindowedLoadStopObserver load_stop_waiter(controller, 1);
482 int n_handlers = 0;
485 WindowedAuthNeededObserver auth_needed_waiter(controller);
487 browser()->OpenURL(OpenURLParams(
488 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
489 false));
490 auth_needed_waiter.Wait();
493 while (n_handlers < kMultiRealmTestRealmCount) {
494 WindowedAuthNeededObserver auth_needed_waiter(controller);
496 while (!observer.handlers().empty()) {
497 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
498 LoginHandler* handler = *observer.handlers().begin();
500 ASSERT_TRUE(handler);
501 n_handlers++;
502 SetAuthFor(handler);
503 auth_supplied_waiter.Wait();
506 if (n_handlers < kMultiRealmTestRealmCount)
507 auth_needed_waiter.Wait();
510 load_stop_waiter.Wait();
512 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
513 EXPECT_LT(0, observer.auth_needed_count());
514 EXPECT_LT(0, observer.auth_supplied_count());
515 EXPECT_EQ(0, observer.auth_cancelled_count());
516 EXPECT_TRUE(test_server()->Stop());
519 // Testing for recovery from an incorrect password for the case where
520 // there are multiple authenticated resources.
521 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, IncorrectConfirmation) {
522 ASSERT_TRUE(test_server()->Start());
523 GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
525 content::WebContents* contents =
526 browser()->tab_strip_model()->GetActiveWebContents();
527 NavigationController* controller = &contents->GetController();
528 LoginPromptBrowserTestObserver observer;
530 observer.Register(content::Source<NavigationController>(controller));
533 WindowedAuthNeededObserver auth_needed_waiter(controller);
534 browser()->OpenURL(OpenURLParams(
535 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
536 false));
537 auth_needed_waiter.Wait();
540 EXPECT_FALSE(observer.handlers().empty());
542 if (!observer.handlers().empty()) {
543 WindowedAuthNeededObserver auth_needed_waiter(controller);
544 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
545 LoginHandler* handler = *observer.handlers().begin();
547 ASSERT_TRUE(handler);
548 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
549 base::UTF8ToUTF16(bad_password_));
550 auth_supplied_waiter.Wait();
552 // The request should be retried after the incorrect password is
553 // supplied. This should result in a new AUTH_NEEDED notification
554 // for the same realm.
555 auth_needed_waiter.Wait();
558 int n_handlers = 0;
560 while (n_handlers < 1) {
561 WindowedAuthNeededObserver auth_needed_waiter(controller);
563 while (!observer.handlers().empty()) {
564 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
565 LoginHandler* handler = *observer.handlers().begin();
567 ASSERT_TRUE(handler);
568 n_handlers++;
569 SetAuthFor(handler);
570 auth_supplied_waiter.Wait();
573 if (n_handlers < 1)
574 auth_needed_waiter.Wait();
577 // The single realm test has only one realm, and thus only one login
578 // prompt.
579 EXPECT_EQ(1, n_handlers);
580 EXPECT_LT(0, observer.auth_needed_count());
581 EXPECT_EQ(0, observer.auth_cancelled_count());
582 EXPECT_EQ(observer.auth_needed_count(), observer.auth_supplied_count());
583 EXPECT_TRUE(test_server()->Stop());
586 // If the favicon is an authenticated resource, we shouldn't prompt
587 // for credentials. The same URL, if requested elsewhere should
588 // prompt for credentials.
589 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, NoLoginPromptForFavicon) {
590 const char* kFaviconTestPage = "files/login/has_favicon.html";
591 const char* kFaviconResource = "auth-basic/favicon.gif";
593 ASSERT_TRUE(test_server()->Start());
595 content::WebContents* contents =
596 browser()->tab_strip_model()->GetActiveWebContents();
597 NavigationController* controller = &contents->GetController();
598 LoginPromptBrowserTestObserver observer;
600 observer.Register(content::Source<NavigationController>(controller));
602 // First load a page that has a favicon that requires
603 // authentication. There should be no login prompt.
605 GURL test_page = test_server()->GetURL(kFaviconTestPage);
606 WindowedLoadStopObserver load_stop_waiter(controller, 1);
607 browser()->OpenURL(OpenURLParams(
608 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
609 false));
610 load_stop_waiter.Wait();
613 // Now request the same favicon, but directly as the document.
614 // There should be one login prompt.
616 GURL test_page = test_server()->GetURL(kFaviconResource);
617 WindowedLoadStopObserver load_stop_waiter(controller, 1);
618 WindowedAuthNeededObserver auth_needed_waiter(controller);
619 browser()->OpenURL(OpenURLParams(
620 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
621 false));
622 auth_needed_waiter.Wait();
623 ASSERT_EQ(1u, observer.handlers().size());
625 while (!observer.handlers().empty()) {
626 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
627 LoginHandler* handler = *observer.handlers().begin();
629 ASSERT_TRUE(handler);
630 handler->CancelAuth();
631 auth_cancelled_waiter.Wait();
634 load_stop_waiter.Wait();
637 EXPECT_EQ(0, observer.auth_supplied_count());
638 EXPECT_EQ(1, observer.auth_needed_count());
639 EXPECT_EQ(1, observer.auth_cancelled_count());
640 EXPECT_TRUE(test_server()->Stop());
643 // Block crossdomain image login prompting as a phishing defense.
644 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
645 BlockCrossdomainPromptForSubresources) {
646 const char* kTestPage = "files/login/load_img_from_b.html";
648 host_resolver()->AddRule("www.a.com", "127.0.0.1");
649 host_resolver()->AddRule("www.b.com", "127.0.0.1");
650 ASSERT_TRUE(test_server()->Start());
652 content::WebContents* contents =
653 browser()->tab_strip_model()->GetActiveWebContents();
654 NavigationController* controller = &contents->GetController();
655 LoginPromptBrowserTestObserver observer;
656 observer.Register(content::Source<NavigationController>(controller));
658 // Load a page that has a cross-domain sub-resource authentication.
659 // There should be no login prompt.
661 GURL test_page = test_server()->GetURL(kTestPage);
662 ASSERT_EQ("127.0.0.1", test_page.host());
664 // Change the host from 127.0.0.1 to www.a.com so that when the
665 // page tries to load from b, it will be cross-origin.
666 GURL::Replacements replacements;
667 replacements.SetHostStr("www.a.com");
668 test_page = test_page.ReplaceComponents(replacements);
670 WindowedLoadStopObserver load_stop_waiter(controller, 1);
671 browser()->OpenURL(OpenURLParams(
672 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
673 false));
674 load_stop_waiter.Wait();
677 EXPECT_EQ(0, observer.auth_needed_count());
679 // Now request the same page, but from the same origin.
680 // There should be one login prompt.
682 GURL test_page = test_server()->GetURL(kTestPage);
683 ASSERT_EQ("127.0.0.1", test_page.host());
685 // Change the host from 127.0.0.1 to www.b.com so that when the
686 // page tries to load from b, it will be same-origin.
687 GURL::Replacements replacements;
688 replacements.SetHostStr("www.b.com");
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,
694 false));
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 static const char kNewHost[] = "www.a.com";
735 GURL::Replacements replacements;
736 replacements.SetHostStr(kNewHost);
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,
742 false));
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(kNewHost, 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();
776 // Open a new tab.
777 ui_test_utils::NavigateToURLWithDisposition(
778 browser(),
779 GURL("about:blank"),
780 NEW_FOREGROUND_TAB,
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"),
799 content::Referrer(),
800 CURRENT_TAB,
801 ui::PAGE_TRANSITION_TYPED,
802 false));
803 contents_2->OpenURL(OpenURLParams(
804 test_server()->GetURL("auth-basic/2"),
805 content::Referrer(),
806 CURRENT_TAB,
807 ui::PAGE_TRANSITION_TYPED,
808 false));
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();
840 // Open a new tab.
841 ui_test_utils::NavigateToURLWithDisposition(
842 browser(),
843 GURL("about:blank"),
844 NEW_FOREGROUND_TAB,
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"),
863 content::Referrer(),
864 CURRENT_TAB,
865 ui::PAGE_TRANSITION_TYPED,
866 false));
867 contents_2->OpenURL(OpenURLParams(
868 test_server()->GetURL("auth-basic/2"),
869 content::Referrer(),
870 CURRENT_TAB,
871 ui::PAGE_TRANSITION_TYPED,
872 false));
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"),
928 content::Referrer(),
929 CURRENT_TAB,
930 ui::PAGE_TRANSITION_TYPED,
931 false));
932 contents_incognito->OpenURL(OpenURLParams(
933 test_server()->GetURL("auth-basic/2"),
934 content::Referrer(),
935 CURRENT_TAB,
936 ui::PAGE_TRANSITION_TYPED,
937 false));
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);
948 SetAuthFor(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,
991 false));
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,
1026 false));
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
1040 // prompt.
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,
1061 false));
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,
1125 false));
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,
1165 false));
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());
1175 EXPECT_EQ(LoginInterstitialDelegate::kTypeForTesting,
1176 contents->GetInterstitialPage()
1177 ->GetDelegateForTesting()
1178 ->GetTypeForTesting());
1180 // Cancel and wait for the interstitial to detach.
1181 LoginHandler* handler = *observer.handlers().begin();
1182 content::RunTaskAndWaitForInterstitialDetach(
1183 contents, base::Bind(&LoginHandler::CancelAuth, handler));
1185 EXPECT_EQ(auth_host, contents->GetVisibleURL().host());
1186 EXPECT_FALSE(contents->ShowingInterstitialPage());
1190 // If a cross origin direct navigation triggers a login prompt, the login
1191 // interstitial should be shown.
1192 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1193 ShowCorrectUrlForCrossOriginMainFrameRequests) {
1194 ASSERT_TRUE(test_server()->Start());
1196 GURL test_page = test_server()->GetURL(kAuthBasicPage);
1197 ASSERT_EQ("127.0.0.1", test_page.host());
1198 std::string auth_host("127.0.0.1");
1199 TestCrossOriginPrompt(test_page, auth_host);
1202 // If a cross origin redirect triggers a login prompt, the destination URL
1203 // should be shown in the omnibox when the auth dialog is displayed.
1204 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1205 ShowCorrectUrlForCrossOriginMainFrameRedirects) {
1206 host_resolver()->AddRule("www.a.com", "127.0.0.1");
1207 ASSERT_TRUE(test_server()->Start());
1209 const char* kTestPage = "files/login/cross_origin.html";
1210 GURL test_page = test_server()->GetURL(kTestPage);
1211 ASSERT_EQ("127.0.0.1", test_page.host());
1212 std::string auth_host("www.a.com");
1213 TestCrossOriginPrompt(test_page, auth_host);
1216 // Test the scenario where proceeding through a different type of interstitial
1217 // that ends up with an auth URL works fine. This can happen if a URL that
1218 // triggers the auth dialog can also trigger an SSL interstitial (or any other
1219 // type of interstitial).
1220 IN_PROC_BROWSER_TEST_F(
1221 LoginPromptBrowserTest,
1222 DISABLED_LoginInterstitialShouldReplaceExistingInterstitial) {
1223 net::SpawnedTestServer https_server(
1224 net::SpawnedTestServer::TYPE_HTTPS,
1225 net::SpawnedTestServer::SSLOptions(
1226 net::SpawnedTestServer::SSLOptions::CERT_EXPIRED),
1227 base::FilePath());
1228 ASSERT_TRUE(https_server.Start());
1230 content::WebContents* contents =
1231 browser()->tab_strip_model()->GetActiveWebContents();
1232 NavigationController* controller = &contents->GetController();
1233 LoginPromptBrowserTestObserver observer;
1235 observer.Register(content::Source<NavigationController>(controller));
1237 // Load a page which triggers an SSL interstitial. Proceeding through it
1238 // should show the login page with the blank interstitial.
1240 GURL test_page = https_server.GetURL(kAuthBasicPage);
1241 ASSERT_EQ("127.0.0.1", test_page.host());
1243 WindowedAuthNeededObserver auth_needed_waiter(controller);
1244 browser()->OpenURL(OpenURLParams(
1245 test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1246 false));
1247 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1248 content::WaitForInterstitialAttach(contents);
1250 EXPECT_EQ(SSLBlockingPage::kTypeForTesting, contents->GetInterstitialPage()
1251 ->GetDelegateForTesting()
1252 ->GetTypeForTesting());
1253 // An overrideable SSL interstitial is now being displayed. Proceed through
1254 // the interstitial to see the login prompt.
1255 contents->GetInterstitialPage()->Proceed();
1256 auth_needed_waiter.Wait();
1257 ASSERT_EQ(1u, observer.handlers().size());
1258 content::WaitForInterstitialAttach(contents);
1260 // The omnibox should show the correct origin while the login prompt is
1261 // being displayed.
1262 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1263 EXPECT_TRUE(contents->ShowingInterstitialPage());
1264 EXPECT_EQ(LoginInterstitialDelegate::kTypeForTesting,
1265 contents->GetInterstitialPage()
1266 ->GetDelegateForTesting()
1267 ->GetTypeForTesting());
1269 // Cancelling the login prompt should detach the interstitial while keeping
1270 // the correct origin.
1271 LoginHandler* handler = *observer.handlers().begin();
1272 content::RunTaskAndWaitForInterstitialDetach(
1273 contents, base::Bind(&LoginHandler::CancelAuth, handler));
1275 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1276 EXPECT_FALSE(contents->ShowingInterstitialPage());
1280 // Test the scenario where an auth interstitial should replace a different type
1281 // of interstitial (e.g. SSL) even though the navigation isn't cross origin.
1282 // This is different than the above scenario in that the last
1283 // committed url is the same as the auth url. This can happen when:
1285 // 1. Tab is navigated to the auth URL and the auth prompt is cancelled.
1286 // 2. Tab is then navigated to an SSL interstitial.
1287 // 3. Tab is again navigated to the same auth URL in (1).
1289 // In this case, the last committed url is the same as the auth URL since the
1290 // navigation at (1) is committed (user clicked cancel and the page loaded), but
1291 // the navigation at (2) isn't (navigations ending up in interstitials don't
1292 // immediately commit). So just checking for cross origin navigation before
1293 // prompting the auth interstitial is not sufficient, must also check if there
1294 // is any other interstitial being displayed.
1295 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1296 ShouldReplaceExistingInterstitialWhenNavigated) {
1297 ASSERT_TRUE(test_server()->Start());
1298 net::SpawnedTestServer https_server(
1299 net::SpawnedTestServer::TYPE_HTTPS,
1300 net::SpawnedTestServer::SSLOptions(
1301 net::SpawnedTestServer::SSLOptions::CERT_EXPIRED),
1302 base::FilePath());
1303 ASSERT_TRUE(https_server.Start());
1305 content::WebContents* contents =
1306 browser()->tab_strip_model()->GetActiveWebContents();
1307 NavigationController* controller = &contents->GetController();
1308 LoginPromptBrowserTestObserver observer;
1310 observer.Register(content::Source<NavigationController>(controller));
1312 GURL auth_url = test_server()->GetURL(kAuthBasicPage);
1313 GURL broken_ssl_page = https_server.GetURL("/");
1315 // Navigate to an auth url and wait for the login prompt.
1317 WindowedAuthNeededObserver auth_needed_waiter(controller);
1318 browser()->OpenURL(OpenURLParams(auth_url, Referrer(), CURRENT_TAB,
1319 ui::PAGE_TRANSITION_TYPED, false));
1320 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1321 ASSERT_TRUE(contents->GetURL().SchemeIs("http"));
1322 auth_needed_waiter.Wait();
1323 ASSERT_EQ(1u, observer.handlers().size());
1324 content::WaitForInterstitialAttach(contents);
1325 ASSERT_TRUE(contents->ShowingInterstitialPage());
1326 EXPECT_EQ(LoginInterstitialDelegate::kTypeForTesting,
1327 contents->GetInterstitialPage()
1328 ->GetDelegateForTesting()
1329 ->GetTypeForTesting());
1330 // Cancel the auth prompt. This commits the navigation.
1331 LoginHandler* handler = *observer.handlers().begin();
1332 content::RunTaskAndWaitForInterstitialDetach(
1333 contents, base::Bind(&LoginHandler::CancelAuth, handler));
1334 EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1335 EXPECT_FALSE(contents->ShowingInterstitialPage());
1336 EXPECT_EQ(auth_url, contents->GetLastCommittedURL());
1339 // Navigate to a broken SSL page. This is a cross origin navigation since
1340 // schemes don't match (http vs https).
1342 ASSERT_EQ("127.0.0.1", broken_ssl_page.host());
1343 browser()->OpenURL(OpenURLParams(broken_ssl_page, Referrer(), CURRENT_TAB,
1344 ui::PAGE_TRANSITION_TYPED, false));
1345 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1346 ASSERT_TRUE(contents->GetURL().SchemeIs("https"));
1347 content::WaitForInterstitialAttach(contents);
1348 EXPECT_TRUE(contents->ShowingInterstitialPage());
1349 EXPECT_EQ(SSLBlockingPage::kTypeForTesting, contents->GetInterstitialPage()
1350 ->GetDelegateForTesting()
1351 ->GetTypeForTesting());
1352 EXPECT_EQ(auth_url, contents->GetLastCommittedURL());
1355 // An overrideable SSL interstitial is now being displayed. Navigate to the
1356 // auth URL again. This is again a cross origin navigation, but last committed
1357 // URL is the same as the auth URL (since SSL navigation never committed).
1358 // Should still replace SSL interstitial with an auth interstitial even though
1359 // last committed URL and the new URL is the same.
1361 WindowedAuthNeededObserver auth_needed_waiter(controller);
1362 browser()->OpenURL(OpenURLParams(auth_url, Referrer(), CURRENT_TAB,
1363 ui::PAGE_TRANSITION_TYPED, false));
1364 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1365 ASSERT_TRUE(contents->GetURL().SchemeIs("http"));
1366 ASSERT_TRUE(contents->ShowingInterstitialPage());
1368 auth_needed_waiter.Wait();
1369 ASSERT_EQ(1u, observer.handlers().size());
1370 content::WaitForInterstitialAttach(contents);
1371 EXPECT_EQ(LoginInterstitialDelegate::kTypeForTesting,
1372 contents->GetInterstitialPage()
1373 ->GetDelegateForTesting()
1374 ->GetTypeForTesting());
1378 } // namespace