Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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_client.h" | |
| 6 | |
| 7 #include "base/message_loop.h" | |
| 8 #include "base/rand_util.h" | |
| 9 #include "base/string_util.h" | |
| 10 #include "chrome/browser/policy/cloud_policy_cache.h" | |
| 11 #include "chrome/browser/policy/cloud_policy_context.h" | |
| 12 #include "chrome/browser/policy/device_management_backend.h" | |
| 13 #include "chrome/browser/policy/proto/device_management_constants.h" | |
| 14 | |
| 15 // Domain names that are known not to be managed. | |
| 16 // We don't register the device when such a user logs in. | |
| 17 static const char* kNonManagedDomains[] = { | |
| 18 "@googlemail.com", | |
| 19 "@gmail.com" | |
| 20 }; | |
| 21 | |
| 22 // Checks the domain part of the given username against the list of known | |
| 23 // non-managed domain names. Returns false if |username| is empty or its | |
|
danno
2011/02/04 16:01:33
s/its/it's/
Jakob Kummerow
2011/02/14 13:50:34
Done.
| |
| 24 // in a domain known not to be managed. | |
| 25 static bool CanBeInManagedDomain(const std::string& username) { | |
| 26 if (username.empty()) { | |
| 27 // This means incognito user in case of ChromiumOS and | |
| 28 // no logged-in user in case of Chromium (SigninService). | |
| 29 return false; | |
| 30 } | |
| 31 for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) { | |
| 32 if (EndsWith(username, kNonManagedDomains[i], true)) { | |
| 33 return false; | |
| 34 } | |
| 35 } | |
| 36 return true; | |
| 37 } | |
| 38 | |
| 39 namespace policy { | |
| 40 | |
| 41 namespace em = enterprise_management; | |
| 42 | |
| 43 // The maximum ratio in percent of the policy refresh rate we use for adjusting | |
| 44 // the policy refresh time instant. The rationale is to avoid load spikes from | |
| 45 // many devices that were set up in sync for some reason. | |
| 46 const int kPolicyRefreshDeviationFactorPercent = 10; | |
| 47 // Maximum deviation we are willing to accept. | |
| 48 const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000; | |
| 49 | |
| 50 // These are the base values for delays before retrying after an error. They | |
| 51 // will be doubled each time they are used. | |
| 52 const int64 kPolicyRefreshErrorDelayInMilliseconds = 3 * 1000; // 3 seconds | |
| 53 | |
| 54 CloudPolicyClient::CloudPolicyClient(CloudPolicyCache* cache, | |
| 55 DeviceManagementBackend* backend, | |
| 56 DeviceTokenFetcher* token_fetcher, | |
| 57 CloudPolicyController* controller) | |
| 58 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | |
| 59 Initialize(cache, | |
| 60 backend, | |
| 61 token_fetcher, | |
| 62 controller, | |
| 63 CloudPolicyContext::kDefaultPolicyRefreshRateInMilliseconds, | |
| 64 kPolicyRefreshDeviationFactorPercent, | |
| 65 kPolicyRefreshDeviationMaxInMilliseconds, | |
| 66 kPolicyRefreshErrorDelayInMilliseconds); | |
| 67 } | |
| 68 | |
| 69 CloudPolicyClient::~CloudPolicyClient() { | |
| 70 token_fetcher_->RemoveObserver(this); | |
| 71 controller_->RemoveObserver(this); | |
| 72 CancelDelayedWork(); | |
| 73 } | |
| 74 | |
| 75 void CloudPolicyClient::SetRefreshRate(int64 refresh_rate_milliseconds) { | |
| 76 policy_refresh_rate_ms_ = refresh_rate_milliseconds; | |
| 77 | |
| 78 // Reschedule the refresh task if necessary. | |
| 79 if (state_ == STATE_POLICY_VALID) | |
| 80 SetState(STATE_POLICY_VALID); | |
| 81 } | |
| 82 | |
| 83 void CloudPolicyClient::HandlePolicyResponse( | |
| 84 const em::DevicePolicyResponse& response) { | |
| 85 if (state_ == STATE_TOKEN_UNAVAILABLE) | |
| 86 return; | |
| 87 | |
| 88 cache_->SetPolicy(response); | |
| 89 SetState(STATE_POLICY_VALID); | |
| 90 } | |
| 91 | |
| 92 void CloudPolicyClient::OnError(DeviceManagementBackend::ErrorCode code) { | |
| 93 if (state_ == STATE_TOKEN_UNAVAILABLE) | |
| 94 return; | |
| 95 | |
| 96 if (code == DeviceManagementBackend::kErrorServiceDeviceNotFound || | |
| 97 code == DeviceManagementBackend::kErrorServiceManagementTokenInvalid) { | |
| 98 LOG(WARNING) << "The device token was either invalid or unknown to the " | |
| 99 << "device manager, re-registering device."; | |
| 100 SetState(STATE_TOKEN_UNAVAILABLE); | |
| 101 } else if (code == | |
| 102 DeviceManagementBackend::kErrorServiceManagementNotSupported) { | |
| 103 VLOG(1) << "The device is no longer managed, resetting device token."; | |
| 104 SetState(STATE_TOKEN_UNAVAILABLE); | |
| 105 } else { | |
| 106 LOG(WARNING) << "Could not provide policy from the device manager (error = " | |
| 107 << code << "), will retry in " | |
| 108 << (effective_policy_refresh_error_delay_ms_ / 1000) | |
| 109 << " seconds."; | |
| 110 SetState(STATE_POLICY_ERROR); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 void CloudPolicyClient::OnTokenAvailable() { | |
| 115 controller_->OnTokenAvailable(token_fetcher_->GetDeviceToken()); | |
| 116 } | |
| 117 | |
| 118 void CloudPolicyClient::OnTokenChanged() { | |
| 119 if (controller_->GetDeviceToken().empty()) | |
| 120 SetState(STATE_TOKEN_UNAVAILABLE); | |
| 121 else | |
| 122 SetState(STATE_TOKEN_VALID); | |
| 123 } | |
| 124 | |
| 125 void CloudPolicyClient::OnCredentialsChanged() { | |
| 126 SetState(STATE_TOKEN_UNAVAILABLE); | |
| 127 } | |
| 128 | |
| 129 CloudPolicyClient::CloudPolicyClient( | |
| 130 CloudPolicyCache* cache, | |
| 131 DeviceManagementBackend* backend, | |
| 132 DeviceTokenFetcher* token_fetcher, | |
| 133 CloudPolicyController* controller, | |
| 134 int64 policy_refresh_rate_ms, | |
| 135 int policy_refresh_deviation_factor_percent, | |
| 136 int64 policy_refresh_deviation_max_ms, | |
| 137 int64 policy_refresh_error_delay_ms) | |
| 138 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | |
| 139 Initialize(cache, | |
| 140 backend, | |
| 141 token_fetcher, | |
| 142 controller, | |
| 143 policy_refresh_rate_ms, | |
| 144 policy_refresh_deviation_factor_percent, | |
| 145 policy_refresh_deviation_max_ms, | |
| 146 policy_refresh_error_delay_ms); | |
| 147 } | |
| 148 | |
| 149 void CloudPolicyClient::Initialize( | |
| 150 CloudPolicyCache* cache, | |
| 151 DeviceManagementBackend* backend, | |
| 152 DeviceTokenFetcher* token_fetcher, | |
| 153 CloudPolicyController* controller, | |
| 154 int64 policy_refresh_rate_ms, | |
| 155 int policy_refresh_deviation_factor_percent, | |
| 156 int64 policy_refresh_deviation_max_ms, | |
| 157 int64 policy_refresh_error_delay_ms) { | |
| 158 DCHECK(cache); | |
| 159 | |
| 160 cache_ = cache; | |
| 161 backend_.reset(backend); | |
| 162 token_fetcher_ = token_fetcher; | |
| 163 controller_ = controller; | |
| 164 state_ = STATE_TOKEN_UNAVAILABLE; | |
| 165 delayed_work_task_ = NULL; | |
| 166 policy_refresh_rate_ms_ = policy_refresh_rate_ms; | |
| 167 policy_refresh_deviation_factor_percent_ = | |
| 168 policy_refresh_deviation_factor_percent; | |
| 169 policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms; | |
| 170 policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms; | |
| 171 effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms; | |
| 172 | |
| 173 token_fetcher_->AddObserver(this); | |
| 174 controller_->AddObserver(this); | |
| 175 if (!controller_->GetDeviceToken().empty()) | |
| 176 SetState(STATE_TOKEN_VALID); | |
| 177 else | |
| 178 SetState(STATE_TOKEN_UNAVAILABLE); | |
| 179 } | |
| 180 | |
| 181 void CloudPolicyClient::FetchToken() { | |
| 182 token_fetcher_->Reset(); | |
| 183 | |
| 184 std::string username; | |
| 185 std::string auth_token; | |
| 186 std::string device_id = controller_->GetDeviceID(); | |
| 187 if (controller_->GetCredentials(&username, &auth_token) && | |
| 188 CanBeInManagedDomain(username)) | |
| 189 token_fetcher_->FetchToken(auth_token, device_id); | |
| 190 } | |
| 191 | |
| 192 void CloudPolicyClient::SendPolicyRequest() { | |
| 193 DCHECK(!controller_->GetDeviceToken().empty()); | |
| 194 em::DevicePolicyRequest policy_request; | |
| 195 policy_request.set_policy_scope(kChromePolicyScope); | |
| 196 em::DevicePolicySettingRequest* setting = | |
| 197 policy_request.add_setting_request(); | |
| 198 setting->set_key(kChromeDevicePolicySettingKey); | |
| 199 setting->set_watermark(""); | |
| 200 backend_->ProcessPolicyRequest(controller_->GetDeviceToken(), | |
| 201 controller_->GetDeviceID(), | |
| 202 policy_request, this); | |
| 203 } | |
| 204 | |
| 205 void CloudPolicyClient::DoDelayedWork() { | |
| 206 DCHECK(delayed_work_task_); | |
| 207 delayed_work_task_ = NULL; | |
| 208 | |
| 209 switch (state_) { | |
| 210 case STATE_TOKEN_UNAVAILABLE: | |
| 211 FetchToken(); | |
| 212 return; | |
| 213 case STATE_TOKEN_VALID: | |
| 214 case STATE_POLICY_VALID: | |
| 215 case STATE_POLICY_ERROR: | |
| 216 SendPolicyRequest(); | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 NOTREACHED() << "Unhandled state" << state_; | |
| 221 } | |
| 222 | |
| 223 void CloudPolicyClient::CancelDelayedWork() { | |
| 224 if (delayed_work_task_) { | |
| 225 delayed_work_task_->Cancel(); | |
| 226 delayed_work_task_ = NULL; | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 void CloudPolicyClient::SetState(CloudPolicyClient::ClientState new_state) { | |
| 231 state_ = new_state; | |
| 232 | |
| 233 base::Time now(base::Time::NowFromSystemTime()); | |
| 234 base::Time refresh_at; | |
| 235 base::Time last_refresh(cache_->last_policy_refresh_time()); | |
| 236 if (last_refresh.is_null()) | |
| 237 last_refresh = now; | |
| 238 | |
| 239 // Determine when to take the next step. | |
| 240 switch (state_) { | |
| 241 case STATE_TOKEN_UNAVAILABLE: | |
| 242 case STATE_TOKEN_VALID: | |
| 243 refresh_at = now; | |
| 244 break; | |
| 245 case STATE_POLICY_VALID: | |
| 246 effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_; | |
| 247 refresh_at = | |
| 248 last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay()); | |
| 249 break; | |
| 250 case STATE_POLICY_ERROR: | |
| 251 refresh_at = now + base::TimeDelta::FromMilliseconds( | |
| 252 effective_policy_refresh_error_delay_ms_); | |
| 253 effective_policy_refresh_error_delay_ms_ *= 2; | |
| 254 if (effective_policy_refresh_error_delay_ms_ > policy_refresh_rate_ms_) | |
| 255 effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_; | |
| 256 break; | |
| 257 } | |
| 258 | |
| 259 // Update the delayed work task. | |
| 260 CancelDelayedWork(); | |
| 261 if (!refresh_at.is_null()) { | |
| 262 int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0); | |
| 263 delayed_work_task_ = | |
| 264 method_factory_.NewRunnableMethod(&CloudPolicyClient::DoDelayedWork); | |
| 265 MessageLoop::current()->PostDelayedTask(FROM_HERE, delayed_work_task_, | |
| 266 delay); | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 int64 CloudPolicyClient::GetRefreshDelay() { | |
| 271 int64 deviation = (policy_refresh_deviation_factor_percent_ * | |
| 272 policy_refresh_rate_ms_) / 100; | |
| 273 deviation = std::min(deviation, policy_refresh_deviation_max_ms_); | |
| 274 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1); | |
| 275 } | |
| 276 | |
| 277 } // namespace policy | |
| OLD | NEW |