| Index: chrome/browser/ui/login/login_prompt_browsertest.cc
|
| diff --git a/chrome/browser/ui/login/login_prompt_browsertest.cc b/chrome/browser/ui/login/login_prompt_browsertest.cc
|
| index a284438c112e559c06aae0cd86dc0fcc49d1feb5..acc8bc92a59737706867696bcf76e44122ee1c44 100644
|
| --- a/chrome/browser/ui/login/login_prompt_browsertest.cc
|
| +++ b/chrome/browser/ui/login/login_prompt_browsertest.cc
|
| @@ -7,6 +7,7 @@
|
| #include <map>
|
|
|
| #include "base/metrics/field_trial.h"
|
| +#include "base/strings/stringprintf.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/prerender/prerender_manager.h"
|
| @@ -20,12 +21,15 @@
|
| #include "chrome/test/base/in_process_browser_test.h"
|
| #include "chrome/test/base/ui_test_utils.h"
|
| #include "content/public/browser/interstitial_page.h"
|
| +#include "content/public/browser/navigation_entry.h"
|
| #include "content/public/browser/notification_details.h"
|
| #include "content/public/browser/notification_source.h"
|
| #include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/ssl_status.h"
|
| #include "content/public/test/browser_test_utils.h"
|
| #include "content/public/test/test_navigation_observer.h"
|
| #include "net/base/auth.h"
|
| +#include "net/base/filename_util.h"
|
| #include "net/dns/mock_host_resolver.h"
|
| #include "net/test/spawned_test_server/spawned_test_server.h"
|
|
|
| @@ -35,6 +39,8 @@ using content::Referrer;
|
|
|
| namespace {
|
|
|
| +enum ExpectedSSLStatus { SSL_STATUS_NONE, SSL_STATUS_OK, SSL_STATUS_BROKEN };
|
| +
|
| class LoginPromptBrowserTest : public InProcessBrowserTest {
|
| public:
|
| LoginPromptBrowserTest()
|
| @@ -62,11 +68,16 @@ class LoginPromptBrowserTest : public InProcessBrowserTest {
|
|
|
| typedef std::map<std::string, AuthInfo> AuthMap;
|
|
|
| - void SetAuthFor(LoginHandler* handler);
|
| + void SetAuthFor(LoginHandler* handler) const;
|
|
|
| void TestCrossOriginPrompt(const GURL& visit_url,
|
| const std::string& landing_host) const;
|
|
|
| + void TestSSLState(Browser* browser,
|
| + const GURL& test_page,
|
| + bool has_redirect,
|
| + int expected_ssl_status) const;
|
| +
|
| AuthMap auth_map_;
|
| std::string bad_password_;
|
| std::string bad_username_;
|
| @@ -75,11 +86,11 @@ class LoginPromptBrowserTest : public InProcessBrowserTest {
|
| std::string username_digest_;
|
| };
|
|
|
| -void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
|
| +void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) const {
|
| const net::AuthChallengeInfo* challenge = handler->auth_info();
|
|
|
| ASSERT_TRUE(challenge);
|
| - AuthMap::iterator i = auth_map_.find(challenge->realm);
|
| + AuthMap::const_iterator i = auth_map_.find(challenge->realm);
|
| EXPECT_TRUE(auth_map_.end() != i);
|
| if (i != auth_map_.end()) {
|
| const AuthInfo& info = i->second;
|
| @@ -88,6 +99,32 @@ void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
|
| }
|
| }
|
|
|
| +void CheckSSLState(content::WebContents* contents, int expected_ssl_status) {
|
| + NavigationController* controller = &contents->GetController();
|
| + content::NavigationEntry* entry = controller->GetVisibleEntry();
|
| + const content::SSLStatus& ssl_status = entry->GetSSL();
|
| + EXPECT_EQ(content::SSLStatus::NORMAL_CONTENT, ssl_status.content_status);
|
| + EXPECT_EQ(128, ssl_status.security_bits);
|
| + switch (expected_ssl_status) {
|
| + case SSL_STATUS_OK:
|
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED,
|
| + ssl_status.security_style);
|
| + break;
|
| + case SSL_STATUS_BROKEN:
|
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
|
| + ssl_status.security_style);
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| +}
|
| +
|
| +void CancelAndWaitForInterstitialDetach(LoginHandler* handler,
|
| + content::WebContents* contents) {
|
| + RunTaskAndWaitForInterstitialDetach(
|
| + contents, base::Bind(&LoginHandler::CancelAuth, handler));
|
| +}
|
| +
|
| const char kPrefetchAuthPage[] = "files/login/prefetch.html";
|
|
|
| const char kMultiRealmTestPage[] = "files/login/multi_realm.html";
|
| @@ -1375,4 +1412,155 @@ IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
|
| }
|
| }
|
|
|
| +// Navigates the active tab to |test_page| which should end up at a URL with
|
| +// HTTP auth, and checks if the SSL information at this final URL is set
|
| +// correctly.
|
| +// If |has_redirect| is true, |test_page| redirects to the HTTP auth URL.
|
| +// If |has_redirect| is false, |test_page| is the final HTTP auth URL.
|
| +void LoginPromptBrowserTest::TestSSLState(Browser* browser,
|
| + const GURL& test_page,
|
| + bool has_redirect,
|
| + int expected_ssl_status) const {
|
| + content::WebContents* contents =
|
| + browser->tab_strip_model()->GetActiveWebContents();
|
| + NavigationController* controller = &contents->GetController();
|
| + LoginPromptBrowserTestObserver observer;
|
| +
|
| + observer.Register(content::Source<NavigationController>(controller));
|
| + {
|
| + WindowedAuthNeededObserver auth_needed_waiter(controller);
|
| + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
|
| + browser, test_page, has_redirect ? 2 : 1);
|
| + // After redirects etc., the page should end up at the HTTPS url.
|
| + ASSERT_EQ("127.0.0.1", contents->GetURL().host());
|
| + if (expected_ssl_status == SSL_STATUS_BROKEN) {
|
| + // Wait for the broken SSL interstitial and proceed through it.
|
| + WaitForInterstitialAttach(contents);
|
| + EXPECT_TRUE(contents->ShowingInterstitialPage());
|
| + EXPECT_EQ(SSLBlockingPage::kTypeForTesting,
|
| + contents->GetInterstitialPage()
|
| + ->GetDelegateForTesting()
|
| + ->GetTypeForTesting());
|
| + contents->GetInterstitialPage()->Proceed();
|
| + }
|
| +
|
| + // The auth prompt should show with the blank login interstitial, and the
|
| + // SSL status should be available (but broken).
|
| + auth_needed_waiter.Wait();
|
| + ASSERT_EQ(1u, observer.handlers().size());
|
| + WaitForInterstitialAttach(contents);
|
| + EXPECT_TRUE(contents->ShowingInterstitialPage());
|
| + EXPECT_EQ(LoginInterstitialDelegate::kTypeForTesting,
|
| + contents->GetInterstitialPage()
|
| + ->GetDelegateForTesting()
|
| + ->GetTypeForTesting());
|
| + // Navigation not committed yet when the auth dialog is displayed.
|
| + EXPECT_EQ("", contents->GetLastCommittedURL().host());
|
| + EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
|
| + CheckSSLState(contents, expected_ssl_status);
|
| +
|
| + // Cancelling the login prompt should detach the interstitial while keeping
|
| + // the correct origin and SSL state.
|
| + CancelAndWaitForInterstitialDetach(*observer.handlers().begin(), contents);
|
| + EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host());
|
| + EXPECT_EQ("127.0.0.1", contents->GetLastCommittedURL().host());
|
| + EXPECT_FALSE(contents->ShowingInterstitialPage());
|
| + CheckSSLState(contents, expected_ssl_status);
|
| + }
|
| +}
|
| +
|
| +// Omnibox and connection tab should reflect the correct SSL State when login
|
| +// prompt is displayed in the main frame.
|
| +// This is simply the scenario where the user enters an HTTPS url that ends up
|
| +// with an HTTP auth dialog.
|
| +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
|
| + SSLStateShouldUpdateOnDirectNavigation) {
|
| + net::SpawnedTestServer https_server(
|
| + net::SpawnedTestServer::TYPE_HTTPS,
|
| + net::SpawnedTestServer::SSLOptions(
|
| + net::SpawnedTestServer::SSLOptions::CERT_OK),
|
| + base::FilePath());
|
| + ASSERT_TRUE(https_server.Start());
|
| + GURL test_page = https_server.GetURL(kAuthBasicPage);
|
| + ASSERT_EQ("127.0.0.1", test_page.host());
|
| + TestSSLState(browser(), test_page, false, SSL_STATUS_OK);
|
| +}
|
| +
|
| +// Same as above, except the HTTPS url has a cert error. When the user proceeds
|
| +// through the SSL interstitial, HTTP auth dialog should be displayed with the
|
| +// correct (i.e. broken) SSL information.
|
| +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
|
| + SSLStateShouldUpdateOnDirectNavigation_BrokenSSL) {
|
| + net::SpawnedTestServer https_server(
|
| + net::SpawnedTestServer::TYPE_HTTPS,
|
| + net::SpawnedTestServer::SSLOptions(
|
| + net::SpawnedTestServer::SSLOptions::CERT_CHAIN_WRONG_ROOT),
|
| + base::FilePath());
|
| + ASSERT_TRUE(https_server.Start());
|
| + GURL test_page = https_server.GetURL(kAuthBasicPage);
|
| + ASSERT_EQ("127.0.0.1", test_page.host());
|
| + TestSSLState(browser(), test_page, false, SSL_STATUS_BROKEN);
|
| +}
|
| +
|
| +// Same as |SSLStateShouldUpdateOnDirectNavigation|, except the user doesn't
|
| +// navigate directly to the HTTPS page. Instead, another page redirects to the
|
| +// HTTPS page.
|
| +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, SSLStateShouldUpdateOnRedirect) {
|
| + net::SpawnedTestServer https_server(
|
| + net::SpawnedTestServer::TYPE_HTTPS,
|
| + net::SpawnedTestServer::SSLOptions(
|
| + net::SpawnedTestServer::SSLOptions::CERT_OK),
|
| + base::FilePath());
|
| + ASSERT_TRUE(https_server.Start());
|
| + GURL https_url = https_server.GetURL(kAuthBasicPage);
|
| + ASSERT_EQ("127.0.0.1", https_url.host());
|
| +
|
| + // Write an HTML file that redirects to the HTTPS url above.
|
| + base::ScopedTempDir temp_directory;
|
| + ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| + base::FilePath temp_file;
|
| + ASSERT_TRUE(
|
| + base::CreateTemporaryFileInDir(temp_directory.path(), &temp_file));
|
| + std::string html = base::StringPrintf(
|
| + "<html>"
|
| + "<script>window.location = '%s';</script>"
|
| + "</html>",
|
| + https_url.spec().c_str());
|
| + ASSERT_EQ(static_cast<int>(html.size()),
|
| + base::WriteFile(temp_file, html.data(), html.size()));
|
| + TestSSLState(browser(), net::FilePathToFileURL(temp_file), true,
|
| + SSL_STATUS_OK);
|
| +}
|
| +
|
| +// Same as |SSLStateShouldUpdateOnDirectNavigation_BrokenSSL|, except the user
|
| +// doesn't navigate directly to the HTTPS page. Instead, another page redirects
|
| +// to the HTTPS page.
|
| +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
|
| + SSLStateShouldUpdateOnRedirect_BrokenSSL) {
|
| + net::SpawnedTestServer https_server(
|
| + net::SpawnedTestServer::TYPE_HTTPS,
|
| + net::SpawnedTestServer::SSLOptions(
|
| + net::SpawnedTestServer::SSLOptions::CERT_CHAIN_WRONG_ROOT),
|
| + base::FilePath());
|
| + ASSERT_TRUE(https_server.Start());
|
| + GURL https_url = https_server.GetURL(kAuthBasicPage);
|
| + ASSERT_EQ("127.0.0.1", https_url.host());
|
| +
|
| + // Write an HTML file that redirects to the HTTPS url above.
|
| + base::ScopedTempDir temp_directory;
|
| + ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
|
| + base::FilePath temp_file;
|
| + ASSERT_TRUE(
|
| + base::CreateTemporaryFileInDir(temp_directory.path(), &temp_file));
|
| + std::string html = base::StringPrintf(
|
| + "<html>"
|
| + "<script>window.location = '%s';</script>"
|
| + "</html>",
|
| + https_url.spec().c_str());
|
| + ASSERT_EQ(static_cast<int>(html.size()),
|
| + base::WriteFile(temp_file, html.data(), html.size()));
|
| + TestSSLState(browser(), net::FilePathToFileURL(temp_file), true,
|
| + SSL_STATUS_BROKEN);
|
| +}
|
| +
|
| } // namespace
|
|
|