Index: chrome/browser/policy/device_management_backend_impl.cc |
diff --git a/chrome/browser/policy/device_management_backend_impl.cc b/chrome/browser/policy/device_management_backend_impl.cc |
index c0e9b0722c28a3d36b50e25cb370772b3846cf70..2808c1905619cd8e34808fc317d504bcb0719ff0 100644 |
--- a/chrome/browser/policy/device_management_backend_impl.cc |
+++ b/chrome/browser/policy/device_management_backend_impl.cc |
@@ -7,22 +7,10 @@ |
#include <utility> |
#include <vector> |
-#include "base/stl_util-inl.h" |
#include "base/stringprintf.h" |
-#include "chrome/browser/browser_thread.h" |
-#include "chrome/common/net/url_request_context_getter.h" |
-#include "net/base/cookie_monster.h" |
#include "net/base/escape.h" |
-#include "net/base/host_resolver.h" |
-#include "net/base/ssl_config_service_defaults.h" |
-#include "net/http/http_auth_handler_factory.h" |
-#include "net/http/http_network_layer.h" |
-#include "net/proxy/proxy_service.h" |
-#include "net/url_request/url_request_context.h" |
#include "net/url_request/url_request_status.h" |
-#include "chrome/browser/browser_process.h" |
-#include "chrome/browser/io_thread.h" |
-#include "chrome/browser/net/chrome_net_log.h" |
+#include "chrome/browser/policy/device_management_service.h" |
#include "chrome/common/chrome_version_info.h" |
namespace policy { |
@@ -32,98 +20,20 @@ namespace { |
// Name constants for URL query parameters. |
const char kServiceParamRequest[] = "request"; |
const char kServiceParamDeviceType[] = "devicetype"; |
+const char kServiceParamAppType[] = "apptype"; |
const char kServiceParamDeviceID[] = "deviceid"; |
const char kServiceParamAgent[] = "agent"; |
-// String constants for the device type and agent we report to the service. |
-const char kServiceValueDeviceType[] = "Chrome"; |
+// String constants for the device and app type we report to the server. |
+const char kServiceValueDeviceType[] = "Chrome OS"; |
+const char kServiceValueAppType[] = "Chrome"; |
+ |
const char kServiceValueAgent[] = |
"%s enterprise management client version %s (%s)"; |
const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; |
const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; |
-} // namespace |
- |
-// Custom request context implementation that allows to override the user agent, |
-// amongst others. Using the default request context is not an option since this |
-// service may be constructed before the default request context is created |
-// (i.e. before the profile has been loaded). |
-class DeviceManagementBackendRequestContext : public URLRequestContext { |
- public: |
- explicit DeviceManagementBackendRequestContext(IOThread::Globals* io_globals); |
- virtual ~DeviceManagementBackendRequestContext(); |
- |
- private: |
- virtual const std::string& GetUserAgent(const GURL& url) const; |
- |
- std::string user_agent_; |
-}; |
- |
-DeviceManagementBackendRequestContext::DeviceManagementBackendRequestContext( |
- IOThread::Globals* io_globals) { |
- net_log_ = io_globals->net_log.get(); |
- host_resolver_ = io_globals->host_resolver.get(); |
- proxy_service_ = net::ProxyService::CreateDirect(); |
- ssl_config_service_ = net::SSLConfigService::CreateSystemSSLConfigService(); |
- http_auth_handler_factory_ = |
- net::HttpAuthHandlerFactory::CreateDefault(host_resolver_); |
- http_transaction_factory_ = |
- net::HttpNetworkLayer::CreateFactory(host_resolver_, |
- io_globals->dnsrr_resolver.get(), |
- NULL /* ssl_host_info_factory */, |
- proxy_service_, |
- ssl_config_service_, |
- http_auth_handler_factory_, |
- NULL /* network_delegate */, |
- net_log_); |
- cookie_store_ = new net::CookieMonster(NULL, NULL); |
- user_agent_ = DeviceManagementBackendImpl::GetAgentString(); |
- accept_language_ = "*"; |
- accept_charset_ = "*"; |
-} |
- |
-DeviceManagementBackendRequestContext |
- ::~DeviceManagementBackendRequestContext() { |
- delete http_transaction_factory_; |
- delete http_auth_handler_factory_; |
-} |
- |
-const std::string& |
-DeviceManagementBackendRequestContext::GetUserAgent(const GURL& url) const { |
- return user_agent_; |
-} |
- |
-// Request context holder. |
-class DeviceManagementBackendRequestContextGetter |
- : public URLRequestContextGetter { |
- public: |
- DeviceManagementBackendRequestContextGetter() |
- : io_thread_(g_browser_process->io_thread()) {} |
- |
- // URLRequestContextGetter overrides. |
- virtual URLRequestContext* GetURLRequestContext(); |
- virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const; |
- |
- private: |
- scoped_refptr<URLRequestContext> context_; |
- IOThread* io_thread_; |
-}; |
- |
- |
-URLRequestContext* |
-DeviceManagementBackendRequestContextGetter::GetURLRequestContext() { |
- if (!context_) |
- context_ = new DeviceManagementBackendRequestContext(io_thread_->globals()); |
- |
- return context_.get(); |
-} |
- |
-scoped_refptr<base::MessageLoopProxy> |
-DeviceManagementBackendRequestContextGetter::GetIOMessageLoopProxy() const { |
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); |
-} |
- |
// Helper class for URL query parameter encoding/decoding. |
class URLQueryParameters { |
public: |
@@ -162,31 +72,96 @@ std::string URLQueryParameters::Encode() { |
return result; |
} |
-// Wraps common response parsing and handling functionality. |
-class ResponseHandler { |
+} // namespace |
+ |
+// A base class containing the common code for the jobs created by the backend |
+// implementation. Subclasses provide custom code for handling actual register, |
+// unregister, and policy jobs. |
+class DeviceManagementJobBase |
+ : public DeviceManagementService::DeviceManagementJob { |
public: |
- ResponseHandler() {} |
- virtual ~ResponseHandler() {} |
+ virtual ~DeviceManagementJobBase() { |
+ backend_impl_->JobDone(this); |
+ } |
- // Handles the URL request response. |
- void HandleResponse(const URLRequestStatus& status, |
- int response_code, |
- const ResponseCookies& cookies, |
- const std::string& data); |
+ // DeviceManagementJob overrides: |
+ virtual void HandleResponse(const URLRequestStatus& status, |
+ int response_code, |
+ const ResponseCookies& cookies, |
+ const std::string& data); |
+ virtual GURL GetURL(const std::string& server_url); |
+ virtual void ConfigureRequest(URLFetcher* fetcher); |
+ |
+ protected: |
+ // Constructs a device management job running for the given backend. |
+ DeviceManagementJobBase(DeviceManagementBackendImpl* backend_impl, |
+ const std::string& request_type) |
+ : backend_impl_(backend_impl) { |
+ query_params_.Put(kServiceParamRequest, request_type); |
+ query_params_.Put(kServiceParamDeviceType, kServiceValueDeviceType); |
+ query_params_.Put(kServiceParamAppType, kServiceValueAppType); |
+ chrome::VersionInfo version_info; |
+ std::string agent = base::StringPrintf(kServiceValueAgent, |
+ version_info.Name().c_str(), |
+ version_info.Version().c_str(), |
+ version_info.LastChange().c_str()); |
+ query_params_.Put(kServiceParamAgent, agent); |
+ } |
- // Forwards the given error to the delegate. |
- virtual void OnError(DeviceManagementBackend::ErrorCode error) = 0; |
+ void SetQueryParam(const std::string& name, const std::string& value) { |
+ query_params_.Put(name, value); |
+ } |
+ |
+ void SetAuthToken(const std::string& auth_token) { |
+ auth_token_ = auth_token; |
+ } |
+ |
+ void SetDeviceManagementToken(const std::string& device_management_token) { |
+ device_management_token_ = device_management_token; |
+ } |
+ |
+ void SetDeviceID(const std::string& device_id) { |
+ query_params_.Put(kServiceParamDeviceID, device_id); |
+ } |
+ |
+ void SetPayload(const em::DeviceManagementRequest& request) { |
+ if (!request.SerializeToString(&payload_)) { |
+ NOTREACHED(); |
+ LOG(ERROR) << "Failed to serialize request."; |
+ } |
+ } |
private: |
- // Implemented by subclasses to handle the decoded response. |
- virtual void ProcessResponse( |
+ // Implemented by subclasses to handle decoded responses and errors. |
+ virtual void OnResponse( |
const em::DeviceManagementResponse& response) = 0; |
+ virtual void OnError(DeviceManagementBackend::ErrorCode error) = 0; |
+ |
+ // The backend this job is handling a request for. |
+ DeviceManagementBackendImpl* backend_impl_; |
+ |
+ // Query parameters. |
+ URLQueryParameters query_params_; |
+ |
+ // Auth token (if applicaple). |
+ std::string auth_token_; |
+ |
+ // Device management token (if applicable). |
+ std::string device_management_token_; |
+ |
+ // The payload. |
+ std::string payload_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeviceManagementJobBase); |
}; |
-void ResponseHandler::HandleResponse(const URLRequestStatus& status, |
- int response_code, |
- const ResponseCookies& cookies, |
- const std::string& data) { |
+void DeviceManagementJobBase::HandleResponse(const URLRequestStatus& status, |
+ int response_code, |
+ const ResponseCookies& cookies, |
+ const std::string& data) { |
+ // Delete ourselves when this is done. |
+ scoped_ptr<DeviceManagementJob> scoped_killer(this); |
+ |
if (status.status() != URLRequestStatus::SUCCESS) { |
OnError(DeviceManagementBackend::kErrorRequestFailed); |
return; |
@@ -226,77 +201,162 @@ void ResponseHandler::HandleResponse(const URLRequestStatus& status, |
return; |
} |
- ProcessResponse(response); |
+ OnResponse(response); |
+} |
+ |
+GURL DeviceManagementJobBase::GetURL( |
+ const std::string& server_url) { |
+ return GURL(server_url + '?' + query_params_.Encode()); |
+} |
+ |
+void DeviceManagementJobBase::ConfigureRequest(URLFetcher* fetcher) { |
+ fetcher->set_upload_data("application/octet-stream", payload_); |
+ std::string extra_headers; |
+ if (!auth_token_.empty()) |
+ extra_headers += kServiceTokenAuthHeader + auth_token_ + "\n"; |
+ if (!device_management_token_.empty()) |
+ extra_headers += kDMTokenAuthHeader + device_management_token_ + "\n"; |
+ fetcher->set_extra_request_headers(extra_headers); |
} |
-// Handles device registration responses. |
-class RegisterResponseHandler : public ResponseHandler { |
+// Handles device registration jobs. |
+class DeviceManagementRegisterJob : public DeviceManagementJobBase { |
public: |
- RegisterResponseHandler( |
- DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate) |
- : delegate_(delegate) {} |
+ DeviceManagementRegisterJob( |
+ DeviceManagementBackendImpl* backend_impl, |
+ const std::string& auth_token, |
+ const std::string& device_id, |
+ const em::DeviceRegisterRequest& request, |
+ DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate); |
+ virtual ~DeviceManagementRegisterJob() {} |
private: |
- // ResponseHandler overrides. |
+ // DeviceManagementJobBase overrides. |
virtual void OnError(DeviceManagementBackend::ErrorCode error) { |
delegate_->OnError(error); |
} |
- virtual void ProcessResponse(const em::DeviceManagementResponse& response) { |
+ virtual void OnResponse(const em::DeviceManagementResponse& response) { |
delegate_->HandleRegisterResponse(response.register_response()); |
} |
DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeviceManagementRegisterJob); |
}; |
-// Handles device unregister responses. |
-class UnregisterResponseHandler : public ResponseHandler { |
+DeviceManagementRegisterJob::DeviceManagementRegisterJob( |
+ DeviceManagementBackendImpl* backend_impl, |
+ const std::string& auth_token, |
+ const std::string& device_id, |
+ const em::DeviceRegisterRequest& request, |
+ DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate) |
+ : DeviceManagementJobBase(backend_impl, "register"), |
+ delegate_(delegate) { |
+ SetDeviceID(device_id); |
+ SetAuthToken(auth_token); |
+ em::DeviceManagementRequest request_wrapper; |
+ request_wrapper.mutable_register_request()->CopyFrom(request); |
+ SetPayload(request_wrapper); |
+} |
+ |
+// Handles device unregistration jobs. |
+class DeviceManagementUnregisterJob : public DeviceManagementJobBase { |
public: |
- UnregisterResponseHandler( |
- DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate) |
- : delegate_(delegate) {} |
+ DeviceManagementUnregisterJob( |
+ DeviceManagementBackendImpl* backend_impl, |
+ const std::string& device_management_token, |
+ const em::DeviceUnregisterRequest& request, |
+ DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate); |
+ virtual ~DeviceManagementUnregisterJob() {} |
private: |
- // ResponseHandler overrides. |
+ // DeviceManagementJobBase overrides. |
virtual void OnError(DeviceManagementBackend::ErrorCode error) { |
delegate_->OnError(error); |
} |
- virtual void ProcessResponse(const em::DeviceManagementResponse& response) { |
+ virtual void OnResponse(const em::DeviceManagementResponse& response) { |
delegate_->HandleUnregisterResponse(response.unregister_response()); |
} |
DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeviceManagementUnregisterJob); |
}; |
-// Handles device policy responses. |
-class PolicyResponseHandler : public ResponseHandler { |
+DeviceManagementUnregisterJob::DeviceManagementUnregisterJob( |
+ DeviceManagementBackendImpl* backend_impl, |
+ const std::string& device_management_token, |
+ const em::DeviceUnregisterRequest& request, |
+ DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate) |
+ : DeviceManagementJobBase(backend_impl, "unregister"), |
+ delegate_(delegate) { |
+ SetDeviceManagementToken(device_management_token); |
+ em::DeviceManagementRequest request_wrapper; |
+ request_wrapper.mutable_unregister_request()->CopyFrom(request); |
+ SetPayload(request_wrapper); |
+} |
+ |
+// Handles policy request jobs. |
+class DeviceManagementPolicyJob : public DeviceManagementJobBase { |
public: |
- PolicyResponseHandler( |
- DeviceManagementBackend::DevicePolicyResponseDelegate* delegate) |
- : delegate_(delegate) {} |
+ DeviceManagementPolicyJob( |
+ DeviceManagementBackendImpl* backend_impl, |
+ const std::string& device_management_token, |
+ const em::DevicePolicyRequest& request, |
+ DeviceManagementBackend::DevicePolicyResponseDelegate* delegate); |
+ virtual ~DeviceManagementPolicyJob() {} |
private: |
- // ResponseHandler overrides. |
+ // DeviceManagementJobBase overrides. |
virtual void OnError(DeviceManagementBackend::ErrorCode error) { |
delegate_->OnError(error); |
} |
- virtual void ProcessResponse(const em::DeviceManagementResponse& response) { |
+ virtual void OnResponse(const em::DeviceManagementResponse& response) { |
delegate_->HandlePolicyResponse(response.policy_response()); |
} |
DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob); |
}; |
+DeviceManagementPolicyJob::DeviceManagementPolicyJob( |
+ DeviceManagementBackendImpl* backend_impl, |
+ const std::string& device_management_token, |
+ const em::DevicePolicyRequest& request, |
+ DeviceManagementBackend::DevicePolicyResponseDelegate* delegate) |
+ : DeviceManagementJobBase(backend_impl, "policy"), |
+ delegate_(delegate) { |
+ SetDeviceManagementToken(device_management_token); |
+ em::DeviceManagementRequest request_wrapper; |
+ request_wrapper.mutable_policy_request()->CopyFrom(request); |
+ SetPayload(request_wrapper); |
+} |
+ |
DeviceManagementBackendImpl::DeviceManagementBackendImpl( |
- const std::string& server_url) |
- : server_url_(server_url), |
- request_context_getter_( |
- new DeviceManagementBackendRequestContextGetter()) { |
+ DeviceManagementService* service) |
+ : service_(service) { |
} |
DeviceManagementBackendImpl::~DeviceManagementBackendImpl() { |
- // Cancel all pending requests. |
- STLDeleteContainerPairPointers(response_handlers_.begin(), |
- response_handlers_.end()); |
+ // Swap to a helper, so we don't interfere with the unregistration on delete. |
+ JobSet to_be_deleted; |
+ to_be_deleted.swap(pending_jobs_); |
+ for (JobSet::iterator job(to_be_deleted.begin()); |
+ job != to_be_deleted.end(); |
+ ++job) { |
+ service_->RemoveJob(*job); |
+ delete *job; |
+ } |
+} |
+ |
+void DeviceManagementBackendImpl::JobDone(DeviceManagementJobBase* job) { |
+ pending_jobs_.erase(job); |
+} |
+ |
+void DeviceManagementBackendImpl::AddJob(DeviceManagementJobBase* job) { |
+ pending_jobs_.insert(job); |
+ service_->AddJob(job); |
} |
void DeviceManagementBackendImpl::ProcessRegisterRequest( |
@@ -304,112 +364,24 @@ void DeviceManagementBackendImpl::ProcessRegisterRequest( |
const std::string& device_id, |
const em::DeviceRegisterRequest& request, |
DeviceRegisterResponseDelegate* delegate) { |
- em::DeviceManagementRequest request_wrapper; |
- request_wrapper.mutable_register_request()->CopyFrom(request); |
- |
- URLQueryParameters params; |
- PutCommonQueryParameters(¶ms); |
- params.Put(kServiceParamRequest, "register"); |
- params.Put(kServiceParamDeviceID, device_id); |
- |
- CreateFetcher(request_wrapper, |
- new RegisterResponseHandler(delegate), |
- params.Encode(), |
- kServiceTokenAuthHeader + auth_token); |
+ AddJob(new DeviceManagementRegisterJob(this, auth_token, device_id, request, |
+ delegate)); |
} |
void DeviceManagementBackendImpl::ProcessUnregisterRequest( |
const std::string& device_management_token, |
const em::DeviceUnregisterRequest& request, |
DeviceUnregisterResponseDelegate* delegate) { |
- em::DeviceManagementRequest request_wrapper; |
- request_wrapper.mutable_unregister_request()->CopyFrom(request); |
- |
- URLQueryParameters params; |
- PutCommonQueryParameters(¶ms); |
- params.Put(kServiceParamRequest, "unregister"); |
- |
- CreateFetcher(request_wrapper, |
- new UnregisterResponseHandler(delegate), |
- params.Encode(), |
- kDMTokenAuthHeader + device_management_token); |
+ AddJob(new DeviceManagementUnregisterJob(this, device_management_token, |
+ request, delegate)); |
} |
void DeviceManagementBackendImpl::ProcessPolicyRequest( |
const std::string& device_management_token, |
const em::DevicePolicyRequest& request, |
DevicePolicyResponseDelegate* delegate) { |
- em::DeviceManagementRequest request_wrapper; |
- request_wrapper.mutable_policy_request()->CopyFrom(request); |
- |
- URLQueryParameters params; |
- PutCommonQueryParameters(¶ms); |
- params.Put(kServiceParamRequest, "policy"); |
- |
- CreateFetcher(request_wrapper, |
- new PolicyResponseHandler(delegate), |
- params.Encode(), |
- kDMTokenAuthHeader + device_management_token); |
-} |
- |
-// static |
-std::string DeviceManagementBackendImpl::GetAgentString() { |
- chrome::VersionInfo version_info; |
- return base::StringPrintf(kServiceValueAgent, |
- version_info.Name().c_str(), |
- version_info.Version().c_str(), |
- version_info.LastChange().c_str()); |
-} |
- |
-void DeviceManagementBackendImpl::OnURLFetchComplete( |
- const URLFetcher* source, |
- const GURL& url, |
- const URLRequestStatus& status, |
- int response_code, |
- const ResponseCookies& cookies, |
- const std::string& data) { |
- ResponseHandlerMap::iterator entry(response_handlers_.find(source)); |
- if (entry != response_handlers_.end()) { |
- ResponseHandler* handler = entry->second; |
- handler->HandleResponse(status, response_code, cookies, data); |
- response_handlers_.erase(entry); |
- delete handler; |
- } else { |
- NOTREACHED() << "Callback from foreign URL fetcher"; |
- } |
- delete source; |
-} |
- |
-void DeviceManagementBackendImpl::CreateFetcher( |
- const em::DeviceManagementRequest& request, |
- ResponseHandler* handler, |
- const std::string& query_params, |
- const std::string& extra_headers) { |
- scoped_ptr<ResponseHandler> handler_ptr(handler); |
- |
- // Construct the payload. |
- std::string payload; |
- if (!request.SerializeToString(&payload)) { |
- handler->OnError(DeviceManagementBackend::kErrorRequestInvalid); |
- return; |
- } |
- |
- // Instantiate the fetcher. |
- GURL url(server_url_ + '?' + query_params); |
- URLFetcher* fetcher = URLFetcher::Create(0, url, URLFetcher::POST, this); |
- fetcher->set_request_context(request_context_getter_.get()); |
- fetcher->set_upload_data("application/octet-stream", payload); |
- fetcher->set_extra_request_headers(extra_headers); |
- response_handlers_[fetcher] = handler_ptr.release(); |
- |
- // Start the request. The fetcher will call OnURLFetchComplete when done. |
- fetcher->Start(); |
-} |
- |
-void DeviceManagementBackendImpl::PutCommonQueryParameters( |
- URLQueryParameters* params) { |
- params->Put(kServiceParamDeviceType, kServiceValueDeviceType); |
- params->Put(kServiceParamAgent, GetAgentString()); |
+ AddJob(new DeviceManagementPolicyJob(this, device_management_token, request, |
+ delegate)); |
} |
} // namespace policy |