summaryrefslogtreecommitdiffstats
path: root/net/android/network_change_notifier_delegate_android.cc
diff options
context:
space:
mode:
authorpliard@chromium.org <pliard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-28 17:52:10 +0000
committerpliard@chromium.org <pliard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-28 17:52:10 +0000
commit3967355e7d0ef9aded77e056accb36cfd6af38c4 (patch)
tree5476fc6310b7a4b8b9eaa7e4d74f3afdbf75f762 /net/android/network_change_notifier_delegate_android.cc
parent7f20af93c507c5cdb68728e890995622658cfed5 (diff)
downloadchromium_src-3967355e7d0ef9aded77e056accb36cfd6af38c4.zip
chromium_src-3967355e7d0ef9aded77e056accb36cfd6af38c4.tar.gz
chromium_src-3967355e7d0ef9aded77e056accb36cfd6af38c4.tar.bz2
Fix potential threading issues in NetworkChangeNotifierAndroid.
NetworkChangeNotifierAndroid's constructor can be called on any thread. It calls some Java code (still on any thread) initializing a singleton. This singleton is also accessed from the UI thread on the application side. While in practice it didn't seem to be a problem it seems safer to perform all the JNI calls on a single thread (UI thread) to avoid accessing mutable state from multiple threads. Another potential issue with the current implementation is that NetworkChangeNotifierAndroid could be deleted on the network thread while it was receiving at the same time a notification on the UI thread. That could have led to a user after free. This CL addresses these two issues by introducing a Delegate which outlives NetworkChangeNotifierAndroid and calls JNI methods on the UI thread. Review URL: https://chromiumcodereview.appspot.com/10979055 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169990 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/android/network_change_notifier_delegate_android.cc')
-rw-r--r--net/android/network_change_notifier_delegate_android.cc88
1 files changed, 88 insertions, 0 deletions
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
new file mode 100644
index 0000000..91b0cb0
--- /dev/null
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 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.
+
+#include "net/android/network_change_notifier_delegate_android.h"
+
+#include "base/logging.h"
+#include "jni/NetworkChangeNotifier_jni.h"
+
+namespace net {
+
+namespace {
+
+// Returns whether the provided connection type is known.
+bool CheckConnectionType(int connection_type) {
+ switch (connection_type) {
+ case NetworkChangeNotifier::CONNECTION_UNKNOWN:
+ case NetworkChangeNotifier::CONNECTION_ETHERNET:
+ case NetworkChangeNotifier::CONNECTION_WIFI:
+ case NetworkChangeNotifier::CONNECTION_2G:
+ case NetworkChangeNotifier::CONNECTION_3G:
+ case NetworkChangeNotifier::CONNECTION_4G:
+ case NetworkChangeNotifier::CONNECTION_NONE:
+ return true;
+ default:
+ NOTREACHED() << "Unknown connection type received: " << connection_type;
+ return false;
+ }
+}
+
+} // namespace
+
+NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid()
+ : observers_(new ObserverListThreadSafe<Observer>()) {
+ java_network_change_notifier_.Reset(
+ Java_NetworkChangeNotifier_createInstance(
+ base::android::AttachCurrentThread(),
+ base::android::GetApplicationContext(),
+ reinterpret_cast<jint>(this)));
+}
+
+NetworkChangeNotifierDelegateAndroid::~NetworkChangeNotifierDelegateAndroid() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ observers_->AssertEmpty();
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_NetworkChangeNotifier_destroyInstance(env);
+}
+
+void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged(
+ JNIEnv* env,
+ jobject obj,
+ jint new_connection_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ connection_type_ = CheckConnectionType(new_connection_type) ?
+ static_cast<ConnectionType>(new_connection_type) :
+ NetworkChangeNotifier::CONNECTION_UNKNOWN;
+ observers_->Notify(&Observer::OnConnectionTypeChanged, connection_type_);
+}
+
+jint NetworkChangeNotifierDelegateAndroid::GetConnectionType(JNIEnv*,
+ jobject) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return connection_type_;
+}
+
+void NetworkChangeNotifierDelegateAndroid::AddObserver(
+ Observer* observer) {
+ observers_->AddObserver(observer);
+}
+
+void NetworkChangeNotifierDelegateAndroid::RemoveObserver(
+ Observer* observer) {
+ observers_->RemoveObserver(observer);
+}
+
+void NetworkChangeNotifierDelegateAndroid::ForceConnectivityState(
+ ConnectivityState state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_NetworkChangeNotifier_forceConnectivityState(env, state == ONLINE);
+}
+
+// static
+bool NetworkChangeNotifierDelegateAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace net