Home | History | Annotate | Download | only in ssl
      1 // Copyright 2014 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 "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
      6 
      7 #include <stdint.h>
      8 
      9 #include "base/command_line.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/test/simple_test_clock.h"
     12 #include "chrome/browser/browsing_data/browsing_data_helper.h"
     13 #include "chrome/browser/browsing_data/browsing_data_remover.h"
     14 #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     19 #include "chrome/common/chrome_switches.h"
     20 #include "chrome/test/base/in_process_browser_test.h"
     21 #include "content/public/browser/ssl_host_state_delegate.h"
     22 #include "content/public/browser/web_contents.h"
     23 #include "content/public/test/browser_test_utils.h"
     24 #include "net/base/test_data_directory.h"
     25 #include "net/test/cert_test_util.h"
     26 #include "testing/gtest/include/gtest/gtest.h"
     27 
     28 namespace {
     29 
     30 const char kGoogleCertFile[] = "google.single.der";
     31 
     32 const char kWWWGoogleHost[] = "www.google.com";
     33 const char kGoogleHost[] = "google.com";
     34 const char kExampleHost[] = "example.com";
     35 
     36 const char kForgetAtSessionEnd[] = "-1";
     37 const char kForgetInstantly[] = "0";
     38 const char kDeltaSecondsString[] = "86400";
     39 const uint64_t kDeltaOneDayInSeconds = UINT64_C(86400);
     40 
     41 scoped_refptr<net::X509Certificate> GetGoogleCert() {
     42   return net::ImportCertFromFile(net::GetTestCertsDirectory(), kGoogleCertFile);
     43 }
     44 
     45 }  // namespace
     46 
     47 class ChromeSSLHostStateDelegateTest : public InProcessBrowserTest {};
     48 
     49 // ChromeSSLHostStateDelegateTest tests basic unit test functionality of the
     50 // SSLHostStateDelegate class.  For example, tests that if a certificate is
     51 // accepted, then it is added to queryable, and if it is revoked, it is not
     52 // queryable. Even though it is effectively a unit test, in needs to be an
     53 // InProcessBrowserTest because the actual functionality is provided by
     54 // ChromeSSLHostStateDelegate which is provided per-profile.
     55 //
     56 // QueryPolicy unit tests the expected behavior of calling QueryPolicy on the
     57 // SSLHostStateDelegate class after various SSL cert decisions have been made.
     58 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, QueryPolicy) {
     59   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
     60   content::WebContents* tab =
     61       browser()->tab_strip_model()->GetActiveWebContents();
     62   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
     63   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
     64   bool unused_value;
     65 
     66   // Verifying that all three of the certs we will be looking at are denied
     67   // before any action has been taken.
     68   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
     69             state->QueryPolicy(kWWWGoogleHost,
     70                                *google_cert.get(),
     71                                net::CERT_STATUS_DATE_INVALID,
     72                                &unused_value));
     73   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
     74             state->QueryPolicy(kGoogleHost,
     75                                *google_cert.get(),
     76                                net::CERT_STATUS_DATE_INVALID,
     77                                &unused_value));
     78   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
     79             state->QueryPolicy(kExampleHost,
     80                                *google_cert.get(),
     81                                net::CERT_STATUS_DATE_INVALID,
     82                                &unused_value));
     83 
     84   // Simulate a user decision to allow an invalid certificate exception for
     85   // kWWWGoogleHost.
     86   state->AllowCert(
     87       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
     88 
     89   // Verify that only kWWWGoogleHost is allowed and that the other two certs
     90   // being tested still are denied.
     91   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
     92             state->QueryPolicy(kWWWGoogleHost,
     93                                *google_cert.get(),
     94                                net::CERT_STATUS_DATE_INVALID,
     95                                &unused_value));
     96   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
     97             state->QueryPolicy(kGoogleHost,
     98                                *google_cert.get(),
     99                                net::CERT_STATUS_DATE_INVALID,
    100                                &unused_value));
    101   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    102             state->QueryPolicy(kExampleHost,
    103                                *google_cert.get(),
    104                                net::CERT_STATUS_DATE_INVALID,
    105                                &unused_value));
    106 
    107   // Simulate a user decision to allow an invalid certificate exception for
    108   // kExampleHost.
    109   state->AllowCert(
    110       kExampleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    111 
    112   // Verify that both kWWWGoogleHost and kExampleHost have allow exceptions
    113   // while kGoogleHost still is denied.
    114   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    115             state->QueryPolicy(kWWWGoogleHost,
    116                                *google_cert.get(),
    117                                net::CERT_STATUS_DATE_INVALID,
    118                                &unused_value));
    119   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    120             state->QueryPolicy(kGoogleHost,
    121                                *google_cert.get(),
    122                                net::CERT_STATUS_DATE_INVALID,
    123                                &unused_value));
    124   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    125             state->QueryPolicy(kExampleHost,
    126                                *google_cert.get(),
    127                                net::CERT_STATUS_DATE_INVALID,
    128                                &unused_value));
    129 }
    130 
    131 // HasPolicyAndRevoke unit tests the expected behavior of calling
    132 // HasAllowException before and after calling RevokeUserAllowExceptions on the
    133 // SSLHostStateDelegate class.
    134 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, HasPolicyAndRevoke) {
    135   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    136   content::WebContents* tab =
    137       browser()->tab_strip_model()->GetActiveWebContents();
    138   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    139   ChromeSSLHostStateDelegate* state =
    140       ChromeSSLHostStateDelegateFactory::GetForProfile(profile);
    141   bool unused_value;
    142 
    143   // Simulate a user decision to allow an invalid certificate exception for
    144   // kWWWGoogleHost and for kExampleHost.
    145   state->AllowCert(
    146       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    147   state->AllowCert(
    148       kExampleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    149 
    150   // Verify that HasAllowException correctly acknowledges that a user decision
    151   // has been made about kWWWGoogleHost. Then verify that HasAllowException
    152   // correctly identifies that the decision has been revoked.
    153   EXPECT_TRUE(state->HasAllowException(kWWWGoogleHost));
    154   state->RevokeUserAllowExceptions(kWWWGoogleHost);
    155   EXPECT_FALSE(state->HasAllowException(kWWWGoogleHost));
    156   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    157             state->QueryPolicy(kWWWGoogleHost,
    158                                *google_cert.get(),
    159                                net::CERT_STATUS_DATE_INVALID,
    160                                &unused_value));
    161 
    162   // Verify that the revocation of the kWWWGoogleHost decision does not affect
    163   // the Allow for kExampleHost.
    164   EXPECT_TRUE(state->HasAllowException(kExampleHost));
    165 
    166   // Verify the revocation of the kWWWGoogleHost decision does not affect the
    167   // non-decision for kGoogleHost. Then verify that a revocation of a URL with
    168   // no decision has no effect.
    169   EXPECT_FALSE(state->HasAllowException(kGoogleHost));
    170   state->RevokeUserAllowExceptions(kGoogleHost);
    171   EXPECT_FALSE(state->HasAllowException(kGoogleHost));
    172 }
    173 
    174 // Clear unit tests the expected behavior of calling Clear to forget all cert
    175 // decision state on the SSLHostStateDelegate class.
    176 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, Clear) {
    177   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    178   content::WebContents* tab =
    179       browser()->tab_strip_model()->GetActiveWebContents();
    180   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    181   ChromeSSLHostStateDelegate* state =
    182       ChromeSSLHostStateDelegateFactory::GetForProfile(profile);
    183   bool unused_value;
    184 
    185   // Simulate a user decision to allow an invalid certificate exception for
    186   // kWWWGoogleHost and for kExampleHost.
    187   state->AllowCert(
    188       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    189 
    190   // Do a full clear, then make sure that both kWWWGoogleHost, which had a
    191   // decision made, and kExampleHost, which was untouched, are now in a denied
    192   // state.
    193   state->Clear();
    194   EXPECT_FALSE(state->HasAllowException(kWWWGoogleHost));
    195   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    196             state->QueryPolicy(kWWWGoogleHost,
    197                                *google_cert.get(),
    198                                net::CERT_STATUS_DATE_INVALID,
    199                                &unused_value));
    200   EXPECT_FALSE(state->HasAllowException(kExampleHost));
    201   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    202             state->QueryPolicy(kExampleHost,
    203                                *google_cert.get(),
    204                                net::CERT_STATUS_DATE_INVALID,
    205                                &unused_value));
    206 }
    207 
    208 // DidHostRunInsecureContent unit tests the expected behavior of calling
    209 // DidHostRunInsecureContent as well as HostRanInsecureContent to check if
    210 // insecure content has been run and to mark it as such.
    211 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest,
    212                        DidHostRunInsecureContent) {
    213   content::WebContents* tab =
    214       browser()->tab_strip_model()->GetActiveWebContents();
    215   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    216   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    217 
    218   EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 42));
    219   EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 191));
    220   EXPECT_FALSE(state->DidHostRunInsecureContent("example.com", 42));
    221 
    222   state->HostRanInsecureContent("www.google.com", 42);
    223 
    224   EXPECT_TRUE(state->DidHostRunInsecureContent("www.google.com", 42));
    225   EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 191));
    226   EXPECT_FALSE(state->DidHostRunInsecureContent("example.com", 42));
    227 
    228   state->HostRanInsecureContent("example.com", 42);
    229 
    230   EXPECT_TRUE(state->DidHostRunInsecureContent("www.google.com", 42));
    231   EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 191));
    232   EXPECT_TRUE(state->DidHostRunInsecureContent("example.com", 42));
    233 }
    234 
    235 // QueryPolicyExpired unit tests to make sure that if a certificate decision has
    236 // expired, the return value from QueryPolicy returns the correct vaule.
    237 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, PRE_QueryPolicyExpired) {
    238   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    239   content::WebContents* tab =
    240       browser()->tab_strip_model()->GetActiveWebContents();
    241   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    242   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    243   bool expired_previous_decision;
    244 
    245   // The certificate has never been seen before, so it should be UNKNOWN and
    246   // should also indicate that it hasn't expired.
    247   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    248             state->QueryPolicy(kWWWGoogleHost,
    249                                *google_cert.get(),
    250                                net::CERT_STATUS_DATE_INVALID,
    251                                &expired_previous_decision));
    252   EXPECT_FALSE(expired_previous_decision);
    253 
    254   // After allowing the certificate, a query should say that it is allowed and
    255   // also specify that it hasn't expired.
    256   state->AllowCert(
    257       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    258   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    259             state->QueryPolicy(kWWWGoogleHost,
    260                                *google_cert.get(),
    261                                net::CERT_STATUS_DATE_INVALID,
    262                                &expired_previous_decision));
    263   EXPECT_FALSE(expired_previous_decision);
    264 }
    265 
    266 // Since this is being checked on a browser instance that expires security
    267 // decisions after restart, the test needs to  wait until after a restart to
    268 // verify that the expiration state is correct.
    269 IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, QueryPolicyExpired) {
    270   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    271   content::WebContents* tab =
    272       browser()->tab_strip_model()->GetActiveWebContents();
    273   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    274   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    275   bool expired_previous_decision;
    276 
    277   // The browser content has restart thus expiring the user decision made above,
    278   // so it should indicate that the certificate and error are DENIED but also
    279   // that they expired since the last query.
    280   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    281             state->QueryPolicy(kWWWGoogleHost,
    282                                *google_cert.get(),
    283                                net::CERT_STATUS_DATE_INVALID,
    284                                &expired_previous_decision));
    285   EXPECT_TRUE(expired_previous_decision);
    286 
    287   // However, with a new query, it should indicate that no new expiration has
    288   // occurred.
    289   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    290             state->QueryPolicy(kWWWGoogleHost,
    291                                *google_cert.get(),
    292                                net::CERT_STATUS_DATE_INVALID,
    293                                &expired_previous_decision));
    294   EXPECT_FALSE(expired_previous_decision);
    295 }
    296 
    297 // Tests the basic behavior of cert memory in incognito.
    298 class IncognitoSSLHostStateDelegateTest
    299     : public ChromeSSLHostStateDelegateTest {
    300  protected:
    301   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    302     ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
    303     command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
    304                                     kDeltaSecondsString);
    305   }
    306 };
    307 
    308 IN_PROC_BROWSER_TEST_F(IncognitoSSLHostStateDelegateTest, PRE_AfterRestart) {
    309   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    310   content::WebContents* tab =
    311       browser()->tab_strip_model()->GetActiveWebContents();
    312   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    313   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    314   bool unused_value;
    315 
    316   // Add a cert exception to the profile and then verify that it still exists
    317   // in the incognito profile.
    318   state->AllowCert(
    319       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    320 
    321   scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
    322   content::SSLHostStateDelegate* incognito_state =
    323       incognito->GetSSLHostStateDelegate();
    324 
    325   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    326             incognito_state->QueryPolicy(kWWWGoogleHost,
    327                                          *google_cert.get(),
    328                                          net::CERT_STATUS_DATE_INVALID,
    329                                          &unused_value));
    330 
    331   // Add a cert exception to the incognito profile. It will be checked after
    332   // restart that this exception does not exist. Note the different cert URL and
    333   // error than above thus mapping to a second exception. Also validate that it
    334   // was not added as an exception to the regular profile.
    335   incognito_state->AllowCert(
    336       kGoogleHost, *google_cert.get(), net::CERT_STATUS_COMMON_NAME_INVALID);
    337 
    338   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    339             state->QueryPolicy(kGoogleHost,
    340                                *google_cert.get(),
    341                                net::CERT_STATUS_COMMON_NAME_INVALID,
    342                                &unused_value));
    343 }
    344 
    345 // AfterRestart ensures that any cert decisions made in an incognito profile are
    346 // forgetten after a session restart even if given a command line flag to
    347 // remember cert decisions after restart.
    348 IN_PROC_BROWSER_TEST_F(IncognitoSSLHostStateDelegateTest, AfterRestart) {
    349   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    350   content::WebContents* tab =
    351       browser()->tab_strip_model()->GetActiveWebContents();
    352   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    353   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    354   bool unused_value;
    355 
    356   // Verify that the exception added before restart to the regular
    357   // (non-incognito) profile still exists and was not cleared after the
    358   // incognito session ended.
    359   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    360             state->QueryPolicy(kWWWGoogleHost,
    361                                *google_cert.get(),
    362                                net::CERT_STATUS_DATE_INVALID,
    363                                &unused_value));
    364 
    365   scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
    366   content::SSLHostStateDelegate* incognito_state =
    367       incognito->GetSSLHostStateDelegate();
    368 
    369   // Verify that the exception added before restart to the incognito profile was
    370   // cleared when the incognito session ended.
    371   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    372             incognito_state->QueryPolicy(kGoogleHost,
    373                                          *google_cert.get(),
    374                                          net::CERT_STATUS_COMMON_NAME_INVALID,
    375                                          &unused_value));
    376 }
    377 
    378 // Tests to make sure that if the remember value is set to -1, any decisions
    379 // won't be remembered over a restart.
    380 class ForGetSSLHostStateDelegateTest : public ChromeSSLHostStateDelegateTest {
    381  protected:
    382   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    383     ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
    384     command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
    385                                     kForgetAtSessionEnd);
    386   }
    387 };
    388 
    389 IN_PROC_BROWSER_TEST_F(ForGetSSLHostStateDelegateTest, PRE_AfterRestart) {
    390   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    391   content::WebContents* tab =
    392       browser()->tab_strip_model()->GetActiveWebContents();
    393   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    394   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    395   bool unused_value;
    396 
    397   state->AllowCert(
    398       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    399   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    400             state->QueryPolicy(kWWWGoogleHost,
    401                                *google_cert.get(),
    402                                net::CERT_STATUS_DATE_INVALID,
    403                                &unused_value));
    404 }
    405 
    406 IN_PROC_BROWSER_TEST_F(ForGetSSLHostStateDelegateTest, AfterRestart) {
    407   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    408   content::WebContents* tab =
    409       browser()->tab_strip_model()->GetActiveWebContents();
    410   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    411   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    412   bool unused_value;
    413 
    414   // The cert should now be |DENIED| because the profile is set to forget cert
    415   // exceptions after session end.
    416   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    417             state->QueryPolicy(kWWWGoogleHost,
    418                                *google_cert.get(),
    419                                net::CERT_STATUS_DATE_INVALID,
    420                                &unused_value));
    421 }
    422 
    423 // Tests to make sure that if the remember value is set to 0, any decisions made
    424 // will be forgetten immediately.
    425 class ForgetInstantlySSLHostStateDelegateTest
    426     : public ChromeSSLHostStateDelegateTest {
    427  protected:
    428   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    429     ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
    430     command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
    431                                     kForgetInstantly);
    432   }
    433 };
    434 
    435 IN_PROC_BROWSER_TEST_F(ForgetInstantlySSLHostStateDelegateTest,
    436                        MakeAndForgetException) {
    437   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    438   content::WebContents* tab =
    439       browser()->tab_strip_model()->GetActiveWebContents();
    440   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    441   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    442   bool unused_value;
    443 
    444   // chrome_state takes ownership of this clock
    445   base::SimpleTestClock* clock = new base::SimpleTestClock();
    446   ChromeSSLHostStateDelegate* chrome_state =
    447       static_cast<ChromeSSLHostStateDelegate*>(state);
    448   chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
    449 
    450   // Start the clock at standard system time but do not advance at all to
    451   // emphasize that instant forget works.
    452   clock->SetNow(base::Time::NowFromSystemTime());
    453 
    454   state->AllowCert(
    455       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    456   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    457             state->QueryPolicy(kWWWGoogleHost,
    458                                *google_cert.get(),
    459                                net::CERT_STATUS_DATE_INVALID,
    460                                &unused_value));
    461 }
    462 
    463 // Tests to make sure that if the remember value is set to a non-zero value,
    464 // any decisions will be remembered over a restart, but only for the length
    465 // specified.
    466 class RememberSSLHostStateDelegateTest : public ChromeSSLHostStateDelegateTest {
    467  protected:
    468   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    469     ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
    470     command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
    471                                     kDeltaSecondsString);
    472   }
    473 };
    474 
    475 IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDelegateTest, PRE_AfterRestart) {
    476   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    477   content::WebContents* tab =
    478       browser()->tab_strip_model()->GetActiveWebContents();
    479   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    480   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    481   bool unused_value;
    482 
    483   state->AllowCert(
    484       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    485   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    486             state->QueryPolicy(kWWWGoogleHost,
    487                                *google_cert.get(),
    488                                net::CERT_STATUS_DATE_INVALID,
    489                                &unused_value));
    490 }
    491 
    492 IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDelegateTest, AfterRestart) {
    493   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    494   content::WebContents* tab =
    495       browser()->tab_strip_model()->GetActiveWebContents();
    496   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    497   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    498   bool unused_value;
    499 
    500   // chrome_state takes ownership of this clock
    501   base::SimpleTestClock* clock = new base::SimpleTestClock();
    502   ChromeSSLHostStateDelegate* chrome_state =
    503       static_cast<ChromeSSLHostStateDelegate*>(state);
    504   chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
    505 
    506   // Start the clock at standard system time.
    507   clock->SetNow(base::Time::NowFromSystemTime());
    508 
    509   // This should only pass if the cert was allowed before the test was restart
    510   // and thus has now been rememebered across browser restarts.
    511   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    512             state->QueryPolicy(kWWWGoogleHost,
    513                                *google_cert.get(),
    514                                net::CERT_STATUS_DATE_INVALID,
    515                                &unused_value));
    516 
    517   // Simulate the clock advancing by the specified delta.
    518   clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
    519 
    520   // The cert should now be |DENIED| because the specified delta has passed.
    521   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    522             state->QueryPolicy(kWWWGoogleHost,
    523                                *google_cert.get(),
    524                                net::CERT_STATUS_DATE_INVALID,
    525                                &unused_value));
    526 }
    527 
    528 // The same test as ChromeSSLHostStateDelegateTest.QueryPolicyExpired but now
    529 // applied to a browser context that expires based on time, not restart. This
    530 // unit tests to make sure that if a certificate decision has expired, the
    531 // return value from QueryPolicy returns the correct vaule.
    532 IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDelegateTest, QueryPolicyExpired) {
    533   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    534   content::WebContents* tab =
    535       browser()->tab_strip_model()->GetActiveWebContents();
    536   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    537   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    538   bool expired_previous_decision;
    539 
    540   // chrome_state takes ownership of this clock
    541   base::SimpleTestClock* clock = new base::SimpleTestClock();
    542   ChromeSSLHostStateDelegate* chrome_state =
    543       static_cast<ChromeSSLHostStateDelegate*>(state);
    544   chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
    545 
    546   // Start the clock at standard system time but do not advance at all to
    547   // emphasize that instant forget works.
    548   clock->SetNow(base::Time::NowFromSystemTime());
    549 
    550   // The certificate has never been seen before, so it should be UNKONWN and
    551   // should also indicate that it hasn't expired.
    552   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    553             state->QueryPolicy(kWWWGoogleHost,
    554                                *google_cert.get(),
    555                                net::CERT_STATUS_DATE_INVALID,
    556                                &expired_previous_decision));
    557   EXPECT_FALSE(expired_previous_decision);
    558 
    559   // After allowing the certificate, a query should say that it is allowed and
    560   // also specify that it hasn't expired.
    561   state->AllowCert(
    562       kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    563   EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
    564             state->QueryPolicy(kWWWGoogleHost,
    565                                *google_cert.get(),
    566                                net::CERT_STATUS_DATE_INVALID,
    567                                &expired_previous_decision));
    568   EXPECT_FALSE(expired_previous_decision);
    569 
    570   // Simulate the clock advancing by the specified delta.
    571   clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
    572 
    573   // The decision expiration time has come, so it should indicate that the
    574   // certificate and error are DENIED but also that they expired since the last
    575   // query.
    576   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    577             state->QueryPolicy(kWWWGoogleHost,
    578                                *google_cert.get(),
    579                                net::CERT_STATUS_DATE_INVALID,
    580                                &expired_previous_decision));
    581   EXPECT_TRUE(expired_previous_decision);
    582 
    583   // However, with a new query, it should indicate that no new expiration has
    584   // occurred.
    585   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    586             state->QueryPolicy(kWWWGoogleHost,
    587                                *google_cert.get(),
    588                                net::CERT_STATUS_DATE_INVALID,
    589                                &expired_previous_decision));
    590   EXPECT_FALSE(expired_previous_decision);
    591 }
    592 
    593 // Tests to make sure that if the user deletes their browser history, SSL
    594 // exceptions will be deleted as well.
    595 class RemoveBrowsingHistorySSLHostStateDelegateTest
    596     : public ChromeSSLHostStateDelegateTest {
    597  public:
    598   void RemoveAndWait(Profile* profile) {
    599     BrowsingDataRemover* remover = BrowsingDataRemover::CreateForPeriod(
    600         profile, BrowsingDataRemover::LAST_HOUR);
    601     BrowsingDataRemoverCompletionObserver completion_observer(remover);
    602     remover->Remove(BrowsingDataRemover::REMOVE_HISTORY,
    603                     BrowsingDataHelper::UNPROTECTED_WEB);
    604     completion_observer.BlockUntilCompletion();
    605   }
    606 };
    607 
    608 IN_PROC_BROWSER_TEST_F(RemoveBrowsingHistorySSLHostStateDelegateTest,
    609                        DeleteHistory) {
    610   scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
    611   content::WebContents* tab =
    612       browser()->tab_strip_model()->GetActiveWebContents();
    613   Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
    614   content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
    615   bool unused_value;
    616 
    617   // Add an exception for an invalid certificate. Then remove the last hour's
    618   // worth of browsing history and verify that the exception has been deleted.
    619   state->AllowCert(
    620       kGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
    621   RemoveAndWait(profile);
    622   EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
    623             state->QueryPolicy(kGoogleHost,
    624                                *google_cert.get(),
    625                                net::CERT_STATUS_DATE_INVALID,
    626                                &unused_value));
    627 }
    628