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: 36 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*)); 47 virtual void OnDeviceTokenAvailable(const std::string&) {} 48 49 private: 50 DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyIdentityStrategy); 51 }; 52 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: 61 explicit MockDeviceTokenFetcher(CloudPolicyCacheBase* cache) 62 : DeviceTokenFetcher(NULL, cache, NULL) {} 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: 78 CloudPolicyControllerTest() 79 : ui_thread_(BrowserThread::UI, &loop_), 80 file_thread_(BrowserThread::FILE, &loop_) {} 81 82 virtual ~CloudPolicyControllerTest() {} 83 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 92 virtual void TearDown() { 93 controller_.reset(); // Unregisters observers. 94 } 95 96 // Takes ownership of |backend|. 97 void CreateNewController() { 98 controller_.reset(new CloudPolicyController( 99 &service_, cache_.get(), token_fetcher_.get(), &identity_strategy_, 100 ¬ifier_)); 101 } 102 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 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 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. 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. 185 TEST_F(CloudPolicyControllerTest, StartupWithoutDeviceToken) { 186 SetupIdentityStrategy("", "device_id", "machine_id", "machine_model", 187 "google/chromeos/user", em::DeviceRegisterRequest::USER, 188 "a (at) 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. 196 TEST_F(CloudPolicyControllerTest, StartupUnmanagedUser) { 197 SetupIdentityStrategy("", "device_id", "machine_id", "machine_mode", 198 "google/chromeos/user", em::DeviceRegisterRequest::USER, 199 "DannoHelper (at) 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. 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 (at) 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. 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 (at) 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. 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 (at) 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. 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 (at) 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). 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 (at) 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