1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/metrics/field_trial.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/prerender/prerender_manager.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_commands.h"
15 #include "chrome/browser/ui/login/login_prompt.h"
16 #include "chrome/browser/ui/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
;
34 class LoginPromptBrowserTest
: public InProcessBrowserTest
{
36 LoginPromptBrowserTest()
37 : bad_password_("incorrect"),
38 bad_username_("nouser"),
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_
);
49 std::string username_
;
50 std::string password_
;
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
);
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
{
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_
;
114 content::NotificationRegistrar registrar_
;
116 DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver
);
119 void LoginPromptBrowserTestObserver::Observe(
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(),
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(),
154 EXPECT_TRUE(i
!= handlers_
.end());
155 if (i
!= handlers_
.end())
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
);
167 class WindowedNavigationObserver
168 : public content::WindowedNotificationObserver
{
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
> {
180 WindowedLoadStopObserver(NavigationController
* controller
,
181 int notification_count
)
182 : WindowedNavigationObserver
<content::NOTIFICATION_LOAD_STOP
>(controller
),
183 remaining_notification_count_(notification_count
) {}
185 virtual void Observe(int type
,
186 const content::NotificationSource
& source
,
187 const content::NotificationDetails
& details
) OVERRIDE
;
189 int remaining_notification_count_
; // Number of notifications remaining.
192 void WindowedLoadStopObserver::Observe(
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
{
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();
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(
230 interstitial_attach_loop_runner
->QuitClosure(),
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
{
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_
);
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
,
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
,
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();
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
,
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
));
422 ui_test_utils::NavigateToURLWithDisposition(
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
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
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
,
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
,
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
,
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
,
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
,
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
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
,
591 auth_needed_waiter
.Wait();
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
);
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);
639 WindowedAuthNeededObserver
auth_needed_waiter(controller
);
641 browser()->OpenURL(OpenURLParams(
642 test_page
, Referrer(), CURRENT_TAB
, content::PAGE_TRANSITION_TYPED
,
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
);
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
,
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();
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
);
724 auth_supplied_waiter
.Wait();
728 auth_needed_waiter
.Wait();
731 // The single realm test has only one realm, and thus only one login
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
,
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
,
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
,
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
,
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
,
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();
933 ui_test_utils::NavigateToURLWithDisposition(
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"),
957 content::PAGE_TRANSITION_TYPED
,
959 contents_2
->OpenURL(OpenURLParams(
960 test_server()->GetURL("auth-basic/2"),
963 content::PAGE_TRANSITION_TYPED
,
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();
997 ui_test_utils::NavigateToURLWithDisposition(
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(),
1021 content::PAGE_TRANSITION_TYPED
,
1023 contents_2
->OpenURL(OpenURLParams(
1024 test_server()->GetURL("auth-basic/2"),
1025 content::Referrer(),
1027 content::PAGE_TRANSITION_TYPED
,
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(),
1086 content::PAGE_TRANSITION_TYPED
,
1088 contents_incognito
->OpenURL(OpenURLParams(
1089 test_server()->GetURL("auth-basic/2"),
1090 content::Referrer(),
1092 content::PAGE_TRANSITION_TYPED
,
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
,
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
,
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
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
,
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
,
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
,
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
,
1344 loop_runner
->QuitClosure());
1345 handler
->CancelAuth();
1346 if (content::InterstitialPage::GetInterstitialPage(contents
))
1348 EXPECT_EQ("www.a.com", contents
->GetURL().host());
1349 EXPECT_FALSE(contents
->ShowingInterstitialPage());