diff options
author | mef <mef@chromium.org> | 2015-02-09 18:18:25 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-10 02:19:48 +0000 |
commit | 63643dbe9fd4db0dafaf5055dca59bef904e8431 (patch) | |
tree | 2f7bee2f59cbf6c632359cf7b827cab119454c2e | |
parent | 9035c1053e9d5ae55e662a519f25738345692872 (diff) | |
download | chromium_src-63643dbe9fd4db0dafaf5055dca59bef904e8431.zip chromium_src-63643dbe9fd4db0dafaf5055dca59bef904e8431.tar.gz chromium_src-63643dbe9fd4db0dafaf5055dca59bef904e8431.tar.bz2 |
[Cronet] Hook up library loader, system proxy and network change notifier to Async API.
BUG=409926
TEST=CronetUrlRequestContextTest.*Init*
TEST=ContextInitTest.*
Review URL: https://codereview.chromium.org/726013002
Cr-Commit-Position: refs/heads/master@{#315474}
19 files changed, 538 insertions, 149 deletions
diff --git a/components/cronet.gypi b/components/cronet.gypi index dc29726..4d3787c 100644 --- a/components/cronet.gypi +++ b/components/cronet.gypi @@ -12,6 +12,7 @@ 'type': 'none', 'sources': [ 'cronet/android/java/src/org/chromium/net/CronetHistogramManager.java', + 'cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java', 'cronet/android/java/src/org/chromium/net/CronetUrlRequest.java', 'cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java', 'cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java', @@ -124,8 +125,8 @@ 'cronet/android/chromium_url_request_context.h', 'cronet/android/cronet_histogram_manager.cc', 'cronet/android/cronet_histogram_manager.h', - 'cronet/android/cronet_loader.cc', - 'cronet/android/cronet_loader.h', + 'cronet/android/cronet_library_loader.cc', + 'cronet/android/cronet_library_loader.h', 'cronet/android/cronet_url_request.cc', 'cronet/android/cronet_url_request.h', 'cronet/android/cronet_url_request_adapter.cc', @@ -233,6 +234,7 @@ '**/ChromiumUrlRequestPriority.java', '**/CronetHistogramManager.java', '**/CronetResponseInfo.java', + '**/CronetLibraryLoader.java', '**/CronetUrlRequest.java', '**/CronetUrlRequestContext.java', '**/CronetUrlRequestFactory.java', diff --git a/components/cronet/android/cronet_jni.cc b/components/cronet/android/cronet_jni.cc index 30027a5..c081f6e 100644 --- a/components/cronet/android/cronet_jni.cc +++ b/components/cronet/android/cronet_jni.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/cronet/android/cronet_loader.h" +#include "components/cronet/android/cronet_library_loader.h" // This is called by the VM when the shared library is first loaded. extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { diff --git a/components/cronet/android/cronet_loader.cc b/components/cronet/android/cronet_library_loader.cc index ac68005..af0ac41 100644 --- a/components/cronet/android/cronet_loader.cc +++ b/components/cronet/android/cronet_library_loader.cc @@ -2,16 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/cronet/android/cronet_library_loader.h" + +#include <jni.h> + #include "base/android/base_jni_registrar.h" #include "base/android/jni_android.h" #include "base/android/jni_registrar.h" #include "base/at_exit.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" #include "components/cronet/android/chromium_url_request.h" #include "components/cronet/android/chromium_url_request_context.h" #include "components/cronet/android/cronet_histogram_manager.h" #include "components/cronet/android/cronet_url_request.h" #include "components/cronet/android/cronet_url_request_context.h" +#include "jni/CronetLibraryLoader_jni.h" #include "net/android/net_jni_registrar.h" +#include "net/android/network_change_notifier_factory_android.h" +#include "net/base/network_change_notifier.h" #include "url/android/url_jni_registrar.h" #include "url/url_util.h" @@ -27,6 +36,7 @@ const base::android::RegistrationMethod kCronetRegisteredMethods[] = { {"ChromiumUrlRequest", ChromiumUrlRequestRegisterJni}, {"ChromiumUrlRequestContext", ChromiumUrlRequestContextRegisterJni}, {"CronetHistogramManager", CronetHistogramManagerRegisterJni}, + {"CronetLibraryLoader", RegisterNativesImpl}, {"CronetUrlRequest", CronetUrlRequestRegisterJni}, {"CronetUrlRequestContext", CronetUrlRequestContextRegisterJni}, {"NetAndroid", net::android::RegisterJni}, @@ -34,6 +44,11 @@ const base::android::RegistrationMethod kCronetRegisteredMethods[] = { }; base::AtExitManager* g_at_exit_manager = NULL; +// MessageLoop on the main thread, which is where objects that receive Java +// notifications generally live. +base::MessageLoop* g_main_message_loop = nullptr; + +net::NetworkChangeNotifier* g_network_change_notifier = nullptr; } // namespace @@ -53,10 +68,6 @@ jint CronetOnLoad(JavaVM* vm, void* reserved) { g_at_exit_manager = new base::AtExitManager(); -#if !defined(USE_ICU_ALTERNATIVES_ON_ANDROID) - base::i18n::InitializeICU(); -#endif - url::Initialize(); return JNI_VERSION_1_6; @@ -69,4 +80,23 @@ void CronetOnUnLoad(JavaVM* jvm, void* reserved) { } } +void CronetInitOnMainThread(JNIEnv* env, jclass jcaller, jobject jcontext) { + // Set application context. + base::android::ScopedJavaLocalRef<jobject> scoped_context(env, jcontext); + base::android::InitApplicationContext(env, scoped_context); + +#if !defined(USE_ICU_ALTERNATIVES_ON_ANDROID) + base::i18n::InitializeICU(); +#endif + + DCHECK(!base::MessageLoop::current()); + DCHECK(!g_main_message_loop); + g_main_message_loop = new base::MessageLoopForUI(); + base::MessageLoopForUI::current()->Start(); + DCHECK(!g_network_change_notifier); + net::NetworkChangeNotifier::SetFactory( + new net::NetworkChangeNotifierFactoryAndroid()); + g_network_change_notifier = net::NetworkChangeNotifier::Create(); +} + } // namespace cronet diff --git a/components/cronet/android/cronet_loader.h b/components/cronet/android/cronet_library_loader.h index 4785763..7e3ab3d 100644 --- a/components/cronet/android/cronet_loader.h +++ b/components/cronet/android/cronet_library_loader.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_CRONET_ANDROID_CRONET_LOADER_H_ -#define COMPONENTS_CRONET_ANDROID_CRONET_LOADER_H_ +#ifndef COMPONENTS_CRONET_ANDROID_CRONET_LIBRARY_LOADER_H_ +#define COMPONENTS_CRONET_ANDROID_CRONET_LIBRARY_LOADER_H_ #include <jni.h> @@ -14,4 +14,4 @@ void CronetOnUnLoad(JavaVM* jvm, void* reserved); } // namespace cronet -#endif // COMPONENTS_CRONET_ANDROID_CRONET_LOADER_H_ +#endif // COMPONENTS_CRONET_ANDROID_CRONET_LIBRARY_LOADER_H_ diff --git a/components/cronet/android/cronet_url_request_adapter.cc b/components/cronet/android/cronet_url_request_adapter.cc index e16ebe1..49922d2 100644 --- a/components/cronet/android/cronet_url_request_adapter.cc +++ b/components/cronet/android/cronet_url_request_adapter.cc @@ -47,15 +47,15 @@ void CronetURLRequestAdapter::DisableCache() { load_flags_ |= net::LOAD_DISABLE_CACHE; } -bool CronetURLRequestAdapter::PostTaskToNetworkThread( +void CronetURLRequestAdapter::PostTaskToNetworkThread( const tracked_objects::Location& from_here, const base::Closure& task) { DCHECK(!IsOnNetworkThread()); - return context_->GetNetworkTaskRunner()->PostTask(from_here, task); + context_->PostTaskToNetworkThread(from_here, task); } bool CronetURLRequestAdapter::IsOnNetworkThread() const { - return context_->GetNetworkTaskRunner()->BelongsToCurrentThread(); + return context_->IsOnNetworkThread(); } void CronetURLRequestAdapter::Start() { diff --git a/components/cronet/android/cronet_url_request_adapter.h b/components/cronet/android/cronet_url_request_adapter.h index 293f37c..eb0f62f 100644 --- a/components/cronet/android/cronet_url_request_adapter.h +++ b/components/cronet/android/cronet_url_request_adapter.h @@ -83,7 +83,7 @@ class CronetURLRequestAdapter : public net::URLRequest::Delegate { // Methods called on any thread. // Posts tasks to network thread. - bool PostTaskToNetworkThread(const tracked_objects::Location& from_here, + void PostTaskToNetworkThread(const tracked_objects::Location& from_here, const base::Closure& task); // Returns true if called on network thread. diff --git a/components/cronet/android/cronet_url_request_context.cc b/components/cronet/android/cronet_url_request_context.cc index a9b6014..bae0380 100644 --- a/components/cronet/android/cronet_url_request_context.cc +++ b/components/cronet/android/cronet_url_request_context.cc @@ -33,7 +33,8 @@ bool CronetUrlRequestContextRegisterJni(JNIEnv* env) { return RegisterNativesImpl(env); } -// Sets global user-agent to be used for all subsequent requests. +// Creates RequestContextAdater if config is valid URLRequestContextConfig, +// returns 0 otherwise. static jlong CreateRequestContextAdapter(JNIEnv* env, jobject jcaller, jobject japp_context, @@ -45,19 +46,8 @@ static jlong CreateRequestContextAdapter(JNIEnv* env, if (!context_config->LoadFromJSON(config_string)) return 0; - // Set application context. - base::android::ScopedJavaLocalRef<jobject> scoped_context(env, japp_context); - base::android::InitApplicationContext(env, scoped_context); - - base::android::ScopedJavaGlobalRef<jobject> jcaller_ref; - jcaller_ref.Reset(env, jcaller); - CronetURLRequestContextAdapter* context_adapter = - new CronetURLRequestContextAdapter(); - base::Closure init_java_network_thread = base::Bind(&initJavaNetworkThread, - jcaller_ref); - context_adapter->Initialize(context_config.Pass(), init_java_network_thread); - + new CronetURLRequestContextAdapter(context_config.Pass()); return reinterpret_cast<jlong>(context_adapter); } @@ -106,4 +96,22 @@ static jint SetMinLogLevel(JNIEnv* env, jobject jcaller, jint jlog_level) { return old_log_level; } +// Called on application's main Java thread. +static void InitRequestContextOnMainThread(JNIEnv* env, + jobject jcaller, + jlong jurl_request_context_adapter) { + if (jurl_request_context_adapter == 0) + return; + + CronetURLRequestContextAdapter* context_adapter = + reinterpret_cast<CronetURLRequestContextAdapter*>( + jurl_request_context_adapter); + + base::android::ScopedJavaGlobalRef<jobject> jcaller_ref; + jcaller_ref.Reset(env, jcaller); + base::Closure init_java_network_thread = base::Bind(&initJavaNetworkThread, + jcaller_ref); + context_adapter->InitRequestContextOnMainThread(init_java_network_thread); +} + } // namespace cronet diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc index c5b8686..3c2cfa8 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.cc +++ b/components/cronet/android/cronet_url_request_context_adapter.cc @@ -108,8 +108,15 @@ class BasicNetworkDelegate : public net::NetworkDelegateImpl { namespace cronet { -CronetURLRequestContextAdapter::CronetURLRequestContextAdapter() - : default_load_flags_(0) { +CronetURLRequestContextAdapter::CronetURLRequestContextAdapter( + scoped_ptr<URLRequestContextConfig> context_config) + : network_thread_(new base::Thread("network")), + context_config_(context_config.Pass()), + is_context_initialized_(false), + default_load_flags_(net::LOAD_NORMAL) { + base::Thread::Options options; + options.message_loop_type = base::MessageLoop::TYPE_IO; + network_thread_->StartWithOptions(options); } CronetURLRequestContextAdapter::~CronetURLRequestContextAdapter() { @@ -117,19 +124,15 @@ CronetURLRequestContextAdapter::~CronetURLRequestContextAdapter() { StopNetLogOnNetworkThread(); } -void CronetURLRequestContextAdapter::Initialize( - scoped_ptr<URLRequestContextConfig> config, +void CronetURLRequestContextAdapter::InitRequestContextOnMainThread( const base::Closure& java_init_network_thread) { - network_thread_ = new base::Thread("network"); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - network_thread_->StartWithOptions(options); - + proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService( + GetNetworkTaskRunner(), nullptr)); GetNetworkTaskRunner()->PostTask( FROM_HERE, base::Bind(&CronetURLRequestContextAdapter::InitializeOnNetworkThread, base::Unretained(this), - Passed(&config), + Passed(&context_config_), java_init_network_thread)); } @@ -137,6 +140,7 @@ void CronetURLRequestContextAdapter::InitializeOnNetworkThread( scoped_ptr<URLRequestContextConfig> config, const base::Closure& java_init_network_thread) { DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); + DCHECK(!is_context_initialized_); // TODO(mmenke): Add method to have the builder enable SPDY. net::URLRequestContextBuilder context_builder; context_builder.set_network_delegate(new BasicNetworkDelegate()); @@ -196,6 +200,12 @@ void CronetURLRequestContextAdapter::InitializeOnNetworkThread( } java_init_network_thread.Run(); + + is_context_initialized_ = true; + while (!tasks_waiting_for_context_.empty()) { + tasks_waiting_for_context_.front().Run(); + tasks_waiting_for_context_.pop(); + } } void CronetURLRequestContextAdapter::Destroy() { @@ -215,6 +225,30 @@ net::URLRequestContext* CronetURLRequestContextAdapter::GetURLRequestContext() { return context_.get(); } +void CronetURLRequestContextAdapter::PostTaskToNetworkThread( + const tracked_objects::Location& posted_from, + const base::Closure& callback) { + GetNetworkTaskRunner()->PostTask( + posted_from, base::Bind(&CronetURLRequestContextAdapter:: + RunTaskAfterContextInitOnNetworkThread, + base::Unretained(this), callback)); +} + +void CronetURLRequestContextAdapter::RunTaskAfterContextInitOnNetworkThread( + const base::Closure& task_to_run_after_context_init) { + DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); + if (is_context_initialized_) { + DCHECK(tasks_waiting_for_context_.empty()); + task_to_run_after_context_init.Run(); + return; + } + tasks_waiting_for_context_.push(task_to_run_after_context_init); +} + +bool CronetURLRequestContextAdapter::IsOnNetworkThread() const { + return GetNetworkTaskRunner()->BelongsToCurrentThread(); +} + scoped_refptr<base::SingleThreadTaskRunner> CronetURLRequestContextAdapter::GetNetworkTaskRunner() const { return network_thread_->task_runner(); diff --git a/components/cronet/android/cronet_url_request_context_adapter.h b/components/cronet/android/cronet_url_request_context_adapter.h index b9d1e307..31de6d9 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.h +++ b/components/cronet/android/cronet_url_request_context_adapter.h @@ -5,6 +5,7 @@ #ifndef COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_CONTEXT_ADAPTER_H_ #define COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_CONTEXT_ADAPTER_H_ +#include <queue> #include <string> #include "base/callback.h" @@ -22,6 +23,7 @@ class SingleThreadTaskRunner; namespace net { class NetLogLogger; class URLRequestContext; +class ProxyConfigService; } // namespace net namespace cronet { @@ -31,20 +33,27 @@ struct URLRequestContextConfig; // Adapter between Java CronetUrlRequestContext and net::URLRequestContext. class CronetURLRequestContextAdapter { public: - CronetURLRequestContextAdapter(); + explicit CronetURLRequestContextAdapter( + scoped_ptr<URLRequestContextConfig> context_config); ~CronetURLRequestContextAdapter(); - void Initialize(scoped_ptr<URLRequestContextConfig> config, - const base::Closure& java_init_network_thread); + // Called on main Java thread to initialize URLRequestContext. + void InitRequestContextOnMainThread( + const base::Closure& java_init_network_thread); // Releases all resources for the request context and deletes the object. // Blocks until network thread is destroyed after running all pending tasks. void Destroy(); - net::URLRequestContext* GetURLRequestContext(); + // Posts a task that might depend on the context being initialized + // to the network thread. + void PostTaskToNetworkThread(const tracked_objects::Location& posted_from, + const base::Closure& callback); - scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const; + bool IsOnNetworkThread() const; + + net::URLRequestContext* GetURLRequestContext(); void StartNetLogToFile(const std::string& file_name); @@ -53,12 +62,24 @@ class CronetURLRequestContextAdapter { // Default net::LOAD flags used to create requests. int default_load_flags() const { return default_load_flags_; } + // Called on main Java thread to initialize URLRequestContext. + void InitRequestContextOnMainThread(); + private: // Initializes |context_| on the Network thread. void InitializeOnNetworkThread( scoped_ptr<URLRequestContextConfig> config, const base::Closure& java_init_network_thread); + + // Runs a task that might depend on the context being initialized. + // This method should only be run on the network thread. + void RunTaskAfterContextInitOnNetworkThread( + const base::Closure& task_to_run_after_context_init); + + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const; + void StartNetLogToFileOnNetworkThread(const std::string& file_name); + void StopNetLogOnNetworkThread(); // Network thread is owned by |this|, but is destroyed from java thread. @@ -66,6 +87,14 @@ class CronetURLRequestContextAdapter { // |net_log_logger_| and |context_| should only be accessed on network thread. scoped_ptr<net::NetLogLogger> net_log_logger_; scoped_ptr<net::URLRequestContext> context_; + scoped_ptr<net::ProxyConfigService> proxy_config_service_; + + // Context config is only valid untng context is initialized. + scoped_ptr<URLRequestContextConfig> context_config_; + + // A queue of tasks that need to be run after context has been initialized. + std::queue<base::Closure> tasks_waiting_for_context_; + bool is_context_initialized_; int default_load_flags_; DISALLOW_COPY_AND_ASSIGN(CronetURLRequestContextAdapter); diff --git a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java index f6151cc..eb9ef75 100644 --- a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java +++ b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java @@ -23,7 +23,7 @@ public class ChromiumUrlRequestFactory extends HttpUrlRequestFactory { public ChromiumUrlRequestFactory( Context context, UrlRequestContextConfig config) { if (isEnabled()) { - System.loadLibrary(config.libraryName()); + CronetLibraryLoader.ensureInitialized(context, config); mRequestContext = new ChromiumUrlRequestContext( context.getApplicationContext(), UserAgent.from(context), config.toString()); diff --git a/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java b/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java new file mode 100644 index 0000000..eb5428c --- /dev/null +++ b/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java @@ -0,0 +1,70 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; + +import org.chromium.base.JNINamespace; + +/** + * CronetLibraryLoader loads and initializes native library on main thread. + */ +@JNINamespace("cronet") +class CronetLibraryLoader { + /** + * Synchronize access to sInitTaskPosted and initialization routine. + */ + private static final Object sLoadLock = new Object(); + private static boolean sInitTaskPosted = false; + + /** + * Ensure that native library is loaded and initialized. Can be called from + * any thread, the load and initialization is performed on main thread. + */ + public static void ensureInitialized( + final Context context, final UrlRequestContextConfig config) { + synchronized (sLoadLock) { + if (sInitTaskPosted) { + return; + } + System.loadLibrary(config.libraryName()); + // Init native Chromium URLRequestContext on Main UI thread. + Runnable task = new Runnable() { + public void run() { + initOnMainThread(context); + } + }; + // Run task immediately or post it to the UI thread. + if (Looper.getMainLooper() == Looper.myLooper()) { + task.run(); + } else { + // The initOnMainThread will complete on the main thread prior + // to other tasks posted to the main thread. + new Handler(Looper.getMainLooper()).post(task); + } + sInitTaskPosted = true; + } + } + + private static void initOnMainThread(final Context context) { + NetworkChangeNotifier.init(context); + // Registers to always receive network notifications. Note + // that this call is fine for Cronet because Cronet + // embedders do not have API access to create network change + // observers. Existing observers in the net stack do not + // perform expensive work. + NetworkChangeNotifier.registerToReceiveNotificationsAlways(); + // registerToReceiveNotificationsAlways() is called before the native + // NetworkChangeNotifierAndroid is created, so as to avoid receiving + // the undesired initial network change observer notification, which + // will cause active requests to fail with ERR_NETWORK_CHANGED. + nativeCronetInitOnMainThread(context); + } + + // Native methods are implemented in cronet_loader.cc. + private static native void nativeCronetInitOnMainThread(Context context); +} diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java index 4c7afc6..40c91d2 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java @@ -6,6 +6,9 @@ package org.chromium.net; import android.content.Context; import android.os.Build; +import android.os.ConditionVariable; +import android.os.Handler; +import android.os.Looper; import android.os.Process; import android.util.Log; @@ -25,29 +28,54 @@ public class CronetUrlRequestContext extends UrlRequestContext { private static final int LOG_VERBOSE = -2; // LOG(FATAL...INFO), VLOG(2) static final String LOG_TAG = "ChromiumNetwork"; + /** + * Synchronize access to mUrlRequestContextAdapter and shutdown routine. + */ + private final Object mLock = new Object(); + private final ConditionVariable mInitCompleted = new ConditionVariable(false); + private final AtomicInteger mActiveRequestCount = new AtomicInteger(0); + private long mUrlRequestContextAdapter = 0; private Thread mNetworkThread; - private AtomicInteger mActiveRequestCount = new AtomicInteger(0); public CronetUrlRequestContext(Context context, UrlRequestContextConfig config) { + CronetLibraryLoader.ensureInitialized(context, config); nativeSetMinLogLevel(getLoggingLevel()); mUrlRequestContextAdapter = nativeCreateRequestContextAdapter( context, config.toString()); if (mUrlRequestContextAdapter == 0) { - throw new NullPointerException("Context Adapter creation failed"); + throw new NullPointerException("Context Adapter creation failed."); + } + + // Init native Chromium URLRequestContext on main UI thread. + Runnable task = new Runnable() { + @Override + public void run() { + synchronized (mLock) { + // mUrlRequestContextAdapter is guaranteed to exist until + // initialization on main and network threads completes and + // initNetworkThread is called back on network thread. + nativeInitRequestContextOnMainThread(mUrlRequestContextAdapter); + } + } + }; + // Run task immediately or post it to the UI thread. + if (Looper.getMainLooper() == Looper.myLooper()) { + task.run(); + } else { + new Handler(Looper.getMainLooper()).post(task); } } @Override public UrlRequest createRequest(String url, UrlRequestListener listener, Executor executor) { - if (mUrlRequestContextAdapter == 0) { - throw new IllegalStateException( - "Cannot create requests on shutdown context."); + synchronized (mLock) { + checkHaveAdapter(); + return new CronetUrlRequest(this, mUrlRequestContextAdapter, url, + UrlRequest.REQUEST_PRIORITY_MEDIUM, listener, executor); } - return new CronetUrlRequest(this, mUrlRequestContextAdapter, url, - UrlRequest.REQUEST_PRIORITY_MEDIUM, listener, executor); } @Override @@ -62,28 +90,47 @@ public class CronetUrlRequestContext extends UrlRequestContext { @Override public void shutdown() { - if (mActiveRequestCount.get() != 0) { - throw new IllegalStateException( - "Cannot shutdown with active requests."); + synchronized (mLock) { + checkHaveAdapter(); + if (mActiveRequestCount.get() != 0) { + throw new IllegalStateException( + "Cannot shutdown with active requests."); + } + // Destroying adapter stops the network thread, so it cannot be + // called on network thread. + if (Thread.currentThread() == mNetworkThread) { + throw new IllegalThreadStateException( + "Cannot shutdown from network thread."); + } } - // Destroying adapter stops the network thread, so it cannot be called - // on network thread. - if (Thread.currentThread() == mNetworkThread) { - throw new IllegalThreadStateException( - "Cannot shutdown from network thread."); + // Wait for init to complete on main and network thread (without lock, + // so other thread could access it). + mInitCompleted.block(); + + synchronized (mLock) { + // It is possible that adapter is already destroyed on another thread. + if (!haveRequestContextAdapter()) { + return; + } + nativeDestroyRequestContextAdapter(mUrlRequestContextAdapter); + mUrlRequestContextAdapter = 0; } - nativeDestroyRequestContextAdapter(mUrlRequestContextAdapter); - mUrlRequestContextAdapter = 0; } @Override public void startNetLogToFile(String fileName) { - nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName); + synchronized (mLock) { + checkHaveAdapter(); + nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName); + } } @Override public void stopNetLog() { - nativeStopNetLog(mUrlRequestContextAdapter); + synchronized (mLock) { + checkHaveAdapter(); + nativeStopNetLog(mUrlRequestContextAdapter); + } } /** @@ -103,10 +150,20 @@ public class CronetUrlRequestContext extends UrlRequestContext { } long getUrlRequestContextAdapter() { - if (mUrlRequestContextAdapter == 0) { - throw new IllegalStateException("Context Adapter is destroyed."); + synchronized (mLock) { + checkHaveAdapter(); + return mUrlRequestContextAdapter; } - return mUrlRequestContextAdapter; + } + + private void checkHaveAdapter() throws IllegalStateException { + if (!haveRequestContextAdapter()) { + throw new IllegalStateException("Context is shut down."); + } + } + + private boolean haveRequestContextAdapter() { + return mUrlRequestContextAdapter != 0; } /** @@ -128,7 +185,10 @@ public class CronetUrlRequestContext extends UrlRequestContext { @SuppressWarnings("unused") @CalledByNative private void initNetworkThread() { - mNetworkThread = Thread.currentThread(); + synchronized (mLock) { + mNetworkThread = Thread.currentThread(); + mInitCompleted.open(); + } Thread.currentThread().setName("ChromiumNet"); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } @@ -146,4 +206,7 @@ public class CronetUrlRequestContext extends UrlRequestContext { private native void nativeStopNetLog(long urlRequestContextAdapter); private native int nativeSetMinLogLevel(int loggingLevel); + + private native void nativeInitRequestContextOnMainThread( + long urlRequestContextAdapter); } diff --git a/components/cronet/android/test/cronet_test_jni.cc b/components/cronet/android/test/cronet_test_jni.cc index 1b1b558..4a35300 100644 --- a/components/cronet/android/test/cronet_test_jni.cc +++ b/components/cronet/android/test/cronet_test_jni.cc @@ -7,7 +7,7 @@ #include "base/android/base_jni_registrar.h" #include "base/android/jni_android.h" #include "base/android/jni_registrar.h" -#include "components/cronet/android/cronet_loader.h" +#include "components/cronet/android/cronet_library_loader.h" #include "mock_url_request_job_factory.h" #include "native_test_server.h" #include "network_change_notifier_util.h" diff --git a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/ContextInitTest.java b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/ContextInitTest.java index cc2e934..221231b 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/ContextInitTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/ContextInitTest.java @@ -19,15 +19,13 @@ import java.util.HashMap; public class ContextInitTest extends CronetTestBase { // URL used for base tests. private static final String URL = "http://127.0.0.1:8000"; + // URL used for tests that return HTTP not found (404). + private static final String URL_404 = "http://127.0.0.1:8000/notfound404"; @SmallTest @Feature({"Cronet"}) public void testInitFactoryAndStartRequest() { CronetTestActivity activity = skipFactoryInitInOnCreate(); - // Make sure the activity was created as expected. - assertNotNull(activity); - // Make sure the factory is not created. - assertNull(activity.mRequestFactory); // Immediately make a request after initializing the factory. HttpUrlRequestFactory factory = activity.initRequestFactory(); @@ -40,10 +38,6 @@ public class ContextInitTest extends CronetTestBase { @Feature({"Cronet"}) public void testInitFactoryStartRequestAndCancel() { CronetTestActivity activity = skipFactoryInitInOnCreate(); - // Make sure the activity was created as expected. - assertNotNull(activity); - // Make sure the factory is not created. - assertNull(activity.mRequestFactory); // Make a request and cancel it after initializing the factory. HttpUrlRequestFactory factory = activity.initRequestFactory(); @@ -61,14 +55,10 @@ public class ContextInitTest extends CronetTestBase { @Feature({"Cronet"}) public void testInitFactoryStartTwoRequests() throws Exception { CronetTestActivity activity = skipFactoryInitInOnCreate(); - // Make sure the activity was created as expected. - assertNotNull(activity); - // Make sure the factory is not created. - assertNull(activity.mRequestFactory); // Make two request right after initializing the factory. int[] statusCodes = {0, 0}; - String[] urls = {URL, "http://127.0.0.1:8000/test"}; + String[] urls = {URL, URL_404}; HttpUrlRequestFactory factory = activity.initRequestFactory(); for (int i = 0; i < 2; i++) { TestHttpUrlRequestListener listener = makeRequest(factory, urls[i]); @@ -102,14 +92,9 @@ public class ContextInitTest extends CronetTestBase { @Feature({"Cronet"}) public void testInitTwoFactoriesSimultaneously() throws Exception { final CronetTestActivity activity = skipFactoryInitInOnCreate(); - // Make sure the activity was created as expected. - assertNotNull(activity); - // Make sure the factory is not created. - assertNull(activity.mRequestFactory); RequestThread thread1 = new RequestThread(activity, URL); - RequestThread thread2 = new RequestThread(activity, - "http://127.0.0.1:8000/notfound"); + RequestThread thread2 = new RequestThread(activity, URL_404); thread1.start(); thread2.start(); @@ -123,14 +108,9 @@ public class ContextInitTest extends CronetTestBase { @Feature({"Cronet"}) public void testInitTwoFactoriesInSequence() throws Exception { final CronetTestActivity activity = skipFactoryInitInOnCreate(); - // Make sure the activity was created as expected. - assertNotNull(activity); - // Make sure the factory is not created. - assertNull(activity.mRequestFactory); RequestThread thread1 = new RequestThread(activity, URL); - RequestThread thread2 = new RequestThread(activity, - "http://127.0.0.1:8000/notfound"); + RequestThread thread2 = new RequestThread(activity, URL_404); thread1.start(); thread1.join(); @@ -140,16 +120,6 @@ public class ContextInitTest extends CronetTestBase { assertEquals(404, thread2.mListener.mHttpStatusCode); } - // Helper method to tell the activity to skip factory init in onCreate(). - private CronetTestActivity skipFactoryInitInOnCreate() { - String[] commandLineArgs = { - CronetTestActivity.SKIP_FACTORY_INIT_KEY, "skip" }; - CronetTestActivity activity = - launchCronetTestAppWithUrlAndCommandLineArgs(null, - commandLineArgs); - return activity; - } - // Helper function to make a request. private TestHttpUrlRequestListener makeRequest( HttpUrlRequestFactory factory, String url) { diff --git a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetTestBase.java b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetTestBase.java index a1b13ca..0d1ffca 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetTestBase.java +++ b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetTestBase.java @@ -87,6 +87,15 @@ public class CronetTestBase extends return getActivity(); } + // Helper method to tell the activity to skip factory init in onCreate(). + protected CronetTestActivity skipFactoryInitInOnCreate() { + String[] commandLineArgs = { + CronetTestActivity.LIBRARY_INIT_KEY, CronetTestActivity.LIBRARY_INIT_SKIP}; + CronetTestActivity activity = + launchCronetTestAppWithUrlAndCommandLineArgs(null, commandLineArgs); + return activity; + } + /** * Waits for the Active shell to finish loading. This times out after * WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT milliseconds and it shouldn't be diff --git a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestContextTest.java index 8e1bd54..e059e99 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestContextTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestContextTest.java @@ -4,6 +4,9 @@ package org.chromium.cronet_test_apk; +import android.os.ConditionVariable; +import android.os.Handler; +import android.os.Looper; import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.PathUtils; @@ -13,6 +16,7 @@ import org.chromium.cronet_test_apk.TestUrlRequestListener.ResponseStep; import org.chromium.net.ExtendedResponseInfo; import org.chromium.net.ResponseInfo; import org.chromium.net.UrlRequest; +import org.chromium.net.UrlRequestContext; import org.chromium.net.UrlRequestContextConfig; import org.chromium.net.UrlRequestException; @@ -26,6 +30,7 @@ import java.util.Arrays; public class CronetUrlRequestContextTest extends CronetTestBase { // URLs used for tests. private static final String TEST_URL = "http://127.0.0.1:8000"; + private static final String URL_404 = "http://127.0.0.1:8000/notfound404"; private static final String MOCK_CRONET_TEST_FAILED_URL = "http://mock.failed.request/-2"; private static final String MOCK_CRONET_TEST_SUCCESS_URL = @@ -33,6 +38,32 @@ public class CronetUrlRequestContextTest extends CronetTestBase { CronetTestActivity mActivity; + static class RequestThread extends Thread { + public TestUrlRequestListener mListener; + + final CronetTestActivity mActivity; + final String mUrl; + final ConditionVariable mRunBlocker; + + public RequestThread(CronetTestActivity activity, String url, + ConditionVariable runBlocker) { + mActivity = activity; + mUrl = url; + mRunBlocker = runBlocker; + } + + @Override + public void run() { + mRunBlocker.block(); + UrlRequestContext requestContext = mActivity.initRequestContext(); + mListener = new TestUrlRequestListener(); + UrlRequest urlRequest = + requestContext.createRequest(mUrl, mListener, mListener.getExecutor()); + urlRequest.start(); + mListener.blockForDone(); + } + } + /** * Listener that shutdowns the request context when request has succeeded * or failed. @@ -119,6 +150,87 @@ public class CronetUrlRequestContextTest extends CronetTestBase { @SmallTest @Feature({"Cronet"}) + public void testShutdownDuringInit() throws Exception { + final CronetTestActivity activity = skipFactoryInitInOnCreate(); + final ConditionVariable block = new ConditionVariable(false); + + // Post a task to main thread to block until shutdown is called to test + // scenario when shutdown is called right after construction before + // context is fully initialized on the main thread. + Runnable blockingTask = new Runnable() { + public void run() { + try { + block.block(); + } catch (Exception e) { + fail("Caught " + e.getMessage()); + } + } + }; + // Ensure that test is not running on the main thread. + assertTrue(Looper.getMainLooper() != Looper.myLooper()); + new Handler(Looper.getMainLooper()).post(blockingTask); + + // Create new request context, but its initialization on the main thread + // will be stuck behind blockingTask. + final UrlRequestContext requestContext = activity.initRequestContext(); + // Unblock the main thread, so context gets initialized and shutdown on + // it. + block.open(); + // Shutdown will wait for init to complete on main thread. + requestContext.shutdown(); + // Verify that context is shutdown. + try { + requestContext.stopNetLog(); + fail("Should throw an exception."); + } catch (Exception e) { + assertEquals("Context is shut down.", e.getMessage()); + } + } + + @SmallTest + @Feature({"Cronet"}) + public void testInitAndShutdownOnMainThread() throws Exception { + final CronetTestActivity activity = skipFactoryInitInOnCreate(); + final ConditionVariable block = new ConditionVariable(false); + + // Post a task to main thread to init and shutdown on the main thread. + Runnable blockingTask = new Runnable() { + public void run() { + // Create new request context, loading the library. + final UrlRequestContext requestContext = activity.initRequestContext(); + // Shutdown right after init. + requestContext.shutdown(); + // Verify that context is shutdown. + try { + requestContext.stopNetLog(); + fail("Should throw an exception."); + } catch (Exception e) { + assertEquals("Context is shut down.", e.getMessage()); + } + block.open(); + } + }; + new Handler(Looper.getMainLooper()).post(blockingTask); + // Wait for shutdown to complete on main thread. + block.block(); + } + + @SmallTest + @Feature({"Cronet"}) + public void testMultipleShutdown() throws Exception { + mActivity = launchCronetTestApp(); + try { + mActivity.mUrlRequestContext.shutdown(); + mActivity.mUrlRequestContext.shutdown(); + fail("Should throw an exception"); + } catch (Exception e) { + assertEquals("Context is shut down.", + e.getMessage()); + } + } + + @SmallTest + @Feature({"Cronet"}) public void testShutdownAfterError() throws Exception { mActivity = launchCronetTestApp(); TestUrlRequestListener listener = new ShutdownTestUrlRequestListener(); @@ -218,10 +330,12 @@ public class CronetUrlRequestContextTest extends CronetTestBase { File directory = new File(PathUtils.getDataDirectory( getInstrumentation().getTargetContext())); File file = File.createTempFile("cronet", "json", directory); - mActivity.mUrlRequestContext.startNetLogToFile(file.getPath()); - mActivity.mUrlRequestContext.stopNetLog(); - assertTrue(file.exists()); - assertTrue(file.length() == 0); + try { + mActivity.mUrlRequestContext.startNetLogToFile(file.getPath()); + fail("Should throw an exception."); + } catch (Exception e) { + assertEquals("Context is shut down.", e.getMessage()); + } assertTrue(file.delete()); assertTrue(!file.exists()); } @@ -311,7 +425,6 @@ public class CronetUrlRequestContextTest extends CronetTestBase { urlRequest.start(); listener.blockForDone(); assertEquals(expectCached, listener.mResponseInfo.wasCached()); - assertEquals(200, listener.mResponseInfo.getHttpStatusCode()); } @SmallTest @@ -388,7 +501,7 @@ public class CronetUrlRequestContextTest extends CronetTestBase { // TODO(mef): Simple cache uses global thread pool that is not affected by // shutdown of UrlRequestContext. This test can be flaky unless that thread - // pool is destroyed and recreated. Enable the test when crbug.com/442321 is fixed. + // pool is shutdown and recreated. Enable the test when crbug.com/442321 is fixed. @SmallTest @Feature({"Cronet"}) public void disabled_testEnableHttpCacheDiskNewContext() throws Exception { @@ -415,4 +528,76 @@ public class CronetUrlRequestContextTest extends CronetTestBase { config); checkRequestCaching(url, true); } + + @SmallTest + @Feature({"Cronet"}) + public void testInitContextAndStartRequest() { + CronetTestActivity activity = skipFactoryInitInOnCreate(); + + // Immediately make a request after initializing the context. + UrlRequestContext requestContext = activity.initRequestContext(); + TestUrlRequestListener listener = new TestUrlRequestListener(); + UrlRequest urlRequest = + requestContext.createRequest(TEST_URL, listener, listener.getExecutor()); + urlRequest.start(); + listener.blockForDone(); + assertEquals(200, listener.mResponseInfo.getHttpStatusCode()); + } + + @SmallTest + @Feature({"Cronet"}) + public void testInitContextStartTwoRequests() throws Exception { + CronetTestActivity activity = skipFactoryInitInOnCreate(); + + // Make two requests after initializing the context. + UrlRequestContext requestContext = activity.initRequestContext(); + int[] statusCodes = {0, 0}; + String[] urls = {TEST_URL, URL_404}; + for (int i = 0; i < 2; i++) { + TestUrlRequestListener listener = new TestUrlRequestListener(); + UrlRequest urlRequest = + requestContext.createRequest(urls[i], listener, listener.getExecutor()); + urlRequest.start(); + listener.blockForDone(); + statusCodes[i] = listener.mResponseInfo.getHttpStatusCode(); + } + assertEquals(200, statusCodes[0]); + assertEquals(404, statusCodes[1]); + } + + @SmallTest + @Feature({"Cronet"}) + public void testInitTwoContextsSimultaneously() throws Exception { + final CronetTestActivity activity = skipFactoryInitInOnCreate(); + + // Threads will block on runBlocker to ensure simultaneous execution. + ConditionVariable runBlocker = new ConditionVariable(false); + RequestThread thread1 = new RequestThread(activity, TEST_URL, runBlocker); + RequestThread thread2 = new RequestThread(activity, URL_404, runBlocker); + + thread1.start(); + thread2.start(); + runBlocker.open(); + thread1.join(); + thread2.join(); + assertEquals(200, thread1.mListener.mResponseInfo.getHttpStatusCode()); + assertEquals(404, thread2.mListener.mResponseInfo.getHttpStatusCode()); + } + + @SmallTest + @Feature({"Cronet"}) + public void testInitTwoContextsInSequence() throws Exception { + final CronetTestActivity activity = skipFactoryInitInOnCreate(); + + ConditionVariable runBlocker = new ConditionVariable(true); + RequestThread thread1 = new RequestThread(activity, TEST_URL, runBlocker); + RequestThread thread2 = new RequestThread(activity, URL_404, runBlocker); + + thread1.start(); + thread1.join(); + thread2.start(); + thread2.join(); + assertEquals(200, thread1.mListener.mResponseInfo.getHttpStatusCode()); + assertEquals(404, thread2.mListener.mResponseInfo.getHttpStatusCode()); + } } diff --git a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/HistogramManagerTest.java b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/HistogramManagerTest.java index 9d75b4e..06dc18e 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/HistogramManagerTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/HistogramManagerTest.java @@ -25,7 +25,7 @@ public class HistogramManagerTest extends CronetTestBase { public void testHistogramManager() throws Exception { mActivity = launchCronetTestApp(); byte delta1[] = mActivity.mHistogramManager.getHistogramDeltas(); - assertTrue(delta1.length != 0); + assertEquals(0, delta1.length); TestUrlRequestListener listener = new TestUrlRequestListener(); UrlRequest urlRequest = mActivity.mUrlRequestContext.createRequest( diff --git a/components/cronet/android/test/src/org/chromium/cronet_test_apk/CronetTestActivity.java b/components/cronet/android/test/src/org/chromium/cronet_test_apk/CronetTestActivity.java index df8e6df..333f97a 100644 --- a/components/cronet/android/test/src/org/chromium/cronet_test_apk/CronetTestActivity.java +++ b/components/cronet/android/test/src/org/chromium/cronet_test_apk/CronetTestActivity.java @@ -34,7 +34,16 @@ public class CronetTestActivity extends Activity { public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; public static final String POST_DATA_KEY = "postData"; public static final String CONFIG_KEY = "config"; - public static final String SKIP_FACTORY_INIT_KEY = "skipFactoryInit"; + public static final String LIBRARY_INIT_KEY = "libraryInit"; + /** + * Skip library initialization. + */ + public static final String LIBRARY_INIT_SKIP = "skip"; + + /** + * Initialize Cronet Async API only. + */ + public static final String LIBRARY_INIT_CRONET_ONLY = "cronetOnly"; public CronetURLStreamHandlerFactory mStreamHandlerFactory; public UrlRequestContext mUrlRequestContext; @@ -66,31 +75,28 @@ public class CronetTestActivity extends Activity { protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - try { - System.loadLibrary("cronet_tests"); - } catch (UnsatisfiedLinkError e) { - Log.e(TAG, "libcronet_test initialization failed.", e); - finish(); + String initString = getCommandLineArg(LIBRARY_INIT_KEY); + if (LIBRARY_INIT_SKIP.equals(initString)) { return; } - String skipInitString = getCommandLineArg(SKIP_FACTORY_INIT_KEY); - if (skipInitString != null) { - return; - } - mRequestFactory = initRequestFactory(); - if (mRequestFactory == null) { + mUrlRequestContext = initRequestContext(); + mStreamHandlerFactory = new CronetURLStreamHandlerFactory( + getApplicationContext(), null); + mHistogramManager = HistogramManager.createHistogramManager(); + + if (LIBRARY_INIT_CRONET_ONLY.equals(initString)) { return; } + mRequestFactory = initRequestFactory(); String appUrl = getUrlFromIntent(getIntent()); if (appUrl != null) { startWithURL(appUrl); } } - // Helper function to initialize request factory. Also used in testing. - public HttpUrlRequestFactory initRequestFactory() { + UrlRequestContextConfig getContextConfig() { UrlRequestContextConfig config = new UrlRequestContextConfig(); config.enableHttpCache(UrlRequestContextConfig.HttpCache.IN_MEMORY, 100 * 1024) @@ -112,17 +118,17 @@ public class CronetTestActivity extends Activity { // Setting this here so it isn't overridden on the command line config.setLibraryName("cronet_tests"); + return config; + } - mUrlRequestContext = UrlRequestContext.createContext( - getApplicationContext(), config); - - mHistogramManager = HistogramManager.createHistogramManager(); - - mStreamHandlerFactory = new CronetURLStreamHandlerFactory( - getApplicationContext(), config); + // Helper function to initialize request context. Also used in testing. + public UrlRequestContext initRequestContext() { + return UrlRequestContext.createContext(getApplicationContext(), getContextConfig()); + } - return HttpUrlRequestFactory.createFactory(getApplicationContext(), - config); + // Helper function to initialize request factory. Also used in testing. + public HttpUrlRequestFactory initRequestFactory() { + return HttpUrlRequestFactory.createFactory(getApplicationContext(), getContextConfig()); } private static String getUrlFromIntent(Intent intent) { diff --git a/components/cronet/android/url_request_context_adapter.cc b/components/cronet/android/url_request_context_adapter.cc index cd8a3a9..00daf65 100644 --- a/components/cronet/android/url_request_context_adapter.cc +++ b/components/cronet/android/url_request_context_adapter.cc @@ -30,12 +30,6 @@ namespace { -// MessageLoop on the main thread, which is where objects that receive Java -// notifications generally live. -base::MessageLoop* g_main_message_loop = nullptr; - -net::NetworkChangeNotifier* g_network_change_notifier = nullptr; - class BasicNetworkDelegate : public net::NetworkDelegateImpl { public: BasicNetworkDelegate() {} @@ -137,17 +131,6 @@ void URLRequestContextAdapter::Initialize( } void URLRequestContextAdapter::InitRequestContextOnMainThread() { - if (!base::MessageLoop::current()) { - DCHECK(!g_main_message_loop); - g_main_message_loop = new base::MessageLoopForUI(); - base::MessageLoopForUI::current()->Start(); - } - DCHECK_EQ(g_main_message_loop, base::MessageLoop::current()); - if (!g_network_change_notifier) { - net::NetworkChangeNotifier::SetFactory( - new net::NetworkChangeNotifierFactoryAndroid()); - g_network_change_notifier = net::NetworkChangeNotifier::Create(); - } proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService( GetNetworkTaskRunner(), NULL)); GetNetworkTaskRunner()->PostTask( |