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