1 // Copyright (c) 2012 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/chromeos/policy/auto_enrollment_client.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/testing_pref_service.h"
12 #include "base/values.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/scoped_testing_local_state.h"
16 #include "chrome/test/base/testing_browser_process.h"
17 #include "components/policy/core/common/cloud/mock_device_management_service.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "crypto/sha2.h"
20 #include "net/url_request/url_request_context_getter.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace em
= enterprise_management
;
31 const char* kSerial
= "serial";
32 const char* kSerialHash
=
33 "\x01\x44\xb1\xde\xfc\xf7\x56\x10\x87\x01\x5f\x8d\x83\x0d\x65\xb1"
34 "\x6f\x02\x4a\xd7\xeb\x92\x45\xfc\xd4\xe4\x37\xa1\x55\x2b\x13\x8a";
36 using ::testing::InSequence
;
37 using ::testing::SaveArg
;
40 class AutoEnrollmentClientTest
: public testing::Test
{
42 AutoEnrollmentClientTest()
43 : scoped_testing_local_state_(
44 TestingBrowserProcess::GetGlobal()),
45 local_state_(scoped_testing_local_state_
.Get()),
46 completion_callback_count_(0) {}
48 virtual void SetUp() OVERRIDE
{
49 CreateClient(kSerial
, 4, 8);
50 ASSERT_FALSE(local_state_
->GetUserPref(prefs::kShouldAutoEnroll
));
51 ASSERT_FALSE(local_state_
->GetUserPref(prefs::kAutoEnrollmentPowerLimit
));
54 void CreateClient(const std::string
& serial
,
57 service_
.reset(new MockDeviceManagementService());
58 EXPECT_CALL(*service_
, StartJob(_
, _
, _
, _
, _
, _
, _
))
59 .WillRepeatedly(SaveArg
<6>(&last_request_
));
60 base::Closure callback
=
61 base::Bind(&AutoEnrollmentClientTest::CompletionCallback
,
62 base::Unretained(this));
63 client_
.reset(new AutoEnrollmentClient(
67 new net::TestURLRequestContextGetter(
68 base::MessageLoop::current()->message_loop_proxy()),
74 void CompletionCallback() {
75 completion_callback_count_
++;
78 void ServerWillFail(DeviceManagementStatus error
) {
79 em::DeviceManagementResponse dummy_response
;
80 EXPECT_CALL(*service_
,
81 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT
, _
))
82 .WillOnce(service_
->FailJob(error
));
85 void ServerWillReply(int64 modulus
, bool with_hashes
, bool with_serial_hash
) {
86 em::DeviceManagementResponse response
;
87 em::DeviceAutoEnrollmentResponse
* enrollment_response
=
88 response
.mutable_auto_enrollment_response();
90 enrollment_response
->set_expected_modulus(modulus
);
92 for (size_t i
= 0; i
< 10; ++i
) {
93 std::string serial
= "serial X";
95 std::string hash
= crypto::SHA256HashString(serial
);
96 enrollment_response
->mutable_hash()->Add()->assign(hash
);
99 if (with_serial_hash
) {
100 enrollment_response
->mutable_hash()->Add()->assign(kSerialHash
,
101 crypto::kSHA256Length
);
103 EXPECT_CALL(*service_
,
104 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT
, _
))
105 .WillOnce(service_
->SucceedJob(response
));
108 void ServerWillReplyAsync(MockDeviceManagementJob
** job
) {
109 EXPECT_CALL(*service_
,
110 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT
, _
))
111 .WillOnce(service_
->CreateAsyncJob(job
));
114 bool HasCachedDecision() {
115 return local_state_
->GetUserPref(prefs::kShouldAutoEnroll
);
118 void VerifyCachedResult(bool should_enroll
, int power_limit
) {
119 base::FundamentalValue
value_should_enroll(should_enroll
);
120 base::FundamentalValue
value_power_limit(power_limit
);
121 EXPECT_TRUE(base::Value::Equals(
122 &value_should_enroll
,
123 local_state_
->GetUserPref(prefs::kShouldAutoEnroll
)));
124 EXPECT_TRUE(base::Value::Equals(
126 local_state_
->GetUserPref(prefs::kAutoEnrollmentPowerLimit
)));
129 const em::DeviceAutoEnrollmentRequest
& auto_enrollment_request() {
130 return last_request_
.auto_enrollment_request();
133 content::TestBrowserThreadBundle browser_threads_
;
134 ScopedTestingLocalState scoped_testing_local_state_
;
135 TestingPrefServiceSimple
* local_state_
;
136 scoped_ptr
<MockDeviceManagementService
> service_
;
137 scoped_ptr
<AutoEnrollmentClient
> client_
;
138 em::DeviceManagementRequest last_request_
;
139 int completion_callback_count_
;
142 DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientTest
);
145 TEST_F(AutoEnrollmentClientTest
, NetworkFailure
) {
146 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE
);
148 EXPECT_FALSE(client_
->should_auto_enroll());
149 EXPECT_EQ(0, completion_callback_count_
);
150 EXPECT_FALSE(HasCachedDecision());
153 TEST_F(AutoEnrollmentClientTest
, EmptyReply
) {
154 ServerWillReply(-1, false, false);
156 EXPECT_FALSE(client_
->should_auto_enroll());
157 EXPECT_EQ(1, completion_callback_count_
);
158 VerifyCachedResult(false, 8);
161 TEST_F(AutoEnrollmentClientTest
, ClientUploadsRightBits
) {
162 ServerWillReply(-1, false, false);
164 EXPECT_FALSE(client_
->should_auto_enroll());
165 EXPECT_EQ(1, completion_callback_count_
);
167 EXPECT_TRUE(auto_enrollment_request().has_remainder());
168 EXPECT_TRUE(auto_enrollment_request().has_modulus());
169 EXPECT_EQ(16, auto_enrollment_request().modulus());
170 EXPECT_EQ(kSerialHash
[31] & 0xf, auto_enrollment_request().remainder());
171 VerifyCachedResult(false, 8);
174 TEST_F(AutoEnrollmentClientTest
, AskForMoreThenFail
) {
176 ServerWillReply(32, false, false);
177 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE
);
179 EXPECT_FALSE(client_
->should_auto_enroll());
180 EXPECT_EQ(0, completion_callback_count_
);
181 EXPECT_FALSE(HasCachedDecision());
184 TEST_F(AutoEnrollmentClientTest
, AskForMoreThenEvenMore
) {
186 ServerWillReply(32, false, false);
187 ServerWillReply(64, false, false);
189 EXPECT_FALSE(client_
->should_auto_enroll());
190 EXPECT_EQ(1, completion_callback_count_
);
191 EXPECT_FALSE(HasCachedDecision());
194 TEST_F(AutoEnrollmentClientTest
, AskForLess
) {
196 ServerWillReply(8, false, false);
197 ServerWillReply(-1, true, true);
199 EXPECT_TRUE(client_
->should_auto_enroll());
200 EXPECT_EQ(1, completion_callback_count_
);
201 VerifyCachedResult(true, 8);
204 TEST_F(AutoEnrollmentClientTest
, AskForSame
) {
206 ServerWillReply(16, false, false);
207 ServerWillReply(-1, true, true);
209 EXPECT_TRUE(client_
->should_auto_enroll());
210 EXPECT_EQ(1, completion_callback_count_
);
211 VerifyCachedResult(true, 8);
214 TEST_F(AutoEnrollmentClientTest
, AskForSameTwice
) {
216 ServerWillReply(16, false, false);
217 ServerWillReply(16, false, false);
219 EXPECT_FALSE(client_
->should_auto_enroll());
220 EXPECT_EQ(1, completion_callback_count_
);
221 EXPECT_FALSE(HasCachedDecision());
224 TEST_F(AutoEnrollmentClientTest
, AskForTooMuch
) {
225 ServerWillReply(512, false, false);
227 EXPECT_FALSE(client_
->should_auto_enroll());
228 EXPECT_EQ(1, completion_callback_count_
);
229 EXPECT_FALSE(HasCachedDecision());
232 TEST_F(AutoEnrollmentClientTest
, AskNonPowerOf2
) {
234 ServerWillReply(100, false, false);
235 ServerWillReply(-1, false, false);
237 EXPECT_FALSE(client_
->should_auto_enroll());
238 EXPECT_EQ(1, completion_callback_count_
);
239 EXPECT_TRUE(auto_enrollment_request().has_remainder());
240 EXPECT_TRUE(auto_enrollment_request().has_modulus());
241 EXPECT_EQ(128, auto_enrollment_request().modulus());
242 EXPECT_EQ(kSerialHash
[31] & 0x7f, auto_enrollment_request().remainder());
243 VerifyCachedResult(false, 8);
246 TEST_F(AutoEnrollmentClientTest
, ConsumerDevice
) {
247 ServerWillReply(-1, true, false);
249 EXPECT_FALSE(client_
->should_auto_enroll());
250 EXPECT_EQ(1, completion_callback_count_
);
251 VerifyCachedResult(false, 8);
253 // Network changes don't trigger retries after obtaining a response from
255 client_
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET
);
256 EXPECT_EQ(1, completion_callback_count_
);
259 TEST_F(AutoEnrollmentClientTest
, EnterpriseDevice
) {
260 ServerWillReply(-1, true, true);
262 EXPECT_TRUE(client_
->should_auto_enroll());
263 EXPECT_EQ(1, completion_callback_count_
);
264 VerifyCachedResult(true, 8);
266 // Network changes don't trigger retries after obtaining a response from
268 client_
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET
);
269 EXPECT_EQ(1, completion_callback_count_
);
272 TEST_F(AutoEnrollmentClientTest
, NoSerial
) {
273 CreateClient("", 4, 8);
275 EXPECT_FALSE(client_
->should_auto_enroll());
276 EXPECT_EQ(1, completion_callback_count_
);
277 EXPECT_FALSE(HasCachedDecision());
280 TEST_F(AutoEnrollmentClientTest
, NoBitsUploaded
) {
281 CreateClient(kSerial
, 0, 0);
282 ServerWillReply(-1, false, false);
284 EXPECT_FALSE(client_
->should_auto_enroll());
285 EXPECT_EQ(1, completion_callback_count_
);
286 EXPECT_TRUE(auto_enrollment_request().has_remainder());
287 EXPECT_TRUE(auto_enrollment_request().has_modulus());
288 EXPECT_EQ(1, auto_enrollment_request().modulus());
289 EXPECT_EQ(0, auto_enrollment_request().remainder());
290 VerifyCachedResult(false, 0);
293 TEST_F(AutoEnrollmentClientTest
, ManyBitsUploaded
) {
294 int64 bottom62
= GG_INT64_C(0x14e437a1552b138a);
295 for (int i
= 0; i
<= 62; ++i
) {
296 completion_callback_count_
= 0;
297 CreateClient(kSerial
, i
, i
);
298 ServerWillReply(-1, false, false);
300 EXPECT_FALSE(client_
->should_auto_enroll());
301 EXPECT_EQ(1, completion_callback_count_
);
302 EXPECT_TRUE(auto_enrollment_request().has_remainder());
303 EXPECT_TRUE(auto_enrollment_request().has_modulus());
304 EXPECT_EQ(GG_INT64_C(1) << i
, auto_enrollment_request().modulus());
305 EXPECT_EQ(bottom62
% (GG_INT64_C(1) << i
),
306 auto_enrollment_request().remainder());
307 VerifyCachedResult(false, i
);
311 TEST_F(AutoEnrollmentClientTest
, MoreThan32BitsUploaded
) {
312 CreateClient(kSerial
, 10, 37);
314 ServerWillReply(GG_INT64_C(1) << 37, false, false);
315 ServerWillReply(-1, true, true);
317 EXPECT_TRUE(client_
->should_auto_enroll());
318 EXPECT_EQ(1, completion_callback_count_
);
319 VerifyCachedResult(true, 37);
322 TEST_F(AutoEnrollmentClientTest
, ReuseCachedDecision
) {
323 EXPECT_CALL(*service_
, CreateJob(_
, _
)).Times(0);
324 local_state_
->SetUserPref(prefs::kShouldAutoEnroll
,
325 base::Value::CreateBooleanValue(true));
326 local_state_
->SetUserPref(prefs::kAutoEnrollmentPowerLimit
,
327 base::Value::CreateIntegerValue(8));
329 EXPECT_TRUE(client_
->should_auto_enroll());
330 EXPECT_EQ(1, completion_callback_count_
);
331 AutoEnrollmentClient::CancelAutoEnrollment();
333 EXPECT_FALSE(client_
->should_auto_enroll());
334 EXPECT_EQ(2, completion_callback_count_
);
337 TEST_F(AutoEnrollmentClientTest
, RetryIfPowerLargerThanCached
) {
338 local_state_
->SetUserPref(prefs::kShouldAutoEnroll
,
339 base::Value::CreateBooleanValue(false));
340 local_state_
->SetUserPref(prefs::kAutoEnrollmentPowerLimit
,
341 base::Value::CreateIntegerValue(8));
342 CreateClient(kSerial
, 5, 10);
343 ServerWillReply(-1, true, true);
345 EXPECT_TRUE(client_
->should_auto_enroll());
346 EXPECT_EQ(1, completion_callback_count_
);
349 TEST_F(AutoEnrollmentClientTest
, NetworkChangeRetryAfterErrors
) {
350 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE
);
352 EXPECT_FALSE(client_
->should_auto_enroll());
353 // Don't invoke the callback if there was a network failure.
354 EXPECT_EQ(0, completion_callback_count_
);
355 EXPECT_FALSE(HasCachedDecision());
357 // The client doesn't retry if no new connection became available.
358 client_
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE
);
359 EXPECT_FALSE(client_
->should_auto_enroll());
360 EXPECT_EQ(0, completion_callback_count_
);
361 EXPECT_FALSE(HasCachedDecision());
363 // Retry once the network is back.
364 ServerWillReply(-1, true, true);
365 client_
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET
);
366 EXPECT_TRUE(client_
->should_auto_enroll());
367 EXPECT_EQ(1, completion_callback_count_
);
368 EXPECT_TRUE(HasCachedDecision());
370 // Subsequent network changes don't trigger retries.
371 client_
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE
);
372 client_
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET
);
373 EXPECT_TRUE(client_
->should_auto_enroll());
374 EXPECT_EQ(1, completion_callback_count_
);
375 EXPECT_TRUE(HasCachedDecision());
378 TEST_F(AutoEnrollmentClientTest
, CancelAndDeleteSoonWithPendingRequest
) {
379 MockDeviceManagementJob
* job
= NULL
;
380 ServerWillReplyAsync(&job
);
384 EXPECT_EQ(0, completion_callback_count_
);
386 // Cancel while a request is in flight.
387 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
388 client_
.release()->CancelAndDeleteSoon();
389 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
391 // The client cleans itself up once a reply is received.
392 job
->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE
,
393 em::DeviceManagementResponse());
394 // The DeleteSoon task has been posted:
395 EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting());
396 EXPECT_EQ(0, completion_callback_count_
);
399 TEST_F(AutoEnrollmentClientTest
, NetworkChangedAfterCancelAndDeleteSoon
) {
400 MockDeviceManagementJob
* job
= NULL
;
401 ServerWillReplyAsync(&job
);
405 EXPECT_EQ(0, completion_callback_count_
);
407 // Cancel while a request is in flight.
408 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
409 AutoEnrollmentClient
* client
= client_
.release();
410 client
->CancelAndDeleteSoon();
411 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
413 // Network change events are ignored while a request is pending.
414 client
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET
);
415 EXPECT_EQ(0, completion_callback_count_
);
417 // The client cleans itself up once a reply is received.
418 job
->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE
,
419 em::DeviceManagementResponse());
420 // The DeleteSoon task has been posted:
421 EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting());
422 EXPECT_EQ(0, completion_callback_count_
);
424 // Network changes that have been posted before are also ignored:
425 client
->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET
);
426 EXPECT_EQ(0, completion_callback_count_
);
429 TEST_F(AutoEnrollmentClientTest
, CancelAndDeleteSoonAfterCompletion
) {
430 ServerWillReply(-1, true, true);
432 EXPECT_EQ(1, completion_callback_count_
);
433 EXPECT_TRUE(client_
->should_auto_enroll());
435 // The client will delete itself immediately if there are no pending
437 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
438 client_
.release()->CancelAndDeleteSoon();
439 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
442 TEST_F(AutoEnrollmentClientTest
, CancelAndDeleteSoonAfterNetworkFailure
) {
443 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE
);
445 EXPECT_EQ(0, completion_callback_count_
);
446 EXPECT_FALSE(client_
->should_auto_enroll());
448 // The client will delete itself immediately if there are no pending
450 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
451 client_
.release()->CancelAndDeleteSoon();
452 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
457 } // namespace policy