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

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

Issue 6312121: Add initial device policy infrastructure. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix race condition and tests. 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_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
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 static const int kPolicyRefreshDeviationFactorPercent = 10;
47 // Maximum deviation we are willing to accept.
48 static 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 static const int64 kPolicyRefreshErrorDelayInMilliseconds =
53 3 * 1000; // 3 seconds
54
55 // Default value for the policy refresh rate.
56 static const int kPolicyRefreshRateInMilliseconds =
57 3 * 60 * 60 * 1000; // 3 hours.
58
59 CloudPolicyClient::CloudPolicyClient(CloudPolicyCache* cache,
60 DeviceManagementBackend* backend,
61 DeviceTokenFetcher* token_fetcher,
62 CloudPolicyController* controller)
63 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
64 Initialize(cache,
65 backend,
66 token_fetcher,
67 controller,
68 kPolicyRefreshRateInMilliseconds,
69 kPolicyRefreshDeviationFactorPercent,
70 kPolicyRefreshDeviationMaxInMilliseconds,
71 kPolicyRefreshErrorDelayInMilliseconds);
72 }
73
74 CloudPolicyClient::~CloudPolicyClient() {
75 token_fetcher_->RemoveObserver(this);
76 controller_->RemoveObserver(this);
77 CancelDelayedWork();
78 }
79
80 void CloudPolicyClient::SetRefreshRate(int64 refresh_rate_milliseconds) {
81 policy_refresh_rate_ms_ = refresh_rate_milliseconds;
82
83 // Reschedule the refresh task if necessary.
84 if (state_ == STATE_POLICY_VALID)
85 SetState(STATE_POLICY_VALID);
86 }
87
88 void CloudPolicyClient::HandlePolicyResponse(
89 const em::DevicePolicyResponse& response) {
90 if (state_ == STATE_TOKEN_UNAVAILABLE)
91 return;
92
93 cache_->SetPolicy(response);
94 SetState(STATE_POLICY_VALID);
95 }
96
97 void CloudPolicyClient::OnError(DeviceManagementBackend::ErrorCode code) {
98 if (state_ == STATE_TOKEN_UNAVAILABLE)
99 return;
100
101 if (code == DeviceManagementBackend::kErrorServiceDeviceNotFound ||
102 code == DeviceManagementBackend::kErrorServiceManagementTokenInvalid) {
103 LOG(WARNING) << "The device token was either invalid or unknown to the "
104 << "device manager, re-registering device.";
105 SetState(STATE_TOKEN_UNAVAILABLE);
106 } else if (code ==
107 DeviceManagementBackend::kErrorServiceManagementNotSupported) {
108 VLOG(1) << "The device is no longer managed, resetting device token.";
109 SetState(STATE_TOKEN_UNAVAILABLE);
110 } else {
111 LOG(WARNING) << "Could not provide policy from the device manager (error = "
112 << code << "), will retry in "
113 << (effective_policy_refresh_error_delay_ms_ / 1000)
114 << " seconds.";
115 SetState(STATE_POLICY_ERROR);
116 }
117 }
118
119 void CloudPolicyClient::OnTokenAvailable() {
120 controller_->OnTokenAvailable(token_fetcher_->GetDeviceToken());
121 }
122
123 void CloudPolicyClient::OnTokenChanged() {
124 if (controller_->GetDeviceToken().empty())
125 SetState(STATE_TOKEN_UNAVAILABLE);
126 else
127 SetState(STATE_TOKEN_VALID);
128 }
129
130 void CloudPolicyClient::OnCredentialsChanged() {
131 SetState(STATE_TOKEN_UNAVAILABLE);
132 }
133
134 CloudPolicyClient::CloudPolicyClient(
135 CloudPolicyCache* cache,
136 DeviceManagementBackend* backend,
137 DeviceTokenFetcher* token_fetcher,
138 CloudPolicyController* controller,
139 int64 policy_refresh_rate_ms,
140 int policy_refresh_deviation_factor_percent,
141 int64 policy_refresh_deviation_max_ms,
142 int64 policy_refresh_error_delay_ms)
143 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
144 Initialize(cache,
145 backend,
146 token_fetcher,
147 controller,
148 policy_refresh_rate_ms,
149 policy_refresh_deviation_factor_percent,
150 policy_refresh_deviation_max_ms,
151 policy_refresh_error_delay_ms);
152 }
153
154 void CloudPolicyClient::Initialize(
155 CloudPolicyCache* cache,
156 DeviceManagementBackend* backend,
157 DeviceTokenFetcher* token_fetcher,
158 CloudPolicyController* controller,
159 int64 policy_refresh_rate_ms,
160 int policy_refresh_deviation_factor_percent,
161 int64 policy_refresh_deviation_max_ms,
162 int64 policy_refresh_error_delay_ms) {
163 DCHECK(cache);
164
165 cache_ = cache;
166 backend_.reset(backend);
167 token_fetcher_ = token_fetcher;
168 controller_ = controller;
169 state_ = STATE_TOKEN_UNAVAILABLE;
170 delayed_work_task_ = NULL;
171 policy_refresh_rate_ms_ = policy_refresh_rate_ms;
172 policy_refresh_deviation_factor_percent_ =
173 policy_refresh_deviation_factor_percent;
174 policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms;
175 policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
176 effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
177
178 token_fetcher_->AddObserver(this);
179 controller_->AddObserver(this);
180 if (!controller_->GetDeviceToken().empty())
181 SetState(STATE_TOKEN_VALID);
182 else
183 SetState(STATE_TOKEN_UNAVAILABLE);
184 }
185
186 void CloudPolicyClient::FetchToken() {
187 token_fetcher_->Reset();
188
189 std::string username;
190 std::string auth_token;
191 std::string device_id = controller_->GetDeviceID();
192 if (controller_->GetCredentials(&username, &auth_token) &&
193 CanBeInManagedDomain(username))
194 token_fetcher_->FetchToken(auth_token, device_id);
195 }
196
197 void CloudPolicyClient::SendPolicyRequest() {
198 DCHECK(!controller_->GetDeviceToken().empty());
199 em::DevicePolicyRequest policy_request;
200 policy_request.set_policy_scope(kChromePolicyScope);
201 em::DevicePolicySettingRequest* setting =
202 policy_request.add_setting_request();
203 setting->set_key(kChromeDevicePolicySettingKey);
204 setting->set_watermark("");
205 backend_->ProcessPolicyRequest(controller_->GetDeviceToken(),
206 controller_->GetDeviceID(),
207 policy_request, this);
208 }
209
210 void CloudPolicyClient::DoDelayedWork() {
211 DCHECK(delayed_work_task_);
212 delayed_work_task_ = NULL;
213
214 switch (state_) {
215 case STATE_TOKEN_UNAVAILABLE:
216 FetchToken();
217 return;
218 case STATE_TOKEN_VALID:
219 case STATE_POLICY_VALID:
220 case STATE_POLICY_ERROR:
221 SendPolicyRequest();
222 return;
223 }
224
225 NOTREACHED() << "Unhandled state" << state_;
226 }
227
228 void CloudPolicyClient::CancelDelayedWork() {
229 if (delayed_work_task_) {
230 delayed_work_task_->Cancel();
231 delayed_work_task_ = NULL;
232 }
233 }
234
235 void CloudPolicyClient::SetState(CloudPolicyClient::ClientState new_state) {
236 state_ = new_state;
237
238 base::Time now(base::Time::NowFromSystemTime());
239 base::Time refresh_at;
240 base::Time last_refresh(cache_->last_policy_refresh_time());
241 if (last_refresh.is_null())
242 last_refresh = now;
243
244 // Determine when to take the next step.
245 switch (state_) {
246 case STATE_TOKEN_UNAVAILABLE:
247 case STATE_TOKEN_VALID:
248 refresh_at = now;
249 break;
250 case STATE_POLICY_VALID:
251 effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
252 refresh_at =
253 last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay());
254 break;
255 case STATE_POLICY_ERROR:
256 refresh_at = now + base::TimeDelta::FromMilliseconds(
257 effective_policy_refresh_error_delay_ms_);
258 effective_policy_refresh_error_delay_ms_ *= 2;
259 if (effective_policy_refresh_error_delay_ms_ > policy_refresh_rate_ms_)
260 effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
261 break;
262 }
263
264 // Update the delayed work task.
265 CancelDelayedWork();
266 if (!refresh_at.is_null()) {
267 int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0);
268 delayed_work_task_ =
269 method_factory_.NewRunnableMethod(&CloudPolicyClient::DoDelayedWork);
270 MessageLoop::current()->PostDelayedTask(FROM_HERE, delayed_work_task_,
271 delay);
272 }
273 }
274
275 int64 CloudPolicyClient::GetRefreshDelay() {
276 int64 deviation = (policy_refresh_deviation_factor_percent_ *
277 policy_refresh_rate_ms_) / 100;
278 deviation = std::min(deviation, policy_refresh_deviation_max_ms_);
279 return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1);
280 }
281
282 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/cloud_policy_client.h ('k') | chrome/browser/policy/cloud_policy_client_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698