Remove obsolete entries from .gitignore.
[chromium-blink-merge.git] / components / cronet / android / cronet_url_request_context_adapter.cc
blob8009eb2a6c2474345770c5b8a0a5d0786d09b3a0
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.
5 #include "components/cronet/android/cronet_url_request_context_adapter.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/bind.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_file.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/prefs/pref_filter.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/prefs/pref_service_factory.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/time/time.h"
21 #include "base/values.h"
22 #include "components/cronet/url_request_context_config.h"
23 #include "jni/CronetUrlRequestContext_jni.h"
24 #include "net/base/load_flags.h"
25 #include "net/base/net_errors.h"
26 #include "net/base/network_delegate_impl.h"
27 #include "net/http/http_auth_handler_factory.h"
28 #include "net/http/http_server_properties_manager.h"
29 #include "net/log/write_to_file_net_log_observer.h"
30 #include "net/proxy/proxy_config_service_android.h"
31 #include "net/proxy/proxy_service.h"
32 #include "net/sdch/sdch_owner.h"
33 #include "net/url_request/url_request_context.h"
34 #include "net/url_request/url_request_context_builder.h"
35 #include "net/url_request/url_request_interceptor.h"
37 #if defined(DATA_REDUCTION_PROXY_SUPPORT)
38 #include "components/cronet/android/cronet_data_reduction_proxy.h"
39 #endif
41 namespace {
43 const char kHttpServerProperties[] = "net.http_server_properties";
45 class BasicNetworkDelegate : public net::NetworkDelegateImpl {
46 public:
47 BasicNetworkDelegate() {}
48 ~BasicNetworkDelegate() override {}
50 private:
51 // net::NetworkDelegate implementation.
52 int OnBeforeURLRequest(net::URLRequest* request,
53 const net::CompletionCallback& callback,
54 GURL* new_url) override {
55 return net::OK;
58 int OnBeforeSendHeaders(net::URLRequest* request,
59 const net::CompletionCallback& callback,
60 net::HttpRequestHeaders* headers) override {
61 return net::OK;
64 void OnSendHeaders(net::URLRequest* request,
65 const net::HttpRequestHeaders& headers) override {}
67 int OnHeadersReceived(
68 net::URLRequest* request,
69 const net::CompletionCallback& callback,
70 const net::HttpResponseHeaders* original_response_headers,
71 scoped_refptr<net::HttpResponseHeaders>* _response_headers,
72 GURL* allowed_unsafe_redirect_url) override {
73 return net::OK;
76 void OnBeforeRedirect(net::URLRequest* request,
77 const GURL& new_location) override {}
79 void OnResponseStarted(net::URLRequest* request) override {}
81 void OnCompleted(net::URLRequest* request, bool started) override {}
83 void OnURLRequestDestroyed(net::URLRequest* request) override {}
85 void OnPACScriptError(int line_number, const base::string16& error) override {
88 NetworkDelegate::AuthRequiredResponse OnAuthRequired(
89 net::URLRequest* request,
90 const net::AuthChallengeInfo& auth_info,
91 const AuthCallback& callback,
92 net::AuthCredentials* credentials) override {
93 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
96 bool OnCanGetCookies(const net::URLRequest& request,
97 const net::CookieList& cookie_list) override {
98 return false;
101 bool OnCanSetCookie(const net::URLRequest& request,
102 const std::string& cookie_line,
103 net::CookieOptions* options) override {
104 return false;
107 bool OnCanAccessFile(const net::URLRequest& request,
108 const base::FilePath& path) const override {
109 return false;
112 DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
115 } // namespace
117 namespace cronet {
119 // Explicitly register static JNI functions.
120 bool CronetUrlRequestContextAdapterRegisterJni(JNIEnv* env) {
121 return RegisterNativesImpl(env);
124 CronetURLRequestContextAdapter::CronetURLRequestContextAdapter(
125 scoped_ptr<URLRequestContextConfig> context_config)
126 : network_thread_(new base::Thread("network")),
127 http_server_properties_manager_(nullptr),
128 context_config_(context_config.Pass()),
129 is_context_initialized_(false),
130 default_load_flags_(net::LOAD_NORMAL) {
131 base::Thread::Options options;
132 options.message_loop_type = base::MessageLoop::TYPE_IO;
133 network_thread_->StartWithOptions(options);
136 CronetURLRequestContextAdapter::~CronetURLRequestContextAdapter() {
137 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
139 if (http_server_properties_manager_)
140 http_server_properties_manager_->ShutdownOnPrefThread();
141 if (pref_service_)
142 pref_service_->CommitPendingWrite();
143 StopNetLogOnNetworkThread();
146 void CronetURLRequestContextAdapter::InitRequestContextOnMainThread(
147 JNIEnv* env,
148 jobject jcaller) {
149 base::android::ScopedJavaGlobalRef<jobject> jcaller_ref;
150 jcaller_ref.Reset(env, jcaller);
151 net::ProxyConfigServiceAndroid* android_proxy_config_service =
152 static_cast<net::ProxyConfigServiceAndroid*>(
153 net::ProxyService::CreateSystemProxyConfigService(
154 GetNetworkTaskRunner(), nullptr /* Ignored on Android */));
155 // If a PAC URL is present, ignore it and use the address and port of
156 // Android system's local HTTP proxy server. See: crbug.com/432539.
157 android_proxy_config_service->set_exclude_pac_url(true);
158 proxy_config_service_.reset(android_proxy_config_service);
159 GetNetworkTaskRunner()->PostTask(
160 FROM_HERE,
161 base::Bind(&CronetURLRequestContextAdapter::InitializeOnNetworkThread,
162 base::Unretained(this), Passed(&context_config_),
163 jcaller_ref));
166 void CronetURLRequestContextAdapter::InitializeOnNetworkThread(
167 scoped_ptr<URLRequestContextConfig> config,
168 const base::android::ScopedJavaGlobalRef<jobject>&
169 jcronet_url_request_context) {
170 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
171 DCHECK(!is_context_initialized_);
172 DCHECK(proxy_config_service_);
173 // TODO(mmenke): Add method to have the builder enable SPDY.
174 net::URLRequestContextBuilder context_builder;
176 net_log_.reset(new net::NetLog);
177 scoped_ptr<net::NetworkDelegate> network_delegate(new BasicNetworkDelegate());
178 #if defined(DATA_REDUCTION_PROXY_SUPPORT)
179 DCHECK(!data_reduction_proxy_);
180 // For now, the choice to enable the data reduction proxy happens once,
181 // at initialization. It cannot be disabled thereafter.
182 if (!config->data_reduction_proxy_key.empty()) {
183 data_reduction_proxy_.reset(new CronetDataReductionProxy(
184 config->data_reduction_proxy_key, config->data_reduction_primary_proxy,
185 config->data_reduction_fallback_proxy,
186 config->data_reduction_secure_proxy_check_url, config->user_agent,
187 GetNetworkTaskRunner(), net_log_.get()));
188 network_delegate =
189 data_reduction_proxy_->CreateNetworkDelegate(network_delegate.Pass());
190 ScopedVector<net::URLRequestInterceptor> interceptors;
191 interceptors.push_back(data_reduction_proxy_->CreateInterceptor());
192 context_builder.SetInterceptors(interceptors.Pass());
194 #endif // defined(DATA_REDUCTION_PROXY_SUPPORT)
195 context_builder.set_network_delegate(network_delegate.Pass());
196 context_builder.set_net_log(net_log_.get());
198 // Android provides a local HTTP proxy server that handles proxying when a PAC
199 // URL is present. Create a proxy service without a resolver and rely on this
200 // local HTTP proxy. See: crbug.com/432539.
201 context_builder.set_proxy_service(
202 net::ProxyService::CreateWithoutProxyResolver(
203 proxy_config_service_.release(), net_log_.get()));
204 config->ConfigureURLRequestContextBuilder(&context_builder);
206 // Set up pref file if storage path is specified.
207 if (!config->storage_path.empty()) {
208 base::FilePath filepath(config->storage_path);
209 filepath = filepath.Append(FILE_PATH_LITERAL("local_prefs.json"));
210 json_pref_store_ = new JsonPrefStore(
211 filepath, GetFileThread()->task_runner(), scoped_ptr<PrefFilter>());
212 context_builder.SetFileTaskRunner(GetFileThread()->task_runner());
214 // Set up HttpServerPropertiesManager.
215 base::PrefServiceFactory factory;
216 factory.set_user_prefs(json_pref_store_);
217 scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
218 registry->RegisterDictionaryPref(kHttpServerProperties,
219 new base::DictionaryValue());
220 pref_service_ = factory.Create(registry.get()).Pass();
222 scoped_ptr<net::HttpServerPropertiesManager> http_server_properties_manager(
223 new net::HttpServerPropertiesManager(pref_service_.get(),
224 kHttpServerProperties,
225 GetNetworkTaskRunner()));
226 http_server_properties_manager->InitializeOnNetworkThread();
227 http_server_properties_manager_ = http_server_properties_manager.get();
228 context_builder.SetHttpServerProperties(
229 http_server_properties_manager.Pass());
232 context_ = context_builder.Build().Pass();
234 default_load_flags_ = net::LOAD_DO_NOT_SAVE_COOKIES |
235 net::LOAD_DO_NOT_SEND_COOKIES;
236 if (config->load_disable_cache)
237 default_load_flags_ |= net::LOAD_DISABLE_CACHE;
239 if (config->enable_sdch) {
240 DCHECK(context_->sdch_manager());
241 sdch_owner_.reset(
242 new net::SdchOwner(context_->sdch_manager(), context_.get()));
243 if (json_pref_store_)
244 sdch_owner_->EnablePersistentStorage(json_pref_store_.get());
247 // Currently (circa M39) enabling QUIC requires setting probability threshold.
248 if (config->enable_quic) {
249 context_->http_server_properties()
250 ->SetAlternativeServiceProbabilityThreshold(0.0f);
251 for (auto hint = config->quic_hints.begin();
252 hint != config->quic_hints.end(); ++hint) {
253 const URLRequestContextConfig::QuicHint& quic_hint = **hint;
254 if (quic_hint.host.empty()) {
255 LOG(ERROR) << "Empty QUIC hint host: " << quic_hint.host;
256 continue;
259 url::CanonHostInfo host_info;
260 std::string canon_host(net::CanonicalizeHost(quic_hint.host, &host_info));
261 if (!host_info.IsIPAddress() &&
262 !net::IsCanonicalizedHostCompliant(canon_host)) {
263 LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint.host;
264 continue;
267 if (quic_hint.port <= std::numeric_limits<uint16>::min() ||
268 quic_hint.port > std::numeric_limits<uint16>::max()) {
269 LOG(ERROR) << "Invalid QUIC hint port: "
270 << quic_hint.port;
271 continue;
274 if (quic_hint.alternate_port <= std::numeric_limits<uint16>::min() ||
275 quic_hint.alternate_port > std::numeric_limits<uint16>::max()) {
276 LOG(ERROR) << "Invalid QUIC hint alternate port: "
277 << quic_hint.alternate_port;
278 continue;
281 net::HostPortPair quic_hint_host_port_pair(canon_host,
282 quic_hint.port);
283 net::AlternativeService alternative_service(
284 net::AlternateProtocol::QUIC, "",
285 static_cast<uint16>(quic_hint.alternate_port));
286 context_->http_server_properties()->SetAlternativeService(
287 quic_hint_host_port_pair, alternative_service, 1.0f,
288 base::Time::Max());
292 JNIEnv* env = base::android::AttachCurrentThread();
293 Java_CronetUrlRequestContext_initNetworkThread(
294 env, jcronet_url_request_context.obj());
296 #if defined(DATA_REDUCTION_PROXY_SUPPORT)
297 if (data_reduction_proxy_)
298 data_reduction_proxy_->Init(true, GetURLRequestContext());
299 #endif
300 is_context_initialized_ = true;
301 while (!tasks_waiting_for_context_.empty()) {
302 tasks_waiting_for_context_.front().Run();
303 tasks_waiting_for_context_.pop();
307 void CronetURLRequestContextAdapter::Destroy(JNIEnv* env, jobject jcaller) {
308 DCHECK(!GetNetworkTaskRunner()->BelongsToCurrentThread());
309 // Stick network_thread_ in a local, as |this| may be destroyed from the
310 // network thread before delete network_thread is called.
311 base::Thread* network_thread = network_thread_;
312 GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, this);
313 // Deleting thread stops it after all tasks are completed.
314 delete network_thread;
317 net::URLRequestContext* CronetURLRequestContextAdapter::GetURLRequestContext() {
318 if (!context_) {
319 LOG(ERROR) << "URLRequestContext is not set up";
321 return context_.get();
324 void CronetURLRequestContextAdapter::PostTaskToNetworkThread(
325 const tracked_objects::Location& posted_from,
326 const base::Closure& callback) {
327 GetNetworkTaskRunner()->PostTask(
328 posted_from, base::Bind(&CronetURLRequestContextAdapter::
329 RunTaskAfterContextInitOnNetworkThread,
330 base::Unretained(this), callback));
333 void CronetURLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread(
334 const base::Closure& task_to_run_after_context_init) {
335 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
336 if (is_context_initialized_) {
337 DCHECK(tasks_waiting_for_context_.empty());
338 task_to_run_after_context_init.Run();
339 return;
341 tasks_waiting_for_context_.push(task_to_run_after_context_init);
344 bool CronetURLRequestContextAdapter::IsOnNetworkThread() const {
345 return GetNetworkTaskRunner()->BelongsToCurrentThread();
348 scoped_refptr<base::SingleThreadTaskRunner>
349 CronetURLRequestContextAdapter::GetNetworkTaskRunner() const {
350 return network_thread_->task_runner();
353 void CronetURLRequestContextAdapter::StartNetLogToFile(JNIEnv* env,
354 jobject jcaller,
355 jstring jfile_name,
356 jboolean jlog_all) {
357 PostTaskToNetworkThread(
358 FROM_HERE,
359 base::Bind(
360 &CronetURLRequestContextAdapter::StartNetLogToFileOnNetworkThread,
361 base::Unretained(this),
362 base::android::ConvertJavaStringToUTF8(env, jfile_name), jlog_all));
365 void CronetURLRequestContextAdapter::StopNetLog(JNIEnv* env, jobject jcaller) {
366 PostTaskToNetworkThread(
367 FROM_HERE,
368 base::Bind(&CronetURLRequestContextAdapter::StopNetLogOnNetworkThread,
369 base::Unretained(this)));
372 void CronetURLRequestContextAdapter::StartNetLogToFileOnNetworkThread(
373 const std::string& file_name, bool log_all) {
374 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
375 DCHECK(is_context_initialized_);
376 DCHECK(context_);
377 // Do nothing if already logging to a file.
378 if (write_to_file_observer_)
379 return;
380 base::FilePath file_path(file_name);
381 base::ScopedFILE file(base::OpenFile(file_path, "w"));
382 if (!file)
383 return;
385 write_to_file_observer_.reset(new net::WriteToFileNetLogObserver());
386 if (log_all) {
387 write_to_file_observer_->set_capture_mode(
388 net::NetLogCaptureMode::IncludeSocketBytes());
390 write_to_file_observer_->StartObserving(context_->net_log(), file.Pass(),
391 nullptr, context_.get());
394 void CronetURLRequestContextAdapter::StopNetLogOnNetworkThread() {
395 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
396 if (write_to_file_observer_) {
397 write_to_file_observer_->StopObserving(context_.get());
398 write_to_file_observer_.reset();
402 base::Thread* CronetURLRequestContextAdapter::GetFileThread() {
403 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
404 if (!file_thread_) {
405 file_thread_.reset(new base::Thread("Network File Thread"));
406 file_thread_->Start();
408 return file_thread_.get();
411 // Creates RequestContextAdater if config is valid URLRequestContextConfig,
412 // returns 0 otherwise.
413 static jlong CreateRequestContextAdapter(JNIEnv* env,
414 const JavaParamRef<jclass>& jcaller,
415 const JavaParamRef<jstring>& jconfig) {
416 std::string config_string =
417 base::android::ConvertJavaStringToUTF8(env, jconfig);
418 scoped_ptr<URLRequestContextConfig> context_config(
419 new URLRequestContextConfig());
420 if (!context_config->LoadFromJSON(config_string))
421 return 0;
423 CronetURLRequestContextAdapter* context_adapter =
424 new CronetURLRequestContextAdapter(context_config.Pass());
425 return reinterpret_cast<jlong>(context_adapter);
428 static jint SetMinLogLevel(JNIEnv* env,
429 const JavaParamRef<jclass>& jcaller,
430 jint jlog_level) {
431 jint old_log_level = static_cast<jint>(logging::GetMinLogLevel());
432 // MinLogLevel is global, shared by all URLRequestContexts.
433 logging::SetMinLogLevel(static_cast<int>(jlog_level));
434 return old_log_level;
437 } // namespace cronet