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