Fix infinite recursion on hiding panel when created during fullscreen mode.
[chromium-blink-merge.git] / chrome / browser / chromeos / attestation / platform_verification_flow_unittest.cc
bloba9c97dd62960e788798cd59bfc3ca91e26b5f516
1 // Copyright 2013 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 <string>
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h"
11 #include "chrome/browser/chromeos/attestation/fake_certificate.h"
12 #include "chrome/browser/chromeos/attestation/platform_verification_flow.h"
13 #include "chrome/browser/chromeos/login/mock_user_manager.h"
14 #include "chrome/browser/chromeos/settings/cros_settings.h"
15 #include "chrome/browser/chromeos/settings/device_settings_service.h"
16 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
17 #include "chrome/browser/content_settings/host_content_settings_map.h"
18 #include "chrome/browser/profiles/profile_impl.h"
19 #include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
20 #include "chrome/common/content_settings_pattern.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/base/testing_pref_service_syncable.h"
23 #include "chromeos/attestation/mock_attestation_flow.h"
24 #include "chromeos/cryptohome/mock_async_method_caller.h"
25 #include "chromeos/dbus/fake_cryptohome_client.h"
26 #include "chromeos/settings/cros_settings_names.h"
27 #include "content/public/test/test_browser_thread.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 using testing::_;
31 using testing::DoAll;
32 using testing::Invoke;
33 using testing::Return;
34 using testing::SetArgumentPointee;
35 using testing::StrictMock;
36 using testing::WithArgs;
38 namespace chromeos {
39 namespace attestation {
41 namespace {
43 const char kTestID[] = "test_id";
44 const char kTestChallenge[] = "test_challenge";
45 const char kTestSignedData[] = "test_challenge_with_salt";
46 const char kTestSignature[] = "test_signature";
47 const char kTestCertificate[] = "test_certificate";
48 const char kTestEmail[] = "test_email@chromium.org";
49 const char kTestURL[] = "http://mytestdomain/test";
50 const char kTestURLSecure[] = "https://mytestdomain/test";
51 const char kTestURLExtension[] = "chrome-extension://mytestextension";
53 class FakeDelegate : public PlatformVerificationFlow::Delegate {
54 public:
55 FakeDelegate() : response_(PlatformVerificationFlow::CONSENT_RESPONSE_ALLOW),
56 num_consent_calls_(0),
57 url_(kTestURL),
58 is_incognito_(false) {
59 // Configure a user for the mock user manager.
60 mock_user_manager_.SetActiveUser(kTestEmail);
62 virtual ~FakeDelegate() {}
64 void SetUp() {
65 ProfileImpl::RegisterProfilePrefs(pref_service_.registry());
66 chrome::DeviceIDFetcher::RegisterProfilePrefs(pref_service_.registry());
67 PlatformVerificationFlow::RegisterProfilePrefs(pref_service_.registry());
68 HostContentSettingsMap::RegisterProfilePrefs(pref_service_.registry());
69 content_settings_ = new HostContentSettingsMap(&pref_service_, false);
72 void TearDown() {
73 content_settings_->ShutdownOnUIThread();
76 virtual void ShowConsentPrompt(
77 content::WebContents* web_contents,
78 const PlatformVerificationFlow::Delegate::ConsentCallback& callback)
79 OVERRIDE {
80 num_consent_calls_++;
81 callback.Run(response_);
84 virtual PrefService* GetPrefs(content::WebContents* web_contents) OVERRIDE {
85 return &pref_service_;
88 virtual const GURL& GetURL(content::WebContents* web_contents) OVERRIDE {
89 return url_;
92 virtual User* GetUser(content::WebContents* web_contents) OVERRIDE {
93 return mock_user_manager_.GetActiveUser();
96 virtual HostContentSettingsMap* GetContentSettings(
97 content::WebContents* web_contents) OVERRIDE {
98 return content_settings_;
101 virtual bool IsGuestOrIncognito(content::WebContents* web_contents) OVERRIDE {
102 return is_incognito_;
105 void set_response(PlatformVerificationFlow::ConsentResponse response) {
106 response_ = response;
109 int num_consent_calls() {
110 return num_consent_calls_;
113 TestingPrefServiceSyncable& pref_service() {
114 return pref_service_;
117 void set_url(const GURL& url) {
118 url_ = url;
121 void set_is_incognito(bool is_incognito) {
122 is_incognito_ = is_incognito;
125 private:
126 PlatformVerificationFlow::ConsentResponse response_;
127 int num_consent_calls_;
128 TestingPrefServiceSyncable pref_service_;
129 MockUserManager mock_user_manager_;
130 GURL url_;
131 scoped_refptr<HostContentSettingsMap> content_settings_;
132 bool is_incognito_;
134 DISALLOW_COPY_AND_ASSIGN(FakeDelegate);
137 class CustomFakeCryptohomeClient : public FakeCryptohomeClient {
138 public:
139 CustomFakeCryptohomeClient() : call_status_(DBUS_METHOD_CALL_SUCCESS),
140 attestation_enrolled_(true),
141 attestation_prepared_(true) {}
142 virtual void TpmAttestationIsEnrolled(
143 const BoolDBusMethodCallback& callback) OVERRIDE {
144 base::MessageLoop::current()->PostTask(FROM_HERE,
145 base::Bind(callback,
146 call_status_,
147 attestation_enrolled_));
150 virtual void TpmAttestationIsPrepared(
151 const BoolDBusMethodCallback& callback) OVERRIDE {
152 base::MessageLoop::current()->PostTask(FROM_HERE,
153 base::Bind(callback,
154 call_status_,
155 attestation_prepared_));
158 void set_call_status(DBusMethodCallStatus call_status) {
159 call_status_ = call_status;
162 void set_attestation_enrolled(bool attestation_enrolled) {
163 attestation_enrolled_ = attestation_enrolled;
166 void set_attestation_prepared(bool attestation_prepared) {
167 attestation_prepared_ = attestation_prepared;
170 private:
171 DBusMethodCallStatus call_status_;
172 bool attestation_enrolled_;
173 bool attestation_prepared_;
176 } // namespace
178 class PlatformVerificationFlowTest : public ::testing::Test {
179 public:
180 PlatformVerificationFlowTest()
181 : ui_thread_(content::BrowserThread::UI, &message_loop_),
182 certificate_success_(true),
183 fake_certificate_index_(0),
184 sign_challenge_success_(true),
185 result_(PlatformVerificationFlow::INTERNAL_ERROR) {}
187 void SetUp() {
188 fake_delegate_.SetUp();
190 // Create a verifier for tests to call.
191 verifier_ = new PlatformVerificationFlow(&mock_attestation_flow_,
192 &mock_async_caller_,
193 &fake_cryptohome_client_,
194 &fake_delegate_);
196 // Create callbacks for tests to use with verifier_.
197 callback_ = base::Bind(&PlatformVerificationFlowTest::FakeChallengeCallback,
198 base::Unretained(this));
200 // Configure the global cros_settings.
201 CrosSettings* cros_settings = CrosSettings::Get();
202 device_settings_provider_ =
203 cros_settings->GetProvider(kAttestationForContentProtectionEnabled);
204 cros_settings->RemoveSettingsProvider(device_settings_provider_);
205 cros_settings->AddSettingsProvider(&stub_settings_provider_);
206 cros_settings->SetBoolean(kAttestationForContentProtectionEnabled, true);
208 // Start with the first-time setting set since most tests want this.
209 fake_delegate_.pref_service().SetUserPref(prefs::kRAConsentFirstTime,
210 new base::FundamentalValue(true));
214 void TearDown() {
215 // Restore the real DeviceSettingsProvider.
216 CrosSettings* cros_settings = CrosSettings::Get();
217 cros_settings->RemoveSettingsProvider(&stub_settings_provider_);
218 cros_settings->AddSettingsProvider(device_settings_provider_);
219 fake_delegate_.TearDown();
222 void ExpectAttestationFlow() {
223 // When consent is not given or the feature is disabled, it is important
224 // that there are no calls to the attestation service. Thus, a test must
225 // explicitly expect these calls or the mocks will fail the test.
227 // Configure the mock AttestationFlow to call FakeGetCertificate.
228 EXPECT_CALL(mock_attestation_flow_,
229 GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE,
230 kTestEmail, kTestID, _, _))
231 .WillRepeatedly(WithArgs<4>(Invoke(
232 this, &PlatformVerificationFlowTest::FakeGetCertificate)));
234 // Configure the mock AsyncMethodCaller to call FakeSignChallenge.
235 std::string expected_key_name = std::string(kContentProtectionKeyPrefix) +
236 std::string(kTestID);
237 EXPECT_CALL(mock_async_caller_,
238 TpmAttestationSignSimpleChallenge(KEY_USER, kTestEmail,
239 expected_key_name,
240 kTestChallenge, _))
241 .WillRepeatedly(WithArgs<4>(Invoke(
242 this, &PlatformVerificationFlowTest::FakeSignChallenge)));
245 void SetUserConsent(const GURL& url, bool allow) {
246 verifier_->RecordDomainConsent(fake_delegate_.GetContentSettings(NULL),
247 url,
248 allow);
251 void FakeGetCertificate(
252 const AttestationFlow::CertificateCallback& callback) {
253 std::string certificate =
254 (fake_certificate_index_ < fake_certificate_list_.size()) ?
255 fake_certificate_list_[fake_certificate_index_] : kTestCertificate;
256 base::MessageLoop::current()->PostTask(FROM_HERE,
257 base::Bind(callback,
258 certificate_success_,
259 certificate));
260 ++fake_certificate_index_;
263 void FakeSignChallenge(
264 const cryptohome::AsyncMethodCaller::DataCallback& callback) {
265 base::MessageLoop::current()->PostTask(
266 FROM_HERE,
267 base::Bind(callback,
268 sign_challenge_success_,
269 CreateFakeResponseProto()));
272 void FakeChallengeCallback(PlatformVerificationFlow::Result result,
273 const std::string& salt,
274 const std::string& signature,
275 const std::string& certificate) {
276 result_ = result;
277 challenge_salt_ = salt;
278 challenge_signature_ = signature;
279 certificate_ = certificate;
282 std::string CreateFakeResponseProto() {
283 SignedData pb;
284 pb.set_data(kTestSignedData);
285 pb.set_signature(kTestSignature);
286 std::string serial;
287 CHECK(pb.SerializeToString(&serial));
288 return serial;
291 protected:
292 base::MessageLoopForUI message_loop_;
293 content::TestBrowserThread ui_thread_;
294 StrictMock<MockAttestationFlow> mock_attestation_flow_;
295 cryptohome::MockAsyncMethodCaller mock_async_caller_;
296 CustomFakeCryptohomeClient fake_cryptohome_client_;
297 FakeDelegate fake_delegate_;
298 CrosSettingsProvider* device_settings_provider_;
299 StubCrosSettingsProvider stub_settings_provider_;
300 ScopedTestDeviceSettingsService test_device_settings_service_;
301 ScopedTestCrosSettings test_cros_settings_;
302 scoped_refptr<PlatformVerificationFlow> verifier_;
304 // Controls result of FakeGetCertificate.
305 bool certificate_success_;
306 std::vector<std::string> fake_certificate_list_;
307 size_t fake_certificate_index_;
309 // Controls result of FakeSignChallenge.
310 bool sign_challenge_success_;
312 // Callback functions and data.
313 PlatformVerificationFlow::ChallengeCallback callback_;
314 PlatformVerificationFlow::Result result_;
315 std::string challenge_salt_;
316 std::string challenge_signature_;
317 std::string certificate_;
320 TEST_F(PlatformVerificationFlowTest, SuccessNoConsent) {
321 SetUserConsent(GURL(kTestURL), true);
322 // Make sure the call will fail if consent is requested.
323 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY);
324 ExpectAttestationFlow();
325 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
326 base::RunLoop().RunUntilIdle();
327 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_);
328 EXPECT_EQ(kTestSignedData, challenge_salt_);
329 EXPECT_EQ(kTestSignature, challenge_signature_);
330 EXPECT_EQ(kTestCertificate, certificate_);
331 EXPECT_EQ(0, fake_delegate_.num_consent_calls());
334 TEST_F(PlatformVerificationFlowTest, SuccessWithAttestationConsent) {
335 SetUserConsent(GURL(kTestURL), true);
336 fake_cryptohome_client_.set_attestation_enrolled(false);
337 ExpectAttestationFlow();
338 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
339 base::RunLoop().RunUntilIdle();
340 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_);
341 EXPECT_EQ(kTestSignedData, challenge_salt_);
342 EXPECT_EQ(kTestSignature, challenge_signature_);
343 EXPECT_EQ(kTestCertificate, certificate_);
344 EXPECT_EQ(1, fake_delegate_.num_consent_calls());
347 TEST_F(PlatformVerificationFlowTest, SuccessWithFirstTimeConsent) {
348 SetUserConsent(GURL(kTestURL), true);
349 fake_delegate_.pref_service().SetUserPref(prefs::kRAConsentFirstTime,
350 new base::FundamentalValue(false));
351 ExpectAttestationFlow();
352 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
353 base::RunLoop().RunUntilIdle();
354 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_);
355 EXPECT_EQ(kTestSignedData, challenge_salt_);
356 EXPECT_EQ(kTestSignature, challenge_signature_);
357 EXPECT_EQ(kTestCertificate, certificate_);
358 EXPECT_EQ(1, fake_delegate_.num_consent_calls());
361 TEST_F(PlatformVerificationFlowTest, ConsentRejected) {
362 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY);
363 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
364 base::RunLoop().RunUntilIdle();
365 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_);
366 EXPECT_EQ(1, fake_delegate_.num_consent_calls());
369 TEST_F(PlatformVerificationFlowTest, FeatureDisabled) {
370 CrosSettings::Get()->SetBoolean(kAttestationForContentProtectionEnabled,
371 false);
372 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
373 base::RunLoop().RunUntilIdle();
374 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_);
375 EXPECT_EQ(0, fake_delegate_.num_consent_calls());
378 TEST_F(PlatformVerificationFlowTest, FeatureDisabledByUser) {
379 fake_delegate_.pref_service().SetUserPref(prefs::kEnableDRM,
380 new base::FundamentalValue(false));
381 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
382 base::RunLoop().RunUntilIdle();
383 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_);
384 EXPECT_EQ(0, fake_delegate_.num_consent_calls());
387 TEST_F(PlatformVerificationFlowTest, FeatureDisabledByUserForDomain) {
388 SetUserConsent(GURL(kTestURL), false);
389 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
390 base::RunLoop().RunUntilIdle();
391 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_);
392 EXPECT_EQ(0, fake_delegate_.num_consent_calls());
395 TEST_F(PlatformVerificationFlowTest, NotVerified) {
396 certificate_success_ = false;
397 ExpectAttestationFlow();
398 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
399 base::RunLoop().RunUntilIdle();
400 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_);
403 TEST_F(PlatformVerificationFlowTest, ChallengeSigningError) {
404 sign_challenge_success_ = false;
405 ExpectAttestationFlow();
406 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
407 base::RunLoop().RunUntilIdle();
408 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_);
411 TEST_F(PlatformVerificationFlowTest, DBusFailure) {
412 fake_cryptohome_client_.set_call_status(DBUS_METHOD_CALL_FAILURE);
413 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
414 base::RunLoop().RunUntilIdle();
415 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_);
418 TEST_F(PlatformVerificationFlowTest, ConsentNoResponse) {
419 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_NONE);
420 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
421 base::RunLoop().RunUntilIdle();
422 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_);
425 TEST_F(PlatformVerificationFlowTest, ConsentPerScheme) {
426 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY);
427 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
428 base::RunLoop().RunUntilIdle();
429 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_);
430 // Call again and expect denial based on previous response.
431 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
432 base::RunLoop().RunUntilIdle();
433 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_);
434 // Call with a different scheme and expect another consent prompt.
435 fake_delegate_.set_url(GURL(kTestURLSecure));
436 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
437 base::RunLoop().RunUntilIdle();
438 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_);
439 EXPECT_EQ(2, fake_delegate_.num_consent_calls());
442 TEST_F(PlatformVerificationFlowTest, ConsentForExtension) {
443 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY);
444 fake_delegate_.set_url(GURL(kTestURLExtension));
445 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
446 base::RunLoop().RunUntilIdle();
447 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_);
448 EXPECT_EQ(1, fake_delegate_.num_consent_calls());
451 TEST_F(PlatformVerificationFlowTest, Timeout) {
452 verifier_->set_timeout_delay(base::TimeDelta::FromSeconds(0));
453 ExpectAttestationFlow();
454 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
455 base::RunLoop().RunUntilIdle();
456 EXPECT_EQ(PlatformVerificationFlow::TIMEOUT, result_);
459 TEST_F(PlatformVerificationFlowTest, ExpiredCert) {
460 ExpectAttestationFlow();
461 fake_certificate_list_.resize(2);
462 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(-1),
463 &fake_certificate_list_[0]));
464 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(1),
465 &fake_certificate_list_[1]));
466 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
467 base::RunLoop().RunUntilIdle();
468 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_);
469 EXPECT_EQ(certificate_, fake_certificate_list_[1]);
472 TEST_F(PlatformVerificationFlowTest, IncognitoMode) {
473 fake_delegate_.set_is_incognito(true);
474 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
475 base::RunLoop().RunUntilIdle();
476 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_);
479 } // namespace attestation
480 } // namespace chromeos