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

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

Issue 4098004: Implement device management backend. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix nits. Created 10 years, 1 month 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) 2010 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/device_management_backend_impl.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "base/stl_util-inl.h"
11 #include "base/stringprintf.h"
12 #include "chrome/browser/browser_thread.h"
13 #include "chrome/common/net/url_request_context_getter.h"
14 #include "net/base/cookie_monster.h"
15 #include "net/base/escape.h"
16 #include "net/base/host_resolver.h"
17 #include "net/base/ssl_config_service_defaults.h"
18 #include "net/http/http_auth_handler_factory.h"
19 #include "net/http/http_network_layer.h"
20 #include "net/proxy/proxy_service.h"
21 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_status.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/io_thread.h"
25 #include "chrome/browser/net/chrome_net_log.h"
26 #include "chrome/common/chrome_version_info.h"
27
28 namespace policy {
29
30 namespace {
31
32 // Name constants for URL query parameters.
33 const char kServiceParamRequest[] = "request";
34 const char kServiceParamDeviceType[] = "devicetype";
35 const char kServiceParamDeviceID[] = "deviceid";
36 const char kServiceParamAgent[] = "agent";
37
38 // String constants for the device type and agent we report to the service.
39 const char kServiceValueDeviceType[] = "Chrome";
40 const char kServiceValueAgent[] =
41 "%s enterprise management client version %s (%s)";
42
43 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth=";
44 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token=";
45
46 } // namespace
47
48 // Custom request context implementation that allows to override the user agent,
49 // amongst others. Using the default request context is not an option since this
50 // service may be constructed before the default request context is created
51 // (i.e. before the profile has been loaded).
52 class DeviceManagementBackendRequestContext : public URLRequestContext {
53 public:
54 explicit DeviceManagementBackendRequestContext(IOThread::Globals* io_globals);
55 virtual ~DeviceManagementBackendRequestContext();
56
57 private:
58 virtual const std::string& GetUserAgent(const GURL& url) const;
59
60 std::string user_agent_;
61 };
62
63 DeviceManagementBackendRequestContext::DeviceManagementBackendRequestContext(
64 IOThread::Globals* io_globals) {
65 net_log_ = io_globals->net_log.get();
66 host_resolver_ = io_globals->host_resolver.get();
67 proxy_service_ = net::ProxyService::CreateDirect();
68 ssl_config_service_ = net::SSLConfigService::CreateSystemSSLConfigService();
69 http_auth_handler_factory_ =
70 net::HttpAuthHandlerFactory::CreateDefault(host_resolver_);
71 http_transaction_factory_ =
72 net::HttpNetworkLayer::CreateFactory(host_resolver_,
73 io_globals->dnsrr_resolver.get(),
74 NULL /* ssl_host_info_factory */,
75 proxy_service_,
76 ssl_config_service_,
77 http_auth_handler_factory_,
78 NULL /* network_delegate */,
79 net_log_);
80 cookie_store_ = new net::CookieMonster(NULL, NULL);
81 user_agent_ = DeviceManagementBackendImpl::GetAgentString();
82 accept_language_ = "*";
83 accept_charset_ = "*";
84 }
85
86 DeviceManagementBackendRequestContext
87 ::~DeviceManagementBackendRequestContext() {
88 delete http_transaction_factory_;
89 delete http_auth_handler_factory_;
90 }
91
92 const std::string&
93 DeviceManagementBackendRequestContext::GetUserAgent(const GURL& url) const {
94 return user_agent_;
95 }
96
97 // Request context holder.
98 class DeviceManagementBackendRequestContextGetter
99 : public URLRequestContextGetter {
100 public:
101 DeviceManagementBackendRequestContextGetter()
102 : io_thread_(g_browser_process->io_thread()) {}
103
104 // URLRequestContextGetter overrides.
105 virtual URLRequestContext* GetURLRequestContext();
106 virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const;
107
108 private:
109 scoped_refptr<URLRequestContext> context_;
110 IOThread* io_thread_;
111 };
112
113
114 URLRequestContext*
115 DeviceManagementBackendRequestContextGetter::GetURLRequestContext() {
eroman 2010/11/08 22:38:56 Could you add an assertion that this is currently
116 if (!context_)
117 context_ = new DeviceManagementBackendRequestContext(io_thread_->globals());
118
119 return context_.get();
120 }
121
122 scoped_refptr<base::MessageLoopProxy>
123 DeviceManagementBackendRequestContextGetter::GetIOMessageLoopProxy() const {
124 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
125 }
126
127 // Helper class for URL query parameter encoding/decoding.
128 class URLQueryParameters {
129 public:
130 URLQueryParameters() {}
131
132 // Add a query parameter.
133 void Put(const std::string& name, const std::string& value);
134
135 // Produce the query string, taking care of properly encoding and assembling
136 // the names and values.
137 std::string Encode();
138
139 private:
140 typedef std::vector<std::pair<std::string, std::string> > ParameterMap;
141 ParameterMap params_;
142
143 DISALLOW_COPY_AND_ASSIGN(URLQueryParameters);
144 };
145
146 void URLQueryParameters::Put(const std::string& name,
147 const std::string& value) {
148 params_.push_back(std::make_pair(name, value));
149 }
150
151 std::string URLQueryParameters::Encode() {
152 std::string result;
153 for (ParameterMap::const_iterator entry(params_.begin());
154 entry != params_.end();
155 ++entry) {
156 if (entry != params_.begin())
157 result += '&';
158 result += EscapeUrlEncodedData(entry->first);
159 result += '=';
160 result += EscapeUrlEncodedData(entry->second);
161 }
162 return result;
163 }
164
165 // Wraps common response parsing and handling functionality.
166 class ResponseHandler {
167 public:
168 ResponseHandler() {}
169 virtual ~ResponseHandler() {}
170
171 // Handles the URL request response.
172 void HandleResponse(const URLRequestStatus& status,
173 int response_code,
174 const ResponseCookies& cookies,
175 const std::string& data);
176
177 // Forwards the given error to the delegate.
178 virtual void OnError(DeviceManagementBackend::ErrorCode error) = 0;
179
180 private:
181 // Implemented by subclasses to handle the decoded response.
182 virtual void ProcessResponse(
183 const em::DeviceManagementResponse& response) = 0;
184 };
185
186 void ResponseHandler::HandleResponse(const URLRequestStatus& status,
187 int response_code,
188 const ResponseCookies& cookies,
189 const std::string& data) {
190 if (status.status() != URLRequestStatus::SUCCESS) {
191 OnError(DeviceManagementBackend::kErrorRequestFailed);
192 return;
193 }
194
195 if (response_code != 200) {
196 OnError(DeviceManagementBackend::kErrorHttpStatus);
197 return;
198 }
199
200 em::DeviceManagementResponse response;
201 if (!response.ParseFromString(data)) {
202 OnError(DeviceManagementBackend::kErrorResponseDecoding);
203 return;
204 }
205
206 // Check service error code.
207 switch (response.error()) {
208 case em::DeviceManagementResponse::SUCCESS:
209 break;
210 case em::DeviceManagementResponse::DEVICE_MANAGEMENT_NOT_SUPPORTED:
211 OnError(DeviceManagementBackend::kErrorServiceManagementNotSupported);
212 return;
213 case em::DeviceManagementResponse::DEVICE_NOT_FOUND:
214 OnError(DeviceManagementBackend::kErrorServiceDeviceNotFound);
215 return;
216 case em::DeviceManagementResponse::DEVICE_MANAGEMENT_TOKEN_INVALID:
217 OnError(DeviceManagementBackend::kErrorServiceManagementTokenInvalid);
218 return;
219 case em::DeviceManagementResponse::ACTIVATION_PENDING:
220 OnError(DeviceManagementBackend::kErrorServiceActivationPending);
221 return;
222 default:
223 // This should be caught by the protobuf decoder.
224 NOTREACHED();
225 OnError(DeviceManagementBackend::kErrorResponseDecoding);
226 return;
227 }
228
229 ProcessResponse(response);
230 }
231
232 // Handles device registration responses.
233 class RegisterResponseHandler : public ResponseHandler {
234 public:
235 RegisterResponseHandler(
236 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate)
237 : delegate_(delegate) {}
238
239 private:
240 // ResponseHandler overrides.
241 virtual void OnError(DeviceManagementBackend::ErrorCode error) {
242 delegate_->OnError(error);
243 }
244 virtual void ProcessResponse(const em::DeviceManagementResponse& response) {
245 delegate_->HandleRegisterResponse(response.register_response());
246 }
247
248 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate_;
249 };
250
251 // Handles device unregister responses.
252 class UnregisterResponseHandler : public ResponseHandler {
253 public:
254 UnregisterResponseHandler(
255 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate)
256 : delegate_(delegate) {}
257
258 private:
259 // ResponseHandler overrides.
260 virtual void OnError(DeviceManagementBackend::ErrorCode error) {
261 delegate_->OnError(error);
262 }
263 virtual void ProcessResponse(const em::DeviceManagementResponse& response) {
264 delegate_->HandleUnregisterResponse(response.unregister_response());
265 }
266
267 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate_;
268 };
269
270 // Handles device policy responses.
271 class PolicyResponseHandler : public ResponseHandler {
272 public:
273 PolicyResponseHandler(
274 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate)
275 : delegate_(delegate) {}
276
277 private:
278 // ResponseHandler overrides.
279 virtual void OnError(DeviceManagementBackend::ErrorCode error) {
280 delegate_->OnError(error);
281 }
282 virtual void ProcessResponse(const em::DeviceManagementResponse& response) {
283 delegate_->HandlePolicyResponse(response.policy_response());
284 }
285
286 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_;
287 };
288
289 DeviceManagementBackendImpl::DeviceManagementBackendImpl(
290 const std::string& server_url)
291 : server_url_(server_url),
292 request_context_getter_(
293 new DeviceManagementBackendRequestContextGetter()) {
294 }
295
296 DeviceManagementBackendImpl::~DeviceManagementBackendImpl() {
297 // Cancel all pending requests.
298 STLDeleteContainerPairPointers(response_handlers_.begin(),
299 response_handlers_.end());
300 }
301
302 void DeviceManagementBackendImpl::ProcessRegisterRequest(
303 const std::string& auth_token,
304 const std::string& device_id,
305 const em::DeviceRegisterRequest& request,
306 DeviceRegisterResponseDelegate* delegate) {
307 em::DeviceManagementRequest request_wrapper;
308 request_wrapper.mutable_register_request()->CopyFrom(request);
309
310 URLQueryParameters params;
311 PutCommonQueryParameters(&params);
312 params.Put(kServiceParamRequest, "register");
313 params.Put(kServiceParamDeviceID, device_id);
314
315 CreateFetcher(request_wrapper,
316 new RegisterResponseHandler(delegate),
317 params.Encode(),
318 kServiceTokenAuthHeader + auth_token);
319 }
320
321 void DeviceManagementBackendImpl::ProcessUnregisterRequest(
322 const std::string& device_management_token,
323 const em::DeviceUnregisterRequest& request,
324 DeviceUnregisterResponseDelegate* delegate) {
325 em::DeviceManagementRequest request_wrapper;
326 request_wrapper.mutable_unregister_request()->CopyFrom(request);
327
328 URLQueryParameters params;
329 PutCommonQueryParameters(&params);
330 params.Put(kServiceParamRequest, "unregister");
331
332 CreateFetcher(request_wrapper,
333 new UnregisterResponseHandler(delegate),
334 params.Encode(),
335 kDMTokenAuthHeader + device_management_token);
336 }
337
338 void DeviceManagementBackendImpl::ProcessPolicyRequest(
339 const std::string& device_management_token,
340 const em::DevicePolicyRequest& request,
341 DevicePolicyResponseDelegate* delegate) {
342 em::DeviceManagementRequest request_wrapper;
343 request_wrapper.mutable_policy_request()->CopyFrom(request);
344
345 URLQueryParameters params;
346 PutCommonQueryParameters(&params);
347 params.Put(kServiceParamRequest, "policy");
348
349 CreateFetcher(request_wrapper,
350 new PolicyResponseHandler(delegate),
351 params.Encode(),
352 kDMTokenAuthHeader + device_management_token);
353 }
354
355 // static
356 std::string DeviceManagementBackendImpl::GetAgentString() {
357 chrome::VersionInfo version_info;
358 return base::StringPrintf(kServiceValueAgent,
359 version_info.Name().c_str(),
360 version_info.Version().c_str(),
361 version_info.LastChange().c_str());
362 }
363
364 void DeviceManagementBackendImpl::OnURLFetchComplete(
365 const URLFetcher* source,
366 const GURL& url,
367 const URLRequestStatus& status,
368 int response_code,
369 const ResponseCookies& cookies,
370 const std::string& data) {
371 ResponseHandlerMap::iterator entry(response_handlers_.find(source));
372 if (entry != response_handlers_.end()) {
373 ResponseHandler* handler = entry->second;
374 handler->HandleResponse(status, response_code, cookies, data);
375 response_handlers_.erase(entry);
376 delete handler;
377 } else {
378 NOTREACHED() << "Callback from foreign URL fetcher";
379 }
380 delete source;
381 }
382
383 void DeviceManagementBackendImpl::CreateFetcher(
384 const em::DeviceManagementRequest& request,
385 ResponseHandler* handler,
386 const std::string& query_params,
387 const std::string& extra_headers) {
388 scoped_ptr<ResponseHandler> handler_ptr(handler);
389
390 // Construct the payload.
391 std::string payload;
392 if (!request.SerializeToString(&payload)) {
393 handler->OnError(DeviceManagementBackend::kErrorRequestInvalid);
394 return;
395 }
396
397 // Instantiate the fetcher.
398 GURL url(server_url_ + '?' + query_params);
399 URLFetcher* fetcher = URLFetcher::Create(0, url, URLFetcher::POST, this);
400 fetcher->set_request_context(request_context_getter_.get());
401 fetcher->set_upload_data("application/octet-stream", payload);
402 fetcher->set_extra_request_headers(extra_headers);
403 response_handlers_[fetcher] = handler_ptr.release();
404
405 // Start the request. The fetcher will call OnURLFetchComplete when done.
406 fetcher->Start();
407 }
408
409 void DeviceManagementBackendImpl::PutCommonQueryParameters(
410 URLQueryParameters* params) {
411 params->Put(kServiceParamDeviceType, kServiceValueDeviceType);
412 params->Put(kServiceParamAgent, GetAgentString());
413 }
414
415 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698