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

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

Issue 12189011: Split up chrome/browser/policy subdirectory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, add chrome/browser/chromeos/policy/OWNERS Created 7 years, 9 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) 2012 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_service.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/message_loop.h"
12 #include "base/message_loop_proxy.h"
13 #include "base/stringprintf.h"
14 #include "base/sys_info.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/net/basic_http_user_agent_settings.h"
17 #include "chrome/browser/net/chrome_net_log.h"
18 #include "chrome/common/chrome_version_info.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/content_client.h"
21 #include "googleurl/src/gurl.h"
22 #include "net/base/escape.h"
23 #include "net/base/host_resolver.h"
24 #include "net/base/load_flags.h"
25 #include "net/base/net_errors.h"
26 #include "net/base/ssl_config_service_defaults.h"
27 #include "net/cookies/cookie_monster.h"
28 #include "net/http/http_network_layer.h"
29 #include "net/http/http_response_headers.h"
30 #include "net/proxy/proxy_service.h"
31 #include "net/url_request/url_fetcher.h"
32 #include "net/url_request/url_request_context.h"
33 #include "net/url_request/url_request_context_getter.h"
34 #include "net/url_request/url_request_status.h"
35
36 #if defined(OS_CHROMEOS)
37 #include "chrome/browser/chromeos/system/statistics_provider.h"
38 #endif
39
40 using content::BrowserThread;
41
42 namespace em = enterprise_management;
43
44 namespace policy {
45
46 namespace {
47
48 const char kValueAgent[] = "%s %s(%s)";
49 const char kValuePlatform[] = "%s|%s|%s";
50
51 const char kPostContentType[] = "application/protobuf";
52
53 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth=";
54 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token=";
55
56 // Number of times to retry on ERR_NETWORK_CHANGED errors.
57 const int kMaxNetworkChangedRetries = 3;
58
59 // HTTP Error Codes of the DM Server with their concrete meanings in the context
60 // of the DM Server communication.
61 const int kSuccess = 200;
62 const int kInvalidArgument = 400;
63 const int kInvalidAuthCookieOrDMToken = 401;
64 const int kMissingLicenses = 402;
65 const int kDeviceManagementNotAllowed = 403;
66 const int kInvalidURL = 404; // This error is not coming from the GFE.
67 const int kInvalidSerialNumber = 405;
68 const int kDeviceIdConflict = 409;
69 const int kDeviceNotFound = 410;
70 const int kPendingApproval = 412;
71 const int kInternalServerError = 500;
72 const int kServiceUnavailable = 503;
73 const int kPolicyNotFound = 902; // This error is not sent as HTTP status code.
74
75 #if defined(OS_CHROMEOS)
76 // Machine info keys.
77 const char kMachineInfoHWClass[] = "hardware_class";
78 const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD";
79 #endif
80
81 bool IsProxyError(const net::URLRequestStatus status) {
82 switch (status.error()) {
83 case net::ERR_PROXY_CONNECTION_FAILED:
84 case net::ERR_TUNNEL_CONNECTION_FAILED:
85 case net::ERR_PROXY_AUTH_UNSUPPORTED:
86 case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
87 case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED:
88 case net::ERR_PROXY_CERTIFICATE_INVALID:
89 case net::ERR_SOCKS_CONNECTION_FAILED:
90 case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
91 return true;
92 }
93 return false;
94 }
95
96 bool IsProtobufMimeType(const net::URLFetcher* fetcher) {
97 return fetcher->GetResponseHeaders()->HasHeaderValue(
98 "content-type", "application/x-protobuffer");
99 }
100
101 bool FailedWithProxy(const net::URLFetcher* fetcher) {
102 if ((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) != 0) {
103 // The request didn't use a proxy.
104 return false;
105 }
106
107 if (!fetcher->GetStatus().is_success() &&
108 IsProxyError(fetcher->GetStatus())) {
109 LOG(WARNING) << "Proxy failed while contacting dmserver.";
110 return true;
111 }
112
113 if (fetcher->GetStatus().is_success() &&
114 fetcher->GetResponseCode() == kSuccess &&
115 fetcher->WasFetchedViaProxy() &&
116 !IsProtobufMimeType(fetcher)) {
117 // The proxy server can be misconfigured but pointing to an existing
118 // server that replies to requests. Try to recover if a successful
119 // request that went through a proxy returns an unexpected mime type.
120 LOG(WARNING) << "Got bad mime-type in response from dmserver that was "
121 << "fetched via a proxy.";
122 return true;
123 }
124
125 return false;
126 }
127
128 const char* UserAffiliationToString(UserAffiliation affiliation) {
129 switch (affiliation) {
130 case USER_AFFILIATION_MANAGED:
131 return dm_protocol::kValueUserAffiliationManaged;
132 case USER_AFFILIATION_NONE:
133 return dm_protocol::kValueUserAffiliationNone;
134 }
135 NOTREACHED() << "Invalid user affiliation " << affiliation;
136 return dm_protocol::kValueUserAffiliationNone;
137 }
138
139 const char* JobTypeToRequestType(DeviceManagementRequestJob::JobType type) {
140 switch (type) {
141 case DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT:
142 return dm_protocol::kValueRequestAutoEnrollment;
143 case DeviceManagementRequestJob::TYPE_REGISTRATION:
144 return dm_protocol::kValueRequestRegister;
145 case DeviceManagementRequestJob::TYPE_POLICY_FETCH:
146 return dm_protocol::kValueRequestPolicy;
147 case DeviceManagementRequestJob::TYPE_UNREGISTRATION:
148 return dm_protocol::kValueRequestUnregister;
149 }
150 NOTREACHED() << "Invalid job type " << type;
151 return "";
152 }
153
154 const std::string& GetAgentString() {
155 CR_DEFINE_STATIC_LOCAL(std::string, agent, ());
156 if (!agent.empty())
157 return agent;
158
159 chrome::VersionInfo version_info;
160 agent = base::StringPrintf(kValueAgent,
161 version_info.Name().c_str(),
162 version_info.Version().c_str(),
163 version_info.LastChange().c_str());
164 return agent;
165 }
166
167 const std::string& GetPlatformString() {
168 CR_DEFINE_STATIC_LOCAL(std::string, platform, ());
169 if (!platform.empty())
170 return platform;
171
172 std::string os_name(base::SysInfo::OperatingSystemName());
173 std::string os_hardware(base::SysInfo::OperatingSystemArchitecture());
174
175 #if defined(OS_CHROMEOS)
176 chromeos::system::StatisticsProvider* provider =
177 chromeos::system::StatisticsProvider::GetInstance();
178
179 std::string hwclass;
180 std::string board;
181 if (!provider->GetMachineStatistic(kMachineInfoHWClass, &hwclass) ||
182 !provider->GetMachineStatistic(kMachineInfoBoard, &board)) {
183 LOG(ERROR) << "Failed to get machine information";
184 }
185 os_name += ",CrOS," + board;
186 os_hardware += "," + hwclass;
187 #endif
188
189 std::string os_version("-");
190 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
191 int32 os_major_version = 0;
192 int32 os_minor_version = 0;
193 int32 os_bugfix_version = 0;
194 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
195 &os_minor_version,
196 &os_bugfix_version);
197 os_version = base::StringPrintf("%d.%d.%d",
198 os_major_version,
199 os_minor_version,
200 os_bugfix_version);
201 #endif
202
203 platform = base::StringPrintf(kValuePlatform,
204 os_name.c_str(),
205 os_hardware.c_str(),
206 os_version.c_str());
207 return platform;
208 }
209
210 // Custom request context implementation that allows to override the user agent,
211 // amongst others. Wraps a baseline request context from which we reuse the
212 // networking components.
213 class DeviceManagementRequestContext : public net::URLRequestContext {
214 public:
215 explicit DeviceManagementRequestContext(net::URLRequestContext* base_context);
216 virtual ~DeviceManagementRequestContext();
217
218 private:
219 BasicHttpUserAgentSettings basic_http_user_agent_settings_;
220 };
221
222 DeviceManagementRequestContext::DeviceManagementRequestContext(
223 net::URLRequestContext* base_context)
224 // Use sane Accept-Language and Accept-Charset values for our purposes.
225 : basic_http_user_agent_settings_("*", "*") {
226 // Share resolver, proxy service and ssl bits with the baseline context. This
227 // is important so we don't make redundant requests (e.g. when resolving proxy
228 // auto configuration).
229 set_net_log(base_context->net_log());
230 set_host_resolver(base_context->host_resolver());
231 set_proxy_service(base_context->proxy_service());
232 set_ssl_config_service(base_context->ssl_config_service());
233
234 // Share the http session.
235 set_http_transaction_factory(
236 new net::HttpNetworkLayer(
237 base_context->http_transaction_factory()->GetSession()));
238
239 // No cookies, please.
240 set_cookie_store(new net::CookieMonster(NULL, NULL));
241
242 set_http_user_agent_settings(&basic_http_user_agent_settings_);
243 }
244
245 DeviceManagementRequestContext::~DeviceManagementRequestContext() {
246 delete http_transaction_factory();
247 }
248
249 // Request context holder.
250 class DeviceManagementRequestContextGetter
251 : public net::URLRequestContextGetter {
252 public:
253 explicit DeviceManagementRequestContextGetter(
254 net::URLRequestContextGetter* base_context_getter)
255 : base_context_getter_(base_context_getter) {}
256
257 // Overridden from net::URLRequestContextGetter:
258 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
259 virtual scoped_refptr<base::SingleThreadTaskRunner>
260 GetNetworkTaskRunner() const OVERRIDE;
261
262 protected:
263 virtual ~DeviceManagementRequestContextGetter() {}
264
265 private:
266 scoped_ptr<net::URLRequestContext> context_;
267 scoped_refptr<net::URLRequestContextGetter> base_context_getter_;
268 };
269
270
271 net::URLRequestContext*
272 DeviceManagementRequestContextGetter::GetURLRequestContext() {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
274 if (!context_.get()) {
275 context_.reset(new DeviceManagementRequestContext(
276 base_context_getter_->GetURLRequestContext()));
277 }
278
279 return context_.get();
280 }
281
282 scoped_refptr<base::SingleThreadTaskRunner>
283 DeviceManagementRequestContextGetter::GetNetworkTaskRunner() const {
284 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
285 }
286
287 } // namespace
288
289 // Request job implementation used with DeviceManagementService.
290 class DeviceManagementRequestJobImpl : public DeviceManagementRequestJob {
291 public:
292 DeviceManagementRequestJobImpl(JobType type,
293 DeviceManagementService* service);
294 virtual ~DeviceManagementRequestJobImpl();
295
296 // Handles the URL request response.
297 void HandleResponse(const net::URLRequestStatus& status,
298 int response_code,
299 const net::ResponseCookies& cookies,
300 const std::string& data);
301
302 // Gets the URL to contact.
303 GURL GetURL(const std::string& server_url);
304
305 // Configures the fetcher, setting up payload and headers.
306 void ConfigureRequest(net::URLFetcher* fetcher);
307
308 // Returns true if this job should be retried. |fetcher| has just completed,
309 // and can be inspected to determine if the request failed and should be
310 // retried.
311 bool ShouldRetry(const net::URLFetcher* fetcher);
312
313 // Invoked right before retrying this job.
314 void PrepareRetry();
315
316 protected:
317 // DeviceManagementRequestJob:
318 virtual void Run() OVERRIDE;
319
320 private:
321 // Invokes the callback with the given error code.
322 void ReportError(DeviceManagementStatus code);
323
324 // Pointer to the service this job is associated with.
325 DeviceManagementService* service_;
326
327 // Whether the BYPASS_PROXY flag should be set by ConfigureRequest().
328 bool bypass_proxy_;
329
330 // Number of times that this job has been retried due to ERR_NETWORK_CHANGED.
331 int retries_count_;
332
333 DISALLOW_COPY_AND_ASSIGN(DeviceManagementRequestJobImpl);
334 };
335
336 DeviceManagementRequestJobImpl::DeviceManagementRequestJobImpl(
337 JobType type,
338 DeviceManagementService* service)
339 : DeviceManagementRequestJob(type),
340 service_(service),
341 bypass_proxy_(false),
342 retries_count_(0) {}
343
344 DeviceManagementRequestJobImpl::~DeviceManagementRequestJobImpl() {
345 service_->RemoveJob(this);
346 }
347
348 void DeviceManagementRequestJobImpl::Run() {
349 service_->AddJob(this);
350 }
351
352 void DeviceManagementRequestJobImpl::HandleResponse(
353 const net::URLRequestStatus& status,
354 int response_code,
355 const net::ResponseCookies& cookies,
356 const std::string& data) {
357 if (status.status() != net::URLRequestStatus::SUCCESS) {
358 LOG(WARNING) << "DMServer request failed, status: " << status.status()
359 << ", error: " << status.error();
360 ReportError(DM_STATUS_REQUEST_FAILED);
361 return;
362 }
363
364 if (response_code != kSuccess)
365 LOG(WARNING) << "DMServer sent an error response: " << response_code;
366
367 switch (response_code) {
368 case kSuccess: {
369 em::DeviceManagementResponse response;
370 if (!response.ParseFromString(data)) {
371 ReportError(DM_STATUS_RESPONSE_DECODING_ERROR);
372 return;
373 }
374 callback_.Run(DM_STATUS_SUCCESS, response);
375 return;
376 }
377 case kInvalidArgument:
378 ReportError(DM_STATUS_REQUEST_INVALID);
379 return;
380 case kInvalidAuthCookieOrDMToken:
381 ReportError(DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID);
382 return;
383 case kMissingLicenses:
384 ReportError(DM_STATUS_SERVICE_MISSING_LICENSES);
385 return;
386 case kDeviceManagementNotAllowed:
387 ReportError(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED);
388 return;
389 case kPendingApproval:
390 ReportError(DM_STATUS_SERVICE_ACTIVATION_PENDING);
391 return;
392 case kInvalidURL:
393 case kInternalServerError:
394 case kServiceUnavailable:
395 ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE);
396 return;
397 case kDeviceNotFound:
398 ReportError(DM_STATUS_SERVICE_DEVICE_NOT_FOUND);
399 return;
400 case kPolicyNotFound:
401 ReportError(DM_STATUS_SERVICE_POLICY_NOT_FOUND);
402 return;
403 case kInvalidSerialNumber:
404 ReportError(DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER);
405 return;
406 case kDeviceIdConflict:
407 ReportError(DM_STATUS_SERVICE_DEVICE_ID_CONFLICT);
408 return;
409 default:
410 // Handle all unknown 5xx HTTP error codes as temporary and any other
411 // unknown error as one that needs more time to recover.
412 if (response_code >= 500 && response_code <= 599)
413 ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE);
414 else
415 ReportError(DM_STATUS_HTTP_STATUS_ERROR);
416 return;
417 }
418 }
419
420 GURL DeviceManagementRequestJobImpl::GetURL(
421 const std::string& server_url) {
422 std::string result(server_url);
423 result += '?';
424 for (ParameterMap::const_iterator entry(query_params_.begin());
425 entry != query_params_.end();
426 ++entry) {
427 if (entry != query_params_.begin())
428 result += '&';
429 result += net::EscapeQueryParamValue(entry->first, true);
430 result += '=';
431 result += net::EscapeQueryParamValue(entry->second, true);
432 }
433 return GURL(result);
434 }
435
436 void DeviceManagementRequestJobImpl::ConfigureRequest(
437 net::URLFetcher* fetcher) {
438 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
439 net::LOAD_DO_NOT_SAVE_COOKIES |
440 net::LOAD_DISABLE_CACHE |
441 (bypass_proxy_ ? net::LOAD_BYPASS_PROXY : 0));
442 std::string payload;
443 CHECK(request_.SerializeToString(&payload));
444 fetcher->SetUploadData(kPostContentType, payload);
445 std::string extra_headers;
446 if (!gaia_token_.empty())
447 extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n";
448 if (!dm_token_.empty())
449 extra_headers += kDMTokenAuthHeader + dm_token_ + "\n";
450 fetcher->SetExtraRequestHeaders(extra_headers);
451 }
452
453 bool DeviceManagementRequestJobImpl::ShouldRetry(
454 const net::URLFetcher* fetcher) {
455 if (FailedWithProxy(fetcher) && !bypass_proxy_) {
456 // Retry the job if it failed due to a broken proxy, by bypassing the
457 // proxy on the next try.
458 bypass_proxy_ = true;
459 return true;
460 }
461
462 // Early device policy fetches on ChromeOS and Auto-Enrollment checks are
463 // often interrupted during ChromeOS startup when network change notifications
464 // are sent. Allowing the fetcher to retry once after that is enough to
465 // recover; allow it to retry up to 3 times just in case.
466 if (fetcher->GetStatus().error() == net::ERR_NETWORK_CHANGED &&
467 retries_count_ < kMaxNetworkChangedRetries) {
468 ++retries_count_;
469 return true;
470 }
471
472 // The request didn't fail, or the limit of retry attempts has been reached;
473 // forward the result to the job owner.
474 return false;
475 }
476
477 void DeviceManagementRequestJobImpl::PrepareRetry() {
478 if (!retry_callback_.is_null())
479 retry_callback_.Run(this);
480 }
481
482 void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) {
483 em::DeviceManagementResponse dummy_response;
484 callback_.Run(code, dummy_response);
485 }
486
487 DeviceManagementRequestJob::~DeviceManagementRequestJob() {}
488
489 void DeviceManagementRequestJob::SetGaiaToken(const std::string& gaia_token) {
490 gaia_token_ = gaia_token;
491 }
492
493 void DeviceManagementRequestJob::SetOAuthToken(const std::string& oauth_token) {
494 AddParameter(dm_protocol::kParamOAuthToken, oauth_token);
495 }
496
497 void DeviceManagementRequestJob::SetUserAffiliation(
498 UserAffiliation user_affiliation) {
499 AddParameter(dm_protocol::kParamUserAffiliation,
500 UserAffiliationToString(user_affiliation));
501 }
502
503 void DeviceManagementRequestJob::SetDMToken(const std::string& dm_token) {
504 dm_token_ = dm_token;
505 }
506
507 void DeviceManagementRequestJob::SetClientID(const std::string& client_id) {
508 AddParameter(dm_protocol::kParamDeviceID, client_id);
509 }
510
511 em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() {
512 return &request_;
513 }
514
515 DeviceManagementRequestJob::DeviceManagementRequestJob(JobType type) {
516 AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type));
517 AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType);
518 AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType);
519 AddParameter(dm_protocol::kParamAgent, GetAgentString());
520 AddParameter(dm_protocol::kParamPlatform, GetPlatformString());
521 }
522
523 void DeviceManagementRequestJob::SetRetryCallback(
524 const RetryCallback& retry_callback) {
525 retry_callback_ = retry_callback;
526 }
527
528 void DeviceManagementRequestJob::Start(const Callback& callback) {
529 callback_ = callback;
530 Run();
531 }
532
533 void DeviceManagementRequestJob::AddParameter(const std::string& name,
534 const std::string& value) {
535 query_params_.push_back(std::make_pair(name, value));
536 }
537
538 // A random value that other fetchers won't likely use.
539 const int DeviceManagementService::kURLFetcherID = 0xde71ce1d;
540
541 DeviceManagementService::~DeviceManagementService() {
542 // All running jobs should have been cancelled by now.
543 DCHECK(pending_jobs_.empty());
544 DCHECK(queued_jobs_.empty());
545 }
546
547 DeviceManagementRequestJob* DeviceManagementService::CreateJob(
548 DeviceManagementRequestJob::JobType type) {
549 return new DeviceManagementRequestJobImpl(type, this);
550 }
551
552 void DeviceManagementService::ScheduleInitialization(int64 delay_milliseconds) {
553 if (initialized_)
554 return;
555 MessageLoop::current()->PostDelayedTask(
556 FROM_HERE,
557 base::Bind(&DeviceManagementService::Initialize,
558 weak_ptr_factory_.GetWeakPtr()),
559 base::TimeDelta::FromMilliseconds(delay_milliseconds));
560 }
561
562 void DeviceManagementService::Initialize() {
563 if (initialized_)
564 return;
565 DCHECK(!request_context_getter_);
566 request_context_getter_ = new DeviceManagementRequestContextGetter(
567 g_browser_process->system_request_context());
568 initialized_ = true;
569
570 while (!queued_jobs_.empty()) {
571 StartJob(queued_jobs_.front());
572 queued_jobs_.pop_front();
573 }
574 }
575
576 void DeviceManagementService::Shutdown() {
577 for (JobFetcherMap::iterator job(pending_jobs_.begin());
578 job != pending_jobs_.end();
579 ++job) {
580 delete job->first;
581 queued_jobs_.push_back(job->second);
582 }
583 pending_jobs_.clear();
584 }
585
586 DeviceManagementService::DeviceManagementService(
587 const std::string& server_url)
588 : server_url_(server_url),
589 initialized_(false),
590 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
591 }
592
593 void DeviceManagementService::StartJob(DeviceManagementRequestJobImpl* job) {
594 net::URLFetcher* fetcher = net::URLFetcher::Create(
595 kURLFetcherID, job->GetURL(server_url_), net::URLFetcher::POST, this);
596 fetcher->SetRequestContext(request_context_getter_.get());
597 job->ConfigureRequest(fetcher);
598 pending_jobs_[fetcher] = job;
599 fetcher->Start();
600 }
601
602 void DeviceManagementService::OnURLFetchComplete(
603 const net::URLFetcher* source) {
604 JobFetcherMap::iterator entry(pending_jobs_.find(source));
605 if (entry == pending_jobs_.end()) {
606 NOTREACHED() << "Callback from foreign URL fetcher";
607 return;
608 }
609
610 DeviceManagementRequestJobImpl* job = entry->second;
611 pending_jobs_.erase(entry);
612
613 if (job->ShouldRetry(source)) {
614 VLOG(1) << "Retrying dmserver request.";
615 job->PrepareRetry();
616 StartJob(job);
617 } else {
618 std::string data;
619 source->GetResponseAsString(&data);
620 job->HandleResponse(source->GetStatus(), source->GetResponseCode(),
621 source->GetCookies(), data);
622 }
623 delete source;
624 }
625
626 void DeviceManagementService::AddJob(DeviceManagementRequestJobImpl* job) {
627 if (initialized_)
628 StartJob(job);
629 else
630 queued_jobs_.push_back(job);
631 }
632
633 void DeviceManagementService::RemoveJob(DeviceManagementRequestJobImpl* job) {
634 for (JobFetcherMap::iterator entry(pending_jobs_.begin());
635 entry != pending_jobs_.end();
636 ++entry) {
637 if (entry->second == job) {
638 delete entry->first;
639 pending_jobs_.erase(entry);
640 return;
641 }
642 }
643
644 const JobQueue::iterator elem =
645 std::find(queued_jobs_.begin(), queued_jobs_.end(), job);
646 if (elem != queued_jobs_.end())
647 queued_jobs_.erase(elem);
648 }
649
650 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/device_management_service.h ('k') | chrome/browser/policy/device_management_service_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698