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 |