Chromium Code Reviews| 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..6e9fdf900a38a435ef972e4ee9e51b0039b65abb 100644 |
| --- a/chrome/browser/policy/device_management_backend_impl.cc |
| +++ b/chrome/browser/policy/device_management_backend_impl.cc |
| @@ -5,15 +5,20 @@ |
| #include "chrome/browser/policy/device_management_backend_impl.h" |
| #include <utility> |
| +#include <set> |
| #include <vector> |
| +#include "base/command_line.h" |
| +#include "base/lazy_instance.h" |
| #include "base/stl_util-inl.h" |
| #include "base/stringprintf.h" |
| #include "chrome/browser/browser_thread.h" |
| +#include "chrome/common/chrome_switches.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/load_flags.h" |
| #include "net/base/ssl_config_service_defaults.h" |
| #include "net/http/http_auth_handler_factory.h" |
| #include "net/http/http_network_layer.h" |
| @@ -23,6 +28,8 @@ |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/io_thread.h" |
| #include "chrome/browser/net/chrome_net_log.h" |
| +#include "chrome/browser/profile.h" |
| +#include "chrome/common/chrome_switches.h" |
| #include "chrome/common/chrome_version_info.h" |
| namespace policy { |
| @@ -43,15 +50,51 @@ const char kServiceValueAgent[] = |
| const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; |
| const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; |
| -} // namespace |
| +// Helper class for URL query parameter encoding/decoding. |
| +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
|
| + public: |
| + URLQueryParameters() {} |
| + |
| + // Add a query parameter. |
| + void Put(const std::string& name, const std::string& value); |
| + |
| + // Produce the query string, taking care of properly encoding and assembling |
| + // the names and values. |
| + std::string Encode(); |
| + |
| + private: |
| + typedef std::vector<std::pair<std::string, std::string> > ParameterMap; |
| + ParameterMap params_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(URLQueryParameters); |
| +}; |
| + |
| +void URLQueryParameters::Put(const std::string& name, |
| + const std::string& value) { |
| + params_.push_back(std::make_pair(name, value)); |
| +} |
| + |
| +std::string URLQueryParameters::Encode() { |
| + std::string result; |
| + for (ParameterMap::const_iterator entry(params_.begin()); |
| + entry != params_.end(); |
| + ++entry) { |
| + if (entry != params_.begin()) |
| + result += '&'; |
| + result += EscapeUrlEncodedData(entry->first); |
| + result += '='; |
| + result += EscapeUrlEncodedData(entry->second); |
| + } |
| + return result; |
| +} |
| // 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). |
| +// amongst others. Wraps a baseline request context from which we reuse the |
| +// networking components. |
| class DeviceManagementBackendRequestContext : public URLRequestContext { |
| public: |
| - explicit DeviceManagementBackendRequestContext(IOThread::Globals* io_globals); |
| + explicit DeviceManagementBackendRequestContext( |
| + URLRequestContext* base_context); |
| virtual ~DeviceManagementBackendRequestContext(); |
| private: |
| @@ -61,23 +104,23 @@ class DeviceManagementBackendRequestContext : public URLRequestContext { |
| }; |
| 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_); |
| + URLRequestContext* base_context) { |
| + // Share resolver, proxy service and ssl bits with the baseline context. This |
| + // is important so we don't make redundant requests (e.g. when resolving proxy |
| + // auto configuration). |
| + net_log_ = base_context->net_log(); |
| + host_resolver_ = base_context->host_resolver(); |
| + proxy_service_ = base_context->proxy_service(); |
| + ssl_config_service_ = base_context->ssl_config_service(); |
| + |
| + // Share the http session. |
| + http_transaction_factory_ = net::HttpNetworkLayer::CreateFactory( |
| + base_context->http_transaction_factory()->GetSession()); |
| + |
| + // No cookies, please. |
| cookie_store_ = new net::CookieMonster(NULL, NULL); |
| + |
| + // Initialize these to sane values for our purposes. |
| user_agent_ = DeviceManagementBackendImpl::GetAgentString(); |
| accept_language_ = "*"; |
| accept_charset_ = "*"; |
| @@ -98,8 +141,9 @@ DeviceManagementBackendRequestContext::GetUserAgent(const GURL& url) const { |
| class DeviceManagementBackendRequestContextGetter |
| : public URLRequestContextGetter { |
| public: |
| - DeviceManagementBackendRequestContextGetter() |
| - : io_thread_(g_browser_process->io_thread()) {} |
| + DeviceManagementBackendRequestContextGetter( |
| + URLRequestContextGetter* base_context_getter) |
| + : base_context_getter_(base_context_getter) {} |
| // URLRequestContextGetter overrides. |
| virtual URLRequestContext* GetURLRequestContext(); |
| @@ -107,14 +151,17 @@ class DeviceManagementBackendRequestContextGetter |
| private: |
| scoped_refptr<URLRequestContext> context_; |
| - IOThread* io_thread_; |
| + scoped_refptr<URLRequestContextGetter> base_context_getter_; |
| }; |
| URLRequestContext* |
| DeviceManagementBackendRequestContextGetter::GetURLRequestContext() { |
| - if (!context_) |
| - context_ = new DeviceManagementBackendRequestContext(io_thread_->globals()); |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (!context_) { |
| + context_ = new DeviceManagementBackendRequestContext( |
| + base_context_getter_->GetURLRequestContext()); |
| + } |
| return context_.get(); |
| } |
| @@ -124,49 +171,70 @@ DeviceManagementBackendRequestContextGetter::GetIOMessageLoopProxy() const { |
| return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); |
| } |
| -// Helper class for URL query parameter encoding/decoding. |
| -class URLQueryParameters { |
| +} // namespace |
| + |
| +// A wrapper that implements the actual backend interface. It doesn't hold a |
| +// strong reference to the actual backend implementation object, but tracks |
| +// whether it's currently available or not and postpones requests accordingly. |
| +class DeviceManagementBackendProxy : public DeviceManagementBackend { |
| public: |
| - URLQueryParameters() {} |
| + DeviceManagementBackendProxy(DeviceManagementBackendImpl* backend); |
| + virtual ~DeviceManagementBackendProxy(); |
| - // Add a query parameter. |
| - void Put(const std::string& name, const std::string& value); |
| + // 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
|
| + void JobDone(DeviceManagementJob* job); |
| - // Produce the query string, taking care of properly encoding and assembling |
| - // the names and values. |
| - std::string Encode(); |
| + // Switches all proxies to a different backend instance. |
| + 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.
|
| private: |
| - typedef std::vector<std::pair<std::string, std::string> > ParameterMap; |
| - ParameterMap params_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(URLQueryParameters); |
| + typedef std::set<DeviceManagementJob*> JobSet; |
| + typedef std::set<DeviceManagementBackendProxy*> ProxySet; |
| + |
| + // Resets the backend pointer for this proxy. |
| + void ResetBackend(DeviceManagementBackendImpl* backend); |
| + |
| + // Add a job to the pending job set and register it with the backend (if |
| + // available). |
| + void AddJob(DeviceManagementJob* job); |
| + |
| + // 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.
|
| + virtual void ProcessRegisterRequest( |
| + const std::string& auth_token, |
| + const std::string& device_id, |
| + const em::DeviceRegisterRequest& request, |
| + DeviceRegisterResponseDelegate* response_delegate); |
| + virtual void ProcessUnregisterRequest( |
| + const std::string& device_management_token, |
| + const em::DeviceUnregisterRequest& request, |
| + DeviceUnregisterResponseDelegate* response_delegate); |
| + virtual void ProcessPolicyRequest( |
| + const std::string& device_management_token, |
| + const em::DevicePolicyRequest& request, |
| + DevicePolicyResponseDelegate* response_delegate); |
| + |
| + static ProxySet& proxies() { return proxies_.Get(); } |
| + |
| + // Keeps track of the jobs currently in flight. |
| + JobSet pending_jobs_; |
| + |
| + // The backend implementation pointer. |
| + DeviceManagementBackendImpl* backend_instance_; |
| + |
| + // Keeps a list of currently existing proxies. |
| + static base::LazyInstance<ProxySet> proxies_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DeviceManagementBackendProxy); |
| }; |
| -void URLQueryParameters::Put(const std::string& name, |
| - const std::string& value) { |
| - params_.push_back(std::make_pair(name, value)); |
| -} |
| - |
| -std::string URLQueryParameters::Encode() { |
| - std::string result; |
| - for (ParameterMap::const_iterator entry(params_.begin()); |
| - entry != params_.end(); |
| - ++entry) { |
| - if (entry != params_.begin()) |
| - result += '&'; |
| - result += EscapeUrlEncodedData(entry->first); |
| - result += '='; |
| - result += EscapeUrlEncodedData(entry->second); |
| - } |
| - return result; |
| -} |
| - |
| -// Wraps common response parsing and handling functionality. |
| -class ResponseHandler { |
| +// Represents a job run by the backend. This contains the common code, |
| +// subclasses provide custom code for actual register, unregister, and policy |
| +// jobs. |
| +class DeviceManagementJob { |
| public: |
| - ResponseHandler() {} |
| - virtual ~ResponseHandler() {} |
| + virtual ~DeviceManagementJob() { |
| + proxy_->JobDone(this); |
| + } |
| // Handles the URL request response. |
| void HandleResponse(const URLRequestStatus& status, |
| @@ -174,32 +242,90 @@ class ResponseHandler { |
| const ResponseCookies& cookies, |
| const std::string& data); |
| - // Forwards the given error to the delegate. |
| - virtual void OnError(DeviceManagementBackend::ErrorCode error) = 0; |
| + // Gets the URL to contact. |
| + GURL GetURL(const std::string& server_url); |
| + |
| + // Configures the fetcher, setting up payload and headers. |
| + void ConfigureRequest(URLFetcher* fetcher); |
| + |
| + protected: |
| + // Constructs a device management job running for the given proxy. |
| + DeviceManagementJob(DeviceManagementBackendProxy* proxy, |
| + const std::string& request_type) |
| + : proxy_(proxy) { |
| + query_params_.Put(kServiceParamRequest, request_type); |
| + query_params_.Put(kServiceParamDeviceType, kServiceValueDeviceType); |
| + query_params_.Put(kServiceParamAgent, |
| + DeviceManagementBackendImpl::GetAgentString()); |
| + } |
| + |
| + 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. |
| + // Implemented by subclasses to handle decoded responses and errors. |
| virtual void ProcessResponse( |
| const em::DeviceManagementResponse& response) = 0; |
| + virtual void ProcessError(DeviceManagementBackend::ErrorCode error) = 0; |
| + |
| + // The proxy this job is handling a request for. |
| + DeviceManagementBackendProxy* proxy_; |
| + |
| + // 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(DeviceManagementJob); |
| }; |
| -void ResponseHandler::HandleResponse(const URLRequestStatus& status, |
| - int response_code, |
| - const ResponseCookies& cookies, |
| - const std::string& data) { |
| +void DeviceManagementJob::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); |
| + 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.
|
| return; |
| } |
| if (response_code != 200) { |
| - OnError(DeviceManagementBackend::kErrorHttpStatus); |
| + ProcessError(DeviceManagementBackend::kErrorHttpStatus); |
| return; |
| } |
| em::DeviceManagementResponse response; |
| if (!response.ParseFromString(data)) { |
| - OnError(DeviceManagementBackend::kErrorResponseDecoding); |
| + ProcessError(DeviceManagementBackend::kErrorResponseDecoding); |
| return; |
| } |
| @@ -208,37 +334,57 @@ void ResponseHandler::HandleResponse(const URLRequestStatus& status, |
| case em::DeviceManagementResponse::SUCCESS: |
| break; |
| case em::DeviceManagementResponse::DEVICE_MANAGEMENT_NOT_SUPPORTED: |
| - OnError(DeviceManagementBackend::kErrorServiceManagementNotSupported); |
| + ProcessError( |
| + DeviceManagementBackend::kErrorServiceManagementNotSupported); |
| return; |
| case em::DeviceManagementResponse::DEVICE_NOT_FOUND: |
| - OnError(DeviceManagementBackend::kErrorServiceDeviceNotFound); |
| + ProcessError(DeviceManagementBackend::kErrorServiceDeviceNotFound); |
| return; |
| case em::DeviceManagementResponse::DEVICE_MANAGEMENT_TOKEN_INVALID: |
| - OnError(DeviceManagementBackend::kErrorServiceManagementTokenInvalid); |
| + ProcessError( |
| + DeviceManagementBackend::kErrorServiceManagementTokenInvalid); |
| return; |
| case em::DeviceManagementResponse::ACTIVATION_PENDING: |
| - OnError(DeviceManagementBackend::kErrorServiceActivationPending); |
| + ProcessError(DeviceManagementBackend::kErrorServiceActivationPending); |
| return; |
| default: |
| // This should be caught by the protobuf decoder. |
| NOTREACHED(); |
| - OnError(DeviceManagementBackend::kErrorResponseDecoding); |
| + ProcessError(DeviceManagementBackend::kErrorResponseDecoding); |
| return; |
| } |
| ProcessResponse(response); |
| } |
| -// Handles device registration responses. |
| -class RegisterResponseHandler : public ResponseHandler { |
| +GURL DeviceManagementJob::GetURL(const std::string& server_url) { |
| + return GURL(server_url + '?' + query_params_.Encode()); |
| +} |
| + |
| +void DeviceManagementJob::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 jobs. |
| +class DeviceManagementRegisterJob : public DeviceManagementJob { |
| public: |
| - RegisterResponseHandler( |
| - DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate) |
| - : delegate_(delegate) {} |
| + DeviceManagementRegisterJob( |
| + DeviceManagementBackendProxy* proxy, |
| + const std::string& auth_token, |
| + const std::string& device_id, |
| + const em::DeviceRegisterRequest& request, |
| + DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate); |
| + virtual ~DeviceManagementRegisterJob() {} |
| private: |
| - // ResponseHandler overrides. |
| - virtual void OnError(DeviceManagementBackend::ErrorCode error) { |
| + // DeviceManagementJob overrides. |
| + virtual void ProcessError(DeviceManagementBackend::ErrorCode error) { |
| delegate_->OnError(error); |
| } |
| virtual void ProcessResponse(const em::DeviceManagementResponse& response) { |
| @@ -246,18 +392,38 @@ class RegisterResponseHandler : public ResponseHandler { |
| } |
| DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DeviceManagementRegisterJob); |
| }; |
| -// Handles device unregister responses. |
| -class UnregisterResponseHandler : public ResponseHandler { |
| +DeviceManagementRegisterJob::DeviceManagementRegisterJob( |
| + DeviceManagementBackendProxy* proxy, |
| + const std::string& auth_token, |
| + const std::string& device_id, |
| + const em::DeviceRegisterRequest& request, |
| + DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate) |
| + : DeviceManagementJob(proxy, "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 DeviceManagementJob { |
| public: |
| - UnregisterResponseHandler( |
| - DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate) |
| - : delegate_(delegate) {} |
| + DeviceManagementUnregisterJob( |
| + DeviceManagementBackendProxy* proxy, |
| + const std::string& device_management_token, |
| + const em::DeviceUnregisterRequest& request, |
| + DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate); |
| + virtual ~DeviceManagementUnregisterJob() {} |
| private: |
| - // ResponseHandler overrides. |
| - virtual void OnError(DeviceManagementBackend::ErrorCode error) { |
| + // DeviceManagementJob overrides. |
| + virtual void ProcessError(DeviceManagementBackend::ErrorCode error) { |
| delegate_->OnError(error); |
| } |
| virtual void ProcessResponse(const em::DeviceManagementResponse& response) { |
| @@ -265,18 +431,36 @@ class UnregisterResponseHandler : public ResponseHandler { |
| } |
| DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DeviceManagementUnregisterJob); |
| }; |
| -// Handles device policy responses. |
| -class PolicyResponseHandler : public ResponseHandler { |
| +DeviceManagementUnregisterJob::DeviceManagementUnregisterJob( |
| + DeviceManagementBackendProxy* proxy, |
| + const std::string& device_management_token, |
| + const em::DeviceUnregisterRequest& request, |
| + DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate) |
| + : DeviceManagementJob(proxy, "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 DeviceManagementJob { |
| public: |
| - PolicyResponseHandler( |
| - DeviceManagementBackend::DevicePolicyResponseDelegate* delegate) |
| - : delegate_(delegate) {} |
| + DeviceManagementPolicyJob( |
| + DeviceManagementBackendProxy* proxy, |
| + const std::string& device_management_token, |
| + const em::DevicePolicyRequest& request, |
| + DeviceManagementBackend::DevicePolicyResponseDelegate* delegate); |
| + virtual ~DeviceManagementPolicyJob() {} |
| private: |
| - // ResponseHandler overrides. |
| - virtual void OnError(DeviceManagementBackend::ErrorCode error) { |
| + // DeviceManagementJob overrides. |
| + virtual void ProcessError(DeviceManagementBackend::ErrorCode error) { |
| delegate_->OnError(error); |
| } |
| virtual void ProcessResponse(const em::DeviceManagementResponse& response) { |
| @@ -284,72 +468,135 @@ class PolicyResponseHandler : public ResponseHandler { |
| } |
| DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob); |
| }; |
| -DeviceManagementBackendImpl::DeviceManagementBackendImpl( |
| - const std::string& server_url) |
| - : server_url_(server_url), |
| - request_context_getter_( |
| - new DeviceManagementBackendRequestContextGetter()) { |
| +DeviceManagementPolicyJob::DeviceManagementPolicyJob( |
| + DeviceManagementBackendProxy* proxy, |
| + const std::string& device_management_token, |
| + const em::DevicePolicyRequest& request, |
| + DeviceManagementBackend::DevicePolicyResponseDelegate* delegate) |
| + : DeviceManagementJob(proxy, "policy"), |
| + delegate_(delegate) { |
| + SetDeviceManagementToken(device_management_token); |
| + em::DeviceManagementRequest request_wrapper; |
| + request_wrapper.mutable_policy_request()->CopyFrom(request); |
| + SetPayload(request_wrapper); |
| } |
| -DeviceManagementBackendImpl::~DeviceManagementBackendImpl() { |
| - // Cancel all pending requests. |
| - STLDeleteContainerPairPointers(response_handlers_.begin(), |
| - response_handlers_.end()); |
| +DeviceManagementBackendProxy::DeviceManagementBackendProxy( |
| + DeviceManagementBackendImpl* backend) |
| + : backend_instance_(backend) { |
| + proxies().insert(this); |
| +} |
| + |
| +DeviceManagementBackendProxy::~DeviceManagementBackendProxy() { |
| + // 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) { |
| + if (backend_instance_) |
| + backend_instance_->CancelJob(*job); |
| + delete *job; |
| + } |
| + |
| + proxies().erase(this); |
| +} |
| + |
| +void DeviceManagementBackendProxy::JobDone(DeviceManagementJob* job) { |
| + pending_jobs_.erase(job); |
| +} |
| + |
| +// static |
| +void DeviceManagementBackendProxy::SwitchBackend( |
| + DeviceManagementBackendImpl* backend) { |
| + for (ProxySet::iterator proxy(proxies().begin()); |
| + proxy != proxies().end(); |
| + ++proxy) { |
| + (*proxy)->ResetBackend(backend); |
| + } |
| +} |
| + |
| +void DeviceManagementBackendProxy::ResetBackend( |
| + DeviceManagementBackendImpl* backend) { |
| + if (backend == backend_instance_) |
| + return; |
| + |
| + // Switch our jobs over to the new backend. |
| + for (JobSet::iterator job(pending_jobs_.begin()); |
| + job != pending_jobs_.end(); |
| + ++job) { |
| + if (backend_instance_) |
| + backend_instance_->CancelJob(*job); |
| + if (backend) |
| + backend->StartJob(*job); |
| + } |
| + |
| + backend_instance_ = backend; |
| +} |
| + |
| +void DeviceManagementBackendProxy::AddJob(DeviceManagementJob* job) { |
| + pending_jobs_.insert(job); |
| + if (backend_instance_) |
| + backend_instance_->StartJob(job); |
| } |
| -void DeviceManagementBackendImpl::ProcessRegisterRequest( |
| +void DeviceManagementBackendProxy::ProcessRegisterRequest( |
| const std::string& auth_token, |
| 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( |
| +void DeviceManagementBackendProxy::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( |
| +void DeviceManagementBackendProxy::ProcessPolicyRequest( |
| const std::string& device_management_token, |
| const em::DevicePolicyRequest& request, |
| DevicePolicyResponseDelegate* delegate) { |
| - em::DeviceManagementRequest request_wrapper; |
| - request_wrapper.mutable_policy_request()->CopyFrom(request); |
| + AddJob(new DeviceManagementPolicyJob(this, device_management_token, request, |
| + delegate)); |
| +} |
| - URLQueryParameters params; |
| - PutCommonQueryParameters(¶ms); |
| - params.Put(kServiceParamRequest, "policy"); |
| +base::LazyInstance<DeviceManagementBackendProxy::ProxySet> |
| +DeviceManagementBackendProxy::proxies_(base::LINKER_INITIALIZED); |
| - CreateFetcher(request_wrapper, |
| - new PolicyResponseHandler(delegate), |
| - params.Encode(), |
| - kDMTokenAuthHeader + device_management_token); |
| +DeviceManagementBackendImpl::~DeviceManagementBackendImpl() { |
| + DeviceManagementBackendProxy::SwitchBackend(NULL); |
| + instance_ = NULL; |
| + |
| + // All running jobs should have been canceled by now. |
| + DCHECK(pending_jobs_.empty()); |
| +} |
| + |
| +// static |
| +DeviceManagementBackend* DeviceManagementBackendImpl::Get() { |
| + return new DeviceManagementBackendProxy(instance_); |
| +} |
| + |
| +// static |
| +DeviceManagementBackendImpl* |
| +DeviceManagementBackendImpl::Initialize(Profile* profile) { |
| + DCHECK(!instance_); |
| + CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| + if (command_line->HasSwitch(switches::kDeviceManagementUrl)) { |
| + return new DeviceManagementBackendImpl( |
| + command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl), |
| + profile->GetRequestContext()); |
| + } |
| + |
| + return NULL; |
| } |
| // static |
| @@ -361,6 +608,44 @@ std::string DeviceManagementBackendImpl::GetAgentString() { |
| version_info.LastChange().c_str()); |
| } |
| +DeviceManagementBackendImpl::DeviceManagementBackendImpl( |
| + const std::string& server_url, |
| + URLRequestContextGetter* request_context_getter) |
| + : server_url_(server_url), |
| + request_context_getter_( |
| + new DeviceManagementBackendRequestContextGetter( |
| + request_context_getter)) { |
| + DCHECK(!instance_); |
| + instance_ = this; |
| + |
| + // Tell the proxies there's a new backend. |
| + DeviceManagementBackendProxy::SwitchBackend(this); |
| +} |
| + |
| +void DeviceManagementBackendImpl::StartJob(DeviceManagementJob* job) { |
| + URLFetcher* fetcher = URLFetcher::Create(0, job->GetURL(server_url_), |
| + URLFetcher::POST, this); |
| + fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES | |
| + net::LOAD_DO_NOT_SAVE_COOKIES | |
| + net::LOAD_DISABLE_CACHE); |
| + fetcher->set_request_context(request_context_getter_.get()); |
| + job->ConfigureRequest(fetcher); |
| + pending_jobs_[fetcher] = job; |
| + fetcher->Start(); |
| +} |
| + |
| +void DeviceManagementBackendImpl::CancelJob(DeviceManagementJob* job) { |
| + for (JobFetcherMap::iterator entry(pending_jobs_.begin()); |
| + entry != pending_jobs_.end(); |
| + ++entry) { |
| + if (entry->second == job) { |
| + delete entry->first; |
| + pending_jobs_.erase(entry); |
| + break; |
| + } |
| + } |
| +} |
| + |
| void DeviceManagementBackendImpl::OnURLFetchComplete( |
| const URLFetcher* source, |
| const GURL& url, |
| @@ -368,48 +653,17 @@ void DeviceManagementBackendImpl::OnURLFetchComplete( |
| 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; |
| + JobFetcherMap::iterator entry(pending_jobs_.find(source)); |
| + if (entry != pending_jobs_.end()) { |
| + DeviceManagementJob* job = entry->second; |
| + job->HandleResponse(status, response_code, cookies, data); |
| + pending_jobs_.erase(entry); |
| } 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()); |
| -} |
| +DeviceManagementBackendImpl* DeviceManagementBackendImpl::instance_ = NULL; |
| } // namespace policy |