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