blob: 2461d644b6462e4a5cab42df9bf90be91c941236 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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)2a99a7e2013-03-28 15:31:22 +00005////////////////////////////////////////////////////////////////////////////////
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)58218062012-11-14 11:43:16 +000059
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000060#include "net/android/network_change_notifier_android.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000061
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000062#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)58218062012-11-14 11:43:16 +000066namespace net {
67
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000068// Thread on which we can run DnsConfigService, which requires a TYPE_IO
69// message loop to monitor /system/etc/hosts.
70class 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)58218062012-11-14 11:43:16 +0000108NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000109 delegate_->RemoveObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000110}
111
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000112NetworkChangeNotifier::ConnectionType
113NetworkChangeNotifierAndroid::GetCurrentConnectionType() const {
114 return delegate_->GetCurrentConnectionType();
115}
116
117void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000118 DnsConfigServiceThread::NotifyNetworkChangeNotifierObservers();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000119}
120
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000121// static
122bool NetworkChangeNotifierAndroid::Register(JNIEnv* env) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000123 return NetworkChangeNotifierDelegateAndroid::Register(env);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000124}
125
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000126NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid(
127 NetworkChangeNotifierDelegateAndroid* delegate)
128 : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()),
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000129 delegate_(delegate),
130 dns_config_service_thread_(new DnsConfigServiceThread()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000131 delegate_->AddObserver(this);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000132 dns_config_service_thread_->StartWithOptions(
133 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000134}
135
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000136// static
137NetworkChangeNotifier::NetworkChangeCalculatorParams
138NetworkChangeNotifierAndroid::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)58218062012-11-14 11:43:16 +0000148}
149
150} // namespace net