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