| Index: chrome/browser/policy/cloud/device_management_service.cc
 | 
| diff --git a/chrome/browser/policy/cloud/device_management_service.cc b/chrome/browser/policy/cloud/device_management_service.cc
 | 
| deleted file mode 100644
 | 
| index 51b3a9042bb2e38f800144fca2abfedeedc0ede7..0000000000000000000000000000000000000000
 | 
| --- a/chrome/browser/policy/cloud/device_management_service.cc
 | 
| +++ /dev/null
 | 
| @@ -1,515 +0,0 @@
 | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 | 
| -// Use of this source code is governed by a BSD-style license that can be
 | 
| -// found in the LICENSE file.
 | 
| -
 | 
| -#include "chrome/browser/policy/cloud/device_management_service.h"
 | 
| -
 | 
| -#include <utility>
 | 
| -
 | 
| -#include "base/bind.h"
 | 
| -#include "base/compiler_specific.h"
 | 
| -#include "base/message_loop/message_loop.h"
 | 
| -#include "base/message_loop/message_loop_proxy.h"
 | 
| -#include "net/base/escape.h"
 | 
| -#include "net/base/load_flags.h"
 | 
| -#include "net/base/net_errors.h"
 | 
| -#include "net/http/http_response_headers.h"
 | 
| -#include "net/url_request/url_fetcher.h"
 | 
| -#include "net/url_request/url_request_status.h"
 | 
| -#include "url/gurl.h"
 | 
| -
 | 
| -namespace em = enterprise_management;
 | 
| -
 | 
