chrome_ssl_host_state_delegate_test.cc revision 34680572440d7894ef8dafce81d8039ed80726a2
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
28namespace {
29
30const char kGoogleCertFile[] = "google.single.der";
31
32const char kWWWGoogleHost[] = "www.google.com";
33const char kGoogleHost[] = "google.com";
34const char kExampleHost[] = "example.com";
35
36const char kForgetAtSessionEnd[] = "-1";
37const char kForgetInstantly[] = "0";
38const char kDeltaSecondsString[] = "86400";
39const uint64_t kDeltaOneDayInSeconds = UINT64_C(86400);
40
41scoped_refptr<net::X509Certificate> GetGoogleCert() {
42  return net::ImportCertFromFile(net::GetTestCertsDirectory(), kGoogleCertFile);
43}
44
45}  // namespace
46
47class 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.
58IN_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.
134IN_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.
176IN_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.
211IN_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.
237IN_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.
269IN_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.
298class 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
308IN_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.
348IN_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.
380class 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
389IN_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
406IN_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.
425class 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
435IN_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.
466class 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
475IN_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
492IN_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.
532IN_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.
595class 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
608IN_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