blob: 82e307ce7e5920b7a6831510ade234a32e0938fa [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
#include <stdint.h>
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/simple_test_clock.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "net/base/test_data_directory.h"
#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char kGoogleCertFile[] = "google.single.der";
const char kWWWGoogleHost[] = "www.google.com";
const char kGoogleHost[] = "google.com";
const char kExampleHost[] = "example.com";
const char kForgetAtSessionEnd[] = "-1";
const char kForgetInstantly[] = "0";
const char kDeltaSecondsString[] = "86400";
const uint64_t kDeltaOneDayInSeconds = UINT64_C(86400);
scoped_refptr<net::X509Certificate> GetGoogleCert() {
return net::ImportCertFromFile(net::GetTestCertsDirectory(), kGoogleCertFile);
}
} // namespace
class ChromeSSLHostStateDelegateTest : public InProcessBrowserTest {};
// ChromeSSLHostStateDelegateTest tests basic unit test functionality of the
// SSLHostStateDelegate class. For example, tests that if a certificate is
// accepted, then it is added to queryable, and if it is revoked, it is not
// queryable. Even though it is effectively a unit test, in needs to be an
// InProcessBrowserTest because the actual functionality is provided by
// ChromeSSLHostStateDelegate which is provided per-profile.
//
// QueryPolicy unit tests the expected behavior of calling QueryPolicy on the
// SSLHostStateDelegate class after various SSL cert decisions have been made.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, QueryPolicy) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// Verifying that all three of the certs we will be looking at are denied
// before any action has been taken.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kExampleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
// Simulate a user decision to allow an invalid certificate exception for
// kWWWGoogleHost.
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
// Verify that only kWWWGoogleHost is allowed and that the other two certs
// being tested still are denied.
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kExampleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
// Simulate a user decision to allow an invalid certificate exception for
// kExampleHost.
state->AllowCert(
kExampleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
// Verify that both kWWWGoogleHost and kExampleHost have allow exceptions
// while kGoogleHost still is denied.
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kExampleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
// HasPolicyAndRevoke unit tests the expected behavior of calling
// HasAllowException before and after calling RevokeUserAllowExceptions on the
// SSLHostStateDelegate class.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, HasPolicyAndRevoke) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
ChromeSSLHostStateDelegate* state =
ChromeSSLHostStateDelegateFactory::GetForProfile(profile);
bool unused_value;
// Simulate a user decision to allow an invalid certificate exception for
// kWWWGoogleHost and for kExampleHost.
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
state->AllowCert(
kExampleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
// Verify that HasAllowException correctly acknowledges that a user decision
// has been made about kWWWGoogleHost. Then verify that HasAllowException
// correctly identifies that the decision has been revoked.
EXPECT_TRUE(state->HasAllowException(kWWWGoogleHost));
state->RevokeUserAllowExceptions(kWWWGoogleHost);
EXPECT_FALSE(state->HasAllowException(kWWWGoogleHost));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
// Verify that the revocation of the kWWWGoogleHost decision does not affect
// the Allow for kExampleHost.
EXPECT_TRUE(state->HasAllowException(kExampleHost));
// Verify the revocation of the kWWWGoogleHost decision does not affect the
// non-decision for kGoogleHost. Then verify that a revocation of a URL with
// no decision has no effect.
EXPECT_FALSE(state->HasAllowException(kGoogleHost));
state->RevokeUserAllowExceptions(kGoogleHost);
EXPECT_FALSE(state->HasAllowException(kGoogleHost));
}
// Clear unit tests the expected behavior of calling Clear to forget all cert
// decision state on the SSLHostStateDelegate class.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, Clear) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
ChromeSSLHostStateDelegate* state =
ChromeSSLHostStateDelegateFactory::GetForProfile(profile);
bool unused_value;
// Simulate a user decision to allow an invalid certificate exception for
// kWWWGoogleHost and for kExampleHost.
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
// Do a full clear, then make sure that both kWWWGoogleHost, which had a
// decision made, and kExampleHost, which was untouched, are now in a denied
// state.
state->Clear();
EXPECT_FALSE(state->HasAllowException(kWWWGoogleHost));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
EXPECT_FALSE(state->HasAllowException(kExampleHost));
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kExampleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
// DidHostRunInsecureContent unit tests the expected behavior of calling
// DidHostRunInsecureContent as well as HostRanInsecureContent to check if
// insecure content has been run and to mark it as such.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest,
DidHostRunInsecureContent) {
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 42));
EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 191));
EXPECT_FALSE(state->DidHostRunInsecureContent("example.com", 42));
state->HostRanInsecureContent("www.google.com", 42);
EXPECT_TRUE(state->DidHostRunInsecureContent("www.google.com", 42));
EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 191));
EXPECT_FALSE(state->DidHostRunInsecureContent("example.com", 42));
state->HostRanInsecureContent("example.com", 42);
EXPECT_TRUE(state->DidHostRunInsecureContent("www.google.com", 42));
EXPECT_FALSE(state->DidHostRunInsecureContent("www.google.com", 191));
EXPECT_TRUE(state->DidHostRunInsecureContent("example.com", 42));
}
// QueryPolicyExpired unit tests to make sure that if a certificate decision has
// expired, the return value from QueryPolicy returns the correct vaule.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, PRE_QueryPolicyExpired) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool expired_previous_decision;
// The certificate has never been seen before, so it should be UNKNOWN and
// should also indicate that it hasn't expired.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_FALSE(expired_previous_decision);
// After allowing the certificate, a query should say that it is allowed and
// also specify that it hasn't expired.
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_FALSE(expired_previous_decision);
}
// Since this is being checked on a browser instance that expires security
// decisions after restart, the test needs to wait until after a restart to
// verify that the expiration state is correct.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, QueryPolicyExpired) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool expired_previous_decision;
// The browser content has restart thus expiring the user decision made above,
// so it should indicate that the certificate and error are DENIED but also
// that they expired since the last query.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_TRUE(expired_previous_decision);
// However, with a new query, it should indicate that no new expiration has
// occurred.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_FALSE(expired_previous_decision);
}
// Tests the basic behavior of cert memory in incognito.
class IncognitoSSLHostStateDelegateTest
: public ChromeSSLHostStateDelegateTest {
protected:
void SetUpCommandLine(CommandLine* command_line) override {
ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
kDeltaSecondsString);
}
};
IN_PROC_BROWSER_TEST_F(IncognitoSSLHostStateDelegateTest, PRE_AfterRestart) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// Add a cert exception to the profile and then verify that it still exists
// in the incognito profile.
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
content::SSLHostStateDelegate* incognito_state =
incognito->GetSSLHostStateDelegate();
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
incognito_state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
// Add a cert exception to the incognito profile. It will be checked after
// restart that this exception does not exist. Note the different cert URL and
// error than above thus mapping to a second exception. Also validate that it
// was not added as an exception to the regular profile.
incognito_state->AllowCert(
kGoogleHost, *google_cert.get(), net::CERT_STATUS_COMMON_NAME_INVALID);
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kGoogleHost,
*google_cert.get(),
net::CERT_STATUS_COMMON_NAME_INVALID,
&unused_value));
}
// AfterRestart ensures that any cert decisions made in an incognito profile are
// forgetten after a session restart even if given a command line flag to
// remember cert decisions after restart.
IN_PROC_BROWSER_TEST_F(IncognitoSSLHostStateDelegateTest, AfterRestart) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// Verify that the exception added before restart to the regular
// (non-incognito) profile still exists and was not cleared after the
// incognito session ended.
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
scoped_ptr<Profile> incognito(profile->CreateOffTheRecordProfile());
content::SSLHostStateDelegate* incognito_state =
incognito->GetSSLHostStateDelegate();
// Verify that the exception added before restart to the incognito profile was
// cleared when the incognito session ended.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
incognito_state->QueryPolicy(kGoogleHost,
*google_cert.get(),
net::CERT_STATUS_COMMON_NAME_INVALID,
&unused_value));
}
// Tests to make sure that if the remember value is set to -1, any decisions
// won't be remembered over a restart.
class ForGetSSLHostStateDelegateTest : public ChromeSSLHostStateDelegateTest {
protected:
void SetUpCommandLine(CommandLine* command_line) override {
ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
kForgetAtSessionEnd);
}
};
IN_PROC_BROWSER_TEST_F(ForGetSSLHostStateDelegateTest, PRE_AfterRestart) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
IN_PROC_BROWSER_TEST_F(ForGetSSLHostStateDelegateTest, AfterRestart) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// The cert should now be |DENIED| because the profile is set to forget cert
// exceptions after session end.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
// Tests to make sure that if the remember value is set to 0, any decisions made
// will be forgetten immediately.
class ForgetInstantlySSLHostStateDelegateTest
: public ChromeSSLHostStateDelegateTest {
protected:
void SetUpCommandLine(CommandLine* command_line) override {
ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
kForgetInstantly);
}
};
IN_PROC_BROWSER_TEST_F(ForgetInstantlySSLHostStateDelegateTest,
MakeAndForgetException) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// chrome_state takes ownership of this clock
base::SimpleTestClock* clock = new base::SimpleTestClock();
ChromeSSLHostStateDelegate* chrome_state =
static_cast<ChromeSSLHostStateDelegate*>(state);
chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
// Start the clock at standard system time but do not advance at all to
// emphasize that instant forget works.
clock->SetNow(base::Time::NowFromSystemTime());
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
// Tests to make sure that if the remember value is set to a non-zero value,
// any decisions will be remembered over a restart, but only for the length
// specified.
class RememberSSLHostStateDelegateTest : public ChromeSSLHostStateDelegateTest {
protected:
void SetUpCommandLine(CommandLine* command_line) override {
ChromeSSLHostStateDelegateTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kRememberCertErrorDecisions,
kDeltaSecondsString);
}
};
IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDelegateTest, PRE_AfterRestart) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDelegateTest, AfterRestart) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// chrome_state takes ownership of this clock
base::SimpleTestClock* clock = new base::SimpleTestClock();
ChromeSSLHostStateDelegate* chrome_state =
static_cast<ChromeSSLHostStateDelegate*>(state);
chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
// Start the clock at standard system time.
clock->SetNow(base::Time::NowFromSystemTime());
// This should only pass if the cert was allowed before the test was restart
// and thus has now been rememebered across browser restarts.
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
// Simulate the clock advancing by the specified delta.
clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
// The cert should now be |DENIED| because the specified delta has passed.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}
// The same test as ChromeSSLHostStateDelegateTest.QueryPolicyExpired but now
// applied to a browser context that expires based on time, not restart. This
// unit tests to make sure that if a certificate decision has expired, the
// return value from QueryPolicy returns the correct vaule.
IN_PROC_BROWSER_TEST_F(RememberSSLHostStateDelegateTest, QueryPolicyExpired) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool expired_previous_decision;
// chrome_state takes ownership of this clock
base::SimpleTestClock* clock = new base::SimpleTestClock();
ChromeSSLHostStateDelegate* chrome_state =
static_cast<ChromeSSLHostStateDelegate*>(state);
chrome_state->SetClock(scoped_ptr<base::Clock>(clock));
// Start the clock at standard system time but do not advance at all to
// emphasize that instant forget works.
clock->SetNow(base::Time::NowFromSystemTime());
// The certificate has never been seen before, so it should be UNKONWN and
// should also indicate that it hasn't expired.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_FALSE(expired_previous_decision);
// After allowing the certificate, a query should say that it is allowed and
// also specify that it hasn't expired.
state->AllowCert(
kWWWGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
EXPECT_EQ(content::SSLHostStateDelegate::ALLOWED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_FALSE(expired_previous_decision);
// Simulate the clock advancing by the specified delta.
clock->Advance(base::TimeDelta::FromSeconds(kDeltaOneDayInSeconds + 1));
// The decision expiration time has come, so it should indicate that the
// certificate and error are DENIED but also that they expired since the last
// query.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_TRUE(expired_previous_decision);
// However, with a new query, it should indicate that no new expiration has
// occurred.
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kWWWGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&expired_previous_decision));
EXPECT_FALSE(expired_previous_decision);
}
// Tests to make sure that if the user deletes their browser history, SSL
// exceptions will be deleted as well.
class RemoveBrowsingHistorySSLHostStateDelegateTest
: public ChromeSSLHostStateDelegateTest {
public:
void RemoveAndWait(Profile* profile) {
BrowsingDataRemover* remover = BrowsingDataRemover::CreateForPeriod(
profile, BrowsingDataRemover::LAST_HOUR);
BrowsingDataRemoverCompletionObserver completion_observer(remover);
remover->Remove(BrowsingDataRemover::REMOVE_HISTORY,
BrowsingDataHelper::UNPROTECTED_WEB);
completion_observer.BlockUntilCompletion();
}
};
IN_PROC_BROWSER_TEST_F(RemoveBrowsingHistorySSLHostStateDelegateTest,
DeleteHistory) {
scoped_refptr<net::X509Certificate> google_cert = GetGoogleCert();
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
bool unused_value;
// Add an exception for an invalid certificate. Then remove the last hour's
// worth of browsing history and verify that the exception has been deleted.
state->AllowCert(
kGoogleHost, *google_cert.get(), net::CERT_STATUS_DATE_INVALID);
RemoveAndWait(profile);
EXPECT_EQ(content::SSLHostStateDelegate::DENIED,
state->QueryPolicy(kGoogleHost,
*google_cert.get(),
net::CERT_STATUS_DATE_INVALID,
&unused_value));
}