1// Copyright (c) 2010 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.h"
6#include "build/build_config.h"
7#if defined(OS_WIN)
8#include "net/base/network_change_notifier_win.h"
9#elif defined(OS_LINUX)
10#include "net/base/network_change_notifier_linux.h"
11#elif defined(OS_MACOSX)
12#include "net/base/network_change_notifier_mac.h"
13#endif
14
15namespace net {
16
17namespace {
18
19// The actual singleton notifier.  The class contract forbids usage of the API
20// in ways that would require us to place locks around access to this object.
21// (The prohibition on global non-POD objects makes it tricky to do such a thing
22// anyway.)
23NetworkChangeNotifier* g_network_change_notifier = NULL;
24
25class MockNetworkChangeNotifier : public NetworkChangeNotifier {
26 public:
27  virtual bool IsCurrentlyOffline() const { return false; }
28};
29
30}  // namespace
31
32NetworkChangeNotifier::~NetworkChangeNotifier() {
33  DCHECK_EQ(this, g_network_change_notifier);
34  g_network_change_notifier = NULL;
35}
36
37NetworkChangeNotifier* NetworkChangeNotifier::Create() {
38#if defined(OS_WIN)
39  return new NetworkChangeNotifierWin();
40#elif defined(OS_LINUX)
41  return new NetworkChangeNotifierLinux();
42#elif defined(OS_MACOSX)
43  return new NetworkChangeNotifierMac();
44#else
45  NOTIMPLEMENTED();
46  return NULL;
47#endif
48}
49
50// static
51bool NetworkChangeNotifier::IsOffline() {
52  return g_network_change_notifier &&
53         g_network_change_notifier->IsCurrentlyOffline();
54}
55
56// static
57NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() {
58  return new MockNetworkChangeNotifier();
59}
60
61void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) {
62  if (g_network_change_notifier)
63    g_network_change_notifier->ip_address_observer_list_->AddObserver(observer);
64}
65
66void NetworkChangeNotifier::AddOnlineStateObserver(
67    OnlineStateObserver* observer) {
68  if (g_network_change_notifier) {
69    g_network_change_notifier->online_state_observer_list_->AddObserver(
70        observer);
71  }
72}
73
74void NetworkChangeNotifier::RemoveIPAddressObserver(
75    IPAddressObserver* observer) {
76  if (g_network_change_notifier) {
77    g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
78        observer);
79  }
80}
81
82void NetworkChangeNotifier::RemoveOnlineStateObserver(
83    OnlineStateObserver* observer) {
84  if (g_network_change_notifier) {
85    g_network_change_notifier->online_state_observer_list_->RemoveObserver(
86        observer);
87  }
88}
89
90NetworkChangeNotifier::NetworkChangeNotifier()
91    : ip_address_observer_list_(
92        new ObserverListThreadSafe<IPAddressObserver>(
93            ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
94      online_state_observer_list_(
95        new ObserverListThreadSafe<OnlineStateObserver>(
96            ObserverListBase<OnlineStateObserver>::NOTIFY_EXISTING_ONLY)) {
97  DCHECK(!g_network_change_notifier);
98  g_network_change_notifier = this;
99}
100
101void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
102  if (g_network_change_notifier) {
103    g_network_change_notifier->ip_address_observer_list_->Notify(
104        &IPAddressObserver::OnIPAddressChanged);
105  }
106}
107
108void NetworkChangeNotifier::NotifyObserversOfOnlineStateChange() {
109  online_state_observer_list_->Notify(
110      &OnlineStateObserver::OnOnlineStateChanged, !IsOffline());
111}
112
113}  // namespace net
114