summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormef <mef@chromium.org>2015-02-09 18:18:25 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-10 02:19:48 +0000
commit63643dbe9fd4db0dafaf5055dca59bef904e8431 (patch)
tree2f7bee2f59cbf6c632359cf7b827cab119454c2e
parent9035c1053e9d5ae55e662a519f25738345692872 (diff)
downloadchromium_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}
-rw-r--r--components/cronet.gypi6
-rw-r--r--components/cronet/android/cronet_jni.cc2
-rw-r--r--components/cronet/android/cronet_library_loader.cc (renamed from components/cronet/android/cronet_loader.cc)38
-rw-r--r--components/cronet/android/cronet_library_loader.h (renamed from components/cronet/android/cronet_loader.h)6
-rw-r--r--components/cronet/android/cronet_url_request_adapter.cc6
-rw-r--r--components/cronet/android/cronet_url_request_adapter.h2
-rw-r--r--components/cronet/android/cronet_url_request_context.cc34
-rw-r--r--components/cronet/android/cronet_url_request_context_adapter.cc54
-rw-r--r--components/cronet/android/cronet_url_request_context_adapter.h39
-rw-r--r--components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequestFactory.java2
-rw-r--r--components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java70
-rw-r--r--components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java109
-rw-r--r--components/cronet/android/test/cronet_test_jni.cc2
-rw-r--r--components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/ContextInitTest.java40
-rw-r--r--components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetTestBase.java9
-rw-r--r--components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/CronetUrlRequestContextTest.java197
-rw-r--r--components/cronet/android/test/javatests/src/org/chromium/cronet_test_apk/HistogramManagerTest.java2
-rw-r--r--components/cronet/android/test/src/org/chromium/cronet_test_apk/CronetTestActivity.java52
-rw-r--r--components/cronet/android/url_request_context_adapter.cc17
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(