Clean up extension confirmation prompts and make them consistent between Views and...
[chromium-blink-merge.git] / components / cronet / android / cronet_url_request_context_adapter.cc
blob7cab0d9e281c190994deaa35c41974a1acb13c9f
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/prefs/pref_filter.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/values.h"
17 #include "components/cronet/url_request_context_config.h"
18 #include "jni/CronetUrlRequestContext_jni.h"
19 #include "net/base/load_flags.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/network_delegate_impl.h"
22 #include "net/http/http_auth_handler_factory.h"
23 #include "net/log/write_to_file_net_log_observer.h"
24 #include "net/proxy/proxy_service.h"
25 #include "net/sdch/sdch_owner.h"
26 #include "net/url_request/url_request_context.h"
27 #include "net/url_request/url_request_context_builder.h"
28 #include "net/url_request/url_request_interceptor.h"
30 #if defined(DATA_REDUCTION_PROXY_SUPPORT)
31 #include "components/cronet/android/cronet_data_reduction_proxy.h"
32 #endif
34 namespace {
36 class BasicNetworkDelegate : public net::NetworkDelegateImpl {
37 public:
38 BasicNetworkDelegate() {}
39 ~BasicNetworkDelegate() override {}
41 private:
42 // net::NetworkDelegate implementation.
43 int OnBeforeURLRequest(net::URLRequest* request,
44 const net::CompletionCallback& callback,
45 GURL* new_url) override {
46 return net::OK;
49 int OnBeforeSendHeaders(net::URLRequest* request,
50 const net::CompletionCallback& callback,
51 net::HttpRequestHeaders* headers) override {
52 return net::OK;
55 void OnSendHeaders(net::URLRequest* request,
56 const net::HttpRequestHeaders& headers) override {}
58 int OnHeadersReceived(
59 net::URLRequest* request,
60 const net::CompletionCallback& callback,
61 const net::HttpResponseHeaders* original_response_headers,
62 scoped_refptr<net::HttpResponseHeaders>* _response_headers,
63 GURL* allowed_unsafe_redirect_url) override {
64 return net::OK;
67 void OnBeforeRedirect(net::URLRequest* request,
68 const GURL& new_location) override {}
70 void OnResponseStarted(net::URLRequest* request) override {}
72 void OnRawBytesRead(const net::URLRequest& request, int bytes_read) override {
75 void OnCompleted(net::URLRequest* request, bool started) override {}
77 void OnURLRequestDestroyed(net::URLRequest* request) override {}
79 void OnPACScriptError(int line_number, const base::string16& error) override {
82 NetworkDelegate::AuthRequiredResponse OnAuthRequired(
83 net::URLRequest* request,
84 const net::AuthChallengeInfo& auth_info,
85 const AuthCallback& callback,
86 net::AuthCredentials* credentials) override {
87 return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
90 bool OnCanGetCookies(const net::URLRequest& request,
91 const net::CookieList& cookie_list) override {
92 return false;
95 bool OnCanSetCookie(const net::URLRequest& request,
96 const std::string& cookie_line,
97 net::CookieOptions* options) override {
98 return false;
101 bool OnCanAccessFile(const net::URLRequest& request,
102 const base::FilePath& path) const override {
103 return false;
106 bool OnCanThrottleRequest(const net::URLRequest& request) const override {
107 return false;
110 DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
113 } // namespace
115 namespace cronet {
117 // Explicitly register static JNI functions.
118 bool CronetUrlRequestContextAdapterRegisterJni(JNIEnv* env) {
119 return RegisterNativesImpl(env);
122 CronetURLRequestContextAdapter::CronetURLRequestContextAdapter(
123 scoped_ptr<URLRequestContextConfig> context_config)
124 : network_thread_(new base::Thread("network")),
125 context_config_(context_config.Pass()),
126 is_context_initialized_(false),
127 default_load_flags_(net::LOAD_NORMAL) {
128 base::Thread::Options options;
129 options.message_loop_type = base::MessageLoop::TYPE_IO;
130 network_thread_->StartWithOptions(options);
133 CronetURLRequestContextAdapter::~CronetURLRequestContextAdapter() {
134 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
135 StopNetLogOnNetworkThread();
138 void CronetURLRequestContextAdapter::InitRequestContextOnMainThread(
139 JNIEnv* env,
140 jobject jcaller) {
141 base::android::ScopedJavaGlobalRef<jobject> jcaller_ref;
142 jcaller_ref.Reset(env, jcaller);
143 proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
144 GetNetworkTaskRunner(), nullptr));
145 GetNetworkTaskRunner()->PostTask(
146 FROM_HERE,
147 base::Bind(&CronetURLRequestContextAdapter::InitializeOnNetworkThread,
148 base::Unretained(this), Passed(&context_config_),
149 jcaller_ref));
152 void CronetURLRequestContextAdapter::InitializeOnNetworkThread(
153 scoped_ptr<URLRequestContextConfig> config,
154 const base::android::ScopedJavaGlobalRef<jobject>&
155 jcronet_url_request_context) {
156 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
157 DCHECK(!is_context_initialized_);
158 DCHECK(proxy_config_service_);
159 // TODO(mmenke): Add method to have the builder enable SPDY.
160 net::URLRequestContextBuilder context_builder;
162 scoped_ptr<net::NetLog> net_log(new net::NetLog);
163 scoped_ptr<net::NetworkDelegate> network_delegate(new BasicNetworkDelegate());
164 #if defined(DATA_REDUCTION_PROXY_SUPPORT)
165 DCHECK(!data_reduction_proxy_);
166 // For now, the choice to enable the data reduction proxy happens once,
167 // at initialization. It cannot be disabled thereafter.
168 if (!config->data_reduction_proxy_key.empty()) {
169 data_reduction_proxy_.reset(
170 new CronetDataReductionProxy(
171 config->data_reduction_proxy_key,
172 config->data_reduction_primary_proxy,
173 config->data_reduction_fallback_proxy,
174 config->data_reduction_secure_proxy_check_url,
175 config->user_agent,
176 GetNetworkTaskRunner(),
177 net_log.get()));
178 network_delegate =
179 data_reduction_proxy_->CreateNetworkDelegate(network_delegate.Pass());
180 ScopedVector<net::URLRequestInterceptor> interceptors;
181 interceptors.push_back(data_reduction_proxy_->CreateInterceptor());
182 context_builder.SetInterceptors(interceptors.Pass());
184 #endif // defined(DATA_REDUCTION_PROXY_SUPPORT)
185 context_builder.set_network_delegate(network_delegate.release());
186 context_builder.set_net_log(net_log.release());
187 context_builder.set_proxy_config_service(proxy_config_service_.release());
188 config->ConfigureURLRequestContextBuilder(&context_builder);
190 // Set up pref file if storage path is specified.
191 // TODO(xunjieli): maybe get rid of the condition on sdch.
192 if (!config->storage_path.empty() && config->enable_sdch) {
193 base::FilePath filepath(config->storage_path);
194 filepath = filepath.Append(FILE_PATH_LITERAL("local_prefs.json"));
195 json_pref_store_ = new JsonPrefStore(
196 filepath, GetFileThread()->task_runner(), scoped_ptr<PrefFilter>());
197 json_pref_store_->ReadPrefsAsync(nullptr);
198 context_builder.SetFileTaskRunner(GetFileThread()->task_runner());
201 context_.reset(context_builder.Build());
203 default_load_flags_ = net::LOAD_DO_NOT_SAVE_COOKIES |
204 net::LOAD_DO_NOT_SEND_COOKIES;
205 if (config->load_disable_cache)
206 default_load_flags_ |= net::LOAD_DISABLE_CACHE;
208 if (config->enable_sdch) {
209 DCHECK(context_->sdch_manager());
210 sdch_owner_.reset(
211 new net::SdchOwner(context_->sdch_manager(), context_.get()));
212 if (json_pref_store_)
213 sdch_owner_->EnablePersistentStorage(json_pref_store_.get());
216 // Currently (circa M39) enabling QUIC requires setting probability threshold.
217 if (config->enable_quic) {
218 context_->http_server_properties()
219 ->SetAlternativeServiceProbabilityThreshold(0.0f);
220 for (auto hint = config->quic_hints.begin();
221 hint != config->quic_hints.end(); ++hint) {
222 const URLRequestContextConfig::QuicHint& quic_hint = **hint;
223 if (quic_hint.host.empty()) {
224 LOG(ERROR) << "Empty QUIC hint host: " << quic_hint.host;
225 continue;
228 url::CanonHostInfo host_info;
229 std::string canon_host(net::CanonicalizeHost(quic_hint.host, &host_info));
230 if (!host_info.IsIPAddress() &&
231 !net::IsCanonicalizedHostCompliant(canon_host)) {
232 LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint.host;
233 continue;
236 if (quic_hint.port <= std::numeric_limits<uint16>::min() ||
237 quic_hint.port > std::numeric_limits<uint16>::max()) {
238 LOG(ERROR) << "Invalid QUIC hint port: "
239 << quic_hint.port;
240 continue;
243 if (quic_hint.alternate_port <= std::numeric_limits<uint16>::min() ||
244 quic_hint.alternate_port > std::numeric_limits<uint16>::max()) {
245 LOG(ERROR) << "Invalid QUIC hint alternate port: "
246 << quic_hint.alternate_port;
247 continue;
250 net::HostPortPair quic_hint_host_port_pair(canon_host,
251 quic_hint.port);
252 net::AlternativeService alternative_service(
253 net::AlternateProtocol::QUIC, "",
254 static_cast<uint16>(quic_hint.alternate_port));
255 context_->http_server_properties()->SetAlternativeService(
256 quic_hint_host_port_pair, alternative_service, 1.0f);
260 JNIEnv* env = base::android::AttachCurrentThread();
261 Java_CronetUrlRequestContext_initNetworkThread(
262 env, jcronet_url_request_context.obj());
264 #if defined(DATA_REDUCTION_PROXY_SUPPORT)
265 if (data_reduction_proxy_)
266 data_reduction_proxy_->Init(true, GetURLRequestContext());
267 #endif
268 is_context_initialized_ = true;
269 while (!tasks_waiting_for_context_.empty()) {
270 tasks_waiting_for_context_.front().Run();
271 tasks_waiting_for_context_.pop();
275 void CronetURLRequestContextAdapter::Destroy(JNIEnv* env, jobject jcaller) {
276 DCHECK(!GetNetworkTaskRunner()->BelongsToCurrentThread());
277 // Stick network_thread_ in a local, as |this| may be destroyed from the
278 // network thread before delete network_thread is called.
279 base::Thread* network_thread = network_thread_;
280 GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, this);
281 // Deleting thread stops it after all tasks are completed.
282 delete network_thread;
285 net::URLRequestContext* CronetURLRequestContextAdapter::GetURLRequestContext() {
286 if (!context_) {
287 LOG(ERROR) << "URLRequestContext is not set up";
289 return context_.get();
292 void CronetURLRequestContextAdapter::PostTaskToNetworkThread(
293 const tracked_objects::Location& posted_from,
294 const base::Closure& callback) {
295 GetNetworkTaskRunner()->PostTask(
296 posted_from, base::Bind(&CronetURLRequestContextAdapter::
297 RunTaskAfterContextInitOnNetworkThread,
298 base::Unretained(this), callback));
301 void CronetURLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread(
302 const base::Closure& task_to_run_after_context_init) {
303 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
304 if (is_context_initialized_) {
305 DCHECK(tasks_waiting_for_context_.empty());
306 task_to_run_after_context_init.Run();
307 return;
309 tasks_waiting_for_context_.push(task_to_run_after_context_init);
312 bool CronetURLRequestContextAdapter::IsOnNetworkThread() const {
313 return GetNetworkTaskRunner()->BelongsToCurrentThread();
316 scoped_refptr<base::SingleThreadTaskRunner>
317 CronetURLRequestContextAdapter::GetNetworkTaskRunner() const {
318 return network_thread_->task_runner();
321 void CronetURLRequestContextAdapter::StartNetLogToFile(JNIEnv* env,
322 jobject jcaller,
323 jstring jfile_name,
324 jboolean jlog_all) {
325 PostTaskToNetworkThread(
326 FROM_HERE,
327 base::Bind(
328 &CronetURLRequestContextAdapter::StartNetLogToFileOnNetworkThread,
329 base::Unretained(this),
330 base::android::ConvertJavaStringToUTF8(env, jfile_name), jlog_all));
333 void CronetURLRequestContextAdapter::StopNetLog(JNIEnv* env, jobject jcaller) {
334 PostTaskToNetworkThread(
335 FROM_HERE,
336 base::Bind(&CronetURLRequestContextAdapter::StopNetLogOnNetworkThread,
337 base::Unretained(this)));
340 void CronetURLRequestContextAdapter::StartNetLogToFileOnNetworkThread(
341 const std::string& file_name, bool log_all) {
342 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
343 DCHECK(is_context_initialized_);
344 DCHECK(context_);
345 // Do nothing if already logging to a file.
346 if (write_to_file_observer_)
347 return;
348 base::FilePath file_path(file_name);
349 base::ScopedFILE file(base::OpenFile(file_path, "w"));
350 if (!file)
351 return;
353 write_to_file_observer_.reset(new net::WriteToFileNetLogObserver());
354 if (log_all) {
355 write_to_file_observer_->set_capture_mode(
356 net::NetLogCaptureMode::IncludeSocketBytes());
358 write_to_file_observer_->StartObserving(context_->net_log(), file.Pass(),
359 nullptr, context_.get());
362 void CronetURLRequestContextAdapter::StopNetLogOnNetworkThread() {
363 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
364 if (write_to_file_observer_) {
365 write_to_file_observer_->StopObserving(context_.get());
366 write_to_file_observer_.reset();
370 base::Thread* CronetURLRequestContextAdapter::GetFileThread() {
371 DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
372 if (!file_thread_) {
373 file_thread_.reset(new base::Thread("Network File Thread"));
374 file_thread_->Start();
376 return file_thread_.get();
379 // Creates RequestContextAdater if config is valid URLRequestContextConfig,
380 // returns 0 otherwise.
381 static jlong CreateRequestContextAdapter(JNIEnv* env,
382 jclass jcaller,
383 jstring jconfig) {
384 std::string config_string =
385 base::android::ConvertJavaStringToUTF8(env, jconfig);
386 scoped_ptr<URLRequestContextConfig> context_config(
387 new URLRequestContextConfig());
388 if (!context_config->LoadFromJSON(config_string))
389 return 0;
391 CronetURLRequestContextAdapter* context_adapter =
392 new CronetURLRequestContextAdapter(context_config.Pass());
393 return reinterpret_cast<jlong>(context_adapter);
396 static jint SetMinLogLevel(JNIEnv* env, jclass jcaller, jint jlog_level) {
397 jint old_log_level = static_cast<jint>(logging::GetMinLogLevel());
398 // MinLogLevel is global, shared by all URLRequestContexts.
399 logging::SetMinLogLevel(static_cast<int>(jlog_level));
400 return old_log_level;
403 } // namespace cronet