15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Threading considerations: 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class is designed to meet various threading guarantees starting from the 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ones imposed by NetworkChangeNotifier: 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - The notifier can be constructed on any thread. 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - GetCurrentConnectionType() can be called on any thread. 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The fact that this implementation of NetworkChangeNotifier is backed by a 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Java side singleton class (see NetworkChangeNotifier.java) adds another 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// threading constraint: 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - The calls to the Java side (stateful) object must be performed from a 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// single thread. This object happens to be a singleton which is used on the 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// application side on the main thread. Therefore all the method calls from 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the native NetworkChangeNotifierAndroid class to its Java counterpart are 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// performed on the main thread. 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This leads to a design involving the following native classes: 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 1) NetworkChangeNotifierFactoryAndroid ('factory') 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 2) NetworkChangeNotifierDelegateAndroid ('delegate') 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 3) NetworkChangeNotifierAndroid ('notifier') 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The factory constructs and owns the delegate. The factory is constructed and 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// destroyed on the main thread which makes it construct and destroy the 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// delegate on the main thread too. This guarantees that the calls to the Java 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// side are performed on the main thread. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note that after the factory's construction, the factory's creation method can 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// be called from any thread since the delegate's construction (performing the 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// JNI calls) already happened on the main thread (when the factory was 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// constructed). 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Propagation of network change notifications: 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// When the factory is requested to create a new instance of the notifier, the 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// factory passes the delegate to the notifier (without transferring ownership). 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note that there is a one-to-one mapping between the factory and the 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// delegate as explained above. But the factory naturally creates multiple 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// instances of the notifier. That means that there is a one-to-many mapping 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// between delegate and notifier (i.e. a single delegate can be shared by 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// multiple notifiers). 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// At construction the notifier (which is also an observer) subscribes to 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// notifications fired by the delegate. These notifications, received by the 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// delegate (and forwarded to the notifier(s)), are sent by the Java side 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// notifier (see NetworkChangeNotifier.java) and are initiated by the Android 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// platform. 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Notifications from the Java side always arrive on the main thread. The 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// delegate then forwards these notifications to the threads of each observer 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (network change notifier). The network change notifier than processes the 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// state change, and notifies each of its observers on their threads. 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This can also be seen as: 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Android platform -> NetworkChangeNotifier (Java) -> 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NetworkChangeNotifierDelegateAndroid -> NetworkChangeNotifierAndroid. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/android/network_change_notifier_android.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/thread.h" 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/address_tracker_linux.h" 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/dns/dns_config_service.h" 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Thread on which we can run DnsConfigService, which requires a TYPE_IO 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// message loop to monitor /system/etc/hosts. 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NetworkChangeNotifierAndroid::DnsConfigServiceThread 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public base::Thread { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DnsConfigServiceThread() 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : base::Thread("DnsConfigService"), 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) address_tracker_(base::Bind(base::DoNothing), 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(base::DoNothing), 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We're only interested in tunnel interface changes. 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(NotifyNetworkChangeNotifierObservers)) {} 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~DnsConfigServiceThread() { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Stop(); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void Init() OVERRIDE { 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) address_tracker_.Init(); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_config_service_ = DnsConfigService::CreateSystemService(); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_config_service_->WatchConfig( 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&NetworkChangeNotifier::SetDnsConfig)); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void CleanUp() OVERRIDE { 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_config_service_.reset(); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static void NotifyNetworkChangeNotifierObservers() { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<DnsConfigService> dns_config_service_; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Used to detect tunnel state changes. 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) internal::AddressTrackerLinux address_tracker_; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DnsConfigServiceThread); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->RemoveObserver(this); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifier::ConnectionType 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifierAndroid::GetCurrentConnectionType() const { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return delegate_->GetCurrentConnectionType(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() { 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DnsConfigServiceThread::NotifyNetworkChangeNotifierObservers(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkChangeNotifierAndroid::Register(JNIEnv* env) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NetworkChangeNotifierDelegateAndroid::Register(env); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid( 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetworkChangeNotifierDelegateAndroid* delegate) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()), 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_(delegate), 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_config_service_thread_(new DnsConfigServiceThread()) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->AddObserver(this); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_config_service_thread_->StartWithOptions( 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifier::NetworkChangeCalculatorParams 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid() { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetworkChangeCalculatorParams params; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // IPAddressChanged is produced immediately prior to ConnectionTypeChanged 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so delay IPAddressChanged so they get merged with the following 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ConnectionTypeChanged signal. 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.ip_address_offline_delay_ = base::TimeDelta::FromSeconds(1); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.ip_address_online_delay_ = base::TimeDelta::FromSeconds(1); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.connection_type_offline_delay_ = base::TimeDelta::FromSeconds(0); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.connection_type_online_delay_ = base::TimeDelta::FromSeconds(0); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return params; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 151