OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/android/network_change_notifier_delegate_android.h" | 5 #include "net/android/network_change_notifier_delegate_android.h" |
6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop_proxy.h" |
| 11 #include "base/single_thread_task_runner.h" |
8 #include "jni/NetworkChangeNotifier_jni.h" | 12 #include "jni/NetworkChangeNotifier_jni.h" |
9 | 13 |
10 namespace net { | 14 namespace net { |
11 | 15 |
12 namespace { | 16 namespace { |
13 | 17 |
14 // Returns whether the provided connection type is known. | 18 // Returns whether the provided connection type is known. |
15 bool CheckConnectionType(int connection_type) { | 19 bool CheckConnectionType(int connection_type) { |
16 switch (connection_type) { | 20 switch (connection_type) { |
17 case NetworkChangeNotifier::CONNECTION_UNKNOWN: | 21 case NetworkChangeNotifier::CONNECTION_UNKNOWN: |
18 case NetworkChangeNotifier::CONNECTION_ETHERNET: | 22 case NetworkChangeNotifier::CONNECTION_ETHERNET: |
19 case NetworkChangeNotifier::CONNECTION_WIFI: | 23 case NetworkChangeNotifier::CONNECTION_WIFI: |
20 case NetworkChangeNotifier::CONNECTION_2G: | 24 case NetworkChangeNotifier::CONNECTION_2G: |
21 case NetworkChangeNotifier::CONNECTION_3G: | 25 case NetworkChangeNotifier::CONNECTION_3G: |
22 case NetworkChangeNotifier::CONNECTION_4G: | 26 case NetworkChangeNotifier::CONNECTION_4G: |
23 case NetworkChangeNotifier::CONNECTION_NONE: | 27 case NetworkChangeNotifier::CONNECTION_NONE: |
24 return true; | 28 return true; |
25 default: | 29 default: |
26 NOTREACHED() << "Unknown connection type received: " << connection_type; | 30 NOTREACHED() << "Unknown connection type received: " << connection_type; |
27 return false; | 31 return false; |
28 } | 32 } |
29 } | 33 } |
30 | 34 |
31 } // namespace | 35 } // namespace |
32 | 36 |
33 NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid() | 37 NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid() |
34 : observers_(new ObserverListThreadSafe<Observer>()) { | 38 : jni_task_runner_(base::MessageLoopProxy::current()), |
| 39 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| 40 weak_ptr_(weak_ptr_factory_.GetWeakPtr()), |
| 41 observers_(new ObserverListThreadSafe<Observer>()), |
| 42 connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN) { |
| 43 JNIEnv* env = base::android::AttachCurrentThread(); |
35 java_network_change_notifier_.Reset( | 44 java_network_change_notifier_.Reset( |
36 Java_NetworkChangeNotifier_createInstance( | 45 Java_NetworkChangeNotifier_init( |
37 base::android::AttachCurrentThread(), | 46 env, base::android::GetApplicationContext())); |
38 base::android::GetApplicationContext(), | 47 Java_NetworkChangeNotifier_addNativeObserver( |
39 reinterpret_cast<jint>(this))); | 48 env, java_network_change_notifier_.obj(), reinterpret_cast<jint>(this)); |
40 } | 49 } |
41 | 50 |
42 NetworkChangeNotifierDelegateAndroid::~NetworkChangeNotifierDelegateAndroid() { | 51 NetworkChangeNotifierDelegateAndroid::~NetworkChangeNotifierDelegateAndroid() { |
43 DCHECK(thread_checker_.CalledOnValidThread()); | 52 DCHECK(thread_checker_.CalledOnValidThread()); |
44 observers_->AssertEmpty(); | 53 observers_->AssertEmpty(); |
45 JNIEnv* env = base::android::AttachCurrentThread(); | 54 JNIEnv* env = base::android::AttachCurrentThread(); |
46 Java_NetworkChangeNotifier_destroyInstance(env); | 55 Java_NetworkChangeNotifier_removeNativeObserver( |
| 56 env, java_network_change_notifier_.obj(), reinterpret_cast<jint>(this)); |
47 } | 57 } |
48 | 58 |
49 void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged( | 59 void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged( |
50 JNIEnv* env, | 60 JNIEnv* env, |
51 jobject obj, | 61 jobject obj, |
52 jint new_connection_type) { | 62 jint new_connection_type) { |
53 DCHECK(thread_checker_.CalledOnValidThread()); | 63 DCHECK(thread_checker_.CalledOnValidThread()); |
54 connection_type_ = CheckConnectionType(new_connection_type) ? | 64 connection_type_ = CheckConnectionType(new_connection_type) ? |
55 static_cast<ConnectionType>(new_connection_type) : | 65 static_cast<ConnectionType>(new_connection_type) : |
56 NetworkChangeNotifier::CONNECTION_UNKNOWN; | 66 NetworkChangeNotifier::CONNECTION_UNKNOWN; |
57 observers_->Notify(&Observer::OnConnectionTypeChanged, connection_type_); | 67 observers_->Notify(&Observer::OnConnectionTypeChanged, connection_type_); |
58 } | 68 } |
59 | 69 |
60 jint NetworkChangeNotifierDelegateAndroid::GetConnectionType(JNIEnv*, | 70 jint NetworkChangeNotifierDelegateAndroid::GetConnectionType(JNIEnv*, |
61 jobject) const { | 71 jobject) const { |
62 DCHECK(thread_checker_.CalledOnValidThread()); | 72 DCHECK(thread_checker_.CalledOnValidThread()); |
63 return connection_type_; | 73 return connection_type_; |
64 } | 74 } |
65 | 75 |
66 void NetworkChangeNotifierDelegateAndroid::AddObserver( | 76 void NetworkChangeNotifierDelegateAndroid::AddObserver( |
67 Observer* observer) { | 77 Observer* observer) { |
68 observers_->AddObserver(observer); | 78 observers_->AddObserver(observer); |
| 79 SendInitialNotification(); |
69 } | 80 } |
70 | 81 |
71 void NetworkChangeNotifierDelegateAndroid::RemoveObserver( | 82 void NetworkChangeNotifierDelegateAndroid::RemoveObserver( |
72 Observer* observer) { | 83 Observer* observer) { |
73 observers_->RemoveObserver(observer); | 84 observers_->RemoveObserver(observer); |
74 } | 85 } |
75 | 86 |
76 void NetworkChangeNotifierDelegateAndroid::ForceConnectivityState( | 87 void NetworkChangeNotifierDelegateAndroid::ForceConnectivityState( |
77 ConnectivityState state) { | 88 ConnectivityState state) { |
78 DCHECK(thread_checker_.CalledOnValidThread()); | 89 DCHECK(thread_checker_.CalledOnValidThread()); |
79 JNIEnv* env = base::android::AttachCurrentThread(); | 90 JNIEnv* env = base::android::AttachCurrentThread(); |
80 Java_NetworkChangeNotifier_forceConnectivityState(env, state == ONLINE); | 91 Java_NetworkChangeNotifier_forceConnectivityState(env, state == ONLINE); |
81 } | 92 } |
82 | 93 |
83 // static | 94 // static |
84 bool NetworkChangeNotifierDelegateAndroid::Register(JNIEnv* env) { | 95 bool NetworkChangeNotifierDelegateAndroid::Register(JNIEnv* env) { |
85 return RegisterNativesImpl(env); | 96 return RegisterNativesImpl(env); |
86 } | 97 } |
87 | 98 |
| 99 void NetworkChangeNotifierDelegateAndroid::SendInitialNotification() { |
| 100 // This function must be executed on the JNI thread since it reads |
| 101 // |connection_type_| which is written on the JNI thread (with no lock). |
| 102 if (!jni_task_runner_->BelongsToCurrentThread()) { |
| 103 // Note that copying a weak pointer (which is constructed on the JNI thread |
| 104 // in this case) is thread-safe. |
| 105 jni_task_runner_->PostTask( |
| 106 FROM_HERE, |
| 107 base::Bind( |
| 108 &NetworkChangeNotifierDelegateAndroid::SendInitialNotification, |
| 109 weak_ptr_)); |
| 110 return; |
| 111 } |
| 112 // Ideally only the newly added observer should be notified to receive the |
| 113 // current connection type. ObserverListThreadSafe doesn't support this |
| 114 // functionality unfortunately. Note that the observers (a small number of |
| 115 // NetworkChangeNotifierAndroid instances) will forward the notification only |
| 116 // if the provided connection type is different from the previous one. This |
| 117 // means that notifying all observers has no impact from the client |
| 118 // perspective. |
| 119 observers_->Notify(&Observer::OnConnectionTypeChanged, connection_type_); |
| 120 } |
| 121 |
88 } // namespace net | 122 } // namespace net |
OLD | NEW |