1 // Copyright (c) 2011 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/policy/cloud_policy_controller.h"
6
7 #include "base/memory/scoped_temp_dir.h"
8 #include "base/message_loop.h"
9 #include "chrome/browser/policy/device_management_service.h"
10 #include "chrome/browser/policy/device_token_fetcher.h"
11 #include "chrome/browser/policy/mock_configuration_policy_store.h"
12 #include "chrome/browser/policy/mock_device_management_backend.h"
13 #include "chrome/browser/policy/mock_device_management_service.h"
14 #include "chrome/browser/policy/policy_notifier.h"
15 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
16 #include "chrome/browser/policy/user_policy_cache.h"
17 #include "content/browser/browser_thread.h"
18 #include "policy/policy_constants.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 const char kTestToken[] = "cloud_policy_controller_test_auth_token";
23
24 namespace policy {
25
26 namespace em = enterprise_management;
27
28 using ::testing::_;
29 using ::testing::AtLeast;
30 using ::testing::InSequence;
31 using ::testing::Mock;
32 using ::testing::Return;
33
34 class MockCloudPolicyIdentityStrategy : public CloudPolicyIdentityStrategy {
35 public:
MockCloudPolicyIdentityStrategy()36 MockCloudPolicyIdentityStrategy() {}
~MockCloudPolicyIdentityStrategy()37 virtual ~MockCloudPolicyIdentityStrategy() {}
38
39 MOCK_METHOD0(GetDeviceToken, std::string());
40 MOCK_METHOD0(GetDeviceID, std::string());
41 MOCK_METHOD0(GetMachineID, std::string());
42 MOCK_METHOD0(GetMachineModel, std::string());
43 MOCK_METHOD0(GetPolicyType, std::string());
44 MOCK_METHOD0(GetPolicyRegisterType, em::DeviceRegisterRequest_Type());
45
46 MOCK_METHOD2(GetCredentials, bool(std::string*, std::string*));
OnDeviceTokenAvailable(const std::string &)47 virtual void OnDeviceTokenAvailable(const std::string&) {}
48
49 private:
50 DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyIdentityStrategy);
51 };
52
ACTION_P2(MockCloudPolicyIdentityStrategyGetCredentials,username,auth_token)53 ACTION_P2(MockCloudPolicyIdentityStrategyGetCredentials, username, auth_token) {
54 *arg0 = username;
55 *arg1 = auth_token;
56 return true;
57 }
58
59 class MockDeviceTokenFetcher : public DeviceTokenFetcher {
60 public:
MockDeviceTokenFetcher(CloudPolicyCacheBase * cache)61 explicit MockDeviceTokenFetcher(CloudPolicyCacheBase* cache)
62 : DeviceTokenFetcher(NULL, cache, NULL) {}
~MockDeviceTokenFetcher()63 virtual ~MockDeviceTokenFetcher() {}
64
65 MOCK_METHOD0(GetDeviceToken, const std::string&());
66 MOCK_METHOD5(FetchToken,
67 void(const std::string&, const std::string&,
68 em::DeviceRegisterRequest_Type,
69 const std::string&, const std::string&));
70 MOCK_METHOD0(SetUnmanagedState, void());
71
72 private:
73 DISALLOW_COPY_AND_ASSIGN(MockDeviceTokenFetcher);
74 };
75
76 class CloudPolicyControllerTest : public testing::Test {
77 public:
CloudPolicyControllerTest()78 CloudPolicyControllerTest()
79 : ui_thread_(BrowserThread::UI, &loop_),
80 file_thread_(BrowserThread::FILE, &loop_) {}
81
~CloudPolicyControllerTest()82 virtual ~CloudPolicyControllerTest() {}
83
SetUp()84 virtual void SetUp() {
85 ASSERT_TRUE(temp_user_data_dir_.CreateUniqueTempDir());
86 cache_.reset(new UserPolicyCache(
87 temp_user_data_dir_.path().AppendASCII("CloudPolicyControllerTest")));
88 token_fetcher_.reset(new MockDeviceTokenFetcher(cache_.get()));
89 service_.set_backend(&backend_);
90 }
91
TearDown()92 virtual void TearDown() {
93 controller_.reset(); // Unregisters observers.
94 }
95
96 // Takes ownership of |backend|.
CreateNewController()97 void CreateNewController() {
98 controller_.reset(new CloudPolicyController(
99 &service_, cache_.get(), token_fetcher_.get(), &identity_strategy_,
100 ¬ifier_));
101 }
102
CreateNewController(int64 policy_refresh_rate_ms,int policy_refresh_deviation_factor_percent,int64 policy_refresh_deviation_max_ms,int64 policy_refresh_error_delay_ms)103 void CreateNewController(int64 policy_refresh_rate_ms,
104 int policy_refresh_deviation_factor_percent,
105 int64 policy_refresh_deviation_max_ms,
106 int64 policy_refresh_error_delay_ms) {
107 controller_.reset(new CloudPolicyController(
108 &service_, cache_.get(), token_fetcher_.get(), &identity_strategy_,
109 ¬ifier_,
110 policy_refresh_rate_ms,
111 policy_refresh_deviation_factor_percent,
112 policy_refresh_deviation_max_ms,
113 policy_refresh_error_delay_ms));
114 }
115
ExpectHasSpdyPolicy()116 void ExpectHasSpdyPolicy() {
117 MockConfigurationPolicyStore store;
118 EXPECT_CALL(store, Apply(_, _)).Times(AtLeast(1));
119 cache_->GetManagedPolicyProvider()->Provide(&store);
120 FundamentalValue expected(true);
121 ASSERT_TRUE(store.Get(kPolicyDisableSpdy) != NULL);
122 EXPECT_TRUE(store.Get(kPolicyDisableSpdy)->Equals(&expected));
123 }
124
SetupIdentityStrategy(const std::string & device_token,const std::string & device_id,const std::string & machine_id,const std::string & machine_model,const std::string & policy_type,const em::DeviceRegisterRequest_Type & policy_register_type,const std::string & user_name,const std::string & auth_token)125 void SetupIdentityStrategy(
126 const std::string& device_token,
127 const std::string& device_id,
128 const std::string& machine_id,
129 const std::string& machine_model,
130 const std::string& policy_type,
131 const em::DeviceRegisterRequest_Type& policy_register_type,
132 const std::string& user_name,
133 const std::string& auth_token) {
134 EXPECT_CALL(identity_strategy_, GetDeviceToken()).WillRepeatedly(
135 Return(device_token));
136 EXPECT_CALL(identity_strategy_, GetDeviceID()).WillRepeatedly(
137 Return(device_id));
138 EXPECT_CALL(identity_strategy_, GetMachineID()).WillRepeatedly(
139 Return(machine_id));
140 EXPECT_CALL(identity_strategy_, GetMachineModel()).WillRepeatedly(
141 Return(machine_model));
142 EXPECT_CALL(identity_strategy_, GetPolicyType()).WillRepeatedly(
143 Return(policy_type));
144 EXPECT_CALL(identity_strategy_, GetPolicyRegisterType()).WillRepeatedly(
145 Return(policy_register_type));
146 if (!user_name.empty()) {
147 EXPECT_CALL(identity_strategy_, GetCredentials(_, _)).WillRepeatedly(
148 MockCloudPolicyIdentityStrategyGetCredentials(user_name, auth_token));
149 }
150 }
151
152 protected:
153 scoped_ptr<CloudPolicyCacheBase> cache_;
154 scoped_ptr<CloudPolicyController> controller_;
155 scoped_ptr<MockDeviceTokenFetcher> token_fetcher_;
156 MockCloudPolicyIdentityStrategy identity_strategy_;
157 MockDeviceManagementBackend backend_;
158 MockDeviceManagementService service_;
159 PolicyNotifier notifier_;
160 ScopedTempDir temp_user_data_dir_;
161 MessageLoop loop_;
162
163 private:
164 BrowserThread ui_thread_;
165 BrowserThread file_thread_;
166
167 DISALLOW_COPY_AND_ASSIGN(CloudPolicyControllerTest);
168 };
169
170 // If a device token is present when the controller starts up, it should
171 // fetch and apply policy.
TEST_F(CloudPolicyControllerTest,StartupWithDeviceToken)172 TEST_F(CloudPolicyControllerTest, StartupWithDeviceToken) {
173 SetupIdentityStrategy("fake_device_token", "device_id", "machine_id",
174 "machine_model", "google/chromeos/user",
175 em::DeviceRegisterRequest::USER, "", "");
176 EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
177 MockDeviceManagementBackendSucceedSpdyCloudPolicy());
178 CreateNewController();
179 loop_.RunAllPending();
180 ExpectHasSpdyPolicy();
181 }
182
183 // If no device token is present when the controller starts up, it should
184 // instruct the token_fetcher_ to fetch one.
TEST_F(CloudPolicyControllerTest,StartupWithoutDeviceToken)185 TEST_F(CloudPolicyControllerTest, StartupWithoutDeviceToken) {
186 SetupIdentityStrategy("", "device_id", "machine_id", "machine_model",
187 "google/chromeos/user", em::DeviceRegisterRequest::USER,
188 "a@b.com", "auth_token");
189 EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _, _)).Times(1);
190 CreateNewController();
191 loop_.RunAllPending();
192 }
193
194 // If the current user belongs to a known non-managed domain, no token fetch
195 // should be initiated.
TEST_F(CloudPolicyControllerTest,StartupUnmanagedUser)196 TEST_F(CloudPolicyControllerTest, StartupUnmanagedUser) {
197 SetupIdentityStrategy("", "device_id", "machine_id", "machine_mode",
198 "google/chromeos/user", em::DeviceRegisterRequest::USER,
199 "DannoHelper@gmail.com", "auth_token");
200 EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _, _)).Times(0);
201 CreateNewController();
202 loop_.RunAllPending();
203 }
204
205 // After policy has been fetched successfully, a new fetch should be triggered
206 // after the refresh interval has timed out.
TEST_F(CloudPolicyControllerTest,RefreshAfterSuccessfulPolicy)207 TEST_F(CloudPolicyControllerTest, RefreshAfterSuccessfulPolicy) {
208 SetupIdentityStrategy("device_token", "device_id", "machine_id",
209 "machine_model", "google/chromeos/user",
210 em::DeviceRegisterRequest::USER,
211 "DannoHelperDelegate@b.com", "auth_token");
212 EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
213 MockDeviceManagementBackendSucceedSpdyCloudPolicy()).WillOnce(
214 MockDeviceManagementBackendFailPolicy(
215 DeviceManagementBackend::kErrorRequestFailed));
216 CreateNewController(0, 0, 0, 1000 * 1000);
217 loop_.RunAllPending();
218 ExpectHasSpdyPolicy();
219 }
220
221 // If policy fetching failed, it should be retried.
TEST_F(CloudPolicyControllerTest,RefreshAfterError)222 TEST_F(CloudPolicyControllerTest, RefreshAfterError) {
223 SetupIdentityStrategy("device_token", "device_id", "machine_id",
224 "machine_model", "google/chromeos/user",
225 em::DeviceRegisterRequest::USER,
226 "DannoHelperDelegateImpl@b.com", "auth_token");
227 EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
228 MockDeviceManagementBackendFailPolicy(
229 DeviceManagementBackend::kErrorRequestFailed)).WillOnce(
230 MockDeviceManagementBackendSucceedSpdyCloudPolicy());
231 CreateNewController(1000 * 1000, 0, 0, 0);
232 loop_.RunAllPending();
233 ExpectHasSpdyPolicy();
234 }
235
236 // If the backend reports that the device token was invalid, the controller
237 // should instruct the token fetcher to fetch a new token.
TEST_F(CloudPolicyControllerTest,InvalidToken)238 TEST_F(CloudPolicyControllerTest, InvalidToken) {
239 SetupIdentityStrategy("device_token", "device_id", "machine_id",
240 "machine_model", "google/chromeos/user",
241 em::DeviceRegisterRequest::USER,
242 "standup@ten.am", "auth");
243 EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
244 MockDeviceManagementBackendFailPolicy(
245 DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
246 EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _, _)).Times(1);
247 CreateNewController(1000 * 1000, 0, 0, 0);
248 loop_.RunAllPending();
249 }
250
251 // If the backend reports that the device is unknown to the server, the
252 // controller should instruct the token fetcher to fetch a new token.
TEST_F(CloudPolicyControllerTest,DeviceNotFound)253 TEST_F(CloudPolicyControllerTest, DeviceNotFound) {
254 SetupIdentityStrategy("device_token", "device_id", "machine_id",
255 "machine_model", "google/chromeos/user",
256 em::DeviceRegisterRequest::USER,
257 "me@you.com", "auth");
258 EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
259 MockDeviceManagementBackendFailPolicy(
260 DeviceManagementBackend::kErrorServiceDeviceNotFound));
261 EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _, _)).Times(1);
262 CreateNewController(1000 * 1000, 0, 0, 0);
263 loop_.RunAllPending();
264 }
265
266 // If the backend reports that the device is no longer managed, the controller
267 // should instruct the token fetcher to fetch a new token (which will in turn
268 // set and persist the correct 'unmanaged' state).
TEST_F(CloudPolicyControllerTest,NoLongerManaged)269 TEST_F(CloudPolicyControllerTest, NoLongerManaged) {
270 SetupIdentityStrategy("device_token", "device_id", "machine_id",
271 "machine_model", "google/chromeos/user",
272 em::DeviceRegisterRequest::USER,
273 "who@what.com", "auth");
274 EXPECT_CALL(backend_, ProcessPolicyRequest(_, _, _, _)).WillOnce(
275 MockDeviceManagementBackendFailPolicy(
276 DeviceManagementBackend::kErrorServiceManagementNotSupported));
277 EXPECT_CALL(*token_fetcher_.get(), SetUnmanagedState()).Times(1);
278 CreateNewController(0, 0, 0, 1000 * 1000);
279 loop_.RunAllPending();
280 }
281
282 } // namespace policy
283