Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 5 | //////////////////////////////////////////////////////////////////////////////// |
| 6 | // Threading considerations: |
| 7 | // |
| 8 | // This class is designed to meet various threading guarantees starting from the |
| 9 | // ones imposed by NetworkChangeNotifier: |
| 10 | // - The notifier can be constructed on any thread. |
| 11 | // - GetCurrentConnectionType() can be called on any thread. |
| 12 | // |
| 13 | // The fact that this implementation of NetworkChangeNotifier is backed by a |
| 14 | // Java side singleton class (see NetworkChangeNotifier.java) adds another |
| 15 | // threading constraint: |
| 16 | // - The calls to the Java side (stateful) object must be performed from a |
| 17 | // single thread. This object happens to be a singleton which is used on the |
| 18 | // application side on the main thread. Therefore all the method calls from |
| 19 | // the native NetworkChangeNotifierAndroid class to its Java counterpart are |
| 20 | // performed on the main thread. |
| 21 | // |
| 22 | // This leads to a design involving the following native classes: |
| 23 | // 1) NetworkChangeNotifierFactoryAndroid ('factory') |
| 24 | // 2) NetworkChangeNotifierDelegateAndroid ('delegate') |
| 25 | // 3) NetworkChangeNotifierAndroid ('notifier') |
| 26 | // |
| 27 | // The factory constructs and owns the delegate. The factory is constructed and |
| 28 | // destroyed on the main thread which makes it construct and destroy the |
| 29 | // delegate on the main thread too. This guarantees that the calls to the Java |
| 30 | // side are performed on the main thread. |
| 31 | // Note that after the factory's construction, the factory's creation method can |
| 32 | // be called from any thread since the delegate's construction (performing the |
| 33 | // JNI calls) already happened on the main thread (when the factory was |
| 34 | // constructed). |
| 35 | // |
| 36 | //////////////////////////////////////////////////////////////////////////////// |
| 37 | // Propagation of network change notifications: |
| 38 | // |
| 39 | // When the factory is requested to create a new instance of the notifier, the |
| 40 | // factory passes the delegate to the notifier (without transferring ownership). |
| 41 | // Note that there is a one-to-one mapping between the factory and the |
| 42 | // delegate as explained above. But the factory naturally creates multiple |
| 43 | // instances of the notifier. That means that there is a one-to-many mapping |
| 44 | // between delegate and notifier (i.e. a single delegate can be shared by |
| 45 | // multiple notifiers). |
| 46 | // At construction the notifier (which is also an observer) subscribes to |
| 47 | // notifications fired by the delegate. These notifications, received by the |
| 48 | // delegate (and forwarded to the notifier(s)), are sent by the Java side |
| 49 | // notifier (see NetworkChangeNotifier.java) and are initiated by the Android |
| 50 | // platform. |
| 51 | // Notifications from the Java side always arrive on the main thread. The |
| 52 | // delegate then forwards these notifications to the threads of each observer |
| 53 | // (network change notifier). The network change notifier than processes the |
| 54 | // state change, and notifies each of its observers on their threads. |
| 55 | // |
| 56 | // This can also be seen as: |
| 57 | // Android platform -> NetworkChangeNotifier (Java) -> |
| 58 | // NetworkChangeNotifierDelegateAndroid -> NetworkChangeNotifierAndroid. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 59 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 60 | #include "net/android/network_change_notifier_android.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 61 | |
Torne (Richard Coles) | 5d1f7b1 | 2014-02-21 12:16:55 +0000 | [diff] [blame] | 62 | #include "base/threading/thread.h" |
| 63 | #include "net/base/address_tracker_linux.h" |
| 64 | #include "net/dns/dns_config_service.h" |
| 65 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 66 | namespace net { |
| 67 | |
Torne (Richard Coles) | 5d1f7b1 | 2014-02-21 12:16:55 +0000 | [diff] [blame] | 68 | // Thread on which we can run DnsConfigService, which requires a TYPE_IO |
| 69 | // message loop to monitor /system/etc/hosts. |
| 70 | class NetworkChangeNotifierAndroid::DnsConfigServiceThread |
| 71 | : public base::Thread { |
| 72 | public: |
| 73 | DnsConfigServiceThread() |
| 74 | : base::Thread("DnsConfigService"), |
| 75 | address_tracker_(base::Bind(base::DoNothing), |
| 76 | base::Bind(base::DoNothing), |
| 77 | // We're only interested in tunnel interface changes. |
| 78 | base::Bind(NotifyNetworkChangeNotifierObservers)) {} |
| 79 | |
| 80 | virtual ~DnsConfigServiceThread() { |
| 81 | Stop(); |
| 82 | } |
| 83 | |
| 84 | virtual void Init() OVERRIDE { |
| 85 | address_tracker_.Init(); |
| 86 | dns_config_service_ = DnsConfigService::CreateSystemService(); |
| 87 | dns_config_service_->WatchConfig( |
| 88 | base::Bind(&NetworkChangeNotifier::SetDnsConfig)); |
| 89 | } |
| 90 | |
| 91 | virtual void CleanUp() OVERRIDE { |
| 92 | dns_config_service_.reset(); |
| 93 | } |
| 94 | |
| 95 | static void NotifyNetworkChangeNotifierObservers() { |
| 96 | NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); |
| 97 | NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); |
| 98 | } |
| 99 | |
| 100 | private: |
| 101 | scoped_ptr<DnsConfigService> dns_config_service_; |
| 102 | // Used to detect tunnel state changes. |
| 103 | internal::AddressTrackerLinux address_tracker_; |
| 104 | |
| 105 | DISALLOW_COPY_AND_ASSIGN(DnsConfigServiceThread); |
| 106 | }; |
| 107 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 108 | NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 109 | delegate_->RemoveObserver(this); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 110 | } |
| 111 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 112 | NetworkChangeNotifier::ConnectionType |
| 113 | NetworkChangeNotifierAndroid::GetCurrentConnectionType() const { |
| 114 | return delegate_->GetCurrentConnectionType(); |
| 115 | } |
| 116 | |
| 117 | void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() { |
Torne (Richard Coles) | 5d1f7b1 | 2014-02-21 12:16:55 +0000 | [diff] [blame] | 118 | DnsConfigServiceThread::NotifyNetworkChangeNotifierObservers(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 119 | } |
| 120 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 121 | // static |
| 122 | bool NetworkChangeNotifierAndroid::Register(JNIEnv* env) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 123 | return NetworkChangeNotifierDelegateAndroid::Register(env); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 124 | } |
| 125 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 126 | NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid( |
| 127 | NetworkChangeNotifierDelegateAndroid* delegate) |
| 128 | : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()), |
Torne (Richard Coles) | 5d1f7b1 | 2014-02-21 12:16:55 +0000 | [diff] [blame] | 129 | delegate_(delegate), |
| 130 | dns_config_service_thread_(new DnsConfigServiceThread()) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 131 | delegate_->AddObserver(this); |
Torne (Richard Coles) | 5d1f7b1 | 2014-02-21 12:16:55 +0000 | [diff] [blame] | 132 | dns_config_service_thread_->StartWithOptions( |
| 133 | base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 134 | } |
| 135 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 136 | // static |
| 137 | NetworkChangeNotifier::NetworkChangeCalculatorParams |
| 138 | NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid() { |
| 139 | NetworkChangeCalculatorParams params; |
| 140 | // IPAddressChanged is produced immediately prior to ConnectionTypeChanged |
| 141 | // so delay IPAddressChanged so they get merged with the following |
| 142 | // ConnectionTypeChanged signal. |
| 143 | params.ip_address_offline_delay_ = base::TimeDelta::FromSeconds(1); |
| 144 | params.ip_address_online_delay_ = base::TimeDelta::FromSeconds(1); |
| 145 | params.connection_type_offline_delay_ = base::TimeDelta::FromSeconds(0); |
| 146 | params.connection_type_online_delay_ = base::TimeDelta::FromSeconds(0); |
| 147 | return params; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 148 | } |
| 149 | |
| 150 | } // namespace net |