Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: chrome/browser/policy/cloud_policy_controller.cc

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

Powered by Google App Engine
This is Rietveld 408576698