diff options
author | pliard@chromium.org <pliard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-28 17:52:10 +0000 |
---|---|---|
committer | pliard@chromium.org <pliard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-28 17:52:10 +0000 |
commit | 3967355e7d0ef9aded77e056accb36cfd6af38c4 (patch) | |
tree | 5476fc6310b7a4b8b9eaa7e4d74f3afdbf75f762 /net/android/network_change_notifier_delegate_android.cc | |
parent | 7f20af93c507c5cdb68728e890995622658cfed5 (diff) | |
download | chromium_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.cc | 88 |
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 |