• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/io_thread.h"
8 #include "chrome/browser/net/chrome_net_log.h"
9 #include "chrome/browser/policy/device_management_backend_impl.h"
10 #include "content/browser/browser_thread.h"
11 #include "net/base/cookie_monster.h"
12 #include "net/base/host_resolver.h"
13 #include "net/base/load_flags.h"
14 #include "net/base/ssl_config_service_defaults.h"
15 #include "net/http/http_auth_handler_factory.h"
16 #include "net/http/http_network_layer.h"
17 #include "net/proxy/proxy_service.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "net/url_request/url_request_status.h"
21 #include "webkit/glue/webkit_glue.h"
22 
23 namespace policy {
24 
25 namespace {
26 
27 // Custom request context implementation that allows to override the user agent,
28 // amongst others. Wraps a baseline request context from which we reuse the
29 // networking components.
30 class DeviceManagementRequestContext : public net::URLRequestContext {
31  public:
32   explicit DeviceManagementRequestContext(net::URLRequestContext* base_context);
33   virtual ~DeviceManagementRequestContext();
34 
35  private:
36   // Overridden from net::URLRequestContext:
37   virtual const std::string& GetUserAgent(const GURL& url) const;
38 };
39 
DeviceManagementRequestContext(net::URLRequestContext * base_context)40 DeviceManagementRequestContext::DeviceManagementRequestContext(
41     net::URLRequestContext* base_context) {
42   // Share resolver, proxy service and ssl bits with the baseline context. This
43   // is important so we don't make redundant requests (e.g. when resolving proxy
44   // auto configuration).
45   set_net_log(base_context->net_log());
46   set_host_resolver(base_context->host_resolver());
47   set_proxy_service(base_context->proxy_service());
48   set_ssl_config_service(base_context->ssl_config_service());
49 
50   // Share the http session.
51   set_http_transaction_factory(
52       new net::HttpNetworkLayer(
53           base_context->http_transaction_factory()->GetSession()));
54 
55   // No cookies, please.
56   set_cookie_store(new net::CookieMonster(NULL, NULL));
57 
58   // Initialize these to sane values for our purposes.
59   set_accept_language("*");
60   set_accept_charset("*");
61 }
62 
~DeviceManagementRequestContext()63 DeviceManagementRequestContext::~DeviceManagementRequestContext() {
64   delete http_transaction_factory();
65 }
66 
GetUserAgent(const GURL & url) const67 const std::string& DeviceManagementRequestContext::GetUserAgent(
68     const GURL& url) const {
69   return webkit_glue::GetUserAgent(url);
70 }
71 
72 // Request context holder.
73 class DeviceManagementRequestContextGetter
74     : public net::URLRequestContextGetter {
75  public:
DeviceManagementRequestContextGetter(net::URLRequestContextGetter * base_context_getter)76   DeviceManagementRequestContextGetter(
77       net::URLRequestContextGetter* base_context_getter)
78       : base_context_getter_(base_context_getter) {}
79 
80   // Overridden from net::URLRequestContextGetter:
81   virtual net::URLRequestContext* GetURLRequestContext();
82   virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const;
83 
84  private:
85   scoped_refptr<net::URLRequestContext> context_;
86   scoped_refptr<net::URLRequestContextGetter> base_context_getter_;
87 };
88 
89 
90 net::URLRequestContext*
GetURLRequestContext()91 DeviceManagementRequestContextGetter::GetURLRequestContext() {
92   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
93   if (!context_) {
94     context_ = new DeviceManagementRequestContext(
95         base_context_getter_->GetURLRequestContext());
96   }
97 
98   return context_.get();
99 }
100 
101 scoped_refptr<base::MessageLoopProxy>
GetIOMessageLoopProxy() const102 DeviceManagementRequestContextGetter::GetIOMessageLoopProxy() const {
103   return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
104 }
105 
106 }  // namespace
107 
~DeviceManagementService()108 DeviceManagementService::~DeviceManagementService() {
109   // All running jobs should have been canceled by now. If not, there are
110   // backend objects still around, which is an error.
111   DCHECK(pending_jobs_.empty());
112   DCHECK(queued_jobs_.empty());
113 }
114 
CreateBackend()115 DeviceManagementBackend* DeviceManagementService::CreateBackend() {
116   return new DeviceManagementBackendImpl(this);
117 }
118 
Initialize(net::URLRequestContextGetter * request_context_getter)119 void DeviceManagementService::Initialize(
120     net::URLRequestContextGetter* request_context_getter) {
121   DCHECK(!request_context_getter_);
122   request_context_getter_ =
123       new DeviceManagementRequestContextGetter(request_context_getter);
124   while (!queued_jobs_.empty()) {
125     StartJob(queued_jobs_.front());
126     queued_jobs_.pop_front();
127   }
128 }
129 
Shutdown()130 void DeviceManagementService::Shutdown() {
131   for (JobFetcherMap::iterator job(pending_jobs_.begin());
132        job != pending_jobs_.end();
133        ++job) {
134     delete job->first;
135     queued_jobs_.push_back(job->second);
136   }
137   pending_jobs_.clear();
138 }
139 
DeviceManagementService(const std::string & server_url)140 DeviceManagementService::DeviceManagementService(
141     const std::string& server_url)
142     : server_url_(server_url) {
143 }
144 
AddJob(DeviceManagementJob * job)145 void DeviceManagementService::AddJob(DeviceManagementJob* job) {
146   if (request_context_getter_.get())
147     StartJob(job);
148   else
149     queued_jobs_.push_back(job);
150 }
151 
RemoveJob(DeviceManagementJob * job)152 void DeviceManagementService::RemoveJob(DeviceManagementJob* job) {
153   for (JobFetcherMap::iterator entry(pending_jobs_.begin());
154        entry != pending_jobs_.end();
155        ++entry) {
156     if (entry->second == job) {
157       delete entry->first;
158       pending_jobs_.erase(entry);
159       return;
160     }
161   }
162 
163   const JobQueue::iterator elem =
164       std::find(queued_jobs_.begin(), queued_jobs_.end(), job);
165   if (elem != queued_jobs_.end())
166     queued_jobs_.erase(elem);
167 }
168 
StartJob(DeviceManagementJob * job)169 void DeviceManagementService::StartJob(DeviceManagementJob* job) {
170   URLFetcher* fetcher = URLFetcher::Create(0, job->GetURL(server_url_),
171                                            URLFetcher::POST, this);
172   fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES |
173                           net::LOAD_DO_NOT_SAVE_COOKIES |
174                           net::LOAD_DISABLE_CACHE);
175   fetcher->set_request_context(request_context_getter_.get());
176   job->ConfigureRequest(fetcher);
177   pending_jobs_[fetcher] = job;
178   fetcher->Start();
179 }
180 
OnURLFetchComplete(const URLFetcher * source,const GURL & url,const net::URLRequestStatus & status,int response_code,const ResponseCookies & cookies,const std::string & data)181 void DeviceManagementService::OnURLFetchComplete(
182     const URLFetcher* source,
183     const GURL& url,
184     const net::URLRequestStatus& status,
185     int response_code,
186     const ResponseCookies& cookies,
187     const std::string& data) {
188   JobFetcherMap::iterator entry(pending_jobs_.find(source));
189   if (entry != pending_jobs_.end()) {
190     DeviceManagementJob* job = entry->second;
191     pending_jobs_.erase(entry);
192     job->HandleResponse(status, response_code, cookies, data);
193   } else {
194     NOTREACHED() << "Callback from foreign URL fetcher";
195   }
196   delete source;
197 }
198 
199 }  // namespace policy
200