Chromium Code Reviews

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

Issue 5026001: Rework the device management backend implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/policy/device_management_backend_impl.h" 5 #include "chrome/browser/policy/device_management_backend_impl.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <set>
8 #include <vector> 9 #include <vector>
9 10
11 #include "base/command_line.h"
12 #include "base/lazy_instance.h"
10 #include "base/stl_util-inl.h" 13 #include "base/stl_util-inl.h"
11 #include "base/stringprintf.h" 14 #include "base/stringprintf.h"
12 #include "chrome/browser/browser_thread.h" 15 #include "chrome/browser/browser_thread.h"
16 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/net/url_request_context_getter.h" 17 #include "chrome/common/net/url_request_context_getter.h"
14 #include "net/base/cookie_monster.h" 18 #include "net/base/cookie_monster.h"
15 #include "net/base/escape.h" 19 #include "net/base/escape.h"
16 #include "net/base/host_resolver.h" 20 #include "net/base/host_resolver.h"
21 #include "net/base/load_flags.h"
17 #include "net/base/ssl_config_service_defaults.h" 22 #include "net/base/ssl_config_service_defaults.h"
18 #include "net/http/http_auth_handler_factory.h" 23 #include "net/http/http_auth_handler_factory.h"
19 #include "net/http/http_network_layer.h" 24 #include "net/http/http_network_layer.h"
20 #include "net/proxy/proxy_service.h" 25 #include "net/proxy/proxy_service.h"
21 #include "net/url_request/url_request_context.h" 26 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_status.h" 27 #include "net/url_request/url_request_status.h"
23 #include "chrome/browser/browser_process.h" 28 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/io_thread.h" 29 #include "chrome/browser/io_thread.h"
25 #include "chrome/browser/net/chrome_net_log.h" 30 #include "chrome/browser/net/chrome_net_log.h"
31 #include "chrome/browser/profile.h"
32 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/chrome_version_info.h" 33 #include "chrome/common/chrome_version_info.h"
27 34
28 namespace policy { 35 namespace policy {
29 36
30 namespace { 37 namespace {
31 38
32 // Name constants for URL query parameters. 39 // Name constants for URL query parameters.
33 const char kServiceParamRequest[] = "request"; 40 const char kServiceParamRequest[] = "request";
34 const char kServiceParamDeviceType[] = "devicetype"; 41 const char kServiceParamDeviceType[] = "devicetype";
35 const char kServiceParamDeviceID[] = "deviceid"; 42 const char kServiceParamDeviceID[] = "deviceid";
36 const char kServiceParamAgent[] = "agent"; 43 const char kServiceParamAgent[] = "agent";
37 44
38 // String constants for the device type and agent we report to the service. 45 // String constants for the device type and agent we report to the service.
39 const char kServiceValueDeviceType[] = "Chrome"; 46 const char kServiceValueDeviceType[] = "Chrome";
40 const char kServiceValueAgent[] = 47 const char kServiceValueAgent[] =
41 "%s enterprise management client version %s (%s)"; 48 "%s enterprise management client version %s (%s)";
42 49
43 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; 50 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth=";
44 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; 51 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token=";
45 52
46 } // namespace 53 // Helper class for URL query parameter encoding/decoding.
54 class URLQueryParameters {
danno 2010/11/16 22:02:56 I am surprised that there is no service to do this
Mattias Nissler (ping if slow) 2010/11/19 17:21:53 I've looked pretty hard and couldn't find anything
55 public:
56 URLQueryParameters() {}
57
58 // Add a query parameter.
59 void Put(const std::string& name, const std::string& value);
60
61 // Produce the query string, taking care of properly encoding and assembling
62 // the names and values.
63 std::string Encode();
64
65 private:
66 typedef std::vector<std::pair<std::string, std::string> > ParameterMap;
67 ParameterMap params_;
68
69 DISALLOW_COPY_AND_ASSIGN(URLQueryParameters);
70 };
71
72 void URLQueryParameters::Put(const std::string& name,
73 const std::string& value) {
74 params_.push_back(std::make_pair(name, value));
75 }
76
77 std::string URLQueryParameters::Encode() {
78 std::string result;
79 for (ParameterMap::const_iterator entry(params_.begin());
80 entry != params_.end();
81 ++entry) {
82 if (entry != params_.begin())
83 result += '&';
84 result += EscapeUrlEncodedData(entry->first);
85 result += '=';
86 result += EscapeUrlEncodedData(entry->second);
87 }
88 return result;
89 }
47 90
48 // Custom request context implementation that allows to override the user agent, 91 // 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 92 // amongst others. Wraps a baseline request context from which we reuse the
50 // service may be constructed before the default request context is created 93 // networking components.
51 // (i.e. before the profile has been loaded).
52 class DeviceManagementBackendRequestContext : public URLRequestContext { 94 class DeviceManagementBackendRequestContext : public URLRequestContext {
53 public: 95 public:
54 explicit DeviceManagementBackendRequestContext(IOThread::Globals* io_globals); 96 explicit DeviceManagementBackendRequestContext(
97 URLRequestContext* base_context);
55 virtual ~DeviceManagementBackendRequestContext(); 98 virtual ~DeviceManagementBackendRequestContext();
56 99
57 private: 100 private:
58 virtual const std::string& GetUserAgent(const GURL& url) const; 101 virtual const std::string& GetUserAgent(const GURL& url) const;
59 102
60 std::string user_agent_; 103 std::string user_agent_;
61 }; 104 };
62 105
63 DeviceManagementBackendRequestContext::DeviceManagementBackendRequestContext( 106 DeviceManagementBackendRequestContext::DeviceManagementBackendRequestContext(
64 IOThread::Globals* io_globals) { 107 URLRequestContext* base_context) {
65 net_log_ = io_globals->net_log.get(); 108 // Share resolver, proxy service and ssl bits with the baseline context. This
66 host_resolver_ = io_globals->host_resolver.get(); 109 // is important so we don't make redundant requests (e.g. when resolving proxy
67 proxy_service_ = net::ProxyService::CreateDirect(); 110 // auto configuration).
68 ssl_config_service_ = net::SSLConfigService::CreateSystemSSLConfigService(); 111 net_log_ = base_context->net_log();
69 http_auth_handler_factory_ = 112 host_resolver_ = base_context->host_resolver();
70 net::HttpAuthHandlerFactory::CreateDefault(host_resolver_); 113 proxy_service_ = base_context->proxy_service();
71 http_transaction_factory_ = 114 ssl_config_service_ = base_context->ssl_config_service();
72 net::HttpNetworkLayer::CreateFactory(host_resolver_, 115
73 io_globals->dnsrr_resolver.get(), 116 // Share the http session.
74 NULL /* ssl_host_info_factory */, 117 http_transaction_factory_ = net::HttpNetworkLayer::CreateFactory(
75 proxy_service_, 118 base_context->http_transaction_factory()->GetSession());
76 ssl_config_service_, 119
77 http_auth_handler_factory_, 120 // No cookies, please.
78 NULL /* network_delegate */,
79 net_log_);
80 cookie_store_ = new net::CookieMonster(NULL, NULL); 121 cookie_store_ = new net::CookieMonster(NULL, NULL);
122
123 // Initialize these to sane values for our purposes.
81 user_agent_ = DeviceManagementBackendImpl::GetAgentString(); 124 user_agent_ = DeviceManagementBackendImpl::GetAgentString();
82 accept_language_ = "*"; 125 accept_language_ = "*";
83 accept_charset_ = "*"; 126 accept_charset_ = "*";
84 } 127 }
85 128
86 DeviceManagementBackendRequestContext 129 DeviceManagementBackendRequestContext
87 ::~DeviceManagementBackendRequestContext() { 130 ::~DeviceManagementBackendRequestContext() {
88 delete http_transaction_factory_; 131 delete http_transaction_factory_;
89 delete http_auth_handler_factory_; 132 delete http_auth_handler_factory_;
90 } 133 }
91 134
92 const std::string& 135 const std::string&
93 DeviceManagementBackendRequestContext::GetUserAgent(const GURL& url) const { 136 DeviceManagementBackendRequestContext::GetUserAgent(const GURL& url) const {
94 return user_agent_; 137 return user_agent_;
95 } 138 }
96 139
97 // Request context holder. 140 // Request context holder.
98 class DeviceManagementBackendRequestContextGetter 141 class DeviceManagementBackendRequestContextGetter
99 : public URLRequestContextGetter { 142 : public URLRequestContextGetter {
100 public: 143 public:
101 DeviceManagementBackendRequestContextGetter() 144 DeviceManagementBackendRequestContextGetter(
102 : io_thread_(g_browser_process->io_thread()) {} 145 URLRequestContextGetter* base_context_getter)
146 : base_context_getter_(base_context_getter) {}
103 147
104 // URLRequestContextGetter overrides. 148 // URLRequestContextGetter overrides.
105 virtual URLRequestContext* GetURLRequestContext(); 149 virtual URLRequestContext* GetURLRequestContext();
106 virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const; 150 virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const;
107 151
108 private: 152 private:
109 scoped_refptr<URLRequestContext> context_; 153 scoped_refptr<URLRequestContext> context_;
110 IOThread* io_thread_; 154 scoped_refptr<URLRequestContextGetter> base_context_getter_;
111 }; 155 };
112 156
113 157
114 URLRequestContext* 158 URLRequestContext*
115 DeviceManagementBackendRequestContextGetter::GetURLRequestContext() { 159 DeviceManagementBackendRequestContextGetter::GetURLRequestContext() {
116 if (!context_) 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
117 context_ = new DeviceManagementBackendRequestContext(io_thread_->globals()); 161 if (!context_) {
162 context_ = new DeviceManagementBackendRequestContext(
163 base_context_getter_->GetURLRequestContext());
164 }
118 165
119 return context_.get(); 166 return context_.get();
120 } 167 }
121 168
122 scoped_refptr<base::MessageLoopProxy> 169 scoped_refptr<base::MessageLoopProxy>
123 DeviceManagementBackendRequestContextGetter::GetIOMessageLoopProxy() const { 170 DeviceManagementBackendRequestContextGetter::GetIOMessageLoopProxy() const {
124 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 171 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
125 } 172 }
126 173
127 // Helper class for URL query parameter encoding/decoding. 174 } // namespace
128 class URLQueryParameters { 175
176 // A wrapper that implements the actual backend interface. It doesn't hold a
177 // strong reference to the actual backend implementation object, but tracks
178 // whether it's currently available or not and postpones requests accordingly.
179 class DeviceManagementBackendProxy : public DeviceManagementBackend {
129 public: 180 public:
130 URLQueryParameters() {} 181 DeviceManagementBackendProxy(DeviceManagementBackendImpl* backend);
182 virtual ~DeviceManagementBackendProxy();
131 183
132 // Add a query parameter. 184 // Called by the DeviceManagementJob dtor so we can clean up.
markusheintz_ 2010/11/18 12:40:36 typo? "dtor"?
Mattias Nissler (ping if slow) 2010/11/19 17:21:53 It means destructor and is a well-known abbreviati
133 void Put(const std::string& name, const std::string& value); 185 void JobDone(DeviceManagementJob* job);
134 186
135 // Produce the query string, taking care of properly encoding and assembling 187 // Switches all proxies to a different backend instance.
136 // the names and values. 188 static void SwitchBackend(DeviceManagementBackendImpl* backend);
danno 2010/11/16 22:02:56 In practice, there either only the backend NULL or
Mattias Nissler (ping if slow) 2010/11/19 17:21:53 Doesn't apply any longer.
137 std::string Encode();
138 189
139 private: 190 private:
140 typedef std::vector<std::pair<std::string, std::string> > ParameterMap; 191 typedef std::set<DeviceManagementJob*> JobSet;
141 ParameterMap params_; 192 typedef std::set<DeviceManagementBackendProxy*> ProxySet;
142 193
143 DISALLOW_COPY_AND_ASSIGN(URLQueryParameters); 194 // Resets the backend pointer for this proxy.
195 void ResetBackend(DeviceManagementBackendImpl* backend);
196
197 // Add a job to the pending job set and register it with the backend (if
198 // available).
199 void AddJob(DeviceManagementJob* job);
200
201 // GoogleAppsPolicyService overrides.
danno 2010/11/16 22:02:56 Superclass name is the old one.
Mattias Nissler (ping if slow) 2010/11/19 17:21:53 Done.
202 virtual void ProcessRegisterRequest(
203 const std::string& auth_token,
204 const std::string& device_id,
205 const em::DeviceRegisterRequest& request,
206 DeviceRegisterResponseDelegate* response_delegate);
207 virtual void ProcessUnregisterRequest(
208 const std::string& device_management_token,
209 const em::DeviceUnregisterRequest& request,
210 DeviceUnregisterResponseDelegate* response_delegate);
211 virtual void ProcessPolicyRequest(
212 const std::string& device_management_token,
213 const em::DevicePolicyRequest& request,
214 DevicePolicyResponseDelegate* response_delegate);
215
216 static ProxySet& proxies() { return proxies_.Get(); }
217
218 // Keeps track of the jobs currently in flight.
219 JobSet pending_jobs_;
220
221 // The backend implementation pointer.
222 DeviceManagementBackendImpl* backend_instance_;
223
224 // Keeps a list of currently existing proxies.
225 static base::LazyInstance<ProxySet> proxies_;
226
227 DISALLOW_COPY_AND_ASSIGN(DeviceManagementBackendProxy);
144 }; 228 };
145 229
146 void URLQueryParameters::Put(const std::string& name, 230 // Represents a job run by the backend. This contains the common code,
147 const std::string& value) { 231 // subclasses provide custom code for actual register, unregister, and policy
148 params_.push_back(std::make_pair(name, value)); 232 // jobs.
149 } 233 class DeviceManagementJob {
150 234 public:
151 std::string URLQueryParameters::Encode() { 235 virtual ~DeviceManagementJob() {
152 std::string result; 236 proxy_->JobDone(this);
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 } 237 }
162 return result;
163 }
164
165 // Wraps common response parsing and handling functionality.
166 class ResponseHandler {
167 public:
168 ResponseHandler() {}
169 virtual ~ResponseHandler() {}
170 238
171 // Handles the URL request response. 239 // Handles the URL request response.
172 void HandleResponse(const URLRequestStatus& status, 240 void HandleResponse(const URLRequestStatus& status,
173 int response_code, 241 int response_code,
174 const ResponseCookies& cookies, 242 const ResponseCookies& cookies,
175 const std::string& data); 243 const std::string& data);
176 244
177 // Forwards the given error to the delegate. 245 // Gets the URL to contact.
178 virtual void OnError(DeviceManagementBackend::ErrorCode error) = 0; 246 GURL GetURL(const std::string& server_url);
247
248 // Configures the fetcher, setting up payload and headers.
249 void ConfigureRequest(URLFetcher* fetcher);
250
251 protected:
252 // Constructs a device management job running for the given proxy.
253 DeviceManagementJob(DeviceManagementBackendProxy* proxy,
254 const std::string& request_type)
255 : proxy_(proxy) {
256 query_params_.Put(kServiceParamRequest, request_type);
257 query_params_.Put(kServiceParamDeviceType, kServiceValueDeviceType);
258 query_params_.Put(kServiceParamAgent,
259 DeviceManagementBackendImpl::GetAgentString());
260 }
261
262 void SetQueryParam(const std::string& name, const std::string& value) {
263 query_params_.Put(name, value);
264 }
265
266 void SetAuthToken(const std::string& auth_token) {
267 auth_token_ = auth_token;
268 }
269
270 void SetDeviceManagementToken(const std::string& device_management_token) {
271 device_management_token_ = device_management_token;
272 }
273
274 void SetDeviceID(const std::string& device_id) {
275 query_params_.Put(kServiceParamDeviceID, device_id);
276 }
277
278 void SetPayload(const em::DeviceManagementRequest& request) {
279 if (!request.SerializeToString(&payload_)) {
280 NOTREACHED();
281 LOG(ERROR) << "Failed to serialize request.";
282 }
283 }
179 284
180 private: 285 private:
181 // Implemented by subclasses to handle the decoded response. 286 // Implemented by subclasses to handle decoded responses and errors.
182 virtual void ProcessResponse( 287 virtual void ProcessResponse(
183 const em::DeviceManagementResponse& response) = 0; 288 const em::DeviceManagementResponse& response) = 0;
289 virtual void ProcessError(DeviceManagementBackend::ErrorCode error) = 0;
290
291 // The proxy this job is handling a request for.
292 DeviceManagementBackendProxy* proxy_;
293
294 // Query parameters.
295 URLQueryParameters query_params_;
296
297 // Auth token (if applicaple).
298 std::string auth_token_;
299
300 // Device management token (if applicable).
301 std::string device_management_token_;
302
303 // The payload.
304 std::string payload_;
305
306 DISALLOW_COPY_AND_ASSIGN(DeviceManagementJob);
184 }; 307 };
185 308
186 void ResponseHandler::HandleResponse(const URLRequestStatus& status, 309 void DeviceManagementJob::HandleResponse(const URLRequestStatus& status,
187 int response_code, 310 int response_code,
188 const ResponseCookies& cookies, 311 const ResponseCookies& cookies,
189 const std::string& data) { 312 const std::string& data) {
313 // Delete ourselves when this is done.
314 scoped_ptr<DeviceManagementJob> scoped_killer(this);
315
190 if (status.status() != URLRequestStatus::SUCCESS) { 316 if (status.status() != URLRequestStatus::SUCCESS) {
191 OnError(DeviceManagementBackend::kErrorRequestFailed); 317 ProcessError(DeviceManagementBackend::kErrorRequestFailed);
danno 2010/11/16 22:02:56 Any particular reason for the name change?
markusheintz_ 2010/11/18 12:40:36 +1 for this questions. Especially since the delega
Mattias Nissler (ping if slow) 2010/11/19 17:21:53 Not any longer, it is a leftover. Changed it back.
192 return; 318 return;
193 } 319 }
194 320
195 if (response_code != 200) { 321 if (response_code != 200) {
196 OnError(DeviceManagementBackend::kErrorHttpStatus); 322 ProcessError(DeviceManagementBackend::kErrorHttpStatus);
197 return; 323 return;
198 } 324 }
199 325
200 em::DeviceManagementResponse response; 326 em::DeviceManagementResponse response;
201 if (!response.ParseFromString(data)) { 327 if (!response.ParseFromString(data)) {
202 OnError(DeviceManagementBackend::kErrorResponseDecoding); 328 ProcessError(DeviceManagementBackend::kErrorResponseDecoding);
203 return; 329 return;
204 } 330 }
205 331
206 // Check service error code. 332 // Check service error code.
207 switch (response.error()) { 333 switch (response.error()) {
208 case em::DeviceManagementResponse::SUCCESS: 334 case em::DeviceManagementResponse::SUCCESS:
209 break; 335 break;
210 case em::DeviceManagementResponse::DEVICE_MANAGEMENT_NOT_SUPPORTED: 336 case em::DeviceManagementResponse::DEVICE_MANAGEMENT_NOT_SUPPORTED:
211 OnError(DeviceManagementBackend::kErrorServiceManagementNotSupported); 337 ProcessError(
338 DeviceManagementBackend::kErrorServiceManagementNotSupported);
212 return; 339 return;
213 case em::DeviceManagementResponse::DEVICE_NOT_FOUND: 340 case em::DeviceManagementResponse::DEVICE_NOT_FOUND:
214 OnError(DeviceManagementBackend::kErrorServiceDeviceNotFound); 341 ProcessError(DeviceManagementBackend::kErrorServiceDeviceNotFound);
215 return; 342 return;
216 case em::DeviceManagementResponse::DEVICE_MANAGEMENT_TOKEN_INVALID: 343 case em::DeviceManagementResponse::DEVICE_MANAGEMENT_TOKEN_INVALID:
217 OnError(DeviceManagementBackend::kErrorServiceManagementTokenInvalid); 344 ProcessError(
345 DeviceManagementBackend::kErrorServiceManagementTokenInvalid);
218 return; 346 return;
219 case em::DeviceManagementResponse::ACTIVATION_PENDING: 347 case em::DeviceManagementResponse::ACTIVATION_PENDING:
220 OnError(DeviceManagementBackend::kErrorServiceActivationPending); 348 ProcessError(DeviceManagementBackend::kErrorServiceActivationPending);
221 return; 349 return;
222 default: 350 default:
223 // This should be caught by the protobuf decoder. 351 // This should be caught by the protobuf decoder.
224 NOTREACHED(); 352 NOTREACHED();
225 OnError(DeviceManagementBackend::kErrorResponseDecoding); 353 ProcessError(DeviceManagementBackend::kErrorResponseDecoding);
226 return; 354 return;
227 } 355 }
228 356
229 ProcessResponse(response); 357 ProcessResponse(response);
230 } 358 }
231 359
232 // Handles device registration responses. 360 GURL DeviceManagementJob::GetURL(const std::string& server_url) {
233 class RegisterResponseHandler : public ResponseHandler { 361 return GURL(server_url + '?' + query_params_.Encode());
362 }
363
364 void DeviceManagementJob::ConfigureRequest(URLFetcher* fetcher) {
365 fetcher->set_upload_data("application/octet-stream", payload_);
366 std::string extra_headers;
367 if (!auth_token_.empty())
368 extra_headers += kServiceTokenAuthHeader + auth_token_ + "\n";
369 if (!device_management_token_.empty())
370 extra_headers += kDMTokenAuthHeader + device_management_token_ + "\n";
371 fetcher->set_extra_request_headers(extra_headers);
372 }
373
374 // Handles device registration jobs.
375 class DeviceManagementRegisterJob : public DeviceManagementJob {
234 public: 376 public:
235 RegisterResponseHandler( 377 DeviceManagementRegisterJob(
236 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate) 378 DeviceManagementBackendProxy* proxy,
237 : delegate_(delegate) {} 379 const std::string& auth_token,
380 const std::string& device_id,
381 const em::DeviceRegisterRequest& request,
382 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate);
383 virtual ~DeviceManagementRegisterJob() {}
238 384
239 private: 385 private:
240 // ResponseHandler overrides. 386 // DeviceManagementJob overrides.
241 virtual void OnError(DeviceManagementBackend::ErrorCode error) { 387 virtual void ProcessError(DeviceManagementBackend::ErrorCode error) {
242 delegate_->OnError(error); 388 delegate_->OnError(error);
243 } 389 }
244 virtual void ProcessResponse(const em::DeviceManagementResponse& response) { 390 virtual void ProcessResponse(const em::DeviceManagementResponse& response) {
245 delegate_->HandleRegisterResponse(response.register_response()); 391 delegate_->HandleRegisterResponse(response.register_response());
246 } 392 }
247 393
248 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate_; 394 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate_;
395
396 DISALLOW_COPY_AND_ASSIGN(DeviceManagementRegisterJob);
249 }; 397 };
250 398
251 // Handles device unregister responses. 399 DeviceManagementRegisterJob::DeviceManagementRegisterJob(
252 class UnregisterResponseHandler : public ResponseHandler { 400 DeviceManagementBackendProxy* proxy,
401 const std::string& auth_token,
402 const std::string& device_id,
403 const em::DeviceRegisterRequest& request,
404 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate)
405 : DeviceManagementJob(proxy, "register"),
406 delegate_(delegate) {
407 SetDeviceID(device_id);
408 SetAuthToken(auth_token);
409 em::DeviceManagementRequest request_wrapper;
410 request_wrapper.mutable_register_request()->CopyFrom(request);
411 SetPayload(request_wrapper);
412 }
413
414 // Handles device unregistration jobs.
415 class DeviceManagementUnregisterJob : public DeviceManagementJob {
253 public: 416 public:
254 UnregisterResponseHandler( 417 DeviceManagementUnregisterJob(
255 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate) 418 DeviceManagementBackendProxy* proxy,
256 : delegate_(delegate) {} 419 const std::string& device_management_token,
420 const em::DeviceUnregisterRequest& request,
421 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate);
422 virtual ~DeviceManagementUnregisterJob() {}
257 423
258 private: 424 private:
259 // ResponseHandler overrides. 425 // DeviceManagementJob overrides.
260 virtual void OnError(DeviceManagementBackend::ErrorCode error) { 426 virtual void ProcessError(DeviceManagementBackend::ErrorCode error) {
261 delegate_->OnError(error); 427 delegate_->OnError(error);
262 } 428 }
263 virtual void ProcessResponse(const em::DeviceManagementResponse& response) { 429 virtual void ProcessResponse(const em::DeviceManagementResponse& response) {
264 delegate_->HandleUnregisterResponse(response.unregister_response()); 430 delegate_->HandleUnregisterResponse(response.unregister_response());
265 } 431 }
266 432
267 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate_; 433 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate_;
434
435 DISALLOW_COPY_AND_ASSIGN(DeviceManagementUnregisterJob);
268 }; 436 };
269 437
270 // Handles device policy responses. 438 DeviceManagementUnregisterJob::DeviceManagementUnregisterJob(
271 class PolicyResponseHandler : public ResponseHandler { 439 DeviceManagementBackendProxy* proxy,
440 const std::string& device_management_token,
441 const em::DeviceUnregisterRequest& request,
442 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate)
443 : DeviceManagementJob(proxy, "unregister"),
444 delegate_(delegate) {
445 SetDeviceManagementToken(device_management_token);
446 em::DeviceManagementRequest request_wrapper;
447 request_wrapper.mutable_unregister_request()->CopyFrom(request);
448 SetPayload(request_wrapper);
449 }
450
451 // Handles policy request jobs.
452 class DeviceManagementPolicyJob : public DeviceManagementJob {
272 public: 453 public:
273 PolicyResponseHandler( 454 DeviceManagementPolicyJob(
274 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate) 455 DeviceManagementBackendProxy* proxy,
275 : delegate_(delegate) {} 456 const std::string& device_management_token,
457 const em::DevicePolicyRequest& request,
458 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate);
459 virtual ~DeviceManagementPolicyJob() {}
276 460
277 private: 461 private:
278 // ResponseHandler overrides. 462 // DeviceManagementJob overrides.
279 virtual void OnError(DeviceManagementBackend::ErrorCode error) { 463 virtual void ProcessError(DeviceManagementBackend::ErrorCode error) {
280 delegate_->OnError(error); 464 delegate_->OnError(error);
281 } 465 }
282 virtual void ProcessResponse(const em::DeviceManagementResponse& response) { 466 virtual void ProcessResponse(const em::DeviceManagementResponse& response) {
283 delegate_->HandlePolicyResponse(response.policy_response()); 467 delegate_->HandlePolicyResponse(response.policy_response());
284 } 468 }
285 469
286 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_; 470 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_;
471
472 DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob);
287 }; 473 };
288 474
289 DeviceManagementBackendImpl::DeviceManagementBackendImpl( 475 DeviceManagementPolicyJob::DeviceManagementPolicyJob(
290 const std::string& server_url) 476 DeviceManagementBackendProxy* proxy,
291 : server_url_(server_url), 477 const std::string& device_management_token,
292 request_context_getter_( 478 const em::DevicePolicyRequest& request,
293 new DeviceManagementBackendRequestContextGetter()) { 479 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate)
480 : DeviceManagementJob(proxy, "policy"),
481 delegate_(delegate) {
482 SetDeviceManagementToken(device_management_token);
483 em::DeviceManagementRequest request_wrapper;
484 request_wrapper.mutable_policy_request()->CopyFrom(request);
485 SetPayload(request_wrapper);
294 } 486 }
295 487
296 DeviceManagementBackendImpl::~DeviceManagementBackendImpl() { 488 DeviceManagementBackendProxy::DeviceManagementBackendProxy(
297 // Cancel all pending requests. 489 DeviceManagementBackendImpl* backend)
298 STLDeleteContainerPairPointers(response_handlers_.begin(), 490 : backend_instance_(backend) {
299 response_handlers_.end()); 491 proxies().insert(this);
300 } 492 }
301 493
302 void DeviceManagementBackendImpl::ProcessRegisterRequest( 494 DeviceManagementBackendProxy::~DeviceManagementBackendProxy() {
495 // Swap to a helper, so we don't interfere with the unregistration on delete.
496 JobSet to_be_deleted;
497 to_be_deleted.swap(pending_jobs_);
498 for (JobSet::iterator job(to_be_deleted.begin());
499 job != to_be_deleted.end();
500 ++job) {
501 if (backend_instance_)
502 backend_instance_->CancelJob(*job);
503 delete *job;
504 }
505
506 proxies().erase(this);
507 }
508
509 void DeviceManagementBackendProxy::JobDone(DeviceManagementJob* job) {
510 pending_jobs_.erase(job);
511 }
512
513 // static
514 void DeviceManagementBackendProxy::SwitchBackend(
515 DeviceManagementBackendImpl* backend) {
516 for (ProxySet::iterator proxy(proxies().begin());
517 proxy != proxies().end();
518 ++proxy) {
519 (*proxy)->ResetBackend(backend);
520 }
521 }
522
523 void DeviceManagementBackendProxy::ResetBackend(
524 DeviceManagementBackendImpl* backend) {
525 if (backend == backend_instance_)
526 return;
527
528 // Switch our jobs over to the new backend.
529 for (JobSet::iterator job(pending_jobs_.begin());
530 job != pending_jobs_.end();
531 ++job) {
532 if (backend_instance_)
533 backend_instance_->CancelJob(*job);
534 if (backend)
535 backend->StartJob(*job);
536 }
537
538 backend_instance_ = backend;
539 }
540
541 void DeviceManagementBackendProxy::AddJob(DeviceManagementJob* job) {
542 pending_jobs_.insert(job);
543 if (backend_instance_)
544 backend_instance_->StartJob(job);
545 }
546
547 void DeviceManagementBackendProxy::ProcessRegisterRequest(
303 const std::string& auth_token, 548 const std::string& auth_token,
304 const std::string& device_id, 549 const std::string& device_id,
305 const em::DeviceRegisterRequest& request, 550 const em::DeviceRegisterRequest& request,
306 DeviceRegisterResponseDelegate* delegate) { 551 DeviceRegisterResponseDelegate* delegate) {
307 em::DeviceManagementRequest request_wrapper; 552 AddJob(new DeviceManagementRegisterJob(this, auth_token, device_id, request,
308 request_wrapper.mutable_register_request()->CopyFrom(request); 553 delegate));
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 } 554 }
320 555
321 void DeviceManagementBackendImpl::ProcessUnregisterRequest( 556 void DeviceManagementBackendProxy::ProcessUnregisterRequest(
322 const std::string& device_management_token, 557 const std::string& device_management_token,
323 const em::DeviceUnregisterRequest& request, 558 const em::DeviceUnregisterRequest& request,
324 DeviceUnregisterResponseDelegate* delegate) { 559 DeviceUnregisterResponseDelegate* delegate) {
325 em::DeviceManagementRequest request_wrapper; 560 AddJob(new DeviceManagementUnregisterJob(this, device_management_token,
326 request_wrapper.mutable_unregister_request()->CopyFrom(request); 561 request, delegate));
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 } 562 }
337 563
338 void DeviceManagementBackendImpl::ProcessPolicyRequest( 564 void DeviceManagementBackendProxy::ProcessPolicyRequest(
339 const std::string& device_management_token, 565 const std::string& device_management_token,
340 const em::DevicePolicyRequest& request, 566 const em::DevicePolicyRequest& request,
341 DevicePolicyResponseDelegate* delegate) { 567 DevicePolicyResponseDelegate* delegate) {
342 em::DeviceManagementRequest request_wrapper; 568 AddJob(new DeviceManagementPolicyJob(this, device_management_token, request,
343 request_wrapper.mutable_policy_request()->CopyFrom(request); 569 delegate));
570 }
344 571
345 URLQueryParameters params; 572 base::LazyInstance<DeviceManagementBackendProxy::ProxySet>
346 PutCommonQueryParameters(&params); 573 DeviceManagementBackendProxy::proxies_(base::LINKER_INITIALIZED);
347 params.Put(kServiceParamRequest, "policy");
348 574
349 CreateFetcher(request_wrapper, 575 DeviceManagementBackendImpl::~DeviceManagementBackendImpl() {
350 new PolicyResponseHandler(delegate), 576 DeviceManagementBackendProxy::SwitchBackend(NULL);
351 params.Encode(), 577 instance_ = NULL;
352 kDMTokenAuthHeader + device_management_token); 578
579 // All running jobs should have been canceled by now.
580 DCHECK(pending_jobs_.empty());
353 } 581 }
354 582
355 // static 583 // static
584 DeviceManagementBackend* DeviceManagementBackendImpl::Get() {
585 return new DeviceManagementBackendProxy(instance_);
586 }
587
588 // static
589 DeviceManagementBackendImpl*
590 DeviceManagementBackendImpl::Initialize(Profile* profile) {
591 DCHECK(!instance_);
592 CommandLine* command_line = CommandLine::ForCurrentProcess();
593 if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
594 return new DeviceManagementBackendImpl(
595 command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl),
596 profile->GetRequestContext());
597 }
598
599 return NULL;
600 }
601
602 // static
356 std::string DeviceManagementBackendImpl::GetAgentString() { 603 std::string DeviceManagementBackendImpl::GetAgentString() {
357 chrome::VersionInfo version_info; 604 chrome::VersionInfo version_info;
358 return base::StringPrintf(kServiceValueAgent, 605 return base::StringPrintf(kServiceValueAgent,
359 version_info.Name().c_str(), 606 version_info.Name().c_str(),
360 version_info.Version().c_str(), 607 version_info.Version().c_str(),
361 version_info.LastChange().c_str()); 608 version_info.LastChange().c_str());
362 } 609 }
363 610
611 DeviceManagementBackendImpl::DeviceManagementBackendImpl(
612 const std::string& server_url,
613 URLRequestContextGetter* request_context_getter)
614 : server_url_(server_url),
615 request_context_getter_(
616 new DeviceManagementBackendRequestContextGetter(
617 request_context_getter)) {
618 DCHECK(!instance_);
619 instance_ = this;
620
621 // Tell the proxies there's a new backend.
622 DeviceManagementBackendProxy::SwitchBackend(this);
623 }
624
625 void DeviceManagementBackendImpl::StartJob(DeviceManagementJob* job) {
626 URLFetcher* fetcher = URLFetcher::Create(0, job->GetURL(server_url_),
627 URLFetcher::POST, this);
628 fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES |
629 net::LOAD_DO_NOT_SAVE_COOKIES |
630 net::LOAD_DISABLE_CACHE);
631 fetcher->set_request_context(request_context_getter_.get());
632 job->ConfigureRequest(fetcher);
633 pending_jobs_[fetcher] = job;
634 fetcher->Start();
635 }
636
637 void DeviceManagementBackendImpl::CancelJob(DeviceManagementJob* job) {
638 for (JobFetcherMap::iterator entry(pending_jobs_.begin());
639 entry != pending_jobs_.end();
640 ++entry) {
641 if (entry->second == job) {
642 delete entry->first;
643 pending_jobs_.erase(entry);
644 break;
645 }
646 }
647 }
648
364 void DeviceManagementBackendImpl::OnURLFetchComplete( 649 void DeviceManagementBackendImpl::OnURLFetchComplete(
365 const URLFetcher* source, 650 const URLFetcher* source,
366 const GURL& url, 651 const GURL& url,
367 const URLRequestStatus& status, 652 const URLRequestStatus& status,
368 int response_code, 653 int response_code,
369 const ResponseCookies& cookies, 654 const ResponseCookies& cookies,
370 const std::string& data) { 655 const std::string& data) {
371 ResponseHandlerMap::iterator entry(response_handlers_.find(source)); 656 JobFetcherMap::iterator entry(pending_jobs_.find(source));
372 if (entry != response_handlers_.end()) { 657 if (entry != pending_jobs_.end()) {
373 ResponseHandler* handler = entry->second; 658 DeviceManagementJob* job = entry->second;
374 handler->HandleResponse(status, response_code, cookies, data); 659 job->HandleResponse(status, response_code, cookies, data);
375 response_handlers_.erase(entry); 660 pending_jobs_.erase(entry);
376 delete handler;
377 } else { 661 } else {
378 NOTREACHED() << "Callback from foreign URL fetcher"; 662 NOTREACHED() << "Callback from foreign URL fetcher";
379 } 663 }
380 delete source; 664 delete source;
381 } 665 }
382 666
383 void DeviceManagementBackendImpl::CreateFetcher( 667 DeviceManagementBackendImpl* DeviceManagementBackendImpl::instance_ = NULL;
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 668
415 } // namespace policy 669 } // namespace policy
OLDNEW

Powered by Google App Engine