Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / login / login_prompt_browsertest.cc
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.
4
5 #include <algorithm>
6 #include <list>
7 #include <map>
8
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"
29
30 using content::NavigationController;
31 using content::OpenURLParams;
32 using content::Referrer;
33
34 namespace {
35
36 class LoginPromptBrowserTest : public InProcessBrowserTest {
37  public:
38   LoginPromptBrowserTest()
39       : bad_password_("incorrect"),
40         bad_username_("nouser"),
41         password_("secret"),
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_);
47   }
48
49  protected:
50   struct AuthInfo {
51     std::string username_;
52     std::string password_;
53
54     AuthInfo() {}
55
56     AuthInfo(const std::string& username,
57              const std::string& password)
58         : username_(username), password_(password) {}
59   };
60
61   typedef std::map<std::string, AuthInfo> AuthMap;
62
63   void SetAuthFor(LoginHandler* handler);
64
65   void TestCrossOriginPrompt(const GURL& visit_url,
66                              const std::string& landing_host) const;
67
68   AuthMap auth_map_;
69   std::string bad_password_;
70   std::string bad_username_;
71   std::string password_;
72   std::string username_basic_;
73   std::string username_digest_;
74 };
75
76 void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
77   const net::AuthChallengeInfo* challenge = handler->auth_info();
78
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_));
86   }
87 }
88
89 const char kPrefetchAuthPage[] = "files/login/prefetch.html";
90
91 const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
92 const int  kMultiRealmTestRealmCount = 2;
93
94 const char kSingleRealmTestPage[] = "files/login/single_realm.html";
95
96 const char* kAuthBasicPage = "auth-basic";
97 const char* kAuthDigestPage = "auth-digest";
98
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;
103 }
104
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.
108
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());
115
116   GURL test_page = test_server()->GetURL(kPrefetchAuthPage);
117
118   class SetPrefetchForTest {
119    public:
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);
127     }
128
129     ~SetPrefetchForTest() {
130       prerender::PrerenderManager::SetMode(old_prerender_mode_);
131     }
132
133    private:
134     prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_;
135   } set_prefetch_for_test(true);
136
137   content::WebContents* contents =
138       browser()->tab_strip_model()->GetActiveWebContents();
139   NavigationController* controller = &contents->GetController();
140   LoginPromptBrowserTestObserver observer;
141
142   observer.Register(content::Source<NavigationController>(controller));
143
144   WindowedLoadStopObserver load_stop_waiter(controller, 1);
145   browser()->OpenURL(OpenURLParams(
146       test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
147       false));
148
149   load_stop_waiter.Wait();
150   EXPECT_TRUE(observer.handlers().empty());
151   EXPECT_TRUE(test_server()->Stop());
152 }
153
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);
158
159   content::WebContents* contents =
160       browser()->tab_strip_model()->GetActiveWebContents();
161   NavigationController* controller = &contents->GetController();
162   LoginPromptBrowserTestObserver observer;
163
164   observer.Register(content::Source<NavigationController>(controller));
165
166   {
167     WindowedAuthNeededObserver auth_needed_waiter(controller);
168     browser()->OpenURL(OpenURLParams(
169         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
170         false));
171     auth_needed_waiter.Wait();
172   }
173
174   ASSERT_FALSE(observer.handlers().empty());
175   {
176     WindowedAuthNeededObserver auth_needed_waiter(controller);
177     WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
178     LoginHandler* handler = *observer.handlers().begin();
179
180     ASSERT_TRUE(handler);
181     handler->SetAuth(base::UTF8ToUTF16(bad_username_),
182                      base::UTF8ToUTF16(bad_password_));
183     auth_supplied_waiter.Wait();
184
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();
189   }
190
191   ASSERT_EQ(1u, observer.handlers().size());
192   WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
193   LoginHandler* handler = *observer.handlers().begin();
194   SetAuthFor(handler);
195   auth_supplied_waiter.Wait();
196
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());
202 }
203
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);
208
209   content::WebContents* contents =
210       browser()->tab_strip_model()->GetActiveWebContents();
211   NavigationController* controller = &contents->GetController();
212   LoginPromptBrowserTestObserver observer;
213
214   observer.Register(content::Source<NavigationController>(controller));
215
216   {
217     WindowedAuthNeededObserver auth_needed_waiter(controller);
218     browser()->OpenURL(OpenURLParams(
219         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
220         false));
221     auth_needed_waiter.Wait();
222   }
223
224   ASSERT_FALSE(observer.handlers().empty());
225   {
226     WindowedAuthNeededObserver auth_needed_waiter(controller);
227     WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
228     LoginHandler* handler = *observer.handlers().begin();
229
230     ASSERT_TRUE(handler);
231     handler->SetAuth(base::UTF8ToUTF16(bad_username_),
232                      base::UTF8ToUTF16(bad_password_));
233     auth_supplied_waiter.Wait();
234
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();
239   }
240
241   ASSERT_EQ(1u, observer.handlers().size());
242   WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
243   LoginHandler* handler = *observer.handlers().begin();
244
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();
249
250   base::string16 expected_title = ExpectedTitleFromAuth(username, password);
251   content::TitleWatcher title_watcher(contents, expected_title);
252   EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
253 }
254
255 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestTwoAuths) {
256   ASSERT_TRUE(test_server()->Start());
257
258   content::WebContents* contents1 =
259       browser()->tab_strip_model()->GetActiveWebContents();
260   NavigationController* controller1 = &contents1->GetController();
261   LoginPromptBrowserTestObserver observer;
262
263   observer.Register(content::Source<NavigationController>(controller1));
264
265   // Open a new tab.
266   ui_test_utils::NavigateToURLWithDisposition(
267       browser(),
268       GURL("about:blank"),
269       NEW_FOREGROUND_TAB,
270       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
271
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));
277
278   {
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();
284   }
285
286   {
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();
292   }
293
294   ASSERT_EQ(2u, observer.handlers().size());
295
296   LoginHandler* handler1 = *observer.handlers().begin();
297   LoginHandler* handler2 = *(++(observer.handlers().begin()));
298
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);
305
306   handler1->SetAuth(base::UTF8ToUTF16(username_basic_),
307                     base::UTF8ToUTF16(password_));
308   handler2->SetAuth(base::UTF8ToUTF16(username_digest_),
309                     base::UTF8ToUTF16(password_));
310
311   EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
312   EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
313 }
314
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");
322
323   content::WebContents* contents =
324       browser()->tab_strip_model()->GetActiveWebContents();
325   NavigationController* controller = &contents->GetController();
326
327   LoginPromptBrowserTestObserver observer;
328   observer.Register(content::Source<NavigationController>(controller));
329
330   // First navigate to an unauthenticated page so we have something to
331   // go back to.
332   ui_test_utils::NavigateToURL(browser(), no_auth_page_1);
333
334   // Navigating while auth is requested is the same as cancelling.
335   {
336     // We need to wait for two LOAD_STOP events.  One for auth_page and one for
337     // no_auth_page_2.
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,
342         false));
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,
347         false));
348     auth_cancelled_waiter.Wait();
349     load_stop_waiter.Wait();
350     EXPECT_TRUE(observer.handlers().empty());
351   }
352
353   // Try navigating backwards.
354   {
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,
360         false));
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());
368   }
369
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);
372   {
373     WindowedLoadStopObserver load_stop_waiter(controller, 1);
374     chrome::GoBack(browser(), CURRENT_TAB);  // Should take us to page 1
375     load_stop_waiter.Wait();
376   }
377
378   {
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,
384         false));
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());
392   }
393
394   // Now test that cancelling works as expected.
395   {
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,
400         false));
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());
409   }
410 }
411
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
416 // expected.
417 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
418   ASSERT_TRUE(test_server()->Start());
419   GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
420
421   content::WebContents* contents =
422       browser()->tab_strip_model()->GetActiveWebContents();
423   NavigationController* controller = &contents->GetController();
424   LoginPromptBrowserTestObserver observer;
425
426   observer.Register(content::Source<NavigationController>(controller));
427
428   WindowedLoadStopObserver load_stop_waiter(controller, 1);
429
430   {
431     WindowedAuthNeededObserver auth_needed_waiter(controller);
432     browser()->OpenURL(OpenURLParams(
433         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
434         false));
435     auth_needed_waiter.Wait();
436   }
437
438   int n_handlers = 0;
439
440   while (n_handlers < kMultiRealmTestRealmCount) {
441     WindowedAuthNeededObserver auth_needed_waiter(controller);
442
443     while (!observer.handlers().empty()) {
444       WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
445       LoginHandler* handler = *observer.handlers().begin();
446
447       ASSERT_TRUE(handler);
448       n_handlers++;
449       handler->CancelAuth();
450       auth_cancelled_waiter.Wait();
451     }
452
453     if (n_handlers < kMultiRealmTestRealmCount)
454       auth_needed_waiter.Wait();
455   }
456
457   load_stop_waiter.Wait();
458
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());
464 }
465
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);
471
472   content::WebContents* contents =
473       browser()->tab_strip_model()->GetActiveWebContents();
474   NavigationController* controller = &contents->GetController();
475   LoginPromptBrowserTestObserver observer;
476
477   observer.Register(content::Source<NavigationController>(controller));
478
479   WindowedLoadStopObserver load_stop_waiter(controller, 1);
480   int n_handlers = 0;
481
482   {
483     WindowedAuthNeededObserver auth_needed_waiter(controller);
484
485     browser()->OpenURL(OpenURLParams(
486         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
487         false));
488     auth_needed_waiter.Wait();
489   }
490
491   while (n_handlers < kMultiRealmTestRealmCount) {
492     WindowedAuthNeededObserver auth_needed_waiter(controller);
493
494     while (!observer.handlers().empty()) {
495       WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
496       LoginHandler* handler = *observer.handlers().begin();
497
498       ASSERT_TRUE(handler);
499       n_handlers++;
500       SetAuthFor(handler);
501       auth_supplied_waiter.Wait();
502     }
503
504     if (n_handlers < kMultiRealmTestRealmCount)
505       auth_needed_waiter.Wait();
506   }
507
508   load_stop_waiter.Wait();
509
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());
515 }
516
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);
522
523   content::WebContents* contents =
524       browser()->tab_strip_model()->GetActiveWebContents();
525   NavigationController* controller = &contents->GetController();
526   LoginPromptBrowserTestObserver observer;
527
528   observer.Register(content::Source<NavigationController>(controller));
529
530   {
531     WindowedAuthNeededObserver auth_needed_waiter(controller);
532     browser()->OpenURL(OpenURLParams(
533         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
534         false));
535     auth_needed_waiter.Wait();
536   }
537
538   EXPECT_FALSE(observer.handlers().empty());
539
540   if (!observer.handlers().empty()) {
541     WindowedAuthNeededObserver auth_needed_waiter(controller);
542     WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
543     LoginHandler* handler = *observer.handlers().begin();
544
545     ASSERT_TRUE(handler);
546     handler->SetAuth(base::UTF8ToUTF16(bad_username_),
547                      base::UTF8ToUTF16(bad_password_));
548     auth_supplied_waiter.Wait();
549
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();
554   }
555
556   int n_handlers = 0;
557
558   while (n_handlers < 1) {
559     WindowedAuthNeededObserver auth_needed_waiter(controller);
560
561     while (!observer.handlers().empty()) {
562       WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
563       LoginHandler* handler = *observer.handlers().begin();
564
565       ASSERT_TRUE(handler);
566       n_handlers++;
567       SetAuthFor(handler);
568       auth_supplied_waiter.Wait();
569     }
570
571     if (n_handlers < 1)
572       auth_needed_waiter.Wait();
573   }
574
575   // The single realm test has only one realm, and thus only one login
576   // prompt.
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());
582 }
583
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";
590
591   ASSERT_TRUE(test_server()->Start());
592
593   content::WebContents* contents =
594       browser()->tab_strip_model()->GetActiveWebContents();
595   NavigationController* controller = &contents->GetController();
596   LoginPromptBrowserTestObserver observer;
597
598   observer.Register(content::Source<NavigationController>(controller));
599
600   // First load a page that has a favicon that requires
601   // authentication.  There should be no login prompt.
602   {
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,
607         false));
608     load_stop_waiter.Wait();
609   }
610
611   // Now request the same favicon, but directly as the document.
612   // There should be one login prompt.
613   {
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,
619         false));
620     auth_needed_waiter.Wait();
621     ASSERT_EQ(1u, observer.handlers().size());
622
623     while (!observer.handlers().empty()) {
624       WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
625       LoginHandler* handler = *observer.handlers().begin();
626
627       ASSERT_TRUE(handler);
628       handler->CancelAuth();
629       auth_cancelled_waiter.Wait();
630     }
631
632     load_stop_waiter.Wait();
633   }
634
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());
639 }
640
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";
645
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());
649
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));
655
656   // Load a page that has a cross-domain sub-resource authentication.
657   // There should be no login prompt.
658   {
659     GURL test_page = test_server()->GetURL(kTestPage);
660     ASSERT_EQ("127.0.0.1", test_page.host());
661
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);
668
669     WindowedLoadStopObserver load_stop_waiter(controller, 1);
670     browser()->OpenURL(OpenURLParams(
671         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
672         false));
673     load_stop_waiter.Wait();
674   }
675
676   EXPECT_EQ(0, observer.auth_needed_count());
677
678   // Now request the same page, but from the same origin.
679   // There should be one login prompt.
680   {
681     GURL test_page = test_server()->GetURL(kTestPage);
682     ASSERT_EQ("127.0.0.1", test_page.host());
683
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);
690
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());
697
698     while (!observer.handlers().empty()) {
699       WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
700       LoginHandler* handler = *observer.handlers().begin();
701
702       ASSERT_TRUE(handler);
703       handler->CancelAuth();
704       auth_cancelled_waiter.Wait();
705     }
706   }
707
708   EXPECT_EQ(1, observer.auth_needed_count());
709   EXPECT_TRUE(test_server()->Stop());
710 }
711
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";
716
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());
720
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));
726
727   // Load a page that has a cross-domain iframe authentication.
728   {
729     GURL test_page = test_server()->GetURL(kTestPage);
730     ASSERT_EQ("127.0.0.1", test_page.host());
731
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);
738
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());
745
746     while (!observer.handlers().empty()) {
747       WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
748       LoginHandler* handler = *observer.handlers().begin();
749
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());
755
756       handler->CancelAuth();
757       auth_cancelled_waiter.Wait();
758     }
759   }
760
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());
763
764   EXPECT_EQ(1, observer.auth_needed_count());
765   EXPECT_TRUE(test_server()->Stop());
766 }
767
768 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, SupplyRedundantAuths) {
769   ASSERT_TRUE(test_server()->Start());
770
771   // Get NavigationController for tab 1.
772   content::WebContents* contents_1 =
773       browser()->tab_strip_model()->GetActiveWebContents();
774   NavigationController* controller_1 = &contents_1->GetController();
775
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);
782
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();
788
789   LoginPromptBrowserTestObserver observer;
790   observer.Register(content::Source<NavigationController>(controller_1));
791   observer.Register(content::Source<NavigationController>(controller_2));
792
793   {
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();
811
812     ASSERT_EQ(2U, observer.handlers().size());
813
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);
820
821     // Both tabs should be authenticated.
822     auth_supplied_waiter_1.Wait();
823     auth_supplied_waiter_2.Wait();
824   }
825
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());
830 }
831
832 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, CancelRedundantAuths) {
833   ASSERT_TRUE(test_server()->Start());
834
835   // Get NavigationController for tab 1.
836   content::WebContents* contents_1 =
837       browser()->tab_strip_model()->GetActiveWebContents();
838   NavigationController* controller_1 = &contents_1->GetController();
839
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);
846
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();
852
853   LoginPromptBrowserTestObserver observer;
854   observer.Register(content::Source<NavigationController>(controller_1));
855   observer.Register(content::Source<NavigationController>(controller_2));
856
857   {
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();
875
876     ASSERT_EQ(2U, observer.handlers().size());
877
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();
884
885     // Both tabs should cancel auth.
886     auth_cancelled_waiter_1.Wait();
887     auth_cancelled_waiter_2.Wait();
888   }
889
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());
894 }
895
896 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
897                        SupplyRedundantAuthsMultiProfile) {
898   ASSERT_TRUE(test_server()->Start());
899
900   // Get NavigationController for regular tab.
901   content::WebContents* contents =
902       browser()->tab_strip_model()->GetActiveWebContents();
903   NavigationController* controller = &contents->GetController();
904
905   // Open an incognito window.
906   Browser* browser_incognito = CreateIncognitoBrowser();
907
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();
914
915   LoginPromptBrowserTestObserver observer;
916   observer.Register(content::Source<NavigationController>(controller));
917   LoginPromptBrowserTestObserver observer_incognito;
918   observer_incognito.Register(
919       content::Source<NavigationController>(controller_incognito));
920
921   {
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();
940
941     ASSERT_EQ(1U, observer.handlers().size());
942     ASSERT_EQ(1U, observer_incognito.handlers().size());
943
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);
949
950     // Regular tab should be authenticated.
951     auth_supplied_waiter.Wait();
952
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();
958   }
959
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());
967 }
968
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";
974
975   ASSERT_TRUE(test_server()->Start());
976
977   content::WebContents* contents =
978       browser()->tab_strip_model()->GetActiveWebContents();
979   NavigationController* controller = &contents->GetController();
980   LoginPromptBrowserTestObserver observer;
981
982   observer.Register(content::Source<NavigationController>(controller));
983
984   // Load a page which makes a synchronous XMLHttpRequest for an authenticated
985   // resource with the wrong credentials.  There should be no login prompt.
986   {
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();
993   }
994
995   base::string16 expected_title(base::UTF8ToUTF16("status=401"));
996
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());
1002 }
1003
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";
1009
1010   ASSERT_TRUE(test_server()->Start());
1011
1012   content::WebContents* contents =
1013       browser()->tab_strip_model()->GetActiveWebContents();
1014   NavigationController* controller = &contents->GetController();
1015   LoginPromptBrowserTestObserver observer;
1016
1017   observer.Register(content::Source<NavigationController>(controller));
1018
1019   // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1020   // resource with the wrong credentials.  There should be no login prompt.
1021   {
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();
1028   }
1029
1030   base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1031
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());
1037 }
1038
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";
1044
1045   ASSERT_TRUE(test_server()->Start());
1046
1047   content::WebContents* contents =
1048       browser()->tab_strip_model()->GetActiveWebContents();
1049   NavigationController* controller = &contents->GetController();
1050   LoginPromptBrowserTestObserver observer;
1051
1052   observer.Register(content::Source<NavigationController>(controller));
1053
1054   // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1055   // resource with the wrong credentials.  There should be no login prompt.
1056   {
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();
1063   }
1064
1065   ASSERT_FALSE(observer.handlers().empty());
1066   {
1067     WindowedAuthNeededObserver auth_needed_waiter(controller);
1068     WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1069     LoginHandler* handler = *observer.handlers().begin();
1070
1071     ASSERT_TRUE(handler);
1072     handler->SetAuth(base::UTF8ToUTF16(bad_username_),
1073                      base::UTF8ToUTF16(bad_password_));
1074     auth_supplied_waiter.Wait();
1075
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();
1080   }
1081
1082   ASSERT_EQ(1u, observer.handlers().size());
1083   WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1084   LoginHandler* handler = *observer.handlers().begin();
1085
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();
1090
1091   WindowedLoadStopObserver load_stop_waiter(controller, 1);
1092   load_stop_waiter.Wait();
1093
1094   base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1095
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());
1101 }
1102
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";
1108
1109   ASSERT_TRUE(test_server()->Start());
1110
1111   content::WebContents* contents =
1112       browser()->tab_strip_model()->GetActiveWebContents();
1113   NavigationController* controller = &contents->GetController();
1114   LoginPromptBrowserTestObserver observer;
1115
1116   observer.Register(content::Source<NavigationController>(controller));
1117
1118   // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1119   // resource with the wrong credentials.  There should be no login prompt.
1120   {
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();
1127   }
1128
1129   ASSERT_EQ(1u, observer.handlers().size());
1130   WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
1131   LoginHandler* handler = *observer.handlers().begin();
1132
1133   handler->CancelAuth();
1134   auth_cancelled_waiter.Wait();
1135
1136   WindowedLoadStopObserver load_stop_waiter(controller, 1);
1137   load_stop_waiter.Wait();
1138
1139   base::string16 expected_title(base::UTF8ToUTF16("status=401"));
1140
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());
1146 }
1147
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;
1157
1158   observer.Register(content::Source<NavigationController>(controller));
1159
1160   // Load a page which will trigger a login prompt.
1161   {
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);
1170
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
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));
1180
1181     EXPECT_EQ(auth_host, contents->GetVisibleURL().host());
1182     EXPECT_FALSE(contents->ShowingInterstitialPage());
1183   }
1184 }
1185
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());
1191
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);
1196 }
1197
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());
1204
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);
1210 }
1211
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),
1218       base::FilePath());
1219   ASSERT_TRUE(https_server.Start());
1220
1221   content::WebContents* contents =
1222       browser()->tab_strip_model()->GetActiveWebContents();
1223   NavigationController* controller = &contents->GetController();
1224   LoginPromptBrowserTestObserver observer;
1225
1226   observer.Register(content::Source<NavigationController>(controller));
1227
1228   // Load a page which triggers an SSL interstitial. Proceeding through it
1229   // should show the login page with the blank interstitial.
1230   {
1231     GURL test_page = https_server.GetURL(kAuthBasicPage);
1232     ASSERT_EQ("127.0.0.1", test_page.host());
1233
1234     WindowedAuthNeededObserver auth_needed_waiter(controller);
1235     browser()->OpenURL(OpenURLParams(
1236         test_page, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
1237         false));
1238     ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1239     content::WaitForInterstitialAttach(contents);
1240
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);
1247
1248     // The omnibox should show the correct origin while the login prompt is
1249     // being displayed.
1250     EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1251     EXPECT_TRUE(contents->ShowingInterstitialPage());
1252
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));
1258
1259     EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
1260     EXPECT_FALSE(contents->ShowingInterstitialPage());
1261   }
1262 }
1263
1264 }  // namespace