Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / cronet / android / url_request_context_adapter.cc
1 // Copyright 2014 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 "components/cronet/android/url_request_context_adapter.h"
6
7 #include <limits>
8
9 #include "base/bind.h"
10 #include "base/files/file_util.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "components/cronet/url_request_context_config.h"
14 #include "net/android/network_change_notifier_factory_android.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/net_log_logger.h"
17 #include "net/base/net_util.h"
18 #include "net/base/network_change_notifier.h"
19 #include "net/cert/cert_verifier.h"
20 #include "net/http/http_auth_handler_factory.h"
21 #include "net/http/http_network_layer.h"
22 #include "net/http/http_server_properties.h"
23 #include "net/proxy/proxy_service.h"
24 #include "net/ssl/ssl_config_service_defaults.h"
25 #include "net/url_request/static_http_user_agent_settings.h"
26 #include "net/url_request/url_request_context_builder.h"
27 #include "net/url_request/url_request_context_storage.h"
28 #include "net/url_request/url_request_job_factory_impl.h"
29
30 namespace {
31
32 // MessageLoop on the main thread, which is where objects that receive Java
33 // notifications generally live.
34 base::MessageLoop* g_main_message_loop = nullptr;
35
36 net::NetworkChangeNotifier* g_network_change_notifier = nullptr;
37
38 class BasicNetworkDelegate : public net::NetworkDelegate {
39  public:
40   BasicNetworkDelegate() {}
41   virtual ~BasicNetworkDelegate() {}
42
43  private:
44   // net::NetworkDelegate implementation.
45   int OnBeforeURLRequest(net::URLRequest* request,
46                          const net::CompletionCallback& callback,
47                          GURL* new_url) override {
48     return net::OK;
49   }
50
51   int OnBeforeSendHeaders(net::URLRequest* request,
52                           const net::CompletionCallback& callback,
53                           net::HttpRequestHeaders* headers) override {
54     return net::OK;
55   }
56
57   void OnSendHeaders(net::URLRequest* request,
58                      const net::HttpRequestHeaders& headers) override {}
59
60   int OnHeadersReceived(
61       net::URLRequest* request,
62       const net::CompletionCallback& callback,
63       const net::HttpResponseHeaders* original_response_headers,
64       scoped_refptr<net::HttpResponseHeaders>* _response_headers,
65       GURL* allowed_unsafe_redirect_url) override {
66     return net::OK;
67   }
68
69   void OnBeforeRedirect(net::URLRequest* request,
70                         const GURL& new_location) override {}
71
72   void OnResponseStarted(net::URLRequest* request) override {}
73
74   void OnRawBytesRead(const net::URLRequest& request,
75                       int bytes_read) override {}
76
77   void OnCompleted(net::URLRequest* request, bool started) override {}
78
79   void OnURLRequestDestroyed(net::URLRequest* request) override {}
80
81   void OnPACScriptError(int line_number,
82                         const base::string16& error) override {}
83
84   NetworkDelegate::AuthRequiredResponse OnAuthRequired(
85       net::URLRequest* request,
86       const net::AuthChallengeInfo& auth_info,
87       const AuthCallback& callback,
88       net::AuthCredentials* credentials) override {
89     return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
90   }
91
92   bool OnCanGetCookies(const net::URLRequest& request,
93                        const net::CookieList& cookie_list) override {
94     return false;
95   }
96
97   bool OnCanSetCookie(const net::URLRequest& request,
98                       const std::string& cookie_line,
99                       net::CookieOptions* options) override {
100     return false;
101   }
102
103   bool OnCanAccessFile(const net::URLRequest& request,
104                        const base::FilePath& path) const override {
105     return false;
106   }
107
108   bool OnCanThrottleRequest(
109       const net::URLRequest& request) const override {
110     return false;
111   }
112
113   int OnBeforeSocketStreamConnect(
114       net::SocketStream* stream,
115       const net::CompletionCallback& callback) override {
116     return net::OK;
117   }
118
119   DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
120 };
121
122 }  // namespace
123
124 namespace cronet {
125
126 URLRequestContextAdapter::URLRequestContextAdapter(
127     URLRequestContextAdapterDelegate* delegate,
128     std::string user_agent) {
129   delegate_ = delegate;
130   user_agent_ = user_agent;
131 }
132
133 void URLRequestContextAdapter::Initialize(
134     scoped_ptr<URLRequestContextConfig> config) {
135   network_thread_ = new base::Thread("network");
136   base::Thread::Options options;
137   options.message_loop_type = base::MessageLoop::TYPE_IO;
138   network_thread_->StartWithOptions(options);
139   config_ = config.Pass();
140 }
141
142 void URLRequestContextAdapter::InitRequestContextOnMainThread() {
143   if (!base::MessageLoop::current()) {
144     DCHECK(!g_main_message_loop);
145     g_main_message_loop = new base::MessageLoopForUI();
146     base::MessageLoopForUI::current()->Start();
147   }
148   DCHECK_EQ(g_main_message_loop, base::MessageLoop::current());
149   if (!g_network_change_notifier) {
150     net::NetworkChangeNotifier::SetFactory(
151         new net::NetworkChangeNotifierFactoryAndroid());
152     g_network_change_notifier = net::NetworkChangeNotifier::Create();
153   }
154   proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
155       GetNetworkTaskRunner(), NULL));
156   GetNetworkTaskRunner()->PostTask(
157       FROM_HERE,
158       base::Bind(&URLRequestContextAdapter::InitRequestContextOnNetworkThread,
159                  this));
160 }
161
162 void URLRequestContextAdapter::InitRequestContextOnNetworkThread() {
163   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
164   DCHECK(config_);
165   // TODO(mmenke):  Add method to have the builder enable SPDY.
166   net::URLRequestContextBuilder context_builder;
167   context_builder.set_network_delegate(new BasicNetworkDelegate());
168   context_builder.set_proxy_config_service(proxy_config_service_.get());
169   config_->ConfigureURLRequestContextBuilder(&context_builder);
170
171   context_.reset(context_builder.Build());
172
173   // Currently (circa M39) enabling QUIC requires setting probability threshold.
174   if (config_->enable_quic) {
175     context_->http_server_properties()
176         ->SetAlternateProtocolProbabilityThreshold(0.0f);
177     for (size_t hint = 0; hint < config_->quic_hints.size(); ++hint) {
178       const URLRequestContextConfig::QuicHint& quic_hint =
179           *config_->quic_hints[hint];
180       if (quic_hint.host.empty()) {
181         LOG(ERROR) << "Empty QUIC hint host: " << quic_hint.host;
182         continue;
183       }
184
185       url::CanonHostInfo host_info;
186       std::string canon_host(net::CanonicalizeHost(quic_hint.host, &host_info));
187       if (!host_info.IsIPAddress() &&
188           !net::IsCanonicalizedHostCompliant(canon_host)) {
189         LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint.host;
190         continue;
191       }
192
193       if (quic_hint.port <= std::numeric_limits<uint16>::min() ||
194           quic_hint.port > std::numeric_limits<uint16>::max()) {
195         LOG(ERROR) << "Invalid QUIC hint port: "
196                    << quic_hint.port;
197         continue;
198       }
199
200       if (quic_hint.alternate_port <= std::numeric_limits<uint16>::min() ||
201           quic_hint.alternate_port > std::numeric_limits<uint16>::max()) {
202         LOG(ERROR) << "Invalid QUIC hint alternate port: "
203                    << quic_hint.alternate_port;
204         continue;
205       }
206
207       net::HostPortPair quic_hint_host_port_pair(canon_host,
208                                                  quic_hint.port);
209       context_->http_server_properties()->SetAlternateProtocol(
210           quic_hint_host_port_pair,
211           static_cast<uint16>(quic_hint.alternate_port),
212           net::AlternateProtocol::QUIC,
213           1.0f);
214     }
215   }
216   config_.reset(NULL);
217
218   if (VLOG_IS_ON(2)) {
219     net_log_observer_.reset(new NetLogObserver());
220     context_->net_log()->AddThreadSafeObserver(net_log_observer_.get(),
221                                                net::NetLog::LOG_ALL_BUT_BYTES);
222   }
223
224   is_context_initialized_ = true;
225   while (!tasks_waiting_for_context_.empty()) {
226     tasks_waiting_for_context_.front().Run();
227     tasks_waiting_for_context_.pop();
228   }
229
230   delegate_->OnContextInitialized(this);
231 }
232
233 void URLRequestContextAdapter::PostTaskToNetworkThread(
234     const tracked_objects::Location& posted_from,
235     const RunAfterContextInitTask& callback) {
236   GetNetworkTaskRunner()->PostTask(
237       posted_from,
238       base::Bind(
239           &URLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread,
240           this,
241           callback));
242 }
243
244 void URLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread(
245     const RunAfterContextInitTask& callback) {
246   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
247   if (is_context_initialized_) {
248     callback.Run();
249     return;
250   }
251   tasks_waiting_for_context_.push(callback);
252 }
253
254 URLRequestContextAdapter::~URLRequestContextAdapter() {
255   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
256   if (net_log_observer_) {
257     context_->net_log()->RemoveThreadSafeObserver(net_log_observer_.get());
258     net_log_observer_.reset();
259   }
260   StopNetLogHelper();
261   // TODO(mef): Ensure that |network_thread_| is destroyed properly.
262 }
263
264 const std::string& URLRequestContextAdapter::GetUserAgent(
265     const GURL& url) const {
266   return user_agent_;
267 }
268
269 net::URLRequestContext* URLRequestContextAdapter::GetURLRequestContext() {
270   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
271   if (!context_) {
272     LOG(ERROR) << "URLRequestContext is not set up";
273   }
274   return context_.get();
275 }
276
277 scoped_refptr<base::SingleThreadTaskRunner>
278 URLRequestContextAdapter::GetNetworkTaskRunner() const {
279   return network_thread_->message_loop_proxy();
280 }
281
282 void URLRequestContextAdapter::StartNetLogToFile(const std::string& file_name) {
283   PostTaskToNetworkThread(
284       FROM_HERE,
285       base::Bind(
286           &URLRequestContextAdapter::StartNetLogToFileHelper, this, file_name));
287 }
288
289 void URLRequestContextAdapter::StopNetLog() {
290   PostTaskToNetworkThread(
291       FROM_HERE, base::Bind(&URLRequestContextAdapter::StopNetLogHelper, this));
292 }
293
294 void URLRequestContextAdapter::StartNetLogToFileHelper(
295     const std::string& file_name) {
296   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
297   // Do nothing if already logging to a file.
298   if (net_log_logger_)
299     return;
300
301   base::FilePath file_path(file_name);
302   FILE* file = base::OpenFile(file_path, "w");
303   if (!file)
304     return;
305
306   scoped_ptr<base::Value> constants(net::NetLogLogger::GetConstants());
307   net_log_logger_.reset(new net::NetLogLogger(file, *constants));
308   net_log_logger_->StartObserving(context_->net_log());
309 }
310
311 void URLRequestContextAdapter::StopNetLogHelper() {
312   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
313   if (net_log_logger_) {
314     net_log_logger_->StopObserving();
315     net_log_logger_.reset();
316   }
317 }
318
319 void NetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) {
320   VLOG(2) << "Net log entry: type=" << entry.type()
321           << ", source=" << entry.source().type << ", phase=" << entry.phase();
322 }
323
324 }  // namespace cronet