Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <list> | 6 #include <list> |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/command_line.h" | |
| 9 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/browser_thread.h" | 11 #include "chrome/browser/browser_thread.h" |
| 11 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | 12 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
| 12 #include "chrome/browser/ui/browser.h" | 13 #include "chrome/browser/ui/browser.h" |
| 13 #include "chrome/browser/ui/login/login_prompt.h" | 14 #include "chrome/browser/ui/login/login_prompt.h" |
| 14 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 15 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 16 #include "chrome/common/chrome_switches.h" | |
| 15 #include "chrome/common/notification_service.h" | 17 #include "chrome/common/notification_service.h" |
| 16 #include "chrome/test/in_process_browser_test.h" | 18 #include "chrome/test/in_process_browser_test.h" |
| 17 #include "chrome/test/ui_test_utils.h" | 19 #include "chrome/test/ui_test_utils.h" |
| 18 #include "net/base/auth.h" | 20 #include "net/base/auth.h" |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 class LoginPromptBrowserTest : public InProcessBrowserTest { | 24 class LoginPromptBrowserTest : public InProcessBrowserTest { |
| 23 public: | 25 public: |
| 24 LoginPromptBrowserTest() | 26 LoginPromptBrowserTest() |
| 25 : bad_password_(L"incorrect"), bad_username_(L"nouser") { | 27 : bad_password_(L"incorrect"), bad_username_(L"nouser") { |
| 26 set_show_window(true); | 28 set_show_window(true); |
| 27 | 29 |
| 28 auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword"); | 30 auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword"); |
| 29 auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword"); | 31 auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword"); |
| 32 auth_map_[L"testrealm"] = AuthInfo(L"testuser", L"secret"); | |
| 30 } | 33 } |
| 31 | 34 |
| 32 protected: | 35 protected: |
| 33 void SetAuthFor(LoginHandler* handler); | 36 void SetAuthFor(LoginHandler* handler); |
| 34 | 37 |
| 38 // InProcessBrowserTest | |
| 39 virtual void SetUpCommandLine(CommandLine* command_line); | |
| 40 | |
| 35 struct AuthInfo { | 41 struct AuthInfo { |
| 36 std::wstring username_; | 42 std::wstring username_; |
| 37 std::wstring password_; | 43 std::wstring password_; |
| 38 | 44 |
| 39 AuthInfo() {} | 45 AuthInfo() {} |
| 40 | 46 |
| 41 AuthInfo(const std::wstring username, | 47 AuthInfo(const std::wstring username, |
| 42 const std::wstring password) | 48 const std::wstring password) |
| 43 : username_(username), password_(password) {} | 49 : username_(username), password_(password) {} |
| 44 }; | 50 }; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 55 std::map<std::wstring, AuthInfo>::iterator i = | 61 std::map<std::wstring, AuthInfo>::iterator i = |
| 56 auth_map_.find(challenge->realm); | 62 auth_map_.find(challenge->realm); |
| 57 EXPECT_TRUE(auth_map_.end() != i); | 63 EXPECT_TRUE(auth_map_.end() != i); |
| 58 if (i != auth_map_.end()) { | 64 if (i != auth_map_.end()) { |
| 59 const AuthInfo& info = i->second; | 65 const AuthInfo& info = i->second; |
| 60 handler->SetAuth(WideToUTF16Hack(info.username_), | 66 handler->SetAuth(WideToUTF16Hack(info.username_), |
| 61 WideToUTF16Hack(info.password_)); | 67 WideToUTF16Hack(info.password_)); |
| 62 } | 68 } |
| 63 } | 69 } |
| 64 | 70 |
| 71 void LoginPromptBrowserTest::SetUpCommandLine(CommandLine* command_line) { | |
|
cbentzel
2011/02/16 20:51:39
Should this be in another CL?
asanka
2011/02/16 22:39:19
Removed.
| |
| 72 #if defined(OS_POSIX) && !defined(OS_MACOSX) | |
| 73 // We are not exercising the password store here and using the Gnome | |
| 74 // Keyring can cause tests to timeout (http://crbug.com/68860). So | |
| 75 // just use the basic password store for now. | |
| 76 // TODO(asanka): Remove this after http://crbug.com/68860 is fixed. | |
| 77 command_line->AppendSwitchASCII(switches::kPasswordStore, "basic"); | |
| 78 #endif | |
| 79 } | |
| 80 | |
| 65 // Maintains a set of LoginHandlers that are currently active and | 81 // Maintains a set of LoginHandlers that are currently active and |
| 66 // keeps a count of the notifications that were observed. | 82 // keeps a count of the notifications that were observed. |
| 67 class LoginPromptBrowserTestObserver : public NotificationObserver { | 83 class LoginPromptBrowserTestObserver : public NotificationObserver { |
| 68 public: | 84 public: |
| 69 LoginPromptBrowserTestObserver() | 85 LoginPromptBrowserTestObserver() |
| 70 : auth_needed_count_(0), | 86 : auth_needed_count_(0), |
| 71 auth_supplied_count_(0), | 87 auth_supplied_count_(0), |
| 72 auth_cancelled_count_(0) {} | 88 auth_cancelled_count_(0) {} |
| 73 | 89 |
| 74 virtual void Observe(NotificationType type, | 90 virtual void Observe(NotificationType type, |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 404 // prompt. | 420 // prompt. |
| 405 EXPECT_EQ(1, n_handlers); | 421 EXPECT_EQ(1, n_handlers); |
| 406 EXPECT_LT(0, observer.auth_needed_count_); | 422 EXPECT_LT(0, observer.auth_needed_count_); |
| 407 EXPECT_EQ(0, observer.auth_cancelled_count_); | 423 EXPECT_EQ(0, observer.auth_cancelled_count_); |
| 408 EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_); | 424 EXPECT_EQ(observer.auth_needed_count_, observer.auth_supplied_count_); |
| 409 LOG(INFO) << "Waiting for LOAD_STOP"; | 425 LOG(INFO) << "Waiting for LOAD_STOP"; |
| 410 load_stop_waiter.Wait(); | 426 load_stop_waiter.Wait(); |
| 411 EXPECT_TRUE(test_server()->Stop()); | 427 EXPECT_TRUE(test_server()->Stop()); |
| 412 LOG(INFO) << "Done with test"; | 428 LOG(INFO) << "Done with test"; |
| 413 } | 429 } |
| 430 | |
| 431 // If a 401 response is received after we present cached credentials, | |
|
cbentzel
2011/02/16 20:51:39
Do you want to add a test for different realms?
asanka
2011/02/16 22:39:19
Added. Also added one for Digest.
| |
| 432 // we should remove cached credentials and display a prompt to the | |
| 433 // user. | |
| 434 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, RemoveCredsOn401Basic) { | |
| 435 const char* kTestUrlPre = | |
|
cbentzel
2011/02/16 20:51:39
I've been increasingly seeing const char* const fo
asanka
2011/02/16 22:39:19
Done.
| |
| 436 "auth-basic/a?password=foopassword&realm=foo&"; | |
| 437 const char* kTestUrlPost = | |
| 438 "auth-basic/a?password=foopassword&realm=foo&force=1"; | |
| 439 ASSERT_TRUE(test_server()->Start()); | |
| 440 | |
| 441 TabContentsWrapper* contents = | |
| 442 browser()->GetSelectedTabContentsWrapper(); | |
| 443 ASSERT_TRUE(contents); | |
| 444 | |
| 445 NavigationController* controller = &contents->controller(); | |
| 446 LoginPromptBrowserTestObserver observer; | |
| 447 | |
| 448 observer.Register(Source<NavigationController>(controller)); | |
| 449 | |
| 450 { | |
| 451 GURL test_page = test_server()->GetURL(kTestUrlPre); | |
| 452 WindowedLoadStopObserver load_stop_waiter(controller); | |
| 453 WindowedAuthNeededObserver auth_needed_waiter(controller); | |
| 454 | |
| 455 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED); | |
| 456 auth_needed_waiter.Wait(); | |
| 457 ASSERT_FALSE(observer.handlers_.empty()); | |
| 458 LoginHandler* handler = *observer.handlers_.begin(); | |
| 459 ASSERT_TRUE(handler); | |
| 460 SetAuthFor(handler); | |
| 461 load_stop_waiter.Wait(); | |
| 462 } | |
| 463 | |
| 464 { | |
| 465 GURL test_page = test_server()->GetURL(kTestUrlPost); | |
| 466 WindowedLoadStopObserver load_stop_waiter(controller); | |
| 467 WindowedAuthNeededObserver auth_needed_waiter(controller); | |
| 468 | |
| 469 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED); | |
| 470 | |
| 471 // The OpenURL request should result in the server sending back a | |
| 472 // 401. Chrome should at this point remove any cached credentials | |
| 473 // for this target and prompt for credentials. The test server | |
| 474 // only sends one 401 request and if Chrome responds with cached | |
| 475 // credentials, the wait for AUTH_NEEDED will never complete. | |
| 476 auth_needed_waiter.Wait(); | |
| 477 ASSERT_FALSE(observer.handlers_.empty()); | |
| 478 LoginHandler* handler = *observer.handlers_.begin(); | |
| 479 ASSERT_TRUE(handler); | |
| 480 SetAuthFor(handler); | |
| 481 load_stop_waiter.Wait(); | |
| 482 } | |
| 483 | |
| 484 EXPECT_TRUE(test_server()->Stop()); | |
| 485 } | |
| 486 | |
| 487 // Same as RemoveCredsOn401Basic test, except for Digest | |
| 488 // authentication. If we receive a response from the server with a | |
| 489 // challenge that includes a stale=true token, then we shouldn't | |
| 490 // remove cached credentials. | |
| 491 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, RemoveCredsOn401Digest) { | |
| 492 const char* kTestUrlPre = "auth-digest/a"; | |
| 493 const char* kTestUrlStale = "auth-digest/a/stale"; | |
| 494 const char* kTestUrlPost = "auth-digest/a/force"; | |
| 495 ASSERT_TRUE(test_server()->Start()); | |
| 496 | |
| 497 TabContentsWrapper* contents = | |
| 498 browser()->GetSelectedTabContentsWrapper(); | |
| 499 ASSERT_TRUE(contents); | |
| 500 | |
| 501 NavigationController* controller = &contents->controller(); | |
| 502 LoginPromptBrowserTestObserver observer; | |
| 503 | |
| 504 observer.Register(Source<NavigationController>(controller)); | |
| 505 | |
| 506 { | |
| 507 GURL test_page = test_server()->GetURL(kTestUrlPre); | |
| 508 WindowedLoadStopObserver load_stop_waiter(controller); | |
| 509 WindowedAuthNeededObserver auth_needed_waiter(controller); | |
| 510 | |
| 511 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED); | |
| 512 auth_needed_waiter.Wait(); | |
| 513 ASSERT_FALSE(observer.handlers_.empty()); | |
| 514 LoginHandler* handler = *observer.handlers_.begin(); | |
| 515 ASSERT_TRUE(handler); | |
| 516 SetAuthFor(handler); | |
| 517 load_stop_waiter.Wait(); | |
| 518 } | |
| 519 | |
| 520 // The stale URL will result in a server response that includes a | |
| 521 // stale=true directive. We should respond with a request generated | |
| 522 // using the cached credentials. There should be no login prompt. | |
| 523 { | |
| 524 GURL test_page = test_server()->GetURL(kTestUrlStale); | |
| 525 WindowedLoadStopObserver load_stop_waiter(controller); | |
| 526 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED); | |
| 527 load_stop_waiter.Wait(); | |
| 528 } | |
| 529 | |
| 530 { | |
| 531 GURL test_page = test_server()->GetURL(kTestUrlPost); | |
| 532 WindowedLoadStopObserver load_stop_waiter(controller); | |
| 533 WindowedAuthNeededObserver auth_needed_waiter(controller); | |
| 534 | |
| 535 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED); | |
| 536 | |
| 537 // The OpenURL request should result in the server sending back a | |
| 538 // 401. Chrome should at this point remove any cached credentials | |
| 539 // for this target and prompt for credentials. The test server | |
| 540 // only sends one 401 request and if Chrome responds with cached | |
| 541 // credentials, the wait for AUTH_NEEDED will never complete. | |
| 542 auth_needed_waiter.Wait(); | |
| 543 ASSERT_FALSE(observer.handlers_.empty()); | |
| 544 LoginHandler* handler = *observer.handlers_.begin(); | |
| 545 ASSERT_TRUE(handler); | |
| 546 SetAuthFor(handler); | |
| 547 load_stop_waiter.Wait(); | |
| 548 } | |
| 549 | |
| 550 EXPECT_TRUE(test_server()->Stop()); | |
| 551 } | |
| 414 } // namespace | 552 } // namespace |
| OLD | NEW |