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