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