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