ssl_browser_tests.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 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/stringprintf.h"
6#include "base/time.h"
7#include "chrome/app/chrome_command_ids.h"
8#include "chrome/browser/browser.h"
9#include "chrome/browser/browser_navigator.h"
10#include "chrome/browser/prefs/pref_service.h"
11#include "chrome/browser/profile.h"
12#include "chrome/browser/tab_contents/interstitial_page.h"
13#include "chrome/browser/tab_contents/navigation_entry.h"
14#include "chrome/browser/tab_contents/tab_contents.h"
15#include "chrome/browser/tabs/tab_strip_model.h"
16#include "chrome/common/pref_names.h"
17#include "chrome/test/in_process_browser_test.h"
18#include "chrome/test/ui_test_utils.h"
19#include "net/base/cert_status_flags.h"
20#include "net/test/test_server.h"
21
22const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data");
23
24class SSLUITest : public InProcessBrowserTest {
25  typedef net::TestServer::HTTPSOptions HTTPSOptions;
26
27 public:
28  SSLUITest()
29      : https_server_(
30            HTTPSOptions(HTTPSOptions::CERT_OK), FilePath(kDocRoot)),
31        https_server_expired_(
32            HTTPSOptions(HTTPSOptions::CERT_EXPIRED), FilePath(kDocRoot)),
33        https_server_mismatched_(
34            HTTPSOptions(HTTPSOptions::CERT_MISMATCHED_NAME),
35            FilePath(kDocRoot)) {
36    EnableDOMAutomation();
37  }
38
39  void CheckAuthenticatedState(TabContents* tab,
40                               bool displayed_insecure_content) {
41    NavigationEntry* entry = tab->controller().GetActiveEntry();
42    ASSERT_TRUE(entry);
43    EXPECT_EQ(NavigationEntry::NORMAL_PAGE, entry->page_type());
44    EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, entry->ssl().security_style());
45    EXPECT_EQ(0, entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS);
46    EXPECT_EQ(displayed_insecure_content,
47              entry->ssl().displayed_insecure_content());
48    EXPECT_FALSE(entry->ssl().ran_insecure_content());
49  }
50
51  void CheckUnauthenticatedState(TabContents* tab) {
52    NavigationEntry* entry = tab->controller().GetActiveEntry();
53    ASSERT_TRUE(entry);
54    EXPECT_EQ(NavigationEntry::NORMAL_PAGE, entry->page_type());
55    EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, entry->ssl().security_style());
56    EXPECT_EQ(0, entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS);
57    EXPECT_FALSE(entry->ssl().displayed_insecure_content());
58    EXPECT_FALSE(entry->ssl().ran_insecure_content());
59  }
60
61  void CheckAuthenticationBrokenState(TabContents* tab,
62                                      int error,
63                                      bool ran_insecure_content,
64                                      bool interstitial) {
65    NavigationEntry* entry = tab->controller().GetActiveEntry();
66    ASSERT_TRUE(entry);
67    EXPECT_EQ(interstitial ? NavigationEntry::INTERSTITIAL_PAGE :
68                             NavigationEntry::NORMAL_PAGE,
69              entry->page_type());
70    EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN,
71              entry->ssl().security_style());
72    // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION doesn't lower the security style
73    // to SECURITY_STYLE_AUTHENTICATION_BROKEN.
74    ASSERT_NE(net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION, error);
75    EXPECT_EQ(error, entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS);
76    EXPECT_FALSE(entry->ssl().displayed_insecure_content());
77    EXPECT_EQ(ran_insecure_content, entry->ssl().ran_insecure_content());
78  }
79
80  void CheckWorkerLoadResult(TabContents* tab, bool expectLoaded) {
81    // Workers are async and we don't have notifications for them passing
82    // messages since they do it between renderer and worker processes.
83    // So have a polling loop, check every 200ms, timeout at 30s.
84    const int timeout_ms = 200;
85    base::Time timeToQuit = base::Time::Now() +
86        base::TimeDelta::FromMilliseconds(30000);
87
88    while (base::Time::Now() < timeToQuit) {
89      bool workerFinished = false;
90      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
91          tab->render_view_host(), std::wstring(),
92          L"window.domAutomationController.send(IsWorkerFinished());",
93          &workerFinished));
94
95      if (workerFinished)
96        break;
97
98      // Wait a bit.
99      MessageLoop::current()->PostDelayedTask(
100          FROM_HERE, new MessageLoop::QuitTask, timeout_ms);
101      ui_test_utils::RunMessageLoop();
102    }
103
104    bool actuallyLoadedContent = false;
105    ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
106        tab->render_view_host(), std::wstring(),
107        L"window.domAutomationController.send(IsContentLoaded());",
108        &actuallyLoadedContent));
109    EXPECT_EQ(expectLoaded, actuallyLoadedContent);
110  }
111
112  void ProceedThroughInterstitial(TabContents* tab) {
113    InterstitialPage* interstitial_page = tab->interstitial_page();
114    ASSERT_TRUE(interstitial_page);
115    interstitial_page->Proceed();
116    // Wait for the navigation to be done.
117    ui_test_utils::WaitForNavigation(&(tab->controller()));
118  }
119
120  std::string GetFileWithHostAndPortReplacement(
121      const std::string& original_path,
122      const net::HostPortPair& host_port_pair) const {
123    return StringPrintf("%s?replace_orig=%s&replace_new=%s",
124                        original_path.c_str(),
125                        kReplaceText_,
126                        host_port_pair.ToString().c_str());
127  }
128
129  net::TestServer https_server_;
130  net::TestServer https_server_expired_;
131  net::TestServer https_server_mismatched_;
132
133 private:
134  DISALLOW_COPY_AND_ASSIGN(SSLUITest);
135
136  static const char* const kReplaceText_;
137};
138
139// static
140const char* const SSLUITest::kReplaceText_ = "REPLACE_WITH_HOST_AND_PORT";
141
142// Visits a regular page over http.
143IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTP) {
144  ASSERT_TRUE(test_server()->Start());
145
146  ui_test_utils::NavigateToURL(browser(),
147                               test_server()->GetURL("files/ssl/google.html"));
148
149  CheckUnauthenticatedState(browser()->GetSelectedTabContents());
150}
151
152// Visits a page over http which includes broken https resources (status should
153// be OK).
154// TODO(jcampan): test that bad HTTPS content is blocked (otherwise we'll give
155//                the secure cookies away!).
156IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPWithBrokenHTTPSResource) {
157  ASSERT_TRUE(test_server()->Start());
158  ASSERT_TRUE(https_server_expired_.Start());
159
160  std::string replacement_path = GetFileWithHostAndPortReplacement(
161      "files/ssl/page_with_unsafe_contents.html",
162      https_server_expired_.host_port_pair());
163
164  ui_test_utils::NavigateToURL(
165      browser(), test_server()->GetURL(replacement_path));
166
167  CheckUnauthenticatedState(browser()->GetSelectedTabContents());
168}
169
170// Visits a page over OK https:
171IN_PROC_BROWSER_TEST_F(SSLUITest, TestOKHTTPS) {
172  ASSERT_TRUE(https_server_.Start());
173
174  ui_test_utils::NavigateToURL(browser(),
175                               https_server_.GetURL("files/ssl/google.html"));
176
177  CheckAuthenticatedState(browser()->GetSelectedTabContents(), false);
178}
179
180// Visits a page with https error and proceed:
181IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSExpiredCertAndProceed) {
182  ASSERT_TRUE(https_server_expired_.Start());
183
184  ui_test_utils::NavigateToURL(browser(),
185      https_server_expired_.GetURL("files/ssl/google.html"));
186
187  TabContents* tab = browser()->GetSelectedTabContents();
188  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
189                                 true);  // Interstitial showing
190
191  ProceedThroughInterstitial(tab);
192
193  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
194                                 false);  // No interstitial showing
195}
196
197// Visits a page with https error and don't proceed (and ensure we can still
198// navigate at that point):
199#if defined(OS_WIN)
200// Disabled, flakily exceeds test timeout, http://crbug.com/43575.
201#define MAYBE_TestHTTPSExpiredCertAndDontProceed \
202    DISABLED_TestHTTPSExpiredCertAndDontProceed
203#else
204// Marked as flaky, see bug 40932.
205#define MAYBE_TestHTTPSExpiredCertAndDontProceed \
206    FLAKY_TestHTTPSExpiredCertAndDontProceed
207#endif
208IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestHTTPSExpiredCertAndDontProceed) {
209  ASSERT_TRUE(test_server()->Start());
210  ASSERT_TRUE(https_server_.Start());
211  ASSERT_TRUE(https_server_expired_.Start());
212
213  // First navigate to an OK page.
214  ui_test_utils::NavigateToURL(browser(),
215                               https_server_.GetURL("files/ssl/google.html"));
216
217  TabContents* tab = browser()->GetSelectedTabContents();
218  NavigationEntry* entry = tab->controller().GetActiveEntry();
219  ASSERT_TRUE(entry);
220
221  GURL cross_site_url =
222      https_server_expired_.GetURL("files/ssl/google.html");
223  // Change the host name from 127.0.0.1 to localhost so it triggers a
224  // cross-site navigation so we can test http://crbug.com/5800 is gone.
225  ASSERT_EQ("127.0.0.1", cross_site_url.host());
226  GURL::Replacements replacements;
227  std::string new_host("localhost");
228  replacements.SetHostStr(new_host);
229  cross_site_url = cross_site_url.ReplaceComponents(replacements);
230
231  // Now go to a bad HTTPS page.
232  ui_test_utils::NavigateToURL(browser(), cross_site_url);
233
234  // An interstitial should be showing.
235  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
236                                 false, true);
237
238  // Simulate user clicking "Take me back".
239  InterstitialPage* interstitial_page = tab->interstitial_page();
240  ASSERT_TRUE(interstitial_page);
241  interstitial_page->DontProceed();
242
243  // We should be back to the original good page.
244  CheckAuthenticatedState(tab, false);
245
246  // Try to navigate to a new page. (to make sure bug 5800 is fixed).
247  ui_test_utils::NavigateToURL(browser(),
248                               test_server()->GetURL("files/ssl/google.html"));
249  CheckUnauthenticatedState(tab);
250}
251
252// Visits a page with https error and then goes back using Browser::GoBack.
253#if defined(OS_WIN)
254// Disabled on win. Times out. crbug.com/43575 and crbug.com/61528
255#define TestHTTPSExpiredCertAndGoBackViaButton \
256    DISABLED_TestHTTPSExpiredCertAndGoBackViaButton
257#endif
258IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSExpiredCertAndGoBackViaButton) {
259  ASSERT_TRUE(test_server()->Start());
260  ASSERT_TRUE(https_server_expired_.Start());
261
262  // First navigate to an HTTP page.
263  ui_test_utils::NavigateToURL(browser(),
264      test_server()->GetURL("files/ssl/google.html"));
265  TabContents* tab = browser()->GetSelectedTabContents();
266  NavigationEntry* entry = tab->controller().GetActiveEntry();
267  ASSERT_TRUE(entry);
268
269  // Now go to a bad HTTPS page that shows an interstitial.
270  ui_test_utils::NavigateToURL(browser(),
271      https_server_expired_.GetURL("files/ssl/google.html"));
272  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
273                                 true);  // Interstitial showing
274
275  // Simulate user clicking on back button (crbug.com/39248).
276  browser()->GoBack(CURRENT_TAB);
277
278  // We should be back at the original good page.
279  EXPECT_FALSE(browser()->GetSelectedTabContents()->interstitial_page());
280  CheckUnauthenticatedState(tab);
281}
282
283// Visits a page with https error and then goes back using GoToOffset.
284// Marked as flaky, see bug 40932.
285#if defined(OS_WIN)
286// Disabled on win. Times out. crbug.com/43575 and crbug.com/61528
287#define FLAKY_TestHTTPSExpiredCertAndGoBackViaMenu \
288    DISABLED_TestHTTPSExpiredCertAndGoBackViaMenu
289#endif
290IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestHTTPSExpiredCertAndGoBackViaMenu) {
291  ASSERT_TRUE(test_server()->Start());
292  ASSERT_TRUE(https_server_expired_.Start());
293
294  // First navigate to an HTTP page.
295  ui_test_utils::NavigateToURL(browser(),
296      test_server()->GetURL("files/ssl/google.html"));
297  TabContents* tab = browser()->GetSelectedTabContents();
298  NavigationEntry* entry = tab->controller().GetActiveEntry();
299  ASSERT_TRUE(entry);
300
301  // Now go to a bad HTTPS page that shows an interstitial.
302  ui_test_utils::NavigateToURL(browser(),
303      https_server_expired_.GetURL("files/ssl/google.html"));
304  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
305                                 true);  // Interstitial showing
306
307  // Simulate user clicking and holding on back button (crbug.com/37215).
308  tab->controller().GoToOffset(-1);
309
310  // We should be back at the original good page.
311  EXPECT_FALSE(browser()->GetSelectedTabContents()->interstitial_page());
312  CheckUnauthenticatedState(tab);
313}
314
315// Visits a page with https error and then goes forward using GoToOffset.
316// Marked as flaky, see bug 40932.
317IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestHTTPSExpiredCertAndGoForward) {
318  ASSERT_TRUE(test_server()->Start());
319  ASSERT_TRUE(https_server_expired_.Start());
320
321  // First navigate to two HTTP pages.
322  ui_test_utils::NavigateToURL(browser(),
323      test_server()->GetURL("files/ssl/google.html"));
324  TabContents* tab = browser()->GetSelectedTabContents();
325  NavigationEntry* entry1 = tab->controller().GetActiveEntry();
326  ASSERT_TRUE(entry1);
327  ui_test_utils::NavigateToURL(browser(),
328      test_server()->GetURL("files/ssl/blank_page.html"));
329  NavigationEntry* entry2 = tab->controller().GetActiveEntry();
330  ASSERT_TRUE(entry2);
331
332  // Now go back so that a page is in the forward history.
333  tab->controller().GoBack();
334  ui_test_utils::WaitForNavigation(&(tab->controller()));
335  ASSERT_TRUE(tab->controller().CanGoForward());
336  NavigationEntry* entry3 = tab->controller().GetActiveEntry();
337  ASSERT_TRUE(entry1 == entry3);
338
339  // Now go to a bad HTTPS page that shows an interstitial.
340  ui_test_utils::NavigateToURL(browser(),
341      https_server_expired_.GetURL("files/ssl/google.html"));
342  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
343                                 true);  // Interstitial showing
344
345  // Simulate user clicking and holding on forward button.
346  tab->controller().GoToOffset(1);
347  ui_test_utils::WaitForNavigation(&(tab->controller()));
348
349  // We should be showing the second good page.
350  EXPECT_FALSE(browser()->GetSelectedTabContents()->interstitial_page());
351  CheckUnauthenticatedState(tab);
352  EXPECT_FALSE(tab->controller().CanGoForward());
353  NavigationEntry* entry4 = tab->controller().GetActiveEntry();
354  EXPECT_TRUE(entry2 == entry4);
355}
356
357// Open a page with a HTTPS error in a tab with no prior navigation (through a
358// link with a blank target).  This is to test that the lack of navigation entry
359// does not cause any problems (it was causing a crasher, see
360// http://crbug.com/19941).
361IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSErrorWithNoNavEntry) {
362  ASSERT_TRUE(https_server_expired_.Start());
363
364  GURL url = https_server_expired_.GetURL("files/ssl/google.htm");
365  TabContents* tab2 =
366      browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
367  ui_test_utils::WaitForLoadStop(&(tab2->controller()));
368
369  // Verify our assumption that there was no prior navigation.
370  EXPECT_FALSE(browser()->command_updater()->IsCommandEnabled(IDC_BACK));
371
372  // We should have an interstitial page showing.
373  ASSERT_TRUE(tab2->interstitial_page());
374}
375
376//
377// Insecure content
378//
379
380// Visits a page that displays insecure content.
381IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysInsecureContent) {
382  ASSERT_TRUE(test_server()->Start());
383  ASSERT_TRUE(https_server_.Start());
384
385  std::string replacement_path = GetFileWithHostAndPortReplacement(
386      "files/ssl/page_displays_insecure_content.html",
387      test_server()->host_port_pair());
388
389  // Load a page that displays insecure content.
390  ui_test_utils::NavigateToURL(browser(),
391                               https_server_.GetURL(replacement_path));
392
393  CheckAuthenticatedState(browser()->GetSelectedTabContents(), true);
394}
395
396// Visits a page that runs insecure content and tries to suppress the insecure
397// content warnings by randomizing location.hash.
398// Based on http://crbug.com/8706
399// Fails to terminate on all platforms.  See bug http://crbug.com/58230
400IN_PROC_BROWSER_TEST_F(SSLUITest,
401    DISABLED_TestRunsInsecuredContentRandomizeHash) {
402  ASSERT_TRUE(test_server()->Start());
403  ASSERT_TRUE(https_server_.Start());
404
405  ui_test_utils::NavigateToURL(browser(), https_server_.GetURL(
406      "files/ssl/page_runs_insecure_content.html"));
407
408  CheckAuthenticationBrokenState(browser()->GetSelectedTabContents(), 0, true,
409                                 false);
410}
411
412// Visits a page with unsafe content and make sure that:
413// - frames content is replaced with warning
414// - images and scripts are filtered out entirely
415// Marked as flaky, see bug 40932.
416IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestUnsafeContents) {
417  ASSERT_TRUE(https_server_.Start());
418  ASSERT_TRUE(https_server_expired_.Start());
419
420  std::string replacement_path = GetFileWithHostAndPortReplacement(
421      "files/ssl/page_with_unsafe_contents.html",
422      https_server_expired_.host_port_pair());
423  ui_test_utils::NavigateToURL(browser(),
424                               https_server_.GetURL(replacement_path));
425
426  TabContents* tab = browser()->GetSelectedTabContents();
427  // When the bad content is filtered, the state is expected to be
428  // authenticated.
429  CheckAuthenticatedState(tab, false);
430
431  // Because of cross-frame scripting restrictions, we cannot access the iframe
432  // content.  So to know if the frame was loaded, we just check if a popup was
433  // opened (the iframe content opens one).
434  // Note: because of bug 1115868, no constrained window is opened right now.
435  //       Once the bug is fixed, this will do the real check.
436  EXPECT_EQ(0, static_cast<int>(tab->constrained_window_count()));
437
438  int img_width;
439  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
440      tab->render_view_host(), std::wstring(),
441      L"window.domAutomationController.send(ImageWidth());", &img_width));
442  // In order to check that the image was not loaded, we check its width.
443  // The actual image (Google logo) is 114 pixels wide, we assume the broken
444  // image is less than 100.
445  EXPECT_LT(img_width, 100);
446
447  bool js_result = false;
448  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
449      tab->render_view_host(), std::wstring(),
450      L"window.domAutomationController.send(IsFooSet());", &js_result));
451  EXPECT_FALSE(js_result);
452}
453
454// Visits a page with insecure content loaded by JS (after the initial page
455// load).
456IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysInsecureContentLoadedFromJS) {
457  ASSERT_TRUE(test_server()->Start());
458  ASSERT_TRUE(https_server_.Start());
459
460  std::string replacement_path = GetFileWithHostAndPortReplacement(
461      "files/ssl/page_with_dynamic_insecure_content.html",
462      test_server()->host_port_pair());
463  ui_test_utils::NavigateToURL(browser(), https_server_.GetURL(
464      replacement_path));
465
466  TabContents* tab = browser()->GetSelectedTabContents();
467  CheckAuthenticatedState(tab, false);
468
469  // Load the insecure image.
470  bool js_result = false;
471  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
472      tab->render_view_host(), std::wstring(), L"loadBadImage();", &js_result));
473  EXPECT_TRUE(js_result);
474
475  // We should now have insecure content.
476  CheckAuthenticatedState(tab, true);
477}
478
479// Visits two pages from the same origin: one that displays insecure content and
480// one that doesn't.  The test checks that we do not propagate the insecure
481// content state from one to the other.
482IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysInsecureContentTwoTabs) {
483  ASSERT_TRUE(test_server()->Start());
484  ASSERT_TRUE(https_server_.Start());
485
486  ui_test_utils::NavigateToURL(browser(),
487      https_server_.GetURL("files/ssl/blank_page.html"));
488
489  TabContents* tab1 = browser()->GetSelectedTabContents();
490
491  // This tab should be fine.
492  CheckAuthenticatedState(tab1, false);
493
494  // Create a new tab.
495  std::string replacement_path = GetFileWithHostAndPortReplacement(
496      "files/ssl/page_displays_insecure_content.html",
497      test_server()->host_port_pair());
498
499  GURL url = https_server_.GetURL(replacement_path);
500  browser::NavigateParams params(browser(), url, PageTransition::TYPED);
501  params.disposition = NEW_FOREGROUND_TAB;
502  params.tabstrip_index = 0;
503  params.source_contents = tab1;
504  browser::Navigate(&params);
505  TabContents* tab2 = params.target_contents;
506  ui_test_utils::WaitForNavigation(&(tab2->controller()));
507
508  // The new tab has insecure content.
509  CheckAuthenticatedState(tab2, true);
510
511  // The original tab should not be contaminated.
512  CheckAuthenticatedState(tab1, false);
513}
514
515// Visits two pages from the same origin: one that runs insecure content and one
516// that doesn't.  The test checks that we propagate the insecure content state
517// from one to the other.
518IN_PROC_BROWSER_TEST_F(SSLUITest, TestRunsInsecureContentTwoTabs) {
519  ASSERT_TRUE(test_server()->Start());
520  ASSERT_TRUE(https_server_.Start());
521
522  ui_test_utils::NavigateToURL(browser(),
523      https_server_.GetURL("files/ssl/blank_page.html"));
524
525  TabContents* tab1 = browser()->GetSelectedTabContents();
526
527  // This tab should be fine.
528  CheckAuthenticatedState(tab1, false);
529
530  std::string replacement_path = GetFileWithHostAndPortReplacement(
531      "files/ssl/page_runs_insecure_content.html",
532      test_server()->host_port_pair());
533
534  // Create a new tab.
535  GURL url = https_server_.GetURL(replacement_path);
536  browser::NavigateParams params(browser(), url, PageTransition::TYPED);
537  params.disposition = NEW_FOREGROUND_TAB;
538  params.source_contents = tab1;
539  browser::Navigate(&params);
540  TabContents* tab2 = params.target_contents;
541  ui_test_utils::WaitForNavigation(&(tab2->controller()));
542
543  // The new tab has insecure content.
544  CheckAuthenticationBrokenState(tab2, 0, true, false);
545
546  // Which means the origin for the first tab has also been contaminated with
547  // insecure content.
548  CheckAuthenticationBrokenState(tab1, 0, true, false);
549}
550
551// Visits a page with an image over http.  Visits another page over https
552// referencing that same image over http (hoping it is coming from the webcore
553// memory cache).
554IN_PROC_BROWSER_TEST_F(SSLUITest, TestDisplaysCachedInsecureContent) {
555  ASSERT_TRUE(test_server()->Start());
556  ASSERT_TRUE(https_server_.Start());
557
558  std::string replacement_path = GetFileWithHostAndPortReplacement(
559      "files/ssl/page_displays_insecure_content.html",
560      test_server()->host_port_pair());
561
562  // Load original page over HTTP.
563  const GURL url_http = test_server()->GetURL(replacement_path);
564  ui_test_utils::NavigateToURL(browser(), url_http);
565  TabContents* tab = browser()->GetSelectedTabContents();
566  CheckUnauthenticatedState(tab);
567
568  // Load again but over SSL.  It should be marked as displaying insecure
569  // content (even though the image comes from the WebCore memory cache).
570  const GURL url_https = https_server_.GetURL(replacement_path);
571  ui_test_utils::NavigateToURL(browser(), url_https);
572  CheckAuthenticatedState(tab, true);
573}
574
575// Visits a page with script over http.  Visits another page over https
576// referencing that same script over http (hoping it is coming from the webcore
577// memory cache).
578IN_PROC_BROWSER_TEST_F(SSLUITest, TestRunsCachedInsecureContent) {
579  ASSERT_TRUE(test_server()->Start());
580  ASSERT_TRUE(https_server_.Start());
581
582  std::string replacement_path = GetFileWithHostAndPortReplacement(
583      "files/ssl/page_runs_insecure_content.html",
584      test_server()->host_port_pair());
585
586  // Load original page over HTTP.
587  const GURL url_http = test_server()->GetURL(replacement_path);
588  ui_test_utils::NavigateToURL(browser(), url_http);
589  TabContents* tab = browser()->GetSelectedTabContents();
590  CheckUnauthenticatedState(tab);
591
592  // Load again but over SSL.  It should be marked as displaying insecure
593  // content (even though the image comes from the WebCore memory cache).
594  const GURL url_https = https_server_.GetURL(replacement_path);
595  ui_test_utils::NavigateToURL(browser(), url_https);
596  CheckAuthenticationBrokenState(tab, 0, true, false);
597}
598
599#if defined(OS_WIN)
600// See http://crbug.com/47170
601#define MAYBE_TestCNInvalidStickiness FLAKY_TestCNInvalidStickiness
602#else
603#define MAYBE_TestCNInvalidStickiness TestCNInvalidStickiness
604#endif
605
606// This test ensures the CN invalid status does not 'stick' to a certificate
607// (see bug #1044942) and that it depends on the host-name.
608IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestCNInvalidStickiness) {
609  ASSERT_TRUE(https_server_.Start());
610  ASSERT_TRUE(https_server_mismatched_.Start());
611
612  // First we hit the server with hostname, this generates an invalid policy
613  // error.
614  ui_test_utils::NavigateToURL(browser(),
615      https_server_mismatched_.GetURL("files/ssl/google.html"));
616
617  // We get an interstitial page as a result.
618  TabContents* tab = browser()->GetSelectedTabContents();
619  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
620                                 false, true);  // Interstitial showing.
621  ProceedThroughInterstitial(tab);
622  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
623                                 false, false);  // No interstitial showing.
624
625  // Now we try again with the right host name this time.
626  GURL url(https_server_.GetURL("files/ssl/google.html"));
627  ui_test_utils::NavigateToURL(browser(), url);
628
629  // Security state should be OK.
630  CheckAuthenticatedState(tab, false);
631
632  // Now try again the broken one to make sure it is still broken.
633  ui_test_utils::NavigateToURL(browser(),
634      https_server_mismatched_.GetURL("files/ssl/google.html"));
635
636  // Since we OKed the interstitial last time, we get right to the page.
637  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
638                                 false, false);  // No interstitial showing.
639}
640
641// Test that navigating to a #ref does not change a bad security state.
642IN_PROC_BROWSER_TEST_F(SSLUITest, TestRefNavigation) {
643  ASSERT_TRUE(https_server_expired_.Start());
644
645  ui_test_utils::NavigateToURL(browser(),
646      https_server_expired_.GetURL("files/ssl/page_with_refs.html"));
647
648  TabContents* tab = browser()->GetSelectedTabContents();
649  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
650                                 true);  // Interstitial showing.
651
652  ProceedThroughInterstitial(tab);
653
654  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
655                                 false);  // No interstitial showing.
656
657  // Now navigate to a ref in the page, the security state should not have
658  // changed.
659  ui_test_utils::NavigateToURL(browser(),
660      https_server_expired_.GetURL("files/ssl/page_with_refs.html#jp"));
661
662  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
663                                 false);  // No interstitial showing.
664}
665
666// Tests that closing a page that has a unsafe pop-up does not crash the
667// browser (bug #1966).
668// TODO(jcampan): http://crbug.com/2136 disabled because the popup is not
669//                opened as it is not initiated by a user gesture.
670IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestCloseTabWithUnsafePopup) {
671  ASSERT_TRUE(test_server()->Start());
672  ASSERT_TRUE(https_server_expired_.Start());
673
674  std::string replacement_path = GetFileWithHostAndPortReplacement(
675      "files/ssl/page_with_unsafe_popup.html",
676      https_server_expired_.host_port_pair());
677
678  ui_test_utils::NavigateToURL(browser(),
679                               test_server()->GetURL(replacement_path));
680
681  TabContents* tab1 = browser()->GetSelectedTabContents();
682  // It is probably overkill to add a notification for a popup-opening, let's
683  // just poll.
684  for (int i = 0; i < 10; i++) {
685    if (static_cast<int>(tab1->constrained_window_count()) > 0)
686      break;
687    MessageLoop::current()->PostDelayedTask(FROM_HERE,
688                                            new MessageLoop::QuitTask(), 1000);
689    ui_test_utils::RunMessageLoop();
690  }
691  ASSERT_EQ(1, static_cast<int>(tab1->constrained_window_count()));
692
693  // Let's add another tab to make sure the browser does not exit when we close
694  // the first tab.
695  GURL url = test_server()->GetURL("files/ssl/google.html");
696  TabContents* tab2 =
697      browser()->AddSelectedTabWithURL(url, PageTransition::TYPED);
698  ui_test_utils::WaitForNavigation(&(tab2->controller()));
699
700  // Close the first tab.
701  browser()->CloseTabContents(tab1);
702}
703
704// Visit a page over bad https that is a redirect to a page with good https.
705// Marked as flaky, see bug 40932.
706IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestRedirectBadToGoodHTTPS) {
707  ASSERT_TRUE(https_server_.Start());
708  ASSERT_TRUE(https_server_expired_.Start());
709
710  GURL url1 = https_server_expired_.GetURL("server-redirect?");
711  GURL url2 = https_server_.GetURL("files/ssl/google.html");
712
713  ui_test_utils::NavigateToURL(browser(), GURL(url1.spec() + url2.spec()));
714
715  TabContents* tab = browser()->GetSelectedTabContents();
716
717  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
718                                 true);  // Interstitial showing.
719
720  ProceedThroughInterstitial(tab);
721
722  // We have been redirected to the good page.
723  CheckAuthenticatedState(tab, false);
724}
725
726// Visit a page over good https that is a redirect to a page with bad https.
727// Marked as flaky, see bug 40932.
728IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestRedirectGoodToBadHTTPS) {
729  ASSERT_TRUE(https_server_.Start());
730  ASSERT_TRUE(https_server_expired_.Start());
731
732  GURL url1 = https_server_.GetURL("server-redirect?");
733  GURL url2 = https_server_expired_.GetURL("files/ssl/google.html");
734  ui_test_utils::NavigateToURL(browser(), GURL(url1.spec() + url2.spec()));
735
736  TabContents* tab = browser()->GetSelectedTabContents();
737  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
738                                 true);  // Interstitial showing.
739
740  ProceedThroughInterstitial(tab);
741
742  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
743                                 false);  // No interstitial showing.
744}
745
746// Visit a page over http that is a redirect to a page with good HTTPS.
747IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectHTTPToGoodHTTPS) {
748  ASSERT_TRUE(test_server()->Start());
749  ASSERT_TRUE(https_server_.Start());
750
751  TabContents* tab = browser()->GetSelectedTabContents();
752
753  // HTTP redirects to good HTTPS.
754  GURL http_url = test_server()->GetURL("server-redirect?");
755  GURL good_https_url =
756      https_server_.GetURL("files/ssl/google.html");
757
758  ui_test_utils::NavigateToURL(browser(),
759                               GURL(http_url.spec() + good_https_url.spec()));
760  CheckAuthenticatedState(tab, false);
761}
762
763// Visit a page over http that is a redirect to a page with bad HTTPS.
764IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestRedirectHTTPToBadHTTPS) {
765  ASSERT_TRUE(test_server()->Start());
766  ASSERT_TRUE(https_server_expired_.Start());
767
768  TabContents* tab = browser()->GetSelectedTabContents();
769
770  GURL http_url = test_server()->GetURL("server-redirect?");
771  GURL bad_https_url =
772      https_server_expired_.GetURL("files/ssl/google.html");
773  ui_test_utils::NavigateToURL(browser(),
774                               GURL(http_url.spec() + bad_https_url.spec()));
775  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
776                                 true);  // Interstitial showing.
777
778  ProceedThroughInterstitial(tab);
779
780  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
781                                 false);  // No interstitial showing.
782}
783
784// Visit a page over https that is a redirect to a page with http (to make sure
785// we don't keep the secure state).
786// Marked as flaky, see bug 40932.
787IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestRedirectHTTPSToHTTP) {
788  ASSERT_TRUE(test_server()->Start());
789  ASSERT_TRUE(https_server_.Start());
790
791  GURL https_url = https_server_.GetURL("server-redirect?");
792  GURL http_url = test_server()->GetURL("files/ssl/google.html");
793
794  ui_test_utils::NavigateToURL(browser(),
795                               GURL(https_url.spec() + http_url.spec()));
796  CheckUnauthenticatedState(browser()->GetSelectedTabContents());
797}
798
799// Visits a page to which we could not connect (bad port) over http and https
800// and make sure the security style is correct.
801IN_PROC_BROWSER_TEST_F(SSLUITest, TestConnectToBadPort) {
802  ui_test_utils::NavigateToURL(browser(), GURL("http://localhost:17"));
803  CheckUnauthenticatedState(browser()->GetSelectedTabContents());
804
805  // Same thing over HTTPS.
806  ui_test_utils::NavigateToURL(browser(), GURL("https://localhost:17"));
807  CheckUnauthenticatedState(browser()->GetSelectedTabContents());
808}
809
810//
811// Frame navigation
812//
813
814// From a good HTTPS top frame:
815// - navigate to an OK HTTPS frame
816// - navigate to a bad HTTPS (expect unsafe content and filtered frame), then
817//   back
818// - navigate to HTTP (expect insecure content), then back
819// Disabled, http://crbug.com/18626.
820IN_PROC_BROWSER_TEST_F(SSLUITest, DISABLED_TestGoodFrameNavigation) {
821  ASSERT_TRUE(test_server()->Start());
822  ASSERT_TRUE(https_server_.Start());
823  ASSERT_TRUE(https_server_expired_.Start());
824
825  TabContents* tab = browser()->GetSelectedTabContents();
826  ui_test_utils::NavigateToURL(browser(),
827      https_server_.GetURL("files/ssl/top_frame.html"));
828
829  CheckAuthenticatedState(tab, false);
830
831  bool success = false;
832  // Now navigate inside the frame.
833  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
834      tab->render_view_host(), std::wstring(),
835      L"window.domAutomationController.send(clickLink('goodHTTPSLink'));",
836      &success));
837  EXPECT_TRUE(success);
838  ui_test_utils::WaitForNavigation(&tab->controller());
839
840  // We should still be fine.
841  CheckAuthenticatedState(tab, false);
842
843  // Now let's hit a bad page.
844  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
845      tab->render_view_host(), std::wstring(),
846      L"window.domAutomationController.send(clickLink('badHTTPSLink'));",
847      &success));
848  EXPECT_TRUE(success);
849  ui_test_utils::WaitForNavigation(&tab->controller());
850
851  // The security style should still be secure.
852  CheckAuthenticatedState(tab, false);
853
854  // And the frame should be blocked.
855  bool is_content_evil = true;
856  std::wstring content_frame_xpath(L"html/frameset/frame[2]");
857  std::wstring is_evil_js(L"window.domAutomationController.send("
858                          L"document.getElementById('evilDiv') != null);");
859  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
860      tab->render_view_host(), content_frame_xpath, is_evil_js,
861      &is_content_evil));
862  EXPECT_FALSE(is_content_evil);
863
864  // Now go back, our state should still be OK.
865  tab->controller().GoBack();
866  ui_test_utils::WaitForNavigation(&tab->controller());
867  CheckAuthenticatedState(tab, false);
868
869  // Navigate to a page served over HTTP.
870  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
871      tab->render_view_host(), std::wstring(),
872      L"window.domAutomationController.send(clickLink('HTTPLink'));",
873      &success));
874  EXPECT_TRUE(success);
875  ui_test_utils::WaitForNavigation(&tab->controller());
876
877  // Our state should be insecure.
878  CheckAuthenticatedState(tab, true);
879
880  // Go back, our state should be unchanged.
881  tab->controller().GoBack();
882  ui_test_utils::WaitForNavigation(&tab->controller());
883  CheckAuthenticatedState(tab, true);
884}
885
886// From a bad HTTPS top frame:
887// - navigate to an OK HTTPS frame (expected to be still authentication broken).
888// Marked as flaky, see bug 40932.
889IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestBadFrameNavigation) {
890  ASSERT_TRUE(https_server_.Start());
891  ASSERT_TRUE(https_server_expired_.Start());
892
893  TabContents* tab = browser()->GetSelectedTabContents();
894  ui_test_utils::NavigateToURL(browser(),
895      https_server_expired_.GetURL("files/ssl/top_frame.html"));
896  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
897                                 true);  // Interstitial showing
898
899  ProceedThroughInterstitial(tab);
900
901  // Navigate to a good frame.
902  bool success = false;
903  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
904      tab->render_view_host(), std::wstring(),
905      L"window.domAutomationController.send(clickLink('goodHTTPSLink'));",
906      &success));
907  EXPECT_TRUE(success);
908  ui_test_utils::WaitForNavigation(&tab->controller());
909
910  // We should still be authentication broken.
911  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
912                                 false);
913}
914
915// From an HTTP top frame, navigate to good and bad HTTPS (security state should
916// stay unauthenticated).
917#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_LINUX)
918// Disabled, flakily exceeds test timeout, http://crbug.com/43437.
919#define MAYBE_TestUnauthenticatedFrameNavigation \
920      DISABLED_TestUnauthenticatedFrameNavigation
921#else
922// Marked as flaky, see bug 40932.
923#define MAYBE_TestUnauthenticatedFrameNavigation \
924      FLAKY_TestUnauthenticatedFrameNavigation
925#endif
926IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestUnauthenticatedFrameNavigation) {
927  ASSERT_TRUE(test_server()->Start());
928  ASSERT_TRUE(https_server_.Start());
929  ASSERT_TRUE(https_server_expired_.Start());
930
931  TabContents* tab = browser()->GetSelectedTabContents();
932  ui_test_utils::NavigateToURL(browser(),
933      test_server()->GetURL("files/ssl/top_frame.html"));
934  CheckUnauthenticatedState(tab);
935
936  // Now navigate inside the frame to a secure HTTPS frame.
937  bool success = false;
938  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
939      tab->render_view_host(), std::wstring(),
940      L"window.domAutomationController.send(clickLink('goodHTTPSLink'));",
941      &success));
942  EXPECT_TRUE(success);
943  ui_test_utils::WaitForNavigation(&tab->controller());
944
945  // We should still be unauthenticated.
946  CheckUnauthenticatedState(tab);
947
948  // Now navigate to a bad HTTPS frame.
949  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
950      tab->render_view_host(), std::wstring(),
951      L"window.domAutomationController.send(clickLink('badHTTPSLink'));",
952      &success));
953  EXPECT_TRUE(success);
954  ui_test_utils::WaitForNavigation(&tab->controller());
955
956  // State should not have changed.
957  CheckUnauthenticatedState(tab);
958
959  // And the frame should have been blocked (see bug #2316).
960  bool is_content_evil = true;
961  std::wstring content_frame_xpath(L"html/frameset/frame[2]");
962  std::wstring is_evil_js(L"window.domAutomationController.send("
963                          L"document.getElementById('evilDiv') != null);");
964  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
965      tab->render_view_host(), content_frame_xpath, is_evil_js,
966      &is_content_evil));
967  EXPECT_FALSE(is_content_evil);
968}
969
970// Marked as flaky, see bug 40932.
971IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestUnsafeContentsInWorkerFiltered) {
972  ASSERT_TRUE(https_server_.Start());
973  ASSERT_TRUE(https_server_expired_.Start());
974
975  // This page will spawn a Worker which will try to load content from
976  // BadCertServer.
977  ui_test_utils::NavigateToURL(browser(), https_server_.GetURL(
978      "files/ssl/page_with_unsafe_worker.html"));
979  TabContents* tab = browser()->GetSelectedTabContents();
980  // Expect Worker not to load insecure content.
981  CheckWorkerLoadResult(tab, false);
982  // The bad content is filtered, expect the state to be authenticated.
983  CheckAuthenticatedState(tab, false);
984}
985
986// Marked as flaky, see bug 40932.
987IN_PROC_BROWSER_TEST_F(SSLUITest, FLAKY_TestUnsafeContentsInWorker) {
988  ASSERT_TRUE(https_server_.Start());
989  ASSERT_TRUE(https_server_expired_.Start());
990
991  // Navigate to an unsafe site. Proceed with interstitial page to indicate
992  // the user approves the bad certificate.
993  ui_test_utils::NavigateToURL(browser(),
994      https_server_expired_.GetURL("files/ssl/blank_page.html"));
995  TabContents* tab = browser()->GetSelectedTabContents();
996  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
997                                 true);  // Interstitial showing
998  ProceedThroughInterstitial(tab);
999  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
1000                                 false);  // No Interstitial
1001
1002  // Navigate to safe page that has Worker loading unsafe content.
1003  // Expect content to load but be marked as auth broken due to running insecure
1004  // content.
1005  ui_test_utils::NavigateToURL(browser(), https_server_.GetURL(
1006      "files/ssl/page_with_unsafe_worker.html"));
1007  CheckWorkerLoadResult(tab, true);  // Worker loads insecure content
1008  CheckAuthenticationBrokenState(tab, 0, true, false);
1009}
1010
1011// TODO(jcampan): more tests to do below.
1012
1013// Visit a page over https that contains a frame with a redirect.
1014
1015// XMLHttpRequest insecure content in synchronous mode.
1016
1017// XMLHttpRequest insecure content in asynchronous mode.
1018
1019// XMLHttpRequest over bad ssl in synchronous mode.
1020
1021// XMLHttpRequest over OK ssl in synchronous mode.
1022