consumer_management_service_unittest.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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/chromeos/policy/consumer_management_service.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/prefs/pref_registry_simple.h"
11#include "base/prefs/testing_pref_service.h"
12#include "base/run_loop.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/browser_process_platform_part.h"
15#include "chrome/browser/chrome_notification_types.h"
16#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
17#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
18#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
19#include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
20#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
21#include "chrome/browser/chromeos/policy/fake_device_cloud_policy_initializer.h"
22#include "chrome/browser/profiles/profile.h"
23#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
24#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
25#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
26#include "chrome/browser/signin/signin_manager_factory.h"
27#include "chrome/common/pref_names.h"
28#include "chrome/test/base/scoped_testing_local_state.h"
29#include "chrome/test/base/testing_browser_process.h"
30#include "chrome/test/base/testing_profile.h"
31#include "chromeos/dbus/cryptohome/rpc.pb.h"
32#include "chromeos/dbus/cryptohome_client.h"
33#include "chromeos/dbus/mock_cryptohome_client.h"
34#include "components/signin/core/browser/profile_oauth2_token_service.h"
35#include "components/signin/core/browser/signin_manager_base.h"
36#include "content/public/browser/notification_details.h"
37#include "content/public/browser/notification_source.h"
38#include "content/public/test/test_browser_thread_bundle.h"
39#include "google_apis/gaia/google_service_auth_error.h"
40#include "testing/gmock/include/gmock/gmock.h"
41#include "testing/gtest/include/gtest/gtest.h"
42
43using testing::Invoke;
44using testing::NiceMock;
45using testing::Return;
46using testing::_;
47
48namespace {
49const char* kAttributeOwnerId = "consumer_management.owner_id";
50const char* kTestOwner = "test@chromium.org.test";
51}
52
53namespace policy {
54
55class ConsumerManagementServiceTest : public testing::Test {
56 public:
57  ConsumerManagementServiceTest()
58      : testing_local_state_(TestingBrowserProcess::GetGlobal()),
59        cryptohome_result_(false),
60        set_owner_status_(false) {
61    ON_CALL(mock_cryptohome_client_, GetBootAttribute(_, _))
62        .WillByDefault(
63            Invoke(this, &ConsumerManagementServiceTest::MockGetBootAttribute));
64    ON_CALL(mock_cryptohome_client_, SetBootAttribute(_, _))
65        .WillByDefault(
66            Invoke(this, &ConsumerManagementServiceTest::MockSetBootAttribute));
67    ON_CALL(mock_cryptohome_client_, FlushAndSignBootAttributes(_, _))
68        .WillByDefault(
69            Invoke(this,
70                   &ConsumerManagementServiceTest::
71                       MockFlushAndSignBootAttributes));
72  }
73
74  virtual void SetUp() OVERRIDE {
75    service_.reset(new ConsumerManagementService(&mock_cryptohome_client_));
76  }
77
78  virtual void TearDown() OVERRIDE {
79    service_.reset();
80  }
81
82  ConsumerManagementService::ConsumerEnrollmentState GetEnrollmentState() {
83    return static_cast<ConsumerManagementService::ConsumerEnrollmentState>(
84        testing_local_state_.Get()->GetInteger(
85            prefs::kConsumerManagementEnrollmentState));
86  }
87
88  void SetEnrollmentState(
89      ConsumerManagementService::ConsumerEnrollmentState state) {
90    testing_local_state_.Get()->SetInteger(
91        prefs::kConsumerManagementEnrollmentState, state);
92  }
93
94  void MockGetBootAttribute(
95      const cryptohome::GetBootAttributeRequest& request,
96      const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) {
97    get_boot_attribute_request_ = request;
98    callback.Run(cryptohome_status_, cryptohome_result_, cryptohome_reply_);
99  }
100
101  void MockSetBootAttribute(
102      const cryptohome::SetBootAttributeRequest& request,
103      const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) {
104    set_boot_attribute_request_ = request;
105    callback.Run(cryptohome_status_, cryptohome_result_, cryptohome_reply_);
106  }
107
108  void MockFlushAndSignBootAttributes(
109      const cryptohome::FlushAndSignBootAttributesRequest& request,
110      const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) {
111    callback.Run(cryptohome_status_, cryptohome_result_, cryptohome_reply_);
112  }
113
114  void OnGetOwnerDone(const std::string& owner) {
115    owner_ = owner;
116  }
117
118  void OnSetOwnerDone(bool status) {
119    set_owner_status_ = status;
120  }
121
122  ScopedTestingLocalState testing_local_state_;
123  NiceMock<chromeos::MockCryptohomeClient> mock_cryptohome_client_;
124  scoped_ptr<ConsumerManagementService> service_;
125
126  chromeos::DBusMethodCallStatus cryptohome_status_;
127  bool cryptohome_result_;
128  cryptohome::BaseReply cryptohome_reply_;
129  cryptohome::GetBootAttributeRequest get_boot_attribute_request_;
130  cryptohome::SetBootAttributeRequest set_boot_attribute_request_;
131
132  std::string owner_;
133  bool set_owner_status_;
134};
135
136TEST_F(ConsumerManagementServiceTest, CanGetEnrollmentState) {
137  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_NONE,
138            service_->GetEnrollmentState());
139
140  SetEnrollmentState(ConsumerManagementService::ENROLLMENT_REQUESTED);
141
142  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_REQUESTED,
143            service_->GetEnrollmentState());
144}
145
146TEST_F(ConsumerManagementServiceTest, CanSetEnrollmentState) {
147  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_NONE, GetEnrollmentState());
148
149  service_->SetEnrollmentState(ConsumerManagementService::ENROLLMENT_REQUESTED);
150
151  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_REQUESTED,
152            GetEnrollmentState());
153}
154
155TEST_F(ConsumerManagementServiceTest, CanGetOwner) {
156  cryptohome_status_ = chromeos::DBUS_METHOD_CALL_SUCCESS;
157  cryptohome_result_ = true;
158  cryptohome_reply_.MutableExtension(cryptohome::GetBootAttributeReply::reply)->
159      set_value(kTestOwner);
160
161  service_->GetOwner(base::Bind(&ConsumerManagementServiceTest::OnGetOwnerDone,
162                                base::Unretained(this)));
163
164  EXPECT_EQ(kAttributeOwnerId, get_boot_attribute_request_.name());
165  EXPECT_EQ(kTestOwner, owner_);
166}
167
168TEST_F(ConsumerManagementServiceTest, GetOwnerReturnsAnEmptyStringWhenItFails) {
169  cryptohome_status_ = chromeos::DBUS_METHOD_CALL_FAILURE;
170  cryptohome_result_ = false;
171  cryptohome_reply_.MutableExtension(cryptohome::GetBootAttributeReply::reply)->
172      set_value(kTestOwner);
173
174  service_->GetOwner(base::Bind(&ConsumerManagementServiceTest::OnGetOwnerDone,
175                                base::Unretained(this)));
176
177  EXPECT_EQ("", owner_);
178}
179
180TEST_F(ConsumerManagementServiceTest, CanSetOwner) {
181  cryptohome_status_ = chromeos::DBUS_METHOD_CALL_SUCCESS;
182  cryptohome_result_ = true;
183
184  service_->SetOwner(kTestOwner,
185                     base::Bind(&ConsumerManagementServiceTest::OnSetOwnerDone,
186                                base::Unretained(this)));
187
188  EXPECT_EQ(kAttributeOwnerId, set_boot_attribute_request_.name());
189  EXPECT_EQ(kTestOwner, set_boot_attribute_request_.value());
190  EXPECT_TRUE(set_owner_status_);
191}
192
193TEST_F(ConsumerManagementServiceTest, SetOwnerReturnsFalseWhenItFails) {
194  cryptohome_status_ = chromeos::DBUS_METHOD_CALL_FAILURE;
195  cryptohome_result_ = false;
196
197  service_->SetOwner(kTestOwner,
198                     base::Bind(&ConsumerManagementServiceTest::OnSetOwnerDone,
199                                base::Unretained(this)));
200
201  EXPECT_FALSE(set_owner_status_);
202}
203
204class ConsumerManagementServiceEnrollmentTest
205    : public ConsumerManagementServiceTest {
206 public:
207  ConsumerManagementServiceEnrollmentTest()
208      : mock_user_manager_(new NiceMock<chromeos::MockUserManager>()),
209        scoped_user_manager_enabler_(mock_user_manager_),
210        fake_initializer_(new FakeDeviceCloudPolicyInitializer()),
211        enrollment_status_(EnrollmentStatus::ForStatus(
212            EnrollmentStatus::STATUS_SUCCESS)){
213    // Set up MockUserManager. The first user will be the owner.
214    mock_user_manager_->AddUser(kTestOwner);
215
216    // Return false for IsCurrentUserOwner() so that the enrollment state is not
217    // reset.
218    ON_CALL(*mock_user_manager_, IsCurrentUserOwner())
219        .WillByDefault(Return(false));
220
221    // Create test profile and set up FakeProfileOAuth2TokenService.
222    TestingProfile::Builder builder;
223    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
224                              &BuildAutoIssuingFakeProfileOAuth2TokenService);
225    testing_owner_profile_ = builder.Build();
226    testing_owner_profile_->set_profile_name(kTestOwner);
227
228    // Set up the authenticated user name and ID.
229    SigninManagerFactory::GetForProfile(testing_owner_profile_.get())->
230        SetAuthenticatedUsername(kTestOwner);
231
232    // Issue a fake refresh token.
233    GetFakeProfileOAuth2TokenService()->
234        IssueRefreshTokenForUser(kTestOwner, "fake_token");
235
236    // Inject FakeDeviceCloudPolicyInitializer.
237    BrowserPolicyConnectorChromeOS* connector =
238        g_browser_process->platform_part()->browser_policy_connector_chromeos();
239    connector->SetDeviceCloudPolicyInitializerForTesting(
240        scoped_ptr<DeviceCloudPolicyInitializer>(fake_initializer_));
241
242    // The service should continue the enrollment process if the state is
243    // ENROLLMENT_OWNER_STORED.
244    SetEnrollmentState(ConsumerManagementService::ENROLLMENT_OWNER_STORED);
245  }
246
247  FakeProfileOAuth2TokenService* GetFakeProfileOAuth2TokenService() {
248    return static_cast<FakeProfileOAuth2TokenService*>(
249        ProfileOAuth2TokenServiceFactory::GetForProfile(
250            testing_owner_profile_.get()));
251  }
252
253  void RunEnrollmentTest() {
254    // Send the profile prepared notification to continue the enrollment.
255    service_->Observe(chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
256                      content::Source<void>(NULL),  // Not used.
257                      content::Details<Profile>(testing_owner_profile_.get()));
258    base::RunLoop().RunUntilIdle();
259  }
260
261  content::TestBrowserThreadBundle thread_bundle_;
262
263  NiceMock<chromeos::MockUserManager>* mock_user_manager_;
264  chromeos::ScopedUserManagerEnabler scoped_user_manager_enabler_;
265  scoped_ptr<TestingProfile> testing_owner_profile_;
266  FakeDeviceCloudPolicyInitializer* fake_initializer_;
267  EnrollmentStatus enrollment_status_;
268};
269
270TEST_F(ConsumerManagementServiceEnrollmentTest, EnrollsSuccessfully) {
271  EXPECT_FALSE(fake_initializer_->was_start_enrollment_called());
272
273  RunEnrollmentTest();
274
275  EXPECT_TRUE(fake_initializer_->was_start_enrollment_called());
276  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_SUCCESS,
277            GetEnrollmentState());
278}
279
280TEST_F(ConsumerManagementServiceEnrollmentTest,
281       EnrollmentStateIsResetIfCurrentUserIsOwner) {
282  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_OWNER_STORED,
283            GetEnrollmentState());
284
285  EXPECT_CALL(*mock_user_manager_, IsCurrentUserOwner())
286      .WillOnce(Return(true));
287
288  RunEnrollmentTest();
289
290  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_NONE, GetEnrollmentState());
291}
292
293TEST_F(ConsumerManagementServiceEnrollmentTest, FailsToGetAccessToken) {
294  // Disable auto-posting so that RunEnrollmentTest() should stop and wait for
295  // the access token to be available.
296  GetFakeProfileOAuth2TokenService()->
297      set_auto_post_fetch_response_on_message_loop(false);
298
299  RunEnrollmentTest();
300
301  // The service should have a pending token request.
302  OAuth2TokenService::Request* token_request =
303      service_->GetTokenRequestForTesting();
304  EXPECT_TRUE(token_request);
305
306  // Tell the service that the access token is not available because of some
307  // backend issue.
308  service_->OnGetTokenFailure(
309      token_request,
310      GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR));
311
312  EXPECT_FALSE(fake_initializer_->was_start_enrollment_called());
313  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_GET_TOKEN_FAILED,
314            GetEnrollmentState());
315}
316
317TEST_F(ConsumerManagementServiceEnrollmentTest, FailsToRegister) {
318  EXPECT_FALSE(fake_initializer_->was_start_enrollment_called());
319  fake_initializer_->set_enrollment_status(EnrollmentStatus::ForStatus(
320      EnrollmentStatus::STATUS_REGISTRATION_FAILED));
321
322  RunEnrollmentTest();
323
324  EXPECT_TRUE(fake_initializer_->was_start_enrollment_called());
325  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_DM_SERVER_FAILED,
326            GetEnrollmentState());
327}
328
329TEST_F(ConsumerManagementServiceEnrollmentTest, ShowsDesktopNotificationOnly) {
330  SetEnrollmentState(ConsumerManagementService::ENROLLMENT_CANCELED);
331
332  RunEnrollmentTest();
333
334  // TODO(davidyu): Check that the desktop notification was shown.
335
336  EXPECT_FALSE(fake_initializer_->was_start_enrollment_called());
337  EXPECT_EQ(ConsumerManagementService::ENROLLMENT_NONE, GetEnrollmentState());
338}
339
340}  // namespace policy
341