Temporarily re-enabling SizeAfterPrefChange test with traces (this time for Linux...
[chromium-blink-merge.git] / chrome / browser / ui / login / login_prompt_browsertest.cc
blobb0e0d13103b365708f3ea6958082539802db1c52
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/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/tabs/tab_strip_model.h"
17 #include "chrome/test/base/in_process_browser_test.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/interstitial_page.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_source.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "content/public/test/test_navigation_observer.h"
25 #include "net/base/auth.h"
26 #include "net/dns/mock_host_resolver.h"
28 using content::NavigationController;
29 using content::OpenURLParams;
30 using content::Referrer;
32 namespace {
34 class LoginPromptBrowserTest : public InProcessBrowserTest {
35 public:
36 LoginPromptBrowserTest()
37 : bad_password_("incorrect"),
38 bad_username_("nouser"),
39 password_("secret"),
40 username_basic_("basicuser"),
41 username_digest_("digestuser") {
42 auth_map_["foo"] = AuthInfo("testuser", "foopassword");
43 auth_map_["bar"] = AuthInfo("testuser", "barpassword");
44 auth_map_["testrealm"] = AuthInfo(username_basic_, password_);
47 protected:
48 struct AuthInfo {
49 std::string username_;
50 std::string password_;
52 AuthInfo() {}
54 AuthInfo(const std::string& username,
55 const std::string& password)
56 : username_(username), password_(password) {}
59 typedef std::map<std::string, AuthInfo> AuthMap;
61 void SetAuthFor(LoginHandler* handler);
63 AuthMap auth_map_;
64 std::string bad_password_;
65 std::string bad_username_;
66 std::string password_;
67 std::string username_basic_;
68 std::string username_digest_;
71 void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
72 const net::AuthChallengeInfo* challenge = handler->auth_info();
74 ASSERT_TRUE(challenge);
75 AuthMap::iterator i = auth_map_.find(challenge->realm);
76 EXPECT_TRUE(auth_map_.end() != i);
77 if (i != auth_map_.end()) {
78 const AuthInfo& info = i->second;
79 handler->SetAuth(base::UTF8ToUTF16(info.username_),
80 base::UTF8ToUTF16(info.password_));
84 // Maintains a set of LoginHandlers that are currently active and
85 // keeps a count of the notifications that were observed.
86 class LoginPromptBrowserTestObserver : public content::NotificationObserver {
87 public:
88 LoginPromptBrowserTestObserver()
89 : auth_needed_count_(0),
90 auth_supplied_count_(0),
91 auth_cancelled_count_(0) {}
93 virtual void Observe(int type,
94 const content::NotificationSource& source,
95 const content::NotificationDetails& details) OVERRIDE;
97 void AddHandler(LoginHandler* handler);
99 void RemoveHandler(LoginHandler* handler);
101 void Register(const content::NotificationSource& source);
103 std::list<LoginHandler*> handlers_;
105 // The exact number of notifications we receive is depedent on the
106 // number of requests that were dispatched and is subject to a
107 // number of factors that we don't directly control here. The
108 // values below should only be used qualitatively.
109 int auth_needed_count_;
110 int auth_supplied_count_;
111 int auth_cancelled_count_;
113 private:
114 content::NotificationRegistrar registrar_;
116 DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
119 void LoginPromptBrowserTestObserver::Observe(
120 int type,
121 const content::NotificationSource& source,
122 const content::NotificationDetails& details) {
123 if (type == chrome::NOTIFICATION_AUTH_NEEDED) {
124 LoginNotificationDetails* login_details =
125 content::Details<LoginNotificationDetails>(details).ptr();
126 AddHandler(login_details->handler());
127 auth_needed_count_++;
128 } else if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
129 AuthSuppliedLoginNotificationDetails* login_details =
130 content::Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
131 RemoveHandler(login_details->handler());
132 auth_supplied_count_++;
133 } else if (type == chrome::NOTIFICATION_AUTH_CANCELLED) {
134 LoginNotificationDetails* login_details =
135 content::Details<LoginNotificationDetails>(details).ptr();
136 RemoveHandler(login_details->handler());
137 auth_cancelled_count_++;
141 void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) {
142 std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
143 handlers_.end(),
144 handler);
145 EXPECT_TRUE(i == handlers_.end());
146 if (i == handlers_.end())
147 handlers_.push_back(handler);
150 void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) {
151 std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
152 handlers_.end(),
153 handler);
154 EXPECT_TRUE(i != handlers_.end());
155 if (i != handlers_.end())
156 handlers_.erase(i);
159 void LoginPromptBrowserTestObserver::Register(
160 const content::NotificationSource& source) {
161 registrar_.Add(this, chrome::NOTIFICATION_AUTH_NEEDED, source);
162 registrar_.Add(this, chrome::NOTIFICATION_AUTH_SUPPLIED, source);
163 registrar_.Add(this, chrome::NOTIFICATION_AUTH_CANCELLED, source);
166 template <int T>
167 class WindowedNavigationObserver
168 : public content::WindowedNotificationObserver {
169 public:
170 explicit WindowedNavigationObserver(NavigationController* controller)
171 : content::WindowedNotificationObserver(
172 T, content::Source<NavigationController>(controller)) {}
175 // LOAD_STOP observer is special since we want to be able to wait for
176 // multiple LOAD_STOP events.
177 class WindowedLoadStopObserver
178 : public WindowedNavigationObserver<content::NOTIFICATION_LOAD_STOP> {
179 public:
180 WindowedLoadStopObserver(NavigationController* controller,
181 int notification_count)
182 : WindowedNavigationObserver<content::NOTIFICATION_LOAD_STOP>(controller),
183 remaining_notification_count_(notification_count) {}
184 protected:
185 virtual void Observe(int type,
186 const content::NotificationSource& source,
187 const content::NotificationDetails& details) OVERRIDE;
188 private:
189 int remaining_notification_count_; // Number of notifications remaining.
192 void WindowedLoadStopObserver::Observe(
193 int type,
194 const content::NotificationSource& source,
195 const content::NotificationDetails& details) {
196 if (--remaining_notification_count_ == 0)
197 WindowedNotificationObserver::Observe(type, source, details);
200 class InterstitialObserver : public content::WebContentsObserver {
201 public:
202 InterstitialObserver(content::WebContents* web_contents,
203 const base::Closure& attach_callback,
204 const base::Closure& detach_callback)
205 : WebContentsObserver(web_contents),
206 attach_callback_(attach_callback),
207 detach_callback_(detach_callback) {
210 virtual void DidAttachInterstitialPage() OVERRIDE {
211 attach_callback_.Run();
214 virtual void DidDetachInterstitialPage() OVERRIDE {
215 detach_callback_.Run();
218 private:
219 base::Closure attach_callback_;
220 base::Closure detach_callback_;
222 DISALLOW_COPY_AND_ASSIGN(InterstitialObserver);
225 void WaitForInterstitialAttach(content::WebContents* web_contents) {
226 scoped_refptr<content::MessageLoopRunner> interstitial_attach_loop_runner(
227 new content::MessageLoopRunner);
228 InterstitialObserver observer(
229 web_contents,
230 interstitial_attach_loop_runner->QuitClosure(),
231 base::Closure());
232 if (!content::InterstitialPage::GetInterstitialPage(web_contents))
233 interstitial_attach_loop_runner->Run();
236 typedef WindowedNavigationObserver<chrome::NOTIFICATION_AUTH_NEEDED>
237 WindowedAuthNeededObserver;
239 typedef WindowedNavigationObserver<chrome::NOTIFICATION_AUTH_CANCELLED>
240 WindowedAuthCancelledObserver;
242 typedef WindowedNavigationObserver<chrome::NOTIFICATION_AUTH_SUPPLIED>
243 WindowedAuthSuppliedObserver;
245 const char kPrefetchAuthPage[] = "files/login/prefetch.html";
247 const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
248 const int kMultiRealmTestRealmCount = 2;
250 const char kSingleRealmTestPage[] = "files/login/single_realm.html";
252 const char* kAuthBasicPage = "auth-basic";
253 const char* kAuthDigestPage = "auth-digest";
255 base::string16 ExpectedTitleFromAuth(const base::string16& username,
256 const base::string16& password) {
257 // The TestServer sets the title to username/password on successful login.
258 return username + base::UTF8ToUTF16("/") + password;
261 // Confirm that <link rel="prefetch"> targetting an auth required
262 // resource does not provide a login dialog. These types of requests
263 // should instead just cancel the auth.
265 // Unfortunately, this test doesn't assert on anything for its
266 // correctness. Instead, it relies on the auth dialog blocking the
267 // browser, and triggering a timeout to cause failure when the
268 // prefetch resource requires authorization.
269 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PrefetchAuthCancels) {
270 ASSERT_TRUE(test_server()->Start());
272 GURL test_page = test_server()->GetURL(kPrefetchAuthPage);
274 class SetPrefetchForTest {
275 public:
276 explicit SetPrefetchForTest(bool prefetch)
277 : old_prerender_mode_(prerender::PrerenderManager::GetMode()) {
278 std::string exp_group = prefetch ? "ExperimentYes" : "ExperimentNo";
279 base::FieldTrialList::CreateFieldTrial("Prefetch", exp_group);
280 // Disable prerender so this is just a prefetch of the top-level page.
281 prerender::PrerenderManager::SetMode(
282 prerender::PrerenderManager::PRERENDER_MODE_DISABLED);
285 ~SetPrefetchForTest() {
286 prerender::PrerenderManager::SetMode(old_prerender_mode_);
289 private:
290 prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_;
291 } set_prefetch_for_test(true);
293 content::WebContents* contents =
294 browser()->tab_strip_model()->GetActiveWebContents();
295 NavigationController* controller = &contents->GetController();
296 LoginPromptBrowserTestObserver observer;
298 observer.Register(content::Source<NavigationController>(controller));
300 WindowedLoadStopObserver load_stop_waiter(controller, 1);
301 browser()->OpenURL(OpenURLParams(
302 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
303 false));
305 load_stop_waiter.Wait();
306 EXPECT_TRUE(observer.handlers_.empty());
307 EXPECT_TRUE(test_server()->Stop());
310 // Test that "Basic" HTTP authentication works.
311 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestBasicAuth) {
312 ASSERT_TRUE(test_server()->Start());
313 GURL test_page = test_server()->GetURL(kAuthBasicPage);
315 content::WebContents* contents =
316 browser()->tab_strip_model()->GetActiveWebContents();
317 NavigationController* controller = &contents->GetController();
318 LoginPromptBrowserTestObserver observer;
320 observer.Register(content::Source<NavigationController>(controller));
323 WindowedAuthNeededObserver auth_needed_waiter(controller);
324 browser()->OpenURL(OpenURLParams(
325 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
326 false));
327 auth_needed_waiter.Wait();
330 ASSERT_FALSE(observer.handlers_.empty());
332 WindowedAuthNeededObserver auth_needed_waiter(controller);
333 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
334 LoginHandler* handler = *observer.handlers_.begin();
336 ASSERT_TRUE(handler);
337 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
338 base::UTF8ToUTF16(bad_password_));
339 auth_supplied_waiter.Wait();
341 // The request should be retried after the incorrect password is
342 // supplied. This should result in a new AUTH_NEEDED notification
343 // for the same realm.
344 auth_needed_waiter.Wait();
347 ASSERT_EQ(1u, observer.handlers_.size());
348 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
349 LoginHandler* handler = *observer.handlers_.begin();
350 SetAuthFor(handler);
351 auth_supplied_waiter.Wait();
353 base::string16 expected_title =
354 ExpectedTitleFromAuth(base::ASCIIToUTF16("basicuser"),
355 base::ASCIIToUTF16("secret"));
356 content::TitleWatcher title_watcher(contents, expected_title);
357 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
360 // Test that "Digest" HTTP authentication works.
361 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestDigestAuth) {
362 ASSERT_TRUE(test_server()->Start());
363 GURL test_page = test_server()->GetURL(kAuthDigestPage);
365 content::WebContents* contents =
366 browser()->tab_strip_model()->GetActiveWebContents();
367 NavigationController* controller = &contents->GetController();
368 LoginPromptBrowserTestObserver observer;
370 observer.Register(content::Source<NavigationController>(controller));
373 WindowedAuthNeededObserver auth_needed_waiter(controller);
374 browser()->OpenURL(OpenURLParams(
375 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
376 false));
377 auth_needed_waiter.Wait();
380 ASSERT_FALSE(observer.handlers_.empty());
382 WindowedAuthNeededObserver auth_needed_waiter(controller);
383 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
384 LoginHandler* handler = *observer.handlers_.begin();
386 ASSERT_TRUE(handler);
387 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
388 base::UTF8ToUTF16(bad_password_));
389 auth_supplied_waiter.Wait();
391 // The request should be retried after the incorrect password is
392 // supplied. This should result in a new AUTH_NEEDED notification
393 // for the same realm.
394 auth_needed_waiter.Wait();
397 ASSERT_EQ(1u, observer.handlers_.size());
398 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
399 LoginHandler* handler = *observer.handlers_.begin();
401 base::string16 username(base::UTF8ToUTF16(username_digest_));
402 base::string16 password(base::UTF8ToUTF16(password_));
403 handler->SetAuth(username, password);
404 auth_supplied_waiter.Wait();
406 base::string16 expected_title = ExpectedTitleFromAuth(username, password);
407 content::TitleWatcher title_watcher(contents, expected_title);
408 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
411 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestTwoAuths) {
412 ASSERT_TRUE(test_server()->Start());
414 content::WebContents* contents1 =
415 browser()->tab_strip_model()->GetActiveWebContents();
416 NavigationController* controller1 = &contents1->GetController();
417 LoginPromptBrowserTestObserver observer;
419 observer.Register(content::Source<NavigationController>(controller1));
421 // Open a new tab.
422 ui_test_utils::NavigateToURLWithDisposition(
423 browser(),
424 GURL("about:blank"),
425 NEW_FOREGROUND_TAB,
426 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
428 content::WebContents* contents2 =
429 browser()->tab_strip_model()->GetActiveWebContents();
430 ASSERT_NE(contents1, contents2);
431 NavigationController* controller2 = &contents2->GetController();
432 observer.Register(content::Source<NavigationController>(controller2));
435 WindowedAuthNeededObserver auth_needed_waiter(controller1);
436 contents1->OpenURL(OpenURLParams(
437 test_server()->GetURL(kAuthBasicPage), Referrer(),
438 CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
439 auth_needed_waiter.Wait();
443 WindowedAuthNeededObserver auth_needed_waiter(controller2);
444 contents2->OpenURL(OpenURLParams(
445 test_server()->GetURL(kAuthDigestPage), Referrer(),
446 CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false));
447 auth_needed_waiter.Wait();
450 ASSERT_EQ(2u, observer.handlers_.size());
452 LoginHandler* handler1 = *observer.handlers_.begin();
453 LoginHandler* handler2 = *(++(observer.handlers_.begin()));
455 base::string16 expected_title1 = ExpectedTitleFromAuth(
456 base::UTF8ToUTF16(username_basic_), base::UTF8ToUTF16(password_));
457 base::string16 expected_title2 = ExpectedTitleFromAuth(
458 base::UTF8ToUTF16(username_digest_), base::UTF8ToUTF16(password_));
459 content::TitleWatcher title_watcher1(contents1, expected_title1);
460 content::TitleWatcher title_watcher2(contents2, expected_title2);
462 handler1->SetAuth(base::UTF8ToUTF16(username_basic_),
463 base::UTF8ToUTF16(password_));
464 handler2->SetAuth(base::UTF8ToUTF16(username_digest_),
465 base::UTF8ToUTF16(password_));
467 EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
468 EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
471 // Test login prompt cancellation.
472 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, TestCancelAuth) {
473 ASSERT_TRUE(test_server()->Start());
474 GURL auth_page = test_server()->GetURL(kAuthBasicPage);
475 GURL no_auth_page_1 = test_server()->GetURL("a");
476 GURL no_auth_page_2 = test_server()->GetURL("b");
477 GURL no_auth_page_3 = test_server()->GetURL("c");
479 content::WebContents* contents =
480 browser()->tab_strip_model()->GetActiveWebContents();
481 NavigationController* controller = &contents->GetController();
483 LoginPromptBrowserTestObserver observer;
484 observer.Register(content::Source<NavigationController>(controller));
486 // First navigate to an unauthenticated page so we have something to
487 // go back to.
488 ui_test_utils::NavigateToURL(browser(), no_auth_page_1);
490 // Navigating while auth is requested is the same as cancelling.
492 // We need to wait for two LOAD_STOP events. One for auth_page and one for
493 // no_auth_page_2.
494 WindowedLoadStopObserver load_stop_waiter(controller, 2);
495 WindowedAuthNeededObserver auth_needed_waiter(controller);
496 browser()->OpenURL(OpenURLParams(
497 auth_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
498 false));
499 auth_needed_waiter.Wait();
500 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
501 browser()->OpenURL(OpenURLParams(
502 no_auth_page_2, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
503 false));
504 auth_cancelled_waiter.Wait();
505 load_stop_waiter.Wait();
506 EXPECT_TRUE(observer.handlers_.empty());
509 // Try navigating backwards.
511 // As above, we wait for two LOAD_STOP events; one for each navigation.
512 WindowedLoadStopObserver load_stop_waiter(controller, 2);
513 WindowedAuthNeededObserver auth_needed_waiter(controller);
514 browser()->OpenURL(OpenURLParams(
515 auth_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
516 false));
517 auth_needed_waiter.Wait();
518 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
519 ASSERT_TRUE(chrome::CanGoBack(browser()));
520 chrome::GoBack(browser(), CURRENT_TAB);
521 auth_cancelled_waiter.Wait();
522 load_stop_waiter.Wait();
523 EXPECT_TRUE(observer.handlers_.empty());
526 // Now add a page and go back, so we have something to go forward to.
527 ui_test_utils::NavigateToURL(browser(), no_auth_page_3);
529 WindowedLoadStopObserver load_stop_waiter(controller, 1);
530 chrome::GoBack(browser(), CURRENT_TAB); // Should take us to page 1
531 load_stop_waiter.Wait();
535 // We wait for two LOAD_STOP events; one for each navigation.
536 WindowedLoadStopObserver load_stop_waiter(controller, 2);
537 WindowedAuthNeededObserver auth_needed_waiter(controller);
538 browser()->OpenURL(OpenURLParams(
539 auth_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
540 false));
541 auth_needed_waiter.Wait();
542 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
543 ASSERT_TRUE(chrome::CanGoForward(browser()));
544 chrome::GoForward(browser(), CURRENT_TAB); // Should take us to page 3
545 auth_cancelled_waiter.Wait();
546 load_stop_waiter.Wait();
547 EXPECT_TRUE(observer.handlers_.empty());
550 // Now test that cancelling works as expected.
552 WindowedLoadStopObserver load_stop_waiter(controller, 1);
553 WindowedAuthNeededObserver auth_needed_waiter(controller);
554 browser()->OpenURL(OpenURLParams(
555 auth_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
556 false));
557 auth_needed_waiter.Wait();
558 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
559 LoginHandler* handler = *observer.handlers_.begin();
560 ASSERT_TRUE(handler);
561 handler->CancelAuth();
562 auth_cancelled_waiter.Wait();
563 load_stop_waiter.Wait();
564 EXPECT_TRUE(observer.handlers_.empty());
568 // Test handling of resources that require authentication even though
569 // the page they are included on doesn't. In this case we should only
570 // present the minimal number of prompts necessary for successfully
571 // displaying the page. First we check whether cancelling works as
572 // expected.
573 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
574 ASSERT_TRUE(test_server()->Start());
575 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
577 content::WebContents* contents =
578 browser()->tab_strip_model()->GetActiveWebContents();
579 NavigationController* controller = &contents->GetController();
580 LoginPromptBrowserTestObserver observer;
582 observer.Register(content::Source<NavigationController>(controller));
584 WindowedLoadStopObserver load_stop_waiter(controller, 1);
587 WindowedAuthNeededObserver auth_needed_waiter(controller);
588 browser()->OpenURL(OpenURLParams(
589 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
590 false));
591 auth_needed_waiter.Wait();
594 int n_handlers = 0;
596 while (n_handlers < kMultiRealmTestRealmCount) {
597 WindowedAuthNeededObserver auth_needed_waiter(controller);
599 while (!observer.handlers_.empty()) {
600 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
601 LoginHandler* handler = *observer.handlers_.begin();
603 ASSERT_TRUE(handler);
604 n_handlers++;
605 handler->CancelAuth();
606 auth_cancelled_waiter.Wait();
609 if (n_handlers < kMultiRealmTestRealmCount)
610 auth_needed_waiter.Wait();
613 load_stop_waiter.Wait();
615 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
616 EXPECT_EQ(0, observer.auth_supplied_count_);
617 EXPECT_LT(0, observer.auth_needed_count_);
618 EXPECT_LT(0, observer.auth_cancelled_count_);
619 EXPECT_TRUE(test_server()->Stop());
622 // Similar to the MultipleRealmCancellation test above, but tests
623 // whether supplying credentials work as exepcted.
624 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
625 ASSERT_TRUE(test_server()->Start());
626 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
628 content::WebContents* contents =
629 browser()->tab_strip_model()->GetActiveWebContents();
630 NavigationController* controller = &contents->GetController();
631 LoginPromptBrowserTestObserver observer;
633 observer.Register(content::Source<NavigationController>(controller));
635 WindowedLoadStopObserver load_stop_waiter(controller, 1);
636 int n_handlers = 0;
639 WindowedAuthNeededObserver auth_needed_waiter(controller);
641 browser()->OpenURL(OpenURLParams(
642 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
643 false));
644 auth_needed_waiter.Wait();
647 while (n_handlers < kMultiRealmTestRealmCount) {
648 WindowedAuthNeededObserver auth_needed_waiter(controller);
650 while (!observer.handlers_.empty()) {
651 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
652 LoginHandler* handler = *observer.handlers_.begin();
654 ASSERT_TRUE(handler);
655 n_handlers++;
656 SetAuthFor(handler);
657 auth_supplied_waiter.Wait();
660 if (n_handlers < kMultiRealmTestRealmCount)
661 auth_needed_waiter.Wait();
664 load_stop_waiter.Wait();
666 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
667 EXPECT_LT(0, observer.auth_needed_count_);
668 EXPECT_LT(0, observer.auth_supplied_count_);
669 EXPECT_EQ(0, observer.auth_cancelled_count_);
670 EXPECT_TRUE(test_server()->Stop());
673 // Testing for recovery from an incorrect password for the case where
674 // there are multiple authenticated resources.
675 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, IncorrectConfirmation) {
676 ASSERT_TRUE(test_server()->Start());
677 GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
679 content::WebContents* contents =
680 browser()->tab_strip_model()->GetActiveWebContents();
681 NavigationController* controller = &contents->GetController();
682 LoginPromptBrowserTestObserver observer;
684 observer.Register(content::Source<NavigationController>(controller));
687 WindowedAuthNeededObserver auth_needed_waiter(controller);
688 browser()->OpenURL(OpenURLParams(
689 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
690 false));
691 auth_needed_waiter.Wait();
694 EXPECT_FALSE(observer.handlers_.empty());
696 if (!observer.handlers_.empty()) {
697 WindowedAuthNeededObserver auth_needed_waiter(controller);
698 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
699 LoginHandler* handler = *observer.handlers_.begin();
701 ASSERT_TRUE(handler);
702 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
703 base::UTF8ToUTF16(bad_password_));
704 auth_supplied_waiter.Wait();
706 // The request should be retried after the incorrect password is
707 // supplied. This should result in a new AUTH_NEEDED notification
708 // for the same realm.
709 auth_needed_waiter.Wait();
712 int n_handlers = 0;
714 while (n_handlers < 1) {
715 WindowedAuthNeededObserver auth_needed_waiter(controller);
717 while (!observer.handlers_.empty()) {
718 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
719 LoginHandler* handler = *observer.handlers_.begin();
721 ASSERT_TRUE(handler);
722 n_handlers++;
723 SetAuthFor(handler);
724 auth_supplied_waiter.Wait();
727 if (n_handlers < 1)
728 auth_needed_waiter.Wait();
731 // The single realm test has only one realm, and thus only one login
732 // prompt.
733 EXPECT_EQ(1, n_handlers);
734 EXPECT_LT(0, observer.auth_needed_count_);
735 EXPECT_EQ(0, observer.auth_cancelled_count_);
736 EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_);
737 EXPECT_TRUE(test_server()->Stop());
740 // If the favicon is an authenticated resource, we shouldn't prompt
741 // for credentials. The same URL, if requested elsewhere should
742 // prompt for credentials.
743 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, NoLoginPromptForFavicon) {
744 const char* kFaviconTestPage = "files/login/has_favicon.html";
745 const char* kFaviconResource = "auth-basic/favicon.gif";
747 ASSERT_TRUE(test_server()->Start());
749 content::WebContents* contents =
750 browser()->tab_strip_model()->GetActiveWebContents();
751 NavigationController* controller = &contents->GetController();
752 LoginPromptBrowserTestObserver observer;
754 observer.Register(content::Source<NavigationController>(controller));
756 // First load a page that has a favicon that requires
757 // authentication. There should be no login prompt.
759 GURL test_page = test_server()->GetURL(kFaviconTestPage);
760 WindowedLoadStopObserver load_stop_waiter(controller, 1);
761 browser()->OpenURL(OpenURLParams(
762 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
763 false));
764 load_stop_waiter.Wait();
767 // Now request the same favicon, but directly as the document.
768 // There should be one login prompt.
770 GURL test_page = test_server()->GetURL(kFaviconResource);
771 WindowedLoadStopObserver load_stop_waiter(controller, 1);
772 WindowedAuthNeededObserver auth_needed_waiter(controller);
773 browser()->OpenURL(OpenURLParams(
774 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
775 false));
776 auth_needed_waiter.Wait();
777 ASSERT_EQ(1u, observer.handlers_.size());
779 while (!observer.handlers_.empty()) {
780 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
781 LoginHandler* handler = *observer.handlers_.begin();
783 ASSERT_TRUE(handler);
784 handler->CancelAuth();
785 auth_cancelled_waiter.Wait();
788 load_stop_waiter.Wait();
791 EXPECT_EQ(0, observer.auth_supplied_count_);
792 EXPECT_EQ(1, observer.auth_needed_count_);
793 EXPECT_EQ(1, observer.auth_cancelled_count_);
794 EXPECT_TRUE(test_server()->Stop());
797 // Block crossdomain image login prompting as a phishing defense.
798 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
799 BlockCrossdomainPromptForSubresources) {
800 const char* kTestPage = "files/login/load_img_from_b.html";
802 host_resolver()->AddRule("www.a.com", "127.0.0.1");
803 host_resolver()->AddRule("www.b.com", "127.0.0.1");
804 ASSERT_TRUE(test_server()->Start());
806 content::WebContents* contents =
807 browser()->tab_strip_model()->GetActiveWebContents();
808 NavigationController* controller = &contents->GetController();
809 LoginPromptBrowserTestObserver observer;
810 observer.Register(content::Source<NavigationController>(controller));
812 // Load a page that has a cross-domain sub-resource authentication.
813 // There should be no login prompt.
815 GURL test_page = test_server()->GetURL(kTestPage);
816 ASSERT_EQ("127.0.0.1", test_page.host());
818 // Change the host from 127.0.0.1 to www.a.com so that when the
819 // page tries to load from b, it will be cross-origin.
820 std::string new_host("www.a.com");
821 GURL::Replacements replacements;
822 replacements.SetHostStr(new_host);
823 test_page = test_page.ReplaceComponents(replacements);
825 WindowedLoadStopObserver load_stop_waiter(controller, 1);
826 browser()->OpenURL(OpenURLParams(
827 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
828 false));
829 load_stop_waiter.Wait();
832 EXPECT_EQ(0, observer.auth_needed_count_);
834 // Now request the same page, but from the same origin.
835 // There should be one login prompt.
837 GURL test_page = test_server()->GetURL(kTestPage);
838 ASSERT_EQ("127.0.0.1", test_page.host());
840 // Change the host from 127.0.0.1 to www.b.com so that when the
841 // page tries to load from b, it will be same-origin.
842 std::string new_host("www.b.com");
843 GURL::Replacements replacements;
844 replacements.SetHostStr(new_host);
845 test_page = test_page.ReplaceComponents(replacements);
847 WindowedAuthNeededObserver auth_needed_waiter(controller);
848 browser()->OpenURL(OpenURLParams(
849 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
850 false));
851 auth_needed_waiter.Wait();
852 ASSERT_EQ(1u, observer.handlers_.size());
854 while (!observer.handlers_.empty()) {
855 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
856 LoginHandler* handler = *observer.handlers_.begin();
858 ASSERT_TRUE(handler);
859 handler->CancelAuth();
860 auth_cancelled_waiter.Wait();
864 EXPECT_EQ(1, observer.auth_needed_count_);
865 EXPECT_TRUE(test_server()->Stop());
868 // Allow crossdomain iframe login prompting despite the above.
869 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
870 AllowCrossdomainPromptForSubframes) {
871 const char* kTestPage = "files/login/load_iframe_from_b.html";
873 host_resolver()->AddRule("www.a.com", "127.0.0.1");
874 host_resolver()->AddRule("www.b.com", "127.0.0.1");
875 ASSERT_TRUE(test_server()->Start());
877 content::WebContents* contents =
878 browser()->tab_strip_model()->GetActiveWebContents();
879 NavigationController* controller = &contents->GetController();
880 LoginPromptBrowserTestObserver observer;
881 observer.Register(content::Source<NavigationController>(controller));
883 // Load a page that has a cross-domain iframe authentication.
885 GURL test_page = test_server()->GetURL(kTestPage);
886 ASSERT_EQ("127.0.0.1", test_page.host());
888 // Change the host from 127.0.0.1 to www.a.com so that when the
889 // page tries to load from b, it will be cross-origin.
890 std::string new_host("www.a.com");
891 GURL::Replacements replacements;
892 replacements.SetHostStr(new_host);
893 test_page = test_page.ReplaceComponents(replacements);
895 WindowedAuthNeededObserver auth_needed_waiter(controller);
896 browser()->OpenURL(OpenURLParams(
897 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
898 false));
899 auth_needed_waiter.Wait();
900 ASSERT_EQ(1u, observer.handlers_.size());
902 while (!observer.handlers_.empty()) {
903 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
904 LoginHandler* handler = *observer.handlers_.begin();
906 ASSERT_TRUE(handler);
907 // When a cross origin iframe displays a login prompt, the blank
908 // interstitial shouldn't be displayed and the omnibox should show the
909 // main frame's url, not the iframe's.
910 EXPECT_EQ(new_host, contents->GetURL().host());
912 handler->CancelAuth();
913 auth_cancelled_waiter.Wait();
917 // Should stay on the main frame's url once the prompt the iframe is closed.
918 EXPECT_EQ("www.a.com", contents->GetURL().host());
920 EXPECT_EQ(1, observer.auth_needed_count_);
921 EXPECT_TRUE(test_server()->Stop());
924 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, SupplyRedundantAuths) {
925 ASSERT_TRUE(test_server()->Start());
927 // Get NavigationController for tab 1.
928 content::WebContents* contents_1 =
929 browser()->tab_strip_model()->GetActiveWebContents();
930 NavigationController* controller_1 = &contents_1->GetController();
932 // Open a new tab.
933 ui_test_utils::NavigateToURLWithDisposition(
934 browser(),
935 GURL("about:blank"),
936 NEW_FOREGROUND_TAB,
937 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
939 // Get NavigationController for tab 2.
940 content::WebContents* contents_2 =
941 browser()->tab_strip_model()->GetActiveWebContents();
942 ASSERT_NE(contents_1, contents_2);
943 NavigationController* controller_2 = &contents_2->GetController();
945 LoginPromptBrowserTestObserver observer;
946 observer.Register(content::Source<NavigationController>(controller_1));
947 observer.Register(content::Source<NavigationController>(controller_2));
950 // Open different auth urls in each tab.
951 WindowedAuthNeededObserver auth_needed_waiter_1(controller_1);
952 WindowedAuthNeededObserver auth_needed_waiter_2(controller_2);
953 contents_1->OpenURL(OpenURLParams(
954 test_server()->GetURL("auth-basic/1"),
955 content::Referrer(),
956 CURRENT_TAB,
957 content::PAGE_TRANSITION_TYPED,
958 false));
959 contents_2->OpenURL(OpenURLParams(
960 test_server()->GetURL("auth-basic/2"),
961 content::Referrer(),
962 CURRENT_TAB,
963 content::PAGE_TRANSITION_TYPED,
964 false));
965 auth_needed_waiter_1.Wait();
966 auth_needed_waiter_2.Wait();
968 ASSERT_EQ(2U, observer.handlers_.size());
970 // Supply auth in one of the tabs.
971 WindowedAuthSuppliedObserver auth_supplied_waiter_1(controller_1);
972 WindowedAuthSuppliedObserver auth_supplied_waiter_2(controller_2);
973 LoginHandler* handler_1 = *observer.handlers_.begin();
974 ASSERT_TRUE(handler_1);
975 SetAuthFor(handler_1);
977 // Both tabs should be authenticated.
978 auth_supplied_waiter_1.Wait();
979 auth_supplied_waiter_2.Wait();
982 EXPECT_EQ(2, observer.auth_needed_count_);
983 EXPECT_EQ(2, observer.auth_supplied_count_);
984 EXPECT_EQ(0, observer.auth_cancelled_count_);
985 EXPECT_TRUE(test_server()->Stop());
988 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, CancelRedundantAuths) {
989 ASSERT_TRUE(test_server()->Start());
991 // Get NavigationController for tab 1.
992 content::WebContents* contents_1 =
993 browser()->tab_strip_model()->GetActiveWebContents();
994 NavigationController* controller_1 = &contents_1->GetController();
996 // Open a new tab.
997 ui_test_utils::NavigateToURLWithDisposition(
998 browser(),
999 GURL("about:blank"),
1000 NEW_FOREGROUND_TAB,
1001 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1003 // Get NavigationController for tab 2.
1004 content::WebContents* contents_2 =
1005 browser()->tab_strip_model()->GetActiveWebContents();
1006 ASSERT_NE(contents_1, contents_2);
1007 NavigationController* controller_2 = &contents_2->GetController();
1009 LoginPromptBrowserTestObserver observer;
1010 observer.Register(content::Source<NavigationController>(controller_1));
1011 observer.Register(content::Source<NavigationController>(controller_2));
1014 // Open different auth urls in each tab.
1015 WindowedAuthNeededObserver auth_needed_waiter_1(controller_1);
1016 WindowedAuthNeededObserver auth_needed_waiter_2(controller_2);
1017 contents_1->OpenURL(OpenURLParams(
1018 test_server()->GetURL("auth-basic/1"),
1019 content::Referrer(),
1020 CURRENT_TAB,
1021 content::PAGE_TRANSITION_TYPED,
1022 false));
1023 contents_2->OpenURL(OpenURLParams(
1024 test_server()->GetURL("auth-basic/2"),
1025 content::Referrer(),
1026 CURRENT_TAB,
1027 content::PAGE_TRANSITION_TYPED,
1028 false));
1029 auth_needed_waiter_1.Wait();
1030 auth_needed_waiter_2.Wait();
1032 ASSERT_EQ(2U, observer.handlers_.size());
1034 // Cancel auth in one of the tabs.
1035 WindowedAuthCancelledObserver auth_cancelled_waiter_1(controller_1);
1036 WindowedAuthCancelledObserver auth_cancelled_waiter_2(controller_2);
1037 LoginHandler* handler_1 = *observer.handlers_.begin();
1038 ASSERT_TRUE(handler_1);
1039 handler_1->CancelAuth();
1041 // Both tabs should cancel auth.
1042 auth_cancelled_waiter_1.Wait();
1043 auth_cancelled_waiter_2.Wait();
1046 EXPECT_EQ(2, observer.auth_needed_count_);
1047 EXPECT_EQ(0, observer.auth_supplied_count_);
1048 EXPECT_EQ(2, observer.auth_cancelled_count_);
1049 EXPECT_TRUE(test_server()->Stop());
1052 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1053 SupplyRedundantAuthsMultiProfile) {
1054 ASSERT_TRUE(test_server()->Start());
1056 // Get NavigationController for regular tab.
1057 content::WebContents* contents =
1058 browser()->tab_strip_model()->GetActiveWebContents();
1059 NavigationController* controller = &contents->GetController();
1061 // Open an incognito window.
1062 Browser* browser_incognito = CreateIncognitoBrowser();
1064 // Get NavigationController for incognito tab.
1065 content::WebContents* contents_incognito =
1066 browser_incognito->tab_strip_model()->GetActiveWebContents();
1067 ASSERT_NE(contents, contents_incognito);
1068 NavigationController* controller_incognito =
1069 &contents_incognito->GetController();
1071 LoginPromptBrowserTestObserver observer;
1072 observer.Register(content::Source<NavigationController>(controller));
1073 LoginPromptBrowserTestObserver observer_incognito;
1074 observer_incognito.Register(
1075 content::Source<NavigationController>(controller_incognito));
1078 // Open an auth url in each window.
1079 WindowedAuthNeededObserver auth_needed_waiter(controller);
1080 WindowedAuthNeededObserver auth_needed_waiter_incognito(
1081 controller_incognito);
1082 contents->OpenURL(OpenURLParams(
1083 test_server()->GetURL("auth-basic/1"),
1084 content::Referrer(),
1085 CURRENT_TAB,
1086 content::PAGE_TRANSITION_TYPED,
1087 false));
1088 contents_incognito->OpenURL(OpenURLParams(
1089 test_server()->GetURL("auth-basic/2"),
1090 content::Referrer(),
1091 CURRENT_TAB,
1092 content::PAGE_TRANSITION_TYPED,
1093 false));
1094 auth_needed_waiter.Wait();
1095 auth_needed_waiter_incognito.Wait();
1097 ASSERT_EQ(1U, observer.handlers_.size());
1098 ASSERT_EQ(1U, observer_incognito.handlers_.size());
1100 // Supply auth in regular tab.
1101 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1102 LoginHandler* handler = *observer.handlers_.begin();
1103 ASSERT_TRUE(handler);
1104 SetAuthFor(handler);
1106 // Regular tab should be authenticated.
1107 auth_supplied_waiter.Wait();
1109 // There's not really a way to wait for the incognito window to "do
1110 // nothing". Run anything pending in the message loop just to be sure.
1111 // (This shouldn't be necessary since notifications are synchronous, but
1112 // maybe it will help avoid flake someday in the future..)
1113 content::RunAllPendingInMessageLoop();
1116 EXPECT_EQ(1, observer.auth_needed_count_);
1117 EXPECT_EQ(1, observer.auth_supplied_count_);
1118 EXPECT_EQ(0, observer.auth_cancelled_count_);
1119 EXPECT_EQ(1, observer_incognito.auth_needed_count_);
1120 EXPECT_EQ(0, observer_incognito.auth_supplied_count_);
1121 EXPECT_EQ(0, observer_incognito.auth_cancelled_count_);
1122 EXPECT_TRUE(test_server()->Stop());
1125 // If an XMLHttpRequest is made with incorrect credentials, there should be no
1126 // login prompt; instead the 401 status should be returned to the script.
1127 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1128 NoLoginPromptForXHRWithBadCredentials) {
1129 const char* kXHRTestPage = "files/login/xhr_with_credentials.html#incorrect";
1131 ASSERT_TRUE(test_server()->Start());
1133 content::WebContents* contents =
1134 browser()->tab_strip_model()->GetActiveWebContents();
1135 NavigationController* controller = &contents->GetController();
1136 LoginPromptBrowserTestObserver observer;
1138 observer.Register(content::Source<NavigationController>(controller));
1140 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1141 // resource with the wrong credentials. There should be no login prompt.
1143 GURL test_page = test_server()->GetURL(kXHRTestPage);
1144 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1145 browser()->OpenURL(OpenURLParams(
1146 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
1147 false));
1148 load_stop_waiter.Wait();
1151 base::string16 expected_title(base::UTF8ToUTF16("status=401"));
1153 EXPECT_EQ(expected_title, contents->GetTitle());
1154 EXPECT_EQ(0, observer.auth_supplied_count_);
1155 EXPECT_EQ(0, observer.auth_needed_count_);
1156 EXPECT_EQ(0, observer.auth_cancelled_count_);
1157 EXPECT_TRUE(test_server()->Stop());
1160 // If an XMLHttpRequest is made with correct credentials, there should be no
1161 // login prompt either.
1162 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1163 NoLoginPromptForXHRWithGoodCredentials) {
1164 const char* kXHRTestPage = "files/login/xhr_with_credentials.html#secret";
1166 ASSERT_TRUE(test_server()->Start());
1168 content::WebContents* contents =
1169 browser()->tab_strip_model()->GetActiveWebContents();
1170 NavigationController* controller = &contents->GetController();
1171 LoginPromptBrowserTestObserver observer;
1173 observer.Register(content::Source<NavigationController>(controller));
1175 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1176 // resource with the wrong credentials. There should be no login prompt.
1178 GURL test_page = test_server()->GetURL(kXHRTestPage);
1179 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1180 browser()->OpenURL(OpenURLParams(
1181 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
1182 false));
1183 load_stop_waiter.Wait();
1186 base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1188 EXPECT_EQ(expected_title, contents->GetTitle());
1189 EXPECT_EQ(0, observer.auth_supplied_count_);
1190 EXPECT_EQ(0, observer.auth_needed_count_);
1191 EXPECT_EQ(0, observer.auth_cancelled_count_);
1192 EXPECT_TRUE(test_server()->Stop());
1195 // If an XMLHttpRequest is made without credentials, there should be a login
1196 // prompt.
1197 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1198 LoginPromptForXHRWithoutCredentials) {
1199 const char* kXHRTestPage = "files/login/xhr_without_credentials.html";
1201 ASSERT_TRUE(test_server()->Start());
1203 content::WebContents* contents =
1204 browser()->tab_strip_model()->GetActiveWebContents();
1205 NavigationController* controller = &contents->GetController();
1206 LoginPromptBrowserTestObserver observer;
1208 observer.Register(content::Source<NavigationController>(controller));
1210 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1211 // resource with the wrong credentials. There should be no login prompt.
1213 GURL test_page = test_server()->GetURL(kXHRTestPage);
1214 WindowedAuthNeededObserver auth_needed_waiter(controller);
1215 browser()->OpenURL(OpenURLParams(
1216 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
1217 false));
1218 auth_needed_waiter.Wait();
1221 ASSERT_FALSE(observer.handlers_.empty());
1223 WindowedAuthNeededObserver auth_needed_waiter(controller);
1224 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1225 LoginHandler* handler = *observer.handlers_.begin();
1227 ASSERT_TRUE(handler);
1228 handler->SetAuth(base::UTF8ToUTF16(bad_username_),
1229 base::UTF8ToUTF16(bad_password_));
1230 auth_supplied_waiter.Wait();
1232 // The request should be retried after the incorrect password is
1233 // supplied. This should result in a new AUTH_NEEDED notification
1234 // for the same realm.
1235 auth_needed_waiter.Wait();
1238 ASSERT_EQ(1u, observer.handlers_.size());
1239 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
1240 LoginHandler* handler = *observer.handlers_.begin();
1242 base::string16 username(base::UTF8ToUTF16(username_digest_));
1243 base::string16 password(base::UTF8ToUTF16(password_));
1244 handler->SetAuth(username, password);
1245 auth_supplied_waiter.Wait();
1247 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1248 load_stop_waiter.Wait();
1250 base::string16 expected_title(base::UTF8ToUTF16("status=200"));
1252 EXPECT_EQ(expected_title, contents->GetTitle());
1253 EXPECT_EQ(2, observer.auth_supplied_count_);
1254 EXPECT_EQ(2, observer.auth_needed_count_);
1255 EXPECT_EQ(0, observer.auth_cancelled_count_);
1256 EXPECT_TRUE(test_server()->Stop());
1259 // If an XMLHttpRequest is made without credentials, there should be a login
1260 // prompt. If it's cancelled, the script should get a 401 status.
1261 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1262 LoginPromptForXHRWithoutCredentialsCancelled) {
1263 const char* kXHRTestPage = "files/login/xhr_without_credentials.html";
1265 ASSERT_TRUE(test_server()->Start());
1267 content::WebContents* contents =
1268 browser()->tab_strip_model()->GetActiveWebContents();
1269 NavigationController* controller = &contents->GetController();
1270 LoginPromptBrowserTestObserver observer;
1272 observer.Register(content::Source<NavigationController>(controller));
1274 // Load a page which makes a synchronous XMLHttpRequest for an authenticated
1275 // resource with the wrong credentials. There should be no login prompt.
1277 GURL test_page = test_server()->GetURL(kXHRTestPage);
1278 WindowedAuthNeededObserver auth_needed_waiter(controller);
1279 browser()->OpenURL(OpenURLParams(
1280 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
1281 false));
1282 auth_needed_waiter.Wait();
1285 ASSERT_EQ(1u, observer.handlers_.size());
1286 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
1287 LoginHandler* handler = *observer.handlers_.begin();
1289 handler->CancelAuth();
1290 auth_cancelled_waiter.Wait();
1292 WindowedLoadStopObserver load_stop_waiter(controller, 1);
1293 load_stop_waiter.Wait();
1295 base::string16 expected_title(base::UTF8ToUTF16("status=401"));
1297 EXPECT_EQ(expected_title, contents->GetTitle());
1298 EXPECT_EQ(0, observer.auth_supplied_count_);
1299 EXPECT_EQ(1, observer.auth_needed_count_);
1300 EXPECT_EQ(1, observer.auth_cancelled_count_);
1301 EXPECT_TRUE(test_server()->Stop());
1304 // If a cross origin navigation triggers a login prompt, the destination URL
1305 // should be shown in the omnibox.
1306 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
1307 ShowCorrectUrlForCrossOriginMainFrameRequests) {
1308 const char* kTestPage = "files/login/cross_origin.html";
1309 host_resolver()->AddRule("www.a.com", "127.0.0.1");
1310 ASSERT_TRUE(test_server()->Start());
1312 content::WebContents* contents =
1313 browser()->tab_strip_model()->GetActiveWebContents();
1314 NavigationController* controller = &contents->GetController();
1315 LoginPromptBrowserTestObserver observer;
1317 observer.Register(content::Source<NavigationController>(controller));
1319 // Load a page which navigates to a cross origin page with a login prompt.
1321 GURL test_page = test_server()->GetURL(kTestPage);
1322 ASSERT_EQ("127.0.0.1", test_page.host());
1324 WindowedAuthNeededObserver auth_needed_waiter(controller);
1325 browser()->OpenURL(OpenURLParams(
1326 test_page, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
1327 false));
1328 ASSERT_EQ("127.0.0.1", contents->GetURL().host());
1329 auth_needed_waiter.Wait();
1330 ASSERT_EQ(1u, observer.handlers_.size());
1331 WaitForInterstitialAttach(contents);
1333 // The omnibox should show the correct origin for the new page when the
1334 // login prompt is shown.
1335 EXPECT_EQ("www.a.com", contents->GetURL().host());
1336 EXPECT_TRUE(contents->ShowingInterstitialPage());
1338 // Cancel and wait for the interstitial to detach.
1339 LoginHandler* handler = *observer.handlers_.begin();
1340 scoped_refptr<content::MessageLoopRunner> loop_runner(
1341 new content::MessageLoopRunner);
1342 InterstitialObserver interstitial_observer(contents,
1343 base::Closure(),
1344 loop_runner->QuitClosure());
1345 handler->CancelAuth();
1346 if (content::InterstitialPage::GetInterstitialPage(contents))
1347 loop_runner->Run();
1348 EXPECT_EQ("www.a.com", contents->GetURL().host());
1349 EXPECT_FALSE(contents->ShowingInterstitialPage());
1353 } // namespace