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
5#include "net/base/network_change_notifier_linux.h"
6
7#include "base/bind.h"
8#include "base/compiler_specific.h"
9#include "base/threading/thread.h"
10#include "net/base/address_tracker_linux.h"
11#include "net/dns/dns_config_service.h"
12
13namespace net {
14
15class NetworkChangeNotifierLinux::Thread : public base::Thread {
16 public:
17  Thread();
18  virtual ~Thread();
19
20  // Plumbing for NetworkChangeNotifier::GetCurrentConnectionType.
21  // Safe to call from any thread.
22  NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() {
23    return address_tracker_.GetCurrentConnectionType();
24  }
25
26  const internal::AddressTrackerLinux* address_tracker() const {
27    return &address_tracker_;
28  }
29
30 protected:
31  // base::Thread
32  virtual void Init() OVERRIDE;
33  virtual void CleanUp() OVERRIDE;
34
35 private:
36  scoped_ptr<DnsConfigService> dns_config_service_;
37  // Used to detect online/offline state and IP address changes.
38  internal::AddressTrackerLinux address_tracker_;
39
40  DISALLOW_COPY_AND_ASSIGN(Thread);
41};
42
43NetworkChangeNotifierLinux::Thread::Thread()
44    : base::Thread("NetworkChangeNotifier"),
45      address_tracker_(
46          base::Bind(&NetworkChangeNotifier::
47                     NotifyObserversOfIPAddressChange),
48          base::Bind(&NetworkChangeNotifier::
49                     NotifyObserversOfConnectionTypeChange),
50          base::Bind(base::DoNothing)) {
51}
52
53NetworkChangeNotifierLinux::Thread::~Thread() {
54  DCHECK(!Thread::IsRunning());
55}
56
57void NetworkChangeNotifierLinux::Thread::Init() {
58  address_tracker_.Init();
59  dns_config_service_ = DnsConfigService::CreateSystemService();
60  dns_config_service_->WatchConfig(
61      base::Bind(&NetworkChangeNotifier::SetDnsConfig));
62}
63
64void NetworkChangeNotifierLinux::Thread::CleanUp() {
65  dns_config_service_.reset();
66}
67
68NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::Create() {
69  return new NetworkChangeNotifierLinux();
70}
71
72NetworkChangeNotifierLinux::NetworkChangeNotifierLinux()
73    : NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()),
74      notifier_thread_(new Thread()) {
75  // We create this notifier thread because the notification implementation
76  // needs a MessageLoopForIO, and there's no guarantee that
77  // MessageLoop::current() meets that criterion.
78  base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
79  notifier_thread_->StartWithOptions(thread_options);
80}
81
82NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
83  // Stopping from here allows us to sanity- check that the notifier
84  // thread shut down properly.
85  notifier_thread_->Stop();
86}
87
88// static
89NetworkChangeNotifier::NetworkChangeCalculatorParams
90NetworkChangeNotifierLinux::NetworkChangeCalculatorParamsLinux() {
91  NetworkChangeCalculatorParams params;
92  // Delay values arrived at by simple experimentation and adjusted so as to
93  // produce a single signal when switching between network connections.
94  params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(2000);
95  params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(2000);
96  params.connection_type_offline_delay_ =
97      base::TimeDelta::FromMilliseconds(1500);
98  params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
99  return params;
100}
101
102NetworkChangeNotifier::ConnectionType
103NetworkChangeNotifierLinux::GetCurrentConnectionType() const {
104  return notifier_thread_->GetCurrentConnectionType();
105}
106
107const internal::AddressTrackerLinux*
108NetworkChangeNotifierLinux::GetAddressTrackerInternal() const {
109  return notifier_thread_->address_tracker();
110}
111
112}  // namespace net
113