summaryrefslogtreecommitdiff
path: root/chromium/services/network/network_change_manager.cc
blob: 0c428a188ce1426147f445fc229ea933b63b8ff0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/network_change_manager.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_change_notifier_posix.h"

namespace network {

NetworkChangeManager::NetworkChangeManager(
    std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier)
    : network_change_notifier_(std::move(network_change_notifier)) {
  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
  connection_type_ =
      mojom::ConnectionType(net::NetworkChangeNotifier::GetConnectionType());
}

NetworkChangeManager::~NetworkChangeManager() {
  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}

void NetworkChangeManager::AddReceiver(
    mojo::PendingReceiver<mojom::NetworkChangeManager> receiver) {
  receivers_.Add(this, std::move(receiver));
}

void NetworkChangeManager::RequestNotifications(
    mojo::PendingRemote<mojom::NetworkChangeManagerClient>
        client_pending_remote) {
  mojo::Remote<mojom::NetworkChangeManagerClient> client_remote(
      std::move(client_pending_remote));
  client_remote.set_disconnect_handler(base::BindOnce(
      &NetworkChangeManager::NotificationPipeBroken,
      // base::Unretained is safe as destruction of the
      // NetworkChangeManager will also destroy the
      // |clients_| list (which this object will be
      // inserted into, below), which will destroy the
      // client_remote, rendering this callback moot.
      base::Unretained(this), base::Unretained(client_remote.get())));
  client_remote->OnInitialConnectionType(connection_type_);
  clients_.push_back(std::move(client_remote));
}

#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
void NetworkChangeManager::OnNetworkChanged(
    bool dns_changed,
    bool ip_address_changed,
    bool connection_type_changed,
    mojom::ConnectionType new_connection_type,
    bool connection_subtype_changed,
    mojom::ConnectionSubtype new_connection_subtype) {
  // network_change_notifier_ can be null in unit tests.
  if (!network_change_notifier_)
    return;

  net::NetworkChangeNotifierPosix* notifier =
      static_cast<net::NetworkChangeNotifierPosix*>(
          network_change_notifier_.get());
  if (dns_changed)
    notifier->OnDNSChanged();
  if (ip_address_changed)
    notifier->OnIPAddressChanged();
  if (connection_type_changed) {
    notifier->OnConnectionChanged(
        net::NetworkChangeNotifier::ConnectionType(new_connection_type));
  }
  if (connection_type_changed || connection_subtype_changed) {
    notifier->OnConnectionSubtypeChanged(
        net::NetworkChangeNotifier::ConnectionType(new_connection_type),
        net::NetworkChangeNotifier::ConnectionSubtype(new_connection_subtype));
  }
}
#endif

size_t NetworkChangeManager::GetNumClientsForTesting() const {
  return clients_.size();
}

void NetworkChangeManager::NotificationPipeBroken(
    mojom::NetworkChangeManagerClient* client) {
  clients_.erase(std::find_if(
      clients_.begin(), clients_.end(),
      [client](mojo::Remote<mojom::NetworkChangeManagerClient>& remote) {
        return remote.get() == client;
      }));
}

void NetworkChangeManager::OnNetworkChanged(
    net::NetworkChangeNotifier::ConnectionType type) {
  connection_type_ = mojom::ConnectionType(type);
  for (const auto& client : clients_) {
    client->OnNetworkChanged(connection_type_);
  }
}

}  // namespace network