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.
5 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
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"
30 const char kGoogleCertFile[] = "google.single.der";
32 const char kWWWGoogleHost[] = "www.google.com";
33 const char kGoogleHost[] = "google.com";
34 const char kExampleHost[] = "example.com";
36 const char kForgetAtSessionEnd[] = "-1";
37 const char kForgetInstantly[] = "0";
38 const char kDeltaSecondsString[] = "86400";
39 const uint64_t kDeltaOneDayInSeconds = UINT64_C(86400);
41 scoped_refptr<net::X509Certificate> GetGoogleCert() {
42 return net::ImportCertFromFile(net::GetTestCertsDirectory(), kGoogleCertFile);
47 class ChromeSSLHostStateDelegateTest : public InProcessBrowserTest {};
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.
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();
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,
71 net::CERT_STATUS_DATE_INVALID,
73 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
74 state->QueryPolicy(kGoogleHost,
76 net::CERT_STATUS_DATE_INVALID,
78 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
79 state->QueryPolicy(kExampleHost,
81 net::CERT_STATUS_DATE_INVALID,
84 // Simulate a user decision to allow an invalid certificate exception for
87 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
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,
94 net::CERT_STATUS_DATE_INVALID,
96 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
97 state->QueryPolicy(kGoogleHost,
99 net::CERT_STATUS_DATE_INVALID,
101 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
102 state->QueryPolicy(kExampleHost,
104 net::CERT_STATUS_DATE_INVALID,
107 // Simulate a user decision to allow an invalid certificate exception for
110 kExampleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
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,
117 net::CERT_STATUS_DATE_INVALID,
119 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
120 state->QueryPolicy(kGoogleHost,
122 net::CERT_STATUS_DATE_INVALID,
124 EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
125 state->QueryPolicy(kExampleHost,
127 net::CERT_STATUS_DATE_INVALID,
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);
143 // Simulate a user decision to allow an invalid certificate exception for
144 // kWWWGoogleHost and for kExampleHost.
146 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
148 kExampleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
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,
159 net::CERT_STATUS_DATE_INVALID,
162 // Verify that the revocation of the kWWWGoogleHost decision does not affect
163 // the Allow for kExampleHost.
164 EXPECT_TRUE(state->HasAllowException(kExampleHost));
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));
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);
185 // Simulate a user decision to allow an invalid certificate exception for
186 // kWWWGoogleHost and for kExampleHost.
188 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
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
194 EXPECT_FALSE(state->HasAllowException(kWWWGoogleHost));
195 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
196 state->QueryPolicy(kWWWGoogleHost,
198 net::CERT_STATUS_DATE_INVALID,
200 EXPECT_FALSE(state->HasAllowException(kExampleHost));
201 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
202 state->QueryPolicy(kExampleHost,
204 net::CERT_STATUS_DATE_INVALID,
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();
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));
222 state->HostRanInsecureContent("www.google.com", 42);
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));
228 state->HostRanInsecureContent("example.com", 42);
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));
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;
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,
250 net::CERT_STATUS_DATE_INVALID,
251 &expired_previous_decision));
252 EXPECT_FALSE(expired_previous_decision);
254 // After allowing the certificate, a query should say that it is allowed and
255 // also specify that it hasn't expired.
257 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
258 EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
259 state->QueryPolicy(kWWWGoogleHost,
261 net::CERT_STATUS_DATE_INVALID,
262 &expired_previous_decision));
263 EXPECT_FALSE(expired_previous_decision);
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;
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,
283 net::CERT_STATUS_DATE_INVALID,
284 &expired_previous_decision));
285 EXPECT_TRUE(expired_previous_decision);
287 // However, with a new query, it should indicate that no new expiration has
289 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
290 state->QueryPolicy(kWWWGoogleHost,
292 net::CERT_STATUS_DATE_INVALID,
293 &expired_previous_decision));
294 EXPECT_FALSE(expired_previous_decision);
297 // Tests the basic behavior of cert memory in incognito.
298 class IncognitoSSLHostStateDelegateTest
299 : public ChromeSSLHostStateDelegateTest {
301 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
302 ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
303 command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
304 kDeltaSecondsString);
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();
316 // Add a cert exception to the profile and then verify that it still exists
317 // in the incognito profile.
319 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
321 scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
322 content::SSLHostStateDelegate* incognito_state =
323 incognito->GetSSLHostStateDelegate();
325 EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
326 incognito_state->QueryPolicy(kWWWGoogleHost,
328 net::CERT_STATUS_DATE_INVALID,
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);
338 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
339 state->QueryPolicy(kGoogleHost,
341 net::CERT_STATUS_COMMON_NAME_INVALID,
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();
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,
362 net::CERT_STATUS_DATE_INVALID,
365 scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
366 content::SSLHostStateDelegate* incognito_state =
367 incognito->GetSSLHostStateDelegate();
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,
374 net::CERT_STATUS_COMMON_NAME_INVALID,
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 {
382 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
383 ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
384 command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
385 kForgetAtSessionEnd);
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();
398 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
399 EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
400 state->QueryPolicy(kWWWGoogleHost,
402 net::CERT_STATUS_DATE_INVALID,
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();
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,
419 net::CERT_STATUS_DATE_INVALID,
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 {
428 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
429 ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
430 command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
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();
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));
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());
455 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
456 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
457 state->QueryPolicy(kWWWGoogleHost,
459 net::CERT_STATUS_DATE_INVALID,
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
466 class RememberSSLHostStateDelegateTest : public ChromeSSLHostStateDelegateTest {
468 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
469 ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
470 command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
471 kDeltaSecondsString);
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();
484 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
485 EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
486 state->QueryPolicy(kWWWGoogleHost,
488 net::CERT_STATUS_DATE_INVALID,
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();
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));
506 // Start the clock at standard system time.
507 clock->SetNow(base::Time::NowFromSystemTime());
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,
514 net::CERT_STATUS_DATE_INVALID,
517 // Simulate the clock advancing by the specified delta.
518 clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
520 // The cert should now be |DENIED| because the specified delta has passed.
521 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
522 state->QueryPolicy(kWWWGoogleHost,
524 net::CERT_STATUS_DATE_INVALID,
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;
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));
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());
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,
555 net::CERT_STATUS_DATE_INVALID,
556 &expired_previous_decision));
557 EXPECT_FALSE(expired_previous_decision);
559 // After allowing the certificate, a query should say that it is allowed and
560 // also specify that it hasn't expired.
562 kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
563 EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
564 state->QueryPolicy(kWWWGoogleHost,
566 net::CERT_STATUS_DATE_INVALID,
567 &expired_previous_decision));
568 EXPECT_FALSE(expired_previous_decision);
570 // Simulate the clock advancing by the specified delta.
571 clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
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
576 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
577 state->QueryPolicy(kWWWGoogleHost,
579 net::CERT_STATUS_DATE_INVALID,
580 &expired_previous_decision));
581 EXPECT_TRUE(expired_previous_decision);
583 // However, with a new query, it should indicate that no new expiration has
585 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
586 state->QueryPolicy(kWWWGoogleHost,
588 net::CERT_STATUS_DATE_INVALID,
589 &expired_previous_decision));
590 EXPECT_FALSE(expired_previous_decision);
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 {
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();
608 IN_PROC_BROWSER_TEST_F(RemoveBrowsingHistorySSLHostStateDelegateTest,
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();
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.
620 kGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
621 RemoveAndWait(profile);
622 EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
623 state->QueryPolicy(kGoogleHost,
625 net::CERT_STATUS_DATE_INVALID,