| -namespace policy {
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -const char kPostContentType[] = "application/protobuf";
 | 
| -
 | 
| -const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth=";
 | 
| -const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token=";
 | 
| -
 | 
| -// Number of times to retry on ERR_NETWORK_CHANGED errors.
 | 
| -const int kMaxNetworkChangedRetries = 3;
 | 
| -
 | 
| -// HTTP Error Codes of the DM Server with their concrete meanings in the context
 | 
| -// of the DM Server communication.
 | 
| -const int kSuccess = 200;
 | 
| -const int kInvalidArgument = 400;
 | 
| -const int kInvalidAuthCookieOrDMToken = 401;
 | 
| -const int kMissingLicenses = 402;
 | 
| -const int kDeviceManagementNotAllowed = 403;
 | 
| -const int kInvalidURL = 404;  // This error is not coming from the GFE.
 | 
| -const int kInvalidSerialNumber = 405;
 | 
| -const int kDeviceIdConflict = 409;
 | 
| -const int kDeviceNotFound = 410;
 | 
| -const int kPendingApproval = 412;
 | 
| -const int kInternalServerError = 500;
 | 
| -const int kServiceUnavailable = 503;
 | 
| -const int kPolicyNotFound = 902;  // This error is not sent as HTTP status code.
 | 
| -
 | 
| -bool IsProxyError(const net::URLRequestStatus status) {
 | 
| -  switch (status.error()) {
 | 
| -    case net::ERR_PROXY_CONNECTION_FAILED:
 | 
| -    case net::ERR_TUNNEL_CONNECTION_FAILED:
 | 
| -    case net::ERR_PROXY_AUTH_UNSUPPORTED:
 | 
| -    case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
 | 
| -    case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED:
 | 
| -    case net::ERR_PROXY_CERTIFICATE_INVALID:
 | 
| -    case net::ERR_SOCKS_CONNECTION_FAILED:
 | 
| -    case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
 | 
| -      return true;
 | 
| -  }
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -bool IsProtobufMimeType(const net::URLFetcher* fetcher) {
 | 
| -  return fetcher->GetResponseHeaders()->HasHeaderValue(
 | 
| -      "content-type", "application/x-protobuffer");
 | 
| -}
 | 
| -
 | 
| -bool FailedWithProxy(const net::URLFetcher* fetcher) {
 | 
| -  if ((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) != 0) {
 | 
| -    // The request didn't use a proxy.
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  if (!fetcher->GetStatus().is_success() &&
 | 
| -      IsProxyError(fetcher->GetStatus())) {
 | 
| -    LOG(WARNING) << "Proxy failed while contacting dmserver.";
 | 
| -    return true;
 | 
| -  }
 | 
| -
 | 
| -  if (fetcher->GetStatus().is_success() &&
 | 
| -      fetcher->GetResponseCode() == kSuccess &&
 | 
| -      fetcher->WasFetchedViaProxy() &&
 | 
| -      !IsProtobufMimeType(fetcher)) {
 | 
| -    // The proxy server can be misconfigured but pointing to an existing
 | 
| -    // server that replies to requests. Try to recover if a successful
 | 
| -    // request that went through a proxy returns an unexpected mime type.
 | 
| -    LOG(WARNING) << "Got bad mime-type in response from dmserver that was "
 | 
| -                 << "fetched via a proxy.";
 | 
| -    return true;
 | 
| -  }
 | 
| -
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -const char* UserAffiliationToString(UserAffiliation affiliation) {
 | 
| -  switch (affiliation) {
 | 
| -    case USER_AFFILIATION_MANAGED:
 | 
| -      return dm_protocol::kValueUserAffiliationManaged;
 | 
| -    case USER_AFFILIATION_NONE:
 | 
| -      return dm_protocol::kValueUserAffiliationNone;
 | 
| -  }
 | 
| -  NOTREACHED() << "Invalid user affiliation " << affiliation;
 | 
| -  return dm_protocol::kValueUserAffiliationNone;
 | 
| -}
 | 
| -
 | 
| -const char* JobTypeToRequestType(DeviceManagementRequestJob::JobType type) {
 | 
| -  switch (type) {
 | 
| -    case DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT:
 | 
| -      return dm_protocol::kValueRequestAutoEnrollment;
 | 
| -    case DeviceManagementRequestJob::TYPE_REGISTRATION:
 | 
| -      return dm_protocol::kValueRequestRegister;
 | 
| -    case DeviceManagementRequestJob::TYPE_POLICY_FETCH:
 | 
| -      return dm_protocol::kValueRequestPolicy;
 | 
| -    case DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH:
 | 
| -      return dm_protocol::kValueRequestApiAuthorization;
 | 
| -    case DeviceManagementRequestJob::TYPE_UNREGISTRATION:
 | 
| -      return dm_protocol::kValueRequestUnregister;
 | 
| -    case DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE:
 | 
| -      return dm_protocol::kValueRequestUploadCertificate;
 | 
| -  }
 | 
| -  NOTREACHED() << "Invalid job type " << type;
 | 
| -  return "";
 | 
| -}
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -// Request job implementation used with DeviceManagementService.
 | 
| -class DeviceManagementRequestJobImpl : public DeviceManagementRequestJob {
 | 
| - public:
 | 
| -  DeviceManagementRequestJobImpl(
 | 
| -      JobType type,
 | 
| -      const std::string& agent_parameter,
 | 
| -      const std::string& platform_parameter,
 | 
| -      DeviceManagementService* service,
 | 
| -      net::URLRequestContextGetter* request_context);
 | 
| -  virtual ~DeviceManagementRequestJobImpl();
 | 
| -
 | 
| -  // Handles the URL request response.
 | 
| -  void HandleResponse(const net::URLRequestStatus& status,
 | 
| -                      int response_code,
 | 
| -                      const net::ResponseCookies& cookies,
 | 
| -                      const std::string& data);
 | 
| -
 | 
| -  // Gets the URL to contact.
 | 
| -  GURL GetURL(const std::string& server_url);
 | 
| -
 | 
| -  // Configures the fetcher, setting up payload and headers.
 | 
| -  void ConfigureRequest(net::URLFetcher* fetcher);
 | 
| -
 | 
| -  // Returns true if this job should be retried. |fetcher| has just completed,
 | 
| -  // and can be inspected to determine if the request failed and should be
 | 
| -  // retried.
 | 
| -  bool ShouldRetry(const net::URLFetcher* fetcher);
 | 
| -
 | 
| -  // Invoked right before retrying this job.
 | 
| -  void PrepareRetry();
 | 
| -
 | 
| - protected:
 | 
| -  // DeviceManagementRequestJob:
 | 
| -  virtual void Run() OVERRIDE;
 | 
| -
 | 
| - private:
 | 
| -  // Invokes the callback with the given error code.
 | 
| -  void ReportError(DeviceManagementStatus code);
 | 
| -
 | 
| -  // Pointer to the service this job is associated with.
 | 
| -  DeviceManagementService* service_;
 | 
| -
 | 
| -  // Whether the BYPASS_PROXY flag should be set by ConfigureRequest().
 | 
| -  bool bypass_proxy_;
 | 
| -
 | 
| -  // Number of times that this job has been retried due to ERR_NETWORK_CHANGED.
 | 
| -  int retries_count_;
 | 
| -
 | 
| -  // The request context to use for this job.
 | 
| -  net::URLRequestContextGetter* request_context_;
 | 
| -
 | 
| -  DISALLOW_COPY_AND_ASSIGN(DeviceManagementRequestJobImpl);
 | 
| -};
 | 
| -
 | 
| -DeviceManagementRequestJobImpl::DeviceManagementRequestJobImpl(
 | 
| -    JobType type,
 | 
| -    const std::string& agent_parameter,
 | 
| -    const std::string& platform_parameter,
 | 
| -    DeviceManagementService* service,
 | 
| -    net::URLRequestContextGetter* request_context)
 | 
| -    : DeviceManagementRequestJob(type, agent_parameter, platform_parameter),
 | 
| -      service_(service),
 | 
| -      bypass_proxy_(false),
 | 
| -      retries_count_(0),
 | 
| -      request_context_(request_context) {}
 | 
| -
 | 
| -DeviceManagementRequestJobImpl::~DeviceManagementRequestJobImpl() {
 | 
| -  service_->RemoveJob(this);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJobImpl::Run() {
 | 
| -  service_->AddJob(this);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJobImpl::HandleResponse(
 | 
| -    const net::URLRequestStatus& status,
 | 
| -    int response_code,
 | 
| -    const net::ResponseCookies& cookies,
 | 
| -    const std::string& data) {
 | 
| -  if (status.status() != net::URLRequestStatus::SUCCESS) {
 | 
| -    LOG(WARNING) << "DMServer request failed, status: " << status.status()
 | 
| -                 << ", error: " << status.error();
 | 
| -    em::DeviceManagementResponse dummy_response;
 | 
| -    callback_.Run(DM_STATUS_REQUEST_FAILED, status.error(), dummy_response);
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
| -  if (response_code != kSuccess)
 | 
| -    LOG(WARNING) << "DMServer sent an error response: " << response_code;
 | 
| -
 | 
| -  switch (response_code) {
 | 
| -    case kSuccess: {
 | 
| -      em::DeviceManagementResponse response;
 | 
| -      if (!response.ParseFromString(data)) {
 | 
| -        ReportError(DM_STATUS_RESPONSE_DECODING_ERROR);
 | 
| -        return;
 | 
| -      }
 | 
| -      callback_.Run(DM_STATUS_SUCCESS, net::OK, response);
 | 
| -      return;
 | 
| -    }
 | 
| -    case kInvalidArgument:
 | 
| -      ReportError(DM_STATUS_REQUEST_INVALID);
 | 
| -      return;
 | 
| -    case kInvalidAuthCookieOrDMToken:
 | 
| -      ReportError(DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID);
 | 
| -      return;
 | 
| -    case kMissingLicenses:
 | 
| -      ReportError(DM_STATUS_SERVICE_MISSING_LICENSES);
 | 
| -      return;
 | 
| -    case kDeviceManagementNotAllowed:
 | 
| -      ReportError(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED);
 | 
| -      return;
 | 
| -    case kPendingApproval:
 | 
| -      ReportError(DM_STATUS_SERVICE_ACTIVATION_PENDING);
 | 
| -      return;
 | 
| -    case kInvalidURL:
 | 
| -    case kInternalServerError:
 | 
| -    case kServiceUnavailable:
 | 
| -      ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE);
 | 
| -      return;
 | 
| -    case kDeviceNotFound:
 | 
| -      ReportError(DM_STATUS_SERVICE_DEVICE_NOT_FOUND);
 | 
| -      return;
 | 
| -    case kPolicyNotFound:
 | 
| -      ReportError(DM_STATUS_SERVICE_POLICY_NOT_FOUND);
 | 
| -      return;
 | 
| -    case kInvalidSerialNumber:
 | 
| -      ReportError(DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER);
 | 
| -      return;
 | 
| -    case kDeviceIdConflict:
 | 
| -      ReportError(DM_STATUS_SERVICE_DEVICE_ID_CONFLICT);
 | 
| -      return;
 | 
| -    default:
 | 
| -      // Handle all unknown 5xx HTTP error codes as temporary and any other
 | 
| -      // unknown error as one that needs more time to recover.
 | 
| -      if (response_code >= 500 && response_code <= 599)
 | 
| -        ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE);
 | 
| -      else
 | 
| -        ReportError(DM_STATUS_HTTP_STATUS_ERROR);
 | 
| -      return;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -GURL DeviceManagementRequestJobImpl::GetURL(
 | 
| -    const std::string& server_url) {
 | 
| -  std::string result(server_url);
 | 
| -  result += '?';
 | 
| -  for (ParameterMap::const_iterator entry(query_params_.begin());
 | 
| -       entry != query_params_.end();
 | 
| -       ++entry) {
 | 
| -    if (entry != query_params_.begin())
 | 
| -      result += '&';
 | 
| -    result += net::EscapeQueryParamValue(entry->first, true);
 | 
| -    result += '=';
 | 
| -    result += net::EscapeQueryParamValue(entry->second, true);
 | 
| -  }
 | 
| -  return GURL(result);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJobImpl::ConfigureRequest(
 | 
| -    net::URLFetcher* fetcher) {
 | 
| -  fetcher->SetRequestContext(request_context_);
 | 
| -  fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
 | 
| -                        net::LOAD_DO_NOT_SAVE_COOKIES |
 | 
| -                        net::LOAD_DISABLE_CACHE |
 | 
| -                        (bypass_proxy_ ? net::LOAD_BYPASS_PROXY : 0));
 | 
| -  std::string payload;
 | 
| -  CHECK(request_.SerializeToString(&payload));
 | 
| -  fetcher->SetUploadData(kPostContentType, payload);
 | 
| -  std::string extra_headers;
 | 
| -  if (!gaia_token_.empty())
 | 
| -    extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n";
 | 
| -  if (!dm_token_.empty())
 | 
| -    extra_headers += kDMTokenAuthHeader + dm_token_ + "\n";
 | 
| -  fetcher->SetExtraRequestHeaders(extra_headers);
 | 
| -}
 | 
| -
 | 
| -bool DeviceManagementRequestJobImpl::ShouldRetry(
 | 
| -    const net::URLFetcher* fetcher) {
 | 
| -  if (FailedWithProxy(fetcher) && !bypass_proxy_) {
 | 
| -    // Retry the job if it failed due to a broken proxy, by bypassing the
 | 
| -    // proxy on the next try.
 | 
| -    bypass_proxy_ = true;
 | 
| -    return true;
 | 
| -  }
 | 
| -
 | 
| -  // Early device policy fetches on ChromeOS and Auto-Enrollment checks are
 | 
| -  // often interrupted during ChromeOS startup when network change notifications
 | 
| -  // are sent. Allowing the fetcher to retry once after that is enough to
 | 
| -  // recover; allow it to retry up to 3 times just in case.
 | 
| -  if (fetcher->GetStatus().error() == net::ERR_NETWORK_CHANGED &&
 | 
| -      retries_count_ < kMaxNetworkChangedRetries) {
 | 
| -    ++retries_count_;
 | 
| -    return true;
 | 
| -  }
 | 
| -
 | 
| -  // The request didn't fail, or the limit of retry attempts has been reached;
 | 
| -  // forward the result to the job owner.
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJobImpl::PrepareRetry() {
 | 
| -  if (!retry_callback_.is_null())
 | 
| -    retry_callback_.Run(this);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) {
 | 
| -  em::DeviceManagementResponse dummy_response;
 | 
| -  callback_.Run(code, net::OK, dummy_response);
 | 
| -}
 | 
| -
 | 
| -DeviceManagementRequestJob::~DeviceManagementRequestJob() {}
 | 
| -
 | 
| -void DeviceManagementRequestJob::SetGaiaToken(const std::string& gaia_token) {
 | 
| -  gaia_token_ = gaia_token;
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::SetOAuthToken(const std::string& oauth_token) {
 | 
| -  AddParameter(dm_protocol::kParamOAuthToken, oauth_token);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::SetUserAffiliation(
 | 
| -    UserAffiliation user_affiliation) {
 | 
| -  AddParameter(dm_protocol::kParamUserAffiliation,
 | 
| -               UserAffiliationToString(user_affiliation));
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::SetDMToken(const std::string& dm_token) {
 | 
| -  dm_token_ = dm_token;
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::SetClientID(const std::string& client_id) {
 | 
| -  AddParameter(dm_protocol::kParamDeviceID, client_id);
 | 
| -}
 | 
| -
 | 
| -em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() {
 | 
| -  return &request_;
 | 
| -}
 | 
| -
 | 
| -DeviceManagementRequestJob::DeviceManagementRequestJob(
 | 
| -    JobType type,
 | 
| -    const std::string& agent_parameter,
 | 
| -    const std::string& platform_parameter) {
 | 
| -  AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type));
 | 
| -  AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType);
 | 
| -  AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType);
 | 
| -  AddParameter(dm_protocol::kParamAgent, agent_parameter);
 | 
| -  AddParameter(dm_protocol::kParamPlatform, platform_parameter);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::SetRetryCallback(
 | 
| -    const RetryCallback& retry_callback) {
 | 
| -  retry_callback_ = retry_callback;
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::Start(const Callback& callback) {
 | 
| -  callback_ = callback;
 | 
| -  Run();
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementRequestJob::AddParameter(const std::string& name,
 | 
| -                                              const std::string& value) {
 | 
| -  query_params_.push_back(std::make_pair(name, value));
 | 
| -}
 | 
| -
 | 
| -// A random value that other fetchers won't likely use.
 | 
| -const int DeviceManagementService::kURLFetcherID = 0xde71ce1d;
 | 
| -
 | 
| -DeviceManagementService::~DeviceManagementService() {
 | 
| -  // All running jobs should have been cancelled by now.
 | 
| -  DCHECK(pending_jobs_.empty());
 | 
| -  DCHECK(queued_jobs_.empty());
 | 
| -}
 | 
| -
 | 
| -DeviceManagementRequestJob* DeviceManagementService::CreateJob(
 | 
| -    DeviceManagementRequestJob::JobType type,
 | 
| -    net::URLRequestContextGetter* request_context) {
 | 
| -  return new DeviceManagementRequestJobImpl(
 | 
| -      type,
 | 
| -      configuration_->GetAgentParameter(),
 | 
| -      configuration_->GetPlatformParameter(),
 | 
| -      this,
 | 
| -      request_context);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::ScheduleInitialization(int64 delay_milliseconds) {
 | 
| -  if (initialized_)
 | 
| -    return;
 | 
| -  base::MessageLoop::current()->PostDelayedTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&DeviceManagementService::Initialize,
 | 
| -                 weak_ptr_factory_.GetWeakPtr()),
 | 
| -      base::TimeDelta::FromMilliseconds(delay_milliseconds));
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::Initialize() {
 | 
| -  if (initialized_)
 | 
| -    return;
 | 
| -  initialized_ = true;
 | 
| -
 | 
| -  while (!queued_jobs_.empty()) {
 | 
| -    StartJob(queued_jobs_.front());
 | 
| -    queued_jobs_.pop_front();
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::Shutdown() {
 | 
| -  for (JobFetcherMap::iterator job(pending_jobs_.begin());
 | 
| -       job != pending_jobs_.end();
 | 
| -       ++job) {
 | 
| -    delete job->first;
 | 
| -    queued_jobs_.push_back(job->second);
 | 
| -  }
 | 
| -  pending_jobs_.clear();
 | 
| -}
 | 
| -
 | 
| -DeviceManagementService::DeviceManagementService(
 | 
| -    scoped_ptr<Configuration> configuration)
 | 
| -    : configuration_(configuration.Pass()),
 | 
| -      initialized_(false),
 | 
| -      weak_ptr_factory_(this) {
 | 
| -  DCHECK(configuration_);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::StartJob(DeviceManagementRequestJobImpl* job) {
 | 
| -  std::string server_url = GetServerURL();
 | 
| -  net::URLFetcher* fetcher = net::URLFetcher::Create(
 | 
| -      kURLFetcherID, job->GetURL(server_url), net::URLFetcher::POST, this);
 | 
| -  job->ConfigureRequest(fetcher);
 | 
| -  pending_jobs_[fetcher] = job;
 | 
| -  fetcher->Start();
 | 
| -}
 | 
| -
 | 
| -std::string DeviceManagementService::GetServerURL() {
 | 
| -  return configuration_->GetServerUrl();
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::OnURLFetchComplete(
 | 
| -    const net::URLFetcher* source) {
 | 
| -  JobFetcherMap::iterator entry(pending_jobs_.find(source));
 | 
| -  if (entry == pending_jobs_.end()) {
 | 
| -    NOTREACHED() << "Callback from foreign URL fetcher";
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
| -  DeviceManagementRequestJobImpl* job = entry->second;
 | 
| -  pending_jobs_.erase(entry);
 | 
| -
 | 
| -  if (job->ShouldRetry(source)) {
 | 
| -    VLOG(1) << "Retrying dmserver request.";
 | 
| -    job->PrepareRetry();
 | 
| -    StartJob(job);
 | 
| -  } else {
 | 
| -    std::string data;
 | 
| -    source->GetResponseAsString(&data);
 | 
| -    job->HandleResponse(source->GetStatus(), source->GetResponseCode(),
 | 
| -                        source->GetCookies(), data);
 | 
| -  }
 | 
| -  delete source;
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::AddJob(DeviceManagementRequestJobImpl* job) {
 | 
| -  if (initialized_)
 | 
| -    StartJob(job);
 | 
| -  else
 | 
| -    queued_jobs_.push_back(job);
 | 
| -}
 | 
| -
 | 
| -void DeviceManagementService::RemoveJob(DeviceManagementRequestJobImpl* job) {
 | 
| -  for (JobFetcherMap::iterator entry(pending_jobs_.begin());
 | 
| -       entry != pending_jobs_.end();
 | 
| -       ++entry) {
 | 
| -    if (entry->second == job) {
 | 
| -      delete entry->first;
 | 
| -      pending_jobs_.erase(entry);
 | 
| -      return;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  const JobQueue::iterator elem =
 | 
| -      std::find(queued_jobs_.begin(), queued_jobs_.end(), job);
 | 
| -  if (elem != queued_jobs_.end())
 | 
| -    queued_jobs_.erase(elem);
 | 
| -}
 | 
| -
 | 
| -}  // namespace policy
 | 
| 
 |