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