ssl_browser_tests.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/path_service.h" 7#include "base/string_util.h" 8#include "base/stringprintf.h" 9#include "base/time.h" 10#include "base/utf_string_conversions.h" 11#include "chrome/app/chrome_command_ids.h" 12#include "chrome/browser/content_settings/host_content_settings_map.h" 13#include "chrome/browser/prefs/pref_service.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/browser/ui/browser.h" 16#include "chrome/browser/ui/browser_commands.h" 17#include "chrome/browser/ui/browser_navigator.h" 18#include "chrome/browser/ui/browser_tabstrip.h" 19#include "chrome/browser/ui/constrained_window_tab_helper.h" 20#include "chrome/browser/ui/tab_contents/tab_contents.h" 21#include "chrome/browser/ui/tabs/tab_strip_model.h" 22#include "chrome/common/chrome_notification_types.h" 23#include "chrome/common/chrome_paths.h" 24#include "chrome/common/chrome_switches.h" 25#include "chrome/common/pref_names.h" 26#include "chrome/test/base/in_process_browser_test.h" 27#include "chrome/test/base/ui_test_utils.h" 28#include "content/public/browser/browser_context.h" 29#include "content/public/browser/interstitial_page.h" 30#include "content/public/browser/navigation_controller.h" 31#include "content/public/browser/navigation_entry.h" 32#include "content/public/browser/notification_service.h" 33#include "content/public/browser/render_view_host.h" 34#include "content/public/browser/web_contents.h" 35#include "content/public/browser/web_contents_observer.h" 36#include "content/public/common/security_style.h" 37#include "content/public/common/ssl_status.h" 38#include "content/public/test/browser_test_utils.h" 39#include "content/public/test/download_test_observer.h" 40#include "content/public/test/test_renderer_host.h" 41#include "crypto/nss_util.h" 42#include "net/base/cert_status_flags.h" 43#include "net/base/crypto_module.h" 44#include "net/base/net_errors.h" 45#include "net/base/test_data_directory.h" 46#include "net/test/test_server.h" 47 48#if defined(USE_NSS) 49#include "net/base/nss_cert_database.h" 50#endif // defined(USE_NSS) 51 52using content::InterstitialPage; 53using content::NavigationController; 54using content::NavigationEntry; 55using content::SSLStatus; 56using content::WebContents; 57 58const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); 59 60namespace { 61 62class ProvisionalLoadWaiter : public content::WebContentsObserver { 63 public: 64 explicit ProvisionalLoadWaiter(WebContents* tab) 65 : WebContentsObserver(tab), waiting_(false), seen_(false) {} 66 67 void Wait() { 68 if (seen_) 69 return; 70 71 waiting_ = true; 72 content::RunMessageLoop(); 73 } 74 75 void DidFailProvisionalLoad( 76 int64 frame_id, 77 bool is_main_frame, 78 const GURL& validated_url, 79 int error_code, 80 const string16& error_description, 81 content::RenderViewHost* render_view_host) OVERRIDE { 82 seen_ = true; 83 if (waiting_) 84 MessageLoopForUI::current()->Quit(); 85 } 86 87 private: 88 bool waiting_; 89 bool seen_; 90}; 91 92} // namespace 93 94class SSLUITest : public InProcessBrowserTest { 95 public: 96 SSLUITest() 97 : https_server_(net::TestServer::TYPE_HTTPS, 98 SSLOptions(SSLOptions::CERT_OK), 99 FilePath(kDocRoot)), 100 https_server_expired_(net::TestServer::TYPE_HTTPS, 101 SSLOptions(SSLOptions::CERT_EXPIRED), 102 FilePath(kDocRoot)), 103 https_server_mismatched_(net::TestServer::TYPE_HTTPS, 104 SSLOptions(SSLOptions::CERT_MISMATCHED_NAME), 105 FilePath(kDocRoot)), 106 wss_server_expired_(net::TestServer::TYPE_WSS, 107 SSLOptions(SSLOptions::CERT_EXPIRED), 108 net::GetWebSocketTestDataDirectory()) {} 109 110 virtual void SetUpCommandLine(CommandLine* command_line) { 111 // Browser will both run and display insecure content. 112 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); 113 // Use process-per-site so that navigating to a same-site page in a 114 // new tab will use the same process. 115 command_line->AppendSwitch(switches::kProcessPerSite); 116 } 117 118 void CheckAuthenticatedState(WebContents* tab, 119 bool displayed_insecure_content) { 120 ASSERT_FALSE(tab->IsCrashed()); 121 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 122 ASSERT_TRUE(entry); 123 EXPECT_EQ(content::PAGE_TYPE_NORMAL, entry->GetPageType()); 124 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, 125 entry->GetSSL().security_style); 126 EXPECT_EQ(0U, entry->GetSSL().cert_status & net::CERT_STATUS_ALL_ERRORS); 127 EXPECT_EQ(displayed_insecure_content, 128 !!(entry->GetSSL().content_status & 129 SSLStatus::DISPLAYED_INSECURE_CONTENT)); 130 EXPECT_FALSE( 131 !!(entry->GetSSL().content_status & SSLStatus::RAN_INSECURE_CONTENT)); 132 } 133 134 void CheckUnauthenticatedState(WebContents* tab) { 135 ASSERT_FALSE(tab->IsCrashed()); 136 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 137 ASSERT_TRUE(entry); 138 EXPECT_EQ(content::PAGE_TYPE_NORMAL, entry->GetPageType()); 139 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, 140 entry->GetSSL().security_style); 141 EXPECT_EQ(0U, entry->GetSSL().cert_status & net::CERT_STATUS_ALL_ERRORS); 142 EXPECT_FALSE(!!(entry->GetSSL().content_status & 143 SSLStatus::DISPLAYED_INSECURE_CONTENT)); 144 EXPECT_FALSE( 145 !!(entry->GetSSL().content_status & SSLStatus::RAN_INSECURE_CONTENT)); 146 } 147 148 void CheckAuthenticationBrokenState(WebContents* tab, 149 net::CertStatus error, 150 bool ran_insecure_content, 151 bool interstitial) { 152 ASSERT_FALSE(tab->IsCrashed()); 153 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 154 ASSERT_TRUE(entry); 155 EXPECT_EQ(interstitial ? 156 content::PAGE_TYPE_INTERSTITIAL : content::PAGE_TYPE_NORMAL, 157 entry->GetPageType()); 158 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, 159 entry->GetSSL().security_style); 160 // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION doesn't lower the security style 161 // to SECURITY_STYLE_AUTHENTICATION_BROKEN. 162 ASSERT_NE(net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION, error); 163 EXPECT_EQ(error, entry->GetSSL().cert_status & error); 164 EXPECT_FALSE(!!(entry->GetSSL().content_status & 165 SSLStatus::DISPLAYED_INSECURE_CONTENT)); 166 EXPECT_EQ(ran_insecure_content, 167 !!(entry->GetSSL().content_status & SSLStatus::RAN_INSECURE_CONTENT)); 168 net::CertStatus extra_cert_errors = error ^ (entry->GetSSL().cert_status & 169 net::CERT_STATUS_ALL_ERRORS); 170 if (extra_cert_errors) 171 LOG(WARNING) << "Got unexpected cert error: " << extra_cert_errors; 172 } 173 174 void CheckWorkerLoadResult(WebContents* tab, bool expectLoaded) { 175 // Workers are async and we don't have notifications for them passing 176 // messages since they do it between renderer and worker processes. 177 // So have a polling loop, check every 200ms, timeout at 30s. 178 const int timeout_ms = 200; 179 base::Time timeToQuit = base::Time::Now() + 180 base::TimeDelta::FromMilliseconds(30000); 181 182 while (base::Time::Now() < timeToQuit) { 183 bool workerFinished = false; 184 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractBool( 185 tab->GetRenderViewHost(), std::wstring(), 186 L"window.domAutomationController.send(IsWorkerFinished());", 187 &workerFinished)); 188 189 if (workerFinished) 190 break; 191 192 // Wait a bit. 193 MessageLoop::current()->PostDelayedTask( 194 FROM_HERE, 195 MessageLoop::QuitClosure(), 196 base::TimeDelta::FromMilliseconds(timeout_ms)); 197 content::RunMessageLoop(); 198 } 199 200 bool actuallyLoadedContent = false; 201 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractBool( 202 tab->GetRenderViewHost(), std::wstring(), 203 L"window.domAutomationController.send(IsContentLoaded());", 204 &actuallyLoadedContent)); 205 EXPECT_EQ(expectLoaded, actuallyLoadedContent); 206 } 207 208 void ProceedThroughInterstitial(WebContents* tab) { 209 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); 210 ASSERT_TRUE(interstitial_page); 211 content::WindowedNotificationObserver observer( 212 content::NOTIFICATION_LOAD_STOP, 213 content::Source<NavigationController>(&tab->GetController())); 214 interstitial_page->Proceed(); 215 observer.Wait(); 216 } 217 218 size_t GetConstrainedWindowCount() const { 219 return ConstrainedWindowTabHelper::FromWebContents( 220 chrome::GetActiveWebContents(browser()))->constrained_window_count(); 221 } 222 223 static bool GetFilePathWithHostAndPortReplacement( 224 const std::string& original_file_path, 225 const net::HostPortPair& host_port_pair, 226 std::string* replacement_path) { 227 std::vector<net::TestServer::StringPair> replacement_text; 228 replacement_text.push_back( 229 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); 230 return net::TestServer::GetFilePathWithReplacements( 231 original_file_path, replacement_text, replacement_path); 232 } 233 234 static bool GetTopFramePath(const net::TestServer& http_server, 235 const net::TestServer& good_https_server, 236 const net::TestServer& bad_https_server, 237 std::string* top_frame_path) { 238 // The "frame_left.html" page contained in the top_frame.html page contains 239 // <a href>'s to three different servers. This sets up all of the 240 // replacement text to work with test servers which listen on ephemeral 241 // ports. 242 GURL http_url = http_server.GetURL("files/ssl/google.html"); 243 GURL good_https_url = good_https_server.GetURL("files/ssl/google.html"); 244 GURL bad_https_url = bad_https_server.GetURL( 245 "files/ssl/bad_iframe.html"); 246 247 std::vector<net::TestServer::StringPair> replacement_text_frame_left; 248 replacement_text_frame_left.push_back( 249 make_pair("REPLACE_WITH_HTTP_PAGE", http_url.spec())); 250 replacement_text_frame_left.push_back( 251 make_pair("REPLACE_WITH_GOOD_HTTPS_PAGE", good_https_url.spec())); 252 replacement_text_frame_left.push_back( 253 make_pair("REPLACE_WITH_BAD_HTTPS_PAGE", bad_https_url.spec())); 254 std::string frame_left_path; 255 if (!net::TestServer::GetFilePathWithReplacements( 256 "frame_left.html", 257 replacement_text_frame_left, 258 &frame_left_path)) 259 return false; 260 261 // Substitute the generated frame_left URL into the top_frame page. 262 std::vector<net::TestServer::StringPair> replacement_text_top_frame; 263 replacement_text_top_frame.push_back( 264 make_pair("REPLACE_WITH_FRAME_LEFT_PATH", frame_left_path)); 265 return net::TestServer::GetFilePathWithReplacements( 266 "files/ssl/top_frame.html", 267 replacement_text_top_frame, 268 top_frame_path); 269 } 270 271 static bool GetPageWithUnsafeWorkerPath( 272 const net::TestServer& expired_https_server, 273 std::string* page_with_unsafe_worker_path) { 274 // Get the "imported.js" URL from the expired https server and 275 // substitute it into the unsafe_worker.js file. 276 GURL imported_js_url = expired_https_server.GetURL("files/ssl/imported.js"); 277 std::vector<net::TestServer::StringPair> replacement_text_for_unsafe_worker; 278 replacement_text_for_unsafe_worker.push_back( 279 make_pair("REPLACE_WITH_IMPORTED_JS_URL", imported_js_url.spec())); 280 std::string unsafe_worker_path; 281 if (!net::TestServer::GetFilePathWithReplacements( 282 "unsafe_worker.js", 283 replacement_text_for_unsafe_worker, 284 &unsafe_worker_path)) 285 return false; 286 287 // Now, substitute this into the page with unsafe worker. 288 std::vector<net::TestServer::StringPair> 289 replacement_text_for_page_with_unsafe_worker; 290 replacement_text_for_page_with_unsafe_worker.push_back( 291 make_pair("REPLACE_WITH_UNSAFE_WORKER_PATH", unsafe_worker_path)); 292 return net::TestServer::GetFilePathWithReplacements( 293 "files/ssl/page_with_unsafe_worker.html", 294 replacement_text_for_page_with_unsafe_worker, 295 page_with_unsafe_worker_path); 296 } 297 298 net::TestServer https_server_; 299 net::TestServer https_server_expired_; 300 net::TestServer https_server_mismatched_; 301 net::TestServer wss_server_expired_; 302 303 private: 304 typedef net::TestServer::SSLOptions SSLOptions; 305 306 DISALLOW_COPY_AND_ASSIGN(SSLUITest); 307}; 308 309class SSLUITestBlock : public SSLUITest { 310 public: 311 SSLUITestBlock() : SSLUITest() {} 312 313 // Browser will neither run nor display insecure content. 314 virtual void SetUpCommandLine(CommandLine* command_line) { 315 command_line->AppendSwitch(switches::kNoDisplayingInsecureContent); 316 } 317}; 318 319class SSLUITestIgnoreCertErrors : public SSLUITest { 320 public: 321 SSLUITestIgnoreCertErrors() : SSLUITest() {} 322 323 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 324 // Browser will ignore certificate errors. 325 command_line->AppendSwitch(switches::kIgnoreCertificateErrors); 326 } 327}; 328 329// Visits a regular page over http. 330IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTP) { 331 ASSERT_TRUE(test_server()->Start()); 332 333 ui_test_utils::NavigateToURL(browser(), 334 test_server()->GetURL("files/ssl/google.html")); 335 336 CheckUnauthenticatedState(chrome::GetActiveWebContents(browser())); 337} 338 339// Visits a page over http which includes broken https resources (status should 340// be OK). 341// TODO(jcampan): test that bad HTTPS content is blocked (otherwise we'll give 342// the secure cookies away!). 343IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPWithBrokenHTTPSResource) { 344 ASSERT_TRUE(test_server()->Start()); 345 ASSERT_TRUE(https_server_expired_.Start()); 346 347 std::string replacement_path; 348 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 349 "files/ssl/page_with_unsafe_contents.html", 350 https_server_expired_.host_port_pair(), 351 &replacement_path)); 352 353 ui_test_utils::NavigateToURL( 354 browser(), test_server()->GetURL(replacement_path)); 355 356 CheckUnauthenticatedState(chrome::GetActiveWebContents(browser())); 357} 358 359// http://crbug.com/91745 360#if defined(OS_CHROMEOS) 361#define MAYBE_TestOKHTTPS DISABLED_TestOKHTTPS 362#else 363#define MAYBE_TestOKHTTPS TestOKHTTPS 364#endif 365 366// Visits a page over OK https: 367IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestOKHTTPS) { 368 ASSERT_TRUE(https_server_.Start()); 369 370 ui_test_utils::NavigateToURL(browser(), 371 https_server_.GetURL("files/ssl/google.html")); 372 373 CheckAuthenticatedState(chrome::GetActiveWebContents(browser()), false); 374} 375 376// Visits a page with https error and proceed: 377IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSExpiredCertAndProceed) { 378 ASSERT_TRUE(https_server_expired_.Start()); 379 380 ui_test_utils::NavigateToURL(browser(), 381 https_server_expired_.GetURL("files/ssl/google.html")); 382 383 WebContents* tab = chrome::GetActiveWebContents(browser()); 384 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 385 true); // Interstitial showing 386 387 ProceedThroughInterstitial(tab); 388 389 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 390 false); // No interstitial showing 391} 392 393// Visits a page with https error and don't proceed (and ensure we can still 394// navigate at that point): 395IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSExpiredCertAndDontProceed) { 396 ASSERT_TRUE(test_server()->Start()); 397 ASSERT_TRUE(https_server_.Start()); 398 ASSERT_TRUE(https_server_expired_.Start()); 399 400 // First navigate to an OK page. 401 ui_test_utils::NavigateToURL(browser(), 402 https_server_.GetURL("files/ssl/google.html")); 403 404 WebContents* tab = chrome::GetActiveWebContents(browser()); 405 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 406 ASSERT_TRUE(entry); 407 408 GURL cross_site_url = 409 https_server_expired_.GetURL("files/ssl/google.html"); 410 // Change the host name from 127.0.0.1 to localhost so it triggers a 411 // cross-site navigation so we can test http://crbug.com/5800 is gone. 412 ASSERT_EQ("127.0.0.1", cross_site_url.host()); 413 GURL::Replacements replacements; 414 std::string new_host("localhost"); 415 replacements.SetHostStr(new_host); 416 cross_site_url = cross_site_url.ReplaceComponents(replacements); 417 418 // Now go to a bad HTTPS page. 419 ui_test_utils::NavigateToURL(browser(), cross_site_url); 420 421 // An interstitial should be showing. 422 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, 423 false, true); 424 425 // Simulate user clicking "Take me back". 426 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); 427 ASSERT_TRUE(interstitial_page); 428 interstitial_page->DontProceed(); 429 430 // We should be back to the original good page. 431 CheckAuthenticatedState(tab, false); 432 433 // Try to navigate to a new page. (to make sure bug 5800 is fixed). 434 ui_test_utils::NavigateToURL(browser(), 435 test_server()->GetURL("files/ssl/google.html")); 436 CheckUnauthenticatedState(tab); 437} 438 439// Visits a page with https error and then goes back using Browser::GoBack. 440IN_PROC_BROWSER_TEST_F(SSLUITest, 441 TestHTTPSExpiredCertAndGoBackViaButton) { 442 ASSERT_TRUE(test_server()->Start()); 443 ASSERT_TRUE(https_server_expired_.Start()); 444 445 // First navigate to an HTTP page. 446 ui_test_utils::NavigateToURL(browser(), 447 test_server()->GetURL("files/ssl/google.html")); 448 WebContents* tab = chrome::GetActiveWebContents(browser()); 449 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 450 ASSERT_TRUE(entry); 451 452 // Now go to a bad HTTPS page that shows an interstitial. 453 ui_test_utils::NavigateToURL(browser(), 454 https_server_expired_.GetURL("files/ssl/google.html")); 455 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 456 true); // Interstitial showing 457 458 ProvisionalLoadWaiter load_failed_observer(tab); 459 460 // Simulate user clicking on back button (crbug.com/39248). 461 chrome::GoBack(browser(), CURRENT_TAB); 462 463 // Wait until we hear the load failure, and make sure we haven't swapped out 464 // the previous page. Prevents regression of http://crbug.com/82667. 465 load_failed_observer.Wait(); 466 EXPECT_FALSE(content::RenderViewHostTester::IsRenderViewHostSwappedOut( 467 tab->GetRenderViewHost())); 468 469 // We should be back at the original good page. 470 EXPECT_FALSE(chrome::GetActiveWebContents(browser())->GetInterstitialPage()); 471 CheckUnauthenticatedState(tab); 472} 473 474// Visits a page with https error and then goes back using GoToOffset. 475// Disabled because its flaky: http://crbug.com/40932, http://crbug.com/43575. 476IN_PROC_BROWSER_TEST_F(SSLUITest, 477 TestHTTPSExpiredCertAndGoBackViaMenu) { 478 ASSERT_TRUE(test_server()->Start()); 479 ASSERT_TRUE(https_server_expired_.Start()); 480 481 // First navigate to an HTTP page. 482 ui_test_utils::NavigateToURL(browser(), 483 test_server()->GetURL("files/ssl/google.html")); 484 WebContents* tab = chrome::GetActiveWebContents(browser()); 485 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 486 ASSERT_TRUE(entry); 487 488 // Now go to a bad HTTPS page that shows an interstitial. 489 ui_test_utils::NavigateToURL(browser(), 490 https_server_expired_.GetURL("files/ssl/google.html")); 491 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 492 true); // Interstitial showing 493 494 // Simulate user clicking and holding on back button (crbug.com/37215). 495 tab->GetController().GoToOffset(-1); 496 497 // We should be back at the original good page. 498 EXPECT_FALSE(chrome::GetActiveWebContents(browser())->GetInterstitialPage()); 499 CheckUnauthenticatedState(tab); 500} 501 502// Visits a page with https error and then goes forward using GoToOffset. 503IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSExpiredCertAndGoForward) { 504 ASSERT_TRUE(test_server()->Start()); 505 ASSERT_TRUE(https_server_expired_.Start()); 506 507 // First navigate to two HTTP pages. 508 ui_test_utils::NavigateToURL(browser(), 509 test_server()->GetURL("files/ssl/google.html")); 510 WebContents* tab = chrome::GetActiveWebContents(browser()); 511 NavigationEntry* entry1 = tab->GetController().GetActiveEntry(); 512 ASSERT_TRUE(entry1); 513 ui_test_utils::NavigateToURL(browser(), 514 test_server()->GetURL("files/ssl/blank_page.html")); 515 NavigationEntry* entry2 = tab->GetController().GetActiveEntry(); 516 ASSERT_TRUE(entry2); 517 518 // Now go back so that a page is in the forward history. 519 { 520 content::WindowedNotificationObserver observer( 521 content::NOTIFICATION_LOAD_STOP, 522 content::Source<NavigationController>(&tab->GetController())); 523 tab->GetController().GoBack(); 524 observer.Wait(); 525 } 526 ASSERT_TRUE(tab->GetController().CanGoForward()); 527 NavigationEntry* entry3 = tab->GetController().GetActiveEntry(); 528 ASSERT_TRUE(entry1 == entry3); 529 530 // Now go to a bad HTTPS page that shows an interstitial. 531 ui_test_utils::NavigateToURL(browser(), 532 https_server_expired_.GetURL("files/ssl/google.html")); 533 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 534 true); // Interstitial showing 535 536 // Simulate user clicking and holding on forward button. 537 { 538 content::WindowedNotificationObserver observer( 539 content::NOTIFICATION_LOAD_STOP, 540 content::Source<NavigationController>(&tab->GetController())); 541 tab->GetController().GoToOffset(1); 542 observer.Wait(); 543 } 544 545 // We should be showing the second good page. 546 EXPECT_FALSE(chrome::GetActiveWebContents(browser())->GetInterstitialPage()); 547 CheckUnauthenticatedState(tab); 548 EXPECT_FALSE(tab->GetController().CanGoForward()); 549 NavigationEntry* entry4 = tab->GetController().GetActiveEntry(); 550 EXPECT_TRUE(entry2 == entry4); 551} 552 553// Visit a HTTP page which request WSS connection to a server providing invalid 554// certificate. Close the page while WSS connection waits for SSLManager's 555// response from UI thread. 556IN_PROC_BROWSER_TEST_F(SSLUITest, TestWSSInvalidCertAndClose) { 557 ASSERT_TRUE(test_server()->Start()); 558 ASSERT_TRUE(wss_server_expired_.Start()); 559 560 // Setup page title observer. 561 WebContents* tab = chrome::GetActiveWebContents(browser()); 562 content::TitleWatcher watcher(tab, ASCIIToUTF16("PASS")); 563 watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 564 565 // Create GURLs to test pages. 566 std::string masterUrlPath = StringPrintf("%s?%d", 567 test_server()->GetURL("files/ssl/wss_close.html").spec().c_str(), 568 wss_server_expired_.host_port_pair().port()); 569 GURL masterUrl(masterUrlPath); 570 std::string slaveUrlPath = StringPrintf("%s?%d", 571 test_server()->GetURL("files/ssl/wss_close_slave.html").spec().c_str(), 572 wss_server_expired_.host_port_pair().port()); 573 GURL slaveUrl(slaveUrlPath); 574 575 // Create tabs and visit pages which keep on creating wss connections. 576 TabContents* tabs[16]; 577 for (int i = 0; i < 16; ++i) { 578 tabs[i] = chrome::AddSelectedTabWithURL(browser(), slaveUrl, 579 content::PAGE_TRANSITION_LINK); 580 } 581 chrome::SelectNextTab(browser()); 582 583 // Visit a page which waits for one TLS handshake failure. 584 // The title will be changed to 'PASS'. 585 ui_test_utils::NavigateToURL(browser(), masterUrl); 586 const string16 result = watcher.WaitAndGetTitle(); 587 EXPECT_TRUE(LowerCaseEqualsASCII(result, "pass")); 588 589 // Close tabs which contains the test page. 590 for (int i = 0; i < 16; ++i) 591 chrome::CloseWebContents(browser(), tabs[i]->web_contents()); 592 chrome::CloseWebContents(browser(), tab); 593} 594 595// Visit a HTTPS page and proceeds despite an invalid certificate. The page 596// requests WSS connection to the same origin host to check if WSS connection 597// share certificates policy with HTTPS correcly. 598IN_PROC_BROWSER_TEST_F(SSLUITest, TestWSSInvalidCertAndGoForward) { 599 ASSERT_TRUE(test_server()->Start()); 600 ASSERT_TRUE(wss_server_expired_.Start()); 601 602 // Setup page title observer. 603 WebContents* tab = chrome::GetActiveWebContents(browser()); 604 content::TitleWatcher watcher(tab, ASCIIToUTF16("PASS")); 605 watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 606 607 // Visit bad HTTPS page. 608 std::string scheme("https"); 609 GURL::Replacements replacements; 610 replacements.SetSchemeStr(scheme); 611 ui_test_utils::NavigateToURL( 612 browser(), 613 wss_server_expired_.GetURL( 614 "connect_check.html").ReplaceComponents(replacements)); 615 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 616 true); // Interstitial showing 617 618 // Proceed anyway. 619 ProceedThroughInterstitial(tab); 620 621 // Test page run a WebSocket wss connection test. The result will be shown 622 // as page title. 623 const string16 result = watcher.WaitAndGetTitle(); 624 EXPECT_TRUE(LowerCaseEqualsASCII(result, "pass")); 625} 626 627#if defined(USE_NSS) 628// SSL client certificate tests are only enabled when using NSS for private key 629// storage, as only NSS can avoid modifying global machine state when testing. 630// See http://crbug.com/51132 631 632// Visit a HTTPS page which requires client cert authentication. The client 633// cert will be selected automatically, then a test which uses WebSocket runs. 634// Disabled: http://crbug.com/159985 635IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestWSSClientCert) { 636 // Open a temporary NSS DB for testing. 637 crypto::ScopedTestNSSDB test_nssdb; 638 ASSERT_TRUE(test_nssdb.is_open()); 639 640 // Import client cert for test. These interfaces require NSS. 641 net::NSSCertDatabase* cert_db = net::NSSCertDatabase::GetInstance(); 642 scoped_refptr<net::CryptoModule> crypt_module = cert_db->GetPublicModule(); 643 std::string pkcs12_data; 644 FilePath cert_path = net::GetTestCertsDirectory().Append( 645 FILE_PATH_LITERAL("websocket_client_cert.p12")); 646 EXPECT_TRUE(file_util::ReadFileToString(cert_path, &pkcs12_data)); 647 EXPECT_EQ(net::OK, cert_db->ImportFromPKCS12(crypt_module, 648 pkcs12_data, 649 string16(), 650 true, 651 NULL)); 652 653 // Start WebSocket test server with TLS and client cert authentication. 654 net::TestServer::SSLOptions options(net::TestServer::SSLOptions::CERT_OK); 655 options.request_client_certificate = true; 656 FilePath ca_path = net::GetTestCertsDirectory().Append( 657 FILE_PATH_LITERAL("websocket_cacert.pem")); 658 options.client_authorities.push_back(ca_path); 659 net::TestServer wss_server(net::TestServer::TYPE_WSS, 660 options, 661 net::GetWebSocketTestDataDirectory()); 662 ASSERT_TRUE(wss_server.Start()); 663 std::string scheme("https"); 664 GURL::Replacements replacements; 665 replacements.SetSchemeStr(scheme); 666 GURL url = wss_server.GetURL("connect_check.html").ReplaceComponents( 667 replacements); 668 669 // Setup page title observer. 670 WebContents* tab = chrome::GetActiveWebContents(browser()); 671 content::TitleWatcher watcher(tab, ASCIIToUTF16("PASS")); 672 watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 673 674 // Add an entry into AutoSelectCertificateForUrls policy for automatic client 675 // cert selection. 676 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); 677 DCHECK(profile); 678 scoped_ptr<DictionaryValue> dict(new DictionaryValue()); 679 dict->SetString("ISSUER.CN", "pywebsocket"); 680 profile->GetHostContentSettingsMap()->SetWebsiteSetting( 681 ContentSettingsPattern::FromURL(url), 682 ContentSettingsPattern::FromURL(url), 683 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 684 std::string(), 685 dict.release()); 686 687 // Visit a HTTPS page which requires client certs. 688 ui_test_utils::NavigateToURL(browser(), url); 689 CheckAuthenticatedState(tab, false); 690 691 // Test page runs a WebSocket wss connection test. The result will be shown 692 // as page title. 693 const string16 result = watcher.WaitAndGetTitle(); 694 EXPECT_TRUE(LowerCaseEqualsASCII(result, "pass")); 695} 696#endif // defined(USE_NSS) 697 698// Flaky on CrOS http://crbug.com/92292 699#if defined(OS_CHROMEOS) 700#define MAYBE_TestHTTPSErrorWithNoNavEntry \ 701 DISABLED_TestHTTPSErrorWithNoNavEntry 702#else 703#define MAYBE_TestHTTPSErrorWithNoNavEntry TestHTTPSErrorWithNoNavEntry 704#endif // defined(OS_CHROMEOS) 705 706// Open a page with a HTTPS error in a tab with no prior navigation (through a 707// link with a blank target). This is to test that the lack of navigation entry 708// does not cause any problems (it was causing a crasher, see 709// http://crbug.com/19941). 710IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestHTTPSErrorWithNoNavEntry) { 711 ASSERT_TRUE(https_server_expired_.Start()); 712 713 GURL url = https_server_expired_.GetURL("files/ssl/google.htm"); 714 TabContents* tab2 = chrome::AddSelectedTabWithURL( 715 browser(), url, content::PAGE_TRANSITION_TYPED); 716 content::WaitForLoadStop(tab2->web_contents()); 717 718 // Verify our assumption that there was no prior navigation. 719 EXPECT_FALSE(chrome::CanGoBack(browser())); 720 721 // We should have an interstitial page showing. 722 ASSERT_TRUE(tab2->web_contents()->GetInterstitialPage()); 723} 724 725IN_PROC_BROWSER_TEST_F(SSLUITest, TestBadHTTPSDownload) { 726 ASSERT_TRUE(test_server()->Start()); 727 ASSERT_TRUE(https_server_expired_.Start()); 728 GURL url_non_dangerous = test_server()->GetURL(""); 729 GURL url_dangerous = https_server_expired_.GetURL( 730 "files/downloads/dangerous/dangerous.exe"); 731 ScopedTempDir downloads_directory_; 732 733 // Need empty temp dir to avoid having Chrome ask us for a new filename 734 // when we've downloaded dangerous.exe one hundred times. 735 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir()); 736 737 browser()->profile()->GetPrefs()->SetFilePath( 738 prefs::kDownloadDefaultDirectory, 739 downloads_directory_.path()); 740 741 // Visit a non-dangerous page. 742 ui_test_utils::NavigateToURL(browser(), url_non_dangerous); 743 744 // Now, start a transition to dangerous download. 745 { 746 content::WindowedNotificationObserver observer( 747 content::NOTIFICATION_LOAD_STOP, 748 content::NotificationService::AllSources()); 749 chrome::NavigateParams navigate_params(browser(), url_dangerous, 750 content::PAGE_TRANSITION_TYPED); 751 chrome::Navigate(&navigate_params); 752 observer.Wait(); 753 } 754 755 // To exit the browser cleanly (and this test) we need to complete the 756 // download after completing this test. 757 content::DownloadTestObserverTerminal dangerous_download_observer( 758 content::BrowserContext::GetDownloadManager(browser()->profile()), 759 1, 760 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT); 761 762 // Proceed through the SSL interstitial. This doesn't use 763 // |ProceedThroughInterstitial| since no page load will commit. 764 WebContents* tab = chrome::GetActiveWebContents(browser()); 765 ASSERT_TRUE(tab != NULL); 766 ASSERT_TRUE(tab->GetInterstitialPage() != NULL); 767 { 768 content::WindowedNotificationObserver observer( 769 chrome::NOTIFICATION_DOWNLOAD_INITIATED, 770 content::NotificationService::AllSources()); 771 tab->GetInterstitialPage()->Proceed(); 772 observer.Wait(); 773 } 774 775 // There should still be an interstitial at this point. Press the 776 // back button on the browser. Note that this doesn't wait for a 777 // NAV_ENTRY_COMMITTED notification because going back with an 778 // active interstitial simply hides the interstitial. 779 ASSERT_TRUE(tab->GetInterstitialPage() != NULL); 780 EXPECT_TRUE(chrome::CanGoBack(browser())); 781 chrome::GoBack(browser(), CURRENT_TAB); 782 783 dangerous_download_observer.WaitForFinished(); 784} 785 786// 787// Insecure content 788// 789 790#if defined(OS_WIN) 791// http://crbug.com/152940 Flaky on win. 792#define MAYBE_TestDisplaysInsecureContent DISABLED_TestDisplaysInsecureContent 793#else 794#define MAYBE_TestDisplaysInsecureContent TestDisplaysInsecureContent 795#endif 796 797// Visits a page that displays insecure content. 798IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestDisplaysInsecureContent) { 799 ASSERT_TRUE(test_server()->Start()); 800 ASSERT_TRUE(https_server_.Start()); 801 802 std::string replacement_path; 803 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 804 "files/ssl/page_displays_insecure_content.html", 805 test_server()->host_port_pair(), 806 &replacement_path)); 807 808 // Load a page that displays insecure content. 809 ui_test_utils::NavigateToURL(browser(), 810 https_server_.GetURL(replacement_path)); 811 812 CheckAuthenticatedState(chrome::GetActiveWebContents(browser()), true); 813} 814 815// Visits a page that runs insecure content and tries to suppress the insecure 816// content warnings by randomizing location.hash. 817// Based on http://crbug.com/8706 818IN_PROC_BROWSER_TEST_F(SSLUITest, 819 TestRunsInsecuredContentRandomizeHash) { 820 ASSERT_TRUE(test_server()->Start()); 821 ASSERT_TRUE(https_server_.Start()); 822 823 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL( 824 "files/ssl/page_runs_insecure_content.html")); 825 826 CheckAuthenticationBrokenState(chrome::GetActiveWebContents(browser()), 0, 827 true, false); 828} 829 830// Visits a page with unsafe content and make sure that: 831// - frames content is replaced with warning 832// - images and scripts are filtered out entirely 833IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnsafeContents) { 834 ASSERT_TRUE(https_server_.Start()); 835 ASSERT_TRUE(https_server_expired_.Start()); 836 837 std::string replacement_path; 838 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 839 "files/ssl/page_with_unsafe_contents.html", 840 https_server_expired_.host_port_pair(), 841 &replacement_path)); 842 ui_test_utils::NavigateToURL(browser(), 843 https_server_.GetURL(replacement_path)); 844 845 WebContents* tab = chrome::GetActiveWebContents(browser()); 846 // When the bad content is filtered, the state is expected to be 847 // authenticated. 848 CheckAuthenticatedState(tab, false); 849 850 // Because of cross-frame scripting restrictions, we cannot access the iframe 851 // content. So to know if the frame was loaded, we just check if a popup was 852 // opened (the iframe content opens one). 853 // Note: because of bug 1115868, no constrained window is opened right now. 854 // Once the bug is fixed, this will do the real check. 855 EXPECT_EQ(0U, GetConstrainedWindowCount()); 856 857 int img_width; 858 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractInt( 859 tab->GetRenderViewHost(), std::wstring(), 860 L"window.domAutomationController.send(ImageWidth());", &img_width)); 861 // In order to check that the image was not loaded, we check its width. 862 // The actual image (Google logo) is 114 pixels wide, we assume the broken 863 // image is less than 100. 864 EXPECT_LT(img_width, 100); 865 866 bool js_result = false; 867 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 868 tab->GetRenderViewHost(), std::wstring(), 869 L"window.domAutomationController.send(IsFooSet());", &js_result)); 870 EXPECT_FALSE(js_result); 871} 872 873// Visits a page with insecure content loaded by JS (after the initial page 874// load). 875IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysInsecureContentLoadedFromJS) { 876 ASSERT_TRUE(test_server()->Start()); 877 ASSERT_TRUE(https_server_.Start()); 878 879 std::string replacement_path; 880 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 881 "files/ssl/page_with_dynamic_insecure_content.html", 882 test_server()->host_port_pair(), 883 &replacement_path)); 884 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL( 885 replacement_path)); 886 887 WebContents* tab = chrome::GetActiveWebContents(browser()); 888 CheckAuthenticatedState(tab, false); 889 890 // Load the insecure image. 891 bool js_result = false; 892 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 893 tab->GetRenderViewHost(), std::wstring(), L"loadBadImage();", 894 &js_result)); 895 EXPECT_TRUE(js_result); 896 897 // We should now have insecure content. 898 CheckAuthenticatedState(tab, true); 899} 900 901// Visits two pages from the same origin: one that displays insecure content and 902// one that doesn't. The test checks that we do not propagate the insecure 903// content state from one to the other. 904IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysInsecureContentTwoTabs) { 905 ASSERT_TRUE(test_server()->Start()); 906 ASSERT_TRUE(https_server_.Start()); 907 908 ui_test_utils::NavigateToURL(browser(), 909 https_server_.GetURL("files/ssl/blank_page.html")); 910 911 TabContents* tab1 = chrome::GetActiveTabContents(browser()); 912 913 // This tab should be fine. 914 CheckAuthenticatedState(tab1->web_contents(), false); 915 916 // Create a new tab. 917 std::string replacement_path; 918 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 919 "files/ssl/page_displays_insecure_content.html", 920 test_server()->host_port_pair(), 921 &replacement_path)); 922 923 GURL url = https_server_.GetURL(replacement_path); 924 chrome::NavigateParams params(browser(), url, content::PAGE_TRANSITION_TYPED); 925 params.disposition = NEW_FOREGROUND_TAB; 926 params.tabstrip_index = 0; 927 params.source_contents = tab1; 928 content::WindowedNotificationObserver observer( 929 content::NOTIFICATION_LOAD_STOP, 930 content::NotificationService::AllSources()); 931 chrome::Navigate(¶ms); 932 TabContents* tab2 = params.target_contents; 933 observer.Wait(); 934 935 // The new tab has insecure content. 936 CheckAuthenticatedState(tab2->web_contents(), true); 937 938 // The original tab should not be contaminated. 939 CheckAuthenticatedState(tab1->web_contents(), false); 940} 941 942// Visits two pages from the same origin: one that runs insecure content and one 943// that doesn't. The test checks that we propagate the insecure content state 944// from one to the other. 945IN_PROC_BROWSER_TEST_F(SSLUITest, TestRunsInsecureContentTwoTabs) { 946 ASSERT_TRUE(test_server()->Start()); 947 ASSERT_TRUE(https_server_.Start()); 948 949 ui_test_utils::NavigateToURL(browser(), 950 https_server_.GetURL("files/ssl/blank_page.html")); 951 952 TabContents* tab1 = chrome::GetActiveTabContents(browser()); 953 954 // This tab should be fine. 955 CheckAuthenticatedState(tab1->web_contents(), false); 956 957 std::string replacement_path; 958 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 959 "files/ssl/page_runs_insecure_content.html", 960 test_server()->host_port_pair(), 961 &replacement_path)); 962 963 // Create a new tab in the same process. Using a NEW_FOREGROUND_TAB 964 // disposition won't usually stay in the same process, but this works 965 // because we are using process-per-site in SetUpCommandLine. 966 GURL url = https_server_.GetURL(replacement_path); 967 chrome::NavigateParams params(browser(), url, content::PAGE_TRANSITION_TYPED); 968 params.disposition = NEW_FOREGROUND_TAB; 969 params.source_contents = tab1; 970 content::WindowedNotificationObserver observer( 971 content::NOTIFICATION_LOAD_STOP, 972 content::NotificationService::AllSources()); 973 chrome::Navigate(¶ms); 974 TabContents* tab2 = params.target_contents; 975 observer.Wait(); 976 977 // Both tabs should have the same process. 978 EXPECT_EQ(tab1->web_contents()->GetRenderProcessHost(), 979 tab2->web_contents()->GetRenderProcessHost()); 980 981 // The new tab has insecure content. 982 CheckAuthenticationBrokenState(tab2->web_contents(), 0, true, false); 983 984 // Which means the origin for the first tab has also been contaminated with 985 // insecure content. 986 CheckAuthenticationBrokenState(tab1->web_contents(), 0, true, false); 987} 988 989// Visits a page with an image over http. Visits another page over https 990// referencing that same image over http (hoping it is coming from the webcore 991// memory cache). 992IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysCachedInsecureContent) { 993 ASSERT_TRUE(test_server()->Start()); 994 ASSERT_TRUE(https_server_.Start()); 995 996 std::string replacement_path; 997 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 998 "files/ssl/page_displays_insecure_content.html", 999 test_server()->host_port_pair(), 1000 &replacement_path)); 1001 1002 // Load original page over HTTP. 1003 const GURL url_http = test_server()->GetURL(replacement_path); 1004 ui_test_utils::NavigateToURL(browser(), url_http); 1005 WebContents* tab = chrome::GetActiveWebContents(browser()); 1006 CheckUnauthenticatedState(tab); 1007 1008 // Load again but over SSL. It should be marked as displaying insecure 1009 // content (even though the image comes from the WebCore memory cache). 1010 const GURL url_https = https_server_.GetURL(replacement_path); 1011 ui_test_utils::NavigateToURL(browser(), url_https); 1012 CheckAuthenticatedState(tab, true); 1013} 1014 1015// http://crbug.com/84729 1016#if defined(OS_CHROMEOS) 1017#define MAYBE_TestRunsCachedInsecureContent \ 1018 DISABLED_TestRunsCachedInsecureContent 1019#else 1020#define MAYBE_TestRunsCachedInsecureContent TestRunsCachedInsecureContent 1021#endif // defined(OS_CHROMEOS) 1022 1023// Visits a page with script over http. Visits another page over https 1024// referencing that same script over http (hoping it is coming from the webcore 1025// memory cache). 1026IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestRunsCachedInsecureContent) { 1027 ASSERT_TRUE(test_server()->Start()); 1028 ASSERT_TRUE(https_server_.Start()); 1029 1030 std::string replacement_path; 1031 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 1032 "files/ssl/page_runs_insecure_content.html", 1033 test_server()->host_port_pair(), 1034 &replacement_path)); 1035 1036 // Load original page over HTTP. 1037 const GURL url_http = test_server()->GetURL(replacement_path); 1038 ui_test_utils::NavigateToURL(browser(), url_http); 1039 WebContents* tab = chrome::GetActiveWebContents(browser()); 1040 CheckUnauthenticatedState(tab); 1041 1042 // Load again but over SSL. It should be marked as displaying insecure 1043 // content (even though the image comes from the WebCore memory cache). 1044 const GURL url_https = https_server_.GetURL(replacement_path); 1045 ui_test_utils::NavigateToURL(browser(), url_https); 1046 CheckAuthenticationBrokenState(tab, 0, true, false); 1047} 1048 1049// This test ensures the CN invalid status does not 'stick' to a certificate 1050// (see bug #1044942) and that it depends on the host-name. 1051IN_PROC_BROWSER_TEST_F(SSLUITest, TestCNInvalidStickiness) { 1052 ASSERT_TRUE(https_server_.Start()); 1053 ASSERT_TRUE(https_server_mismatched_.Start()); 1054 1055 // First we hit the server with hostname, this generates an invalid policy 1056 // error. 1057 ui_test_utils::NavigateToURL(browser(), 1058 https_server_mismatched_.GetURL("files/ssl/google.html")); 1059 1060 // We get an interstitial page as a result. 1061 WebContents* tab = chrome::GetActiveWebContents(browser()); 1062 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, 1063 false, true); // Interstitial showing. 1064 ProceedThroughInterstitial(tab); 1065 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, 1066 false, false); // No interstitial showing. 1067 1068 // Now we try again with the right host name this time. 1069 GURL url(https_server_.GetURL("files/ssl/google.html")); 1070 ui_test_utils::NavigateToURL(browser(), url); 1071 1072 // Security state should be OK. 1073 CheckAuthenticatedState(tab, false); 1074 1075 // Now try again the broken one to make sure it is still broken. 1076 ui_test_utils::NavigateToURL(browser(), 1077 https_server_mismatched_.GetURL("files/ssl/google.html")); 1078 1079 // Since we OKed the interstitial last time, we get right to the page. 1080 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, 1081 false, false); // No interstitial showing. 1082} 1083 1084#if defined(OS_CHROMEOS) 1085// This test seems to be flaky and hang on chromiumos. 1086// http://crbug.com/84419 1087#define MAYBE_TestRefNavigation DISABLED_TestRefNavigation 1088#else 1089#define MAYBE_TestRefNavigation TestRefNavigation 1090#endif 1091 1092// Test that navigating to a #ref does not change a bad security state. 1093IN_PROC_BROWSER_TEST_F(SSLUITest, TestRefNavigation) { 1094 ASSERT_TRUE(https_server_expired_.Start()); 1095 1096 ui_test_utils::NavigateToURL(browser(), 1097 https_server_expired_.GetURL("files/ssl/page_with_refs.html")); 1098 1099 WebContents* tab = chrome::GetActiveWebContents(browser()); 1100 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1101 true); // Interstitial showing. 1102 1103 ProceedThroughInterstitial(tab); 1104 1105 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1106 false); // No interstitial showing. 1107 1108 // Now navigate to a ref in the page, the security state should not have 1109 // changed. 1110 ui_test_utils::NavigateToURL(browser(), 1111 https_server_expired_.GetURL("files/ssl/page_with_refs.html#jp")); 1112 1113 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1114 false); // No interstitial showing. 1115} 1116 1117// Tests that closing a page that has a unsafe pop-up does not crash the 1118// browser (bug #1966). 1119// TODO(jcampan): http://crbug.com/2136 disabled because the popup is not 1120// opened as it is not initiated by a user gesture. 1121IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestCloseTabWithUnsafePopup) { 1122 ASSERT_TRUE(test_server()->Start()); 1123 ASSERT_TRUE(https_server_expired_.Start()); 1124 1125 std::string replacement_path; 1126 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 1127 "files/ssl/page_with_unsafe_popup.html", 1128 https_server_expired_.host_port_pair(), 1129 &replacement_path)); 1130 1131 ui_test_utils::NavigateToURL(browser(), 1132 test_server()->GetURL(replacement_path)); 1133 1134 WebContents* tab1 = chrome::GetActiveWebContents(browser()); 1135 // It is probably overkill to add a notification for a popup-opening, let's 1136 // just poll. 1137 for (int i = 0; i < 10; i++) { 1138 if (GetConstrainedWindowCount() > 0) 1139 break; 1140 MessageLoop::current()->PostDelayedTask( 1141 FROM_HERE, MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(1)); 1142 content::RunMessageLoop(); 1143 } 1144 ASSERT_EQ(1U, GetConstrainedWindowCount()); 1145 1146 // Let's add another tab to make sure the browser does not exit when we close 1147 // the first tab. 1148 GURL url = test_server()->GetURL("files/ssl/google.html"); 1149 content::WindowedNotificationObserver observer( 1150 content::NOTIFICATION_LOAD_STOP, 1151 content::NotificationService::AllSources()); 1152 chrome::AddSelectedTabWithURL(browser(), url, content::PAGE_TRANSITION_TYPED); 1153 observer.Wait(); 1154 1155 // Close the first tab. 1156 chrome::CloseWebContents(browser(), tab1); 1157} 1158 1159// Visit a page over bad https that is a redirect to a page with good https. 1160IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectBadToGoodHTTPS) { 1161 ASSERT_TRUE(https_server_.Start()); 1162 ASSERT_TRUE(https_server_expired_.Start()); 1163 1164 GURL url1 = https_server_expired_.GetURL("server-redirect?"); 1165 GURL url2 = https_server_.GetURL("files/ssl/google.html"); 1166 1167 ui_test_utils::NavigateToURL(browser(), GURL(url1.spec() + url2.spec())); 1168 1169 WebContents* tab = chrome::GetActiveWebContents(browser()); 1170 1171 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1172 true); // Interstitial showing. 1173 1174 ProceedThroughInterstitial(tab); 1175 1176 // We have been redirected to the good page. 1177 CheckAuthenticatedState(tab, false); 1178} 1179 1180// Visit a page over good https that is a redirect to a page with bad https. 1181IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectGoodToBadHTTPS) { 1182 ASSERT_TRUE(https_server_.Start()); 1183 ASSERT_TRUE(https_server_expired_.Start()); 1184 1185 GURL url1 = https_server_.GetURL("server-redirect?"); 1186 GURL url2 = https_server_expired_.GetURL("files/ssl/google.html"); 1187 ui_test_utils::NavigateToURL(browser(), GURL(url1.spec() + url2.spec())); 1188 1189 WebContents* tab = chrome::GetActiveWebContents(browser()); 1190 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1191 true); // Interstitial showing. 1192 1193 ProceedThroughInterstitial(tab); 1194 1195 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1196 false); // No interstitial showing. 1197} 1198 1199// Visit a page over http that is a redirect to a page with good HTTPS. 1200IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectHTTPToGoodHTTPS) { 1201 ASSERT_TRUE(test_server()->Start()); 1202 ASSERT_TRUE(https_server_.Start()); 1203 1204 WebContents* tab = chrome::GetActiveWebContents(browser()); 1205 1206 // HTTP redirects to good HTTPS. 1207 GURL http_url = test_server()->GetURL("server-redirect?"); 1208 GURL good_https_url = 1209 https_server_.GetURL("files/ssl/google.html"); 1210 1211 ui_test_utils::NavigateToURL(browser(), 1212 GURL(http_url.spec() + good_https_url.spec())); 1213 CheckAuthenticatedState(tab, false); 1214} 1215 1216// Visit a page over http that is a redirect to a page with bad HTTPS. 1217IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectHTTPToBadHTTPS) { 1218 ASSERT_TRUE(test_server()->Start()); 1219 ASSERT_TRUE(https_server_expired_.Start()); 1220 1221 WebContents* tab = chrome::GetActiveWebContents(browser()); 1222 1223 GURL http_url = test_server()->GetURL("server-redirect?"); 1224 GURL bad_https_url = 1225 https_server_expired_.GetURL("files/ssl/google.html"); 1226 ui_test_utils::NavigateToURL(browser(), 1227 GURL(http_url.spec() + bad_https_url.spec())); 1228 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1229 true); // Interstitial showing. 1230 1231 ProceedThroughInterstitial(tab); 1232 1233 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1234 false); // No interstitial showing. 1235} 1236 1237// Visit a page over https that is a redirect to a page with http (to make sure 1238// we don't keep the secure state). 1239IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectHTTPSToHTTP) { 1240 ASSERT_TRUE(test_server()->Start()); 1241 ASSERT_TRUE(https_server_.Start()); 1242 1243 GURL https_url = https_server_.GetURL("server-redirect?"); 1244 GURL http_url = test_server()->GetURL("files/ssl/google.html"); 1245 1246 ui_test_utils::NavigateToURL(browser(), 1247 GURL(https_url.spec() + http_url.spec())); 1248 CheckUnauthenticatedState(chrome::GetActiveWebContents(browser())); 1249} 1250 1251// Visits a page to which we could not connect (bad port) over http and https 1252// and make sure the security style is correct. 1253IN_PROC_BROWSER_TEST_F(SSLUITest, TestConnectToBadPort) { 1254 ui_test_utils::NavigateToURL(browser(), GURL("http://localhost:17")); 1255 CheckUnauthenticatedState(chrome::GetActiveWebContents(browser())); 1256 1257 // Same thing over HTTPS. 1258 ui_test_utils::NavigateToURL(browser(), GURL("https://localhost:17")); 1259 CheckUnauthenticatedState(chrome::GetActiveWebContents(browser())); 1260} 1261 1262// 1263// Frame navigation 1264// 1265 1266// From a good HTTPS top frame: 1267// - navigate to an OK HTTPS frame 1268// - navigate to a bad HTTPS (expect unsafe content and filtered frame), then 1269// back 1270// - navigate to HTTP (expect insecure content), then back 1271IN_PROC_BROWSER_TEST_F(SSLUITest, TestGoodFrameNavigation) { 1272 ASSERT_TRUE(test_server()->Start()); 1273 ASSERT_TRUE(https_server_.Start()); 1274 ASSERT_TRUE(https_server_expired_.Start()); 1275 1276 std::string top_frame_path; 1277 ASSERT_TRUE(GetTopFramePath(*test_server(), 1278 https_server_, 1279 https_server_expired_, 1280 &top_frame_path)); 1281 1282 WebContents* tab = chrome::GetActiveWebContents(browser()); 1283 ui_test_utils::NavigateToURL(browser(), 1284 https_server_.GetURL(top_frame_path)); 1285 1286 CheckAuthenticatedState(tab, false); 1287 1288 bool success = false; 1289 // Now navigate inside the frame. 1290 { 1291 content::WindowedNotificationObserver observer( 1292 content::NOTIFICATION_LOAD_STOP, 1293 content::Source<NavigationController>(&tab->GetController())); 1294 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1295 tab->GetRenderViewHost(), std::wstring(), 1296 L"window.domAutomationController.send(clickLink('goodHTTPSLink'));", 1297 &success)); 1298 ASSERT_TRUE(success); 1299 observer.Wait(); 1300 } 1301 1302 // We should still be fine. 1303 CheckAuthenticatedState(tab, false); 1304 1305 // Now let's hit a bad page. 1306 { 1307 content::WindowedNotificationObserver observer( 1308 content::NOTIFICATION_LOAD_STOP, 1309 content::Source<NavigationController>(&tab->GetController())); 1310 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1311 tab->GetRenderViewHost(), std::wstring(), 1312 L"window.domAutomationController.send(clickLink('badHTTPSLink'));", 1313 &success)); 1314 ASSERT_TRUE(success); 1315 observer.Wait(); 1316 } 1317 1318 // The security style should still be secure. 1319 CheckAuthenticatedState(tab, false); 1320 1321 // And the frame should be blocked. 1322 bool is_content_evil = true; 1323 std::wstring content_frame_xpath(L"html/frameset/frame[2]"); 1324 std::wstring is_evil_js(L"window.domAutomationController.send(" 1325 L"document.getElementById('evilDiv') != null);"); 1326 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1327 tab->GetRenderViewHost(), content_frame_xpath, is_evil_js, 1328 &is_content_evil)); 1329 EXPECT_FALSE(is_content_evil); 1330 1331 // Now go back, our state should still be OK. 1332 { 1333 content::WindowedNotificationObserver observer( 1334 content::NOTIFICATION_LOAD_STOP, 1335 content::Source<NavigationController>(&tab->GetController())); 1336 tab->GetController().GoBack(); 1337 observer.Wait(); 1338 } 1339 CheckAuthenticatedState(tab, false); 1340 1341 // Navigate to a page served over HTTP. 1342 { 1343 content::WindowedNotificationObserver observer( 1344 content::NOTIFICATION_LOAD_STOP, 1345 content::Source<NavigationController>(&tab->GetController())); 1346 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1347 tab->GetRenderViewHost(), std::wstring(), 1348 L"window.domAutomationController.send(clickLink('HTTPLink'));", 1349 &success)); 1350 ASSERT_TRUE(success); 1351 observer.Wait(); 1352 } 1353 1354 // Our state should be insecure. 1355 CheckAuthenticatedState(tab, true); 1356 1357 // Go back, our state should be unchanged. 1358 { 1359 content::WindowedNotificationObserver observer( 1360 content::NOTIFICATION_LOAD_STOP, 1361 content::Source<NavigationController>(&tab->GetController())); 1362 tab->GetController().GoBack(); 1363 observer.Wait(); 1364 } 1365 CheckAuthenticatedState(tab, true); 1366} 1367 1368// From a bad HTTPS top frame: 1369// - navigate to an OK HTTPS frame (expected to be still authentication broken). 1370IN_PROC_BROWSER_TEST_F(SSLUITest, TestBadFrameNavigation) { 1371 ASSERT_TRUE(https_server_.Start()); 1372 ASSERT_TRUE(https_server_expired_.Start()); 1373 1374 std::string top_frame_path; 1375 ASSERT_TRUE(GetTopFramePath(*test_server(), 1376 https_server_, 1377 https_server_expired_, 1378 &top_frame_path)); 1379 1380 WebContents* tab = chrome::GetActiveWebContents(browser()); 1381 ui_test_utils::NavigateToURL(browser(), 1382 https_server_expired_.GetURL(top_frame_path)); 1383 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1384 true); // Interstitial showing 1385 1386 ProceedThroughInterstitial(tab); 1387 1388 // Navigate to a good frame. 1389 bool success = false; 1390 content::WindowedNotificationObserver observer( 1391 content::NOTIFICATION_LOAD_STOP, 1392 content::Source<NavigationController>(&tab->GetController())); 1393 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1394 tab->GetRenderViewHost(), std::wstring(), 1395 L"window.domAutomationController.send(clickLink('goodHTTPSLink'));", 1396 &success)); 1397 ASSERT_TRUE(success); 1398 observer.Wait(); 1399 1400 // We should still be authentication broken. 1401 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1402 false); 1403} 1404 1405// From an HTTP top frame, navigate to good and bad HTTPS (security state should 1406// stay unauthenticated). 1407// Disabled, flakily exceeds test timeout, http://crbug.com/43437. 1408IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestUnauthenticatedFrameNavigation) { 1409 ASSERT_TRUE(test_server()->Start()); 1410 ASSERT_TRUE(https_server_.Start()); 1411 ASSERT_TRUE(https_server_expired_.Start()); 1412 1413 std::string top_frame_path; 1414 ASSERT_TRUE(GetTopFramePath(*test_server(), 1415 https_server_, 1416 https_server_expired_, 1417 &top_frame_path)); 1418 1419 WebContents* tab = chrome::GetActiveWebContents(browser()); 1420 ui_test_utils::NavigateToURL(browser(), 1421 test_server()->GetURL(top_frame_path)); 1422 CheckUnauthenticatedState(tab); 1423 1424 // Now navigate inside the frame to a secure HTTPS frame. 1425 { 1426 bool success = false; 1427 content::WindowedNotificationObserver observer( 1428 content::NOTIFICATION_LOAD_STOP, 1429 content::Source<NavigationController>(&tab->GetController())); 1430 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1431 tab->GetRenderViewHost(), std::wstring(), 1432 L"window.domAutomationController.send(clickLink('goodHTTPSLink'));", 1433 &success)); 1434 ASSERT_TRUE(success); 1435 observer.Wait(); 1436 } 1437 1438 // We should still be unauthenticated. 1439 CheckUnauthenticatedState(tab); 1440 1441 // Now navigate to a bad HTTPS frame. 1442 { 1443 bool success = false; 1444 content::WindowedNotificationObserver observer( 1445 content::NOTIFICATION_LOAD_STOP, 1446 content::Source<NavigationController>(&tab->GetController())); 1447 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1448 tab->GetRenderViewHost(), std::wstring(), 1449 L"window.domAutomationController.send(clickLink('badHTTPSLink'));", 1450 &success)); 1451 ASSERT_TRUE(success); 1452 observer.Wait(); 1453 } 1454 1455 // State should not have changed. 1456 CheckUnauthenticatedState(tab); 1457 1458 // And the frame should have been blocked (see bug #2316). 1459 bool is_content_evil = true; 1460 std::wstring content_frame_xpath(L"html/frameset/frame[2]"); 1461 std::wstring is_evil_js(L"window.domAutomationController.send(" 1462 L"document.getElementById('evilDiv') != null);"); 1463 EXPECT_TRUE(content::ExecuteJavaScriptAndExtractBool( 1464 tab->GetRenderViewHost(), content_frame_xpath, is_evil_js, 1465 &is_content_evil)); 1466 EXPECT_FALSE(is_content_evil); 1467} 1468 1469IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnsafeContentsInWorkerFiltered) { 1470 ASSERT_TRUE(https_server_.Start()); 1471 ASSERT_TRUE(https_server_expired_.Start()); 1472 1473 // This page will spawn a Worker which will try to load content from 1474 // BadCertServer. 1475 std::string page_with_unsafe_worker_path; 1476 ASSERT_TRUE(GetPageWithUnsafeWorkerPath(https_server_expired_, 1477 &page_with_unsafe_worker_path)); 1478 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL( 1479 page_with_unsafe_worker_path)); 1480 WebContents* tab = chrome::GetActiveWebContents(browser()); 1481 // Expect Worker not to load insecure content. 1482 CheckWorkerLoadResult(tab, false); 1483 // The bad content is filtered, expect the state to be authenticated. 1484 CheckAuthenticatedState(tab, false); 1485} 1486 1487IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnsafeContentsInWorker) { 1488 ASSERT_TRUE(https_server_.Start()); 1489 ASSERT_TRUE(https_server_expired_.Start()); 1490 1491 // Navigate to an unsafe site. Proceed with interstitial page to indicate 1492 // the user approves the bad certificate. 1493 ui_test_utils::NavigateToURL(browser(), 1494 https_server_expired_.GetURL("files/ssl/blank_page.html")); 1495 WebContents* tab = chrome::GetActiveWebContents(browser()); 1496 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1497 true); // Interstitial showing 1498 ProceedThroughInterstitial(tab); 1499 CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false, 1500 false); // No Interstitial 1501 1502 // Navigate to safe page that has Worker loading unsafe content. 1503 // Expect content to load but be marked as auth broken due to running insecure 1504 // content. 1505 std::string page_with_unsafe_worker_path; 1506 ASSERT_TRUE(GetPageWithUnsafeWorkerPath(https_server_expired_, 1507 &page_with_unsafe_worker_path)); 1508 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL( 1509 page_with_unsafe_worker_path)); 1510 CheckWorkerLoadResult(tab, true); // Worker loads insecure content 1511 CheckAuthenticationBrokenState(tab, 0, true, false); 1512} 1513 1514// Test that when the browser blocks displaying insecure content (images), the 1515// indicator shows a secure page, because the blocking made the otherwise 1516// unsafe page safe (the notification of this state is handled by other means). 1517IN_PROC_BROWSER_TEST_F(SSLUITestBlock, TestBlockDisplayingInsecureImage) { 1518 ASSERT_TRUE(test_server()->Start()); 1519 ASSERT_TRUE(https_server_.Start()); 1520 1521 std::string replacement_path; 1522 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 1523 "files/ssl/page_displays_insecure_content.html", 1524 test_server()->host_port_pair(), 1525 &replacement_path)); 1526 1527 ui_test_utils::NavigateToURL(browser(), 1528 https_server_.GetURL(replacement_path)); 1529 1530 CheckAuthenticatedState(chrome::GetActiveWebContents(browser()), false); 1531} 1532 1533// Test that when the browser blocks displaying insecure content (iframes), the 1534// indicator shows a secure page, because the blocking made the otherwise 1535// unsafe page safe (the notification of this state is handled by other means) 1536IN_PROC_BROWSER_TEST_F(SSLUITestBlock, TestBlockDisplayingInsecureIframe) { 1537 ASSERT_TRUE(test_server()->Start()); 1538 ASSERT_TRUE(https_server_.Start()); 1539 1540 std::string replacement_path; 1541 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 1542 "files/ssl/page_displays_insecure_iframe.html", 1543 test_server()->host_port_pair(), 1544 &replacement_path)); 1545 1546 ui_test_utils::NavigateToURL(browser(), 1547 https_server_.GetURL(replacement_path)); 1548 1549 CheckAuthenticatedState(chrome::GetActiveWebContents(browser()), false); 1550} 1551 1552 1553// Test that when the browser blocks running insecure content, the 1554// indicator shows a secure page, because the blocking made the otherwise 1555// unsafe page safe (the notification of this state is handled by other means). 1556IN_PROC_BROWSER_TEST_F(SSLUITestBlock, TestBlockRunningInsecureContent) { 1557 ASSERT_TRUE(test_server()->Start()); 1558 ASSERT_TRUE(https_server_.Start()); 1559 1560 std::string replacement_path; 1561 ASSERT_TRUE(GetFilePathWithHostAndPortReplacement( 1562 "files/ssl/page_runs_insecure_content.html", 1563 test_server()->host_port_pair(), 1564 &replacement_path)); 1565 1566 ui_test_utils::NavigateToURL(browser(), 1567 https_server_.GetURL(replacement_path)); 1568 1569 CheckAuthenticatedState(chrome::GetActiveWebContents(browser()), false); 1570} 1571 1572// Visit a page and establish a WebSocket connection over bad https with 1573// --ignore-certificate-errors. The connection should be established without 1574// interstitial page showing. 1575IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreCertErrors, TestWSS) { 1576 ASSERT_TRUE(test_server()->Start()); 1577 ASSERT_TRUE(wss_server_expired_.Start()); 1578 1579 // Setup page title observer. 1580 WebContents* tab = chrome::GetActiveWebContents(browser()); 1581 content::TitleWatcher watcher(tab, ASCIIToUTF16("PASS")); 1582 watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 1583 1584 // Visit bad HTTPS page. 1585 std::string scheme("https"); 1586 GURL::Replacements replacements; 1587 replacements.SetSchemeStr(scheme); 1588 ui_test_utils::NavigateToURL( 1589 browser(), 1590 wss_server_expired_.GetURL( 1591 "connect_check.html").ReplaceComponents(replacements)); 1592 1593 // We shouldn't have an interstitial page showing here. 1594 1595 // Test page run a WebSocket wss connection test. The result will be shown 1596 // as page title. 1597 const string16 result = watcher.WaitAndGetTitle(); 1598 EXPECT_TRUE(LowerCaseEqualsASCII(result, "pass")); 1599} 1600 1601// TODO(jcampan): more tests to do below. 1602 1603// Visit a page over https that contains a frame with a redirect. 1604 1605// XMLHttpRequest insecure content in synchronous mode. 1606 1607// XMLHttpRequest insecure content in asynchronous mode. 1608 1609// XMLHttpRequest over bad ssl in synchronous mode. 1610 1611// XMLHttpRequest over OK ssl in synchronous mode. 1612