Chromium Code Reviews| Index: chrome/browser/net/discovery_network_monitor.cc |
| diff --git a/chrome/browser/net/discovery_network_monitor.cc b/chrome/browser/net/discovery_network_monitor.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4f8b3ccb4c08ed214c594a2633f5aa335ad07f1b |
| --- /dev/null |
| +++ b/chrome/browser/net/discovery_network_monitor.cc |
| @@ -0,0 +1,194 @@ |
| +// Copyright (c) 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 "chrome/browser/net/discovery_network_monitor.h" |
| + |
| +#include <iostream> |
| + |
| +#include "base/lazy_instance.h" |
| +#include "base/logging.h" |
| +#include "chrome/browser/net/discovery_network_list.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "net/base/network_interfaces.h" |
| + |
| +namespace { |
| + |
| +using content::BrowserThread; |
| + |
| +std::vector<NetworkInfo> GetNetworkInfo() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + net::NetworkInterfaceList interface_list; |
| + if (!net::GetNetworkList(&interface_list, |
| + net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) { |
| + DVLOG(2) << "net::GetNetworkList failed after a network change event"; |
| + return std::vector<NetworkInfo>(); |
| + } |
| + |
| + std::vector<NetworkInfo> network_info_list; |
| + for (const auto& interface : interface_list) { |
| + if (interface.type != net::NetworkChangeNotifier::CONNECTION_ETHERNET && |
| + interface.type != net::NetworkChangeNotifier::CONNECTION_WIFI) { |
| + continue; |
| + } |
| + network_info_list.push_back( |
| + NetworkInfo{interface.interface_index, interface.type, interface.name, |
| + std::string(""), interface.address}); |
| + } |
| + |
| + auto network_ids = GetDiscoveryNetworkIdList(); |
| + for (const auto& network_id : network_ids) { |
| + auto matching_info_it = |
| + std::find_if(begin(network_info_list), end(network_info_list), |
| + [&network_id](const NetworkInfo& network_info) { |
| + return network_info.name == network_id.interface_name; |
| + }); |
| + if (matching_info_it != end(network_info_list)) { |
| + matching_info_it->network_id = network_id.network_id; |
|
imcheng
2017/03/14 22:45:35
So it looks like we are combining information from
btolsch
2017/04/03 10:16:35
Although this is possible on linux, as best as I c
|
| + } |
| + } |
| + return network_info_list; |
|
imcheng
2017/03/14 22:45:35
Do we know if the networks in the returned list ar
btolsch
2017/04/03 10:16:35
Yes, it looks like net::GetNetworkList only return
|
| +} |
| + |
| +base::LazyInstance<DiscoveryNetworkMonitor>::Leaky g_discovery_monitor; |
| + |
| +} // namespace |
| +NetworkInfo::NetworkInfo() {} |
| + |
| +NetworkInfo::NetworkInfo( |
| + uint32_t index, |
| + net::NetworkChangeNotifier::ConnectionType connection_type, |
| + std::string name, |
| + std::string network_id, |
| + net::IPAddress ip_address) |
| + : index(index), |
| + connection_type(connection_type), |
| + name(name), |
| + network_id(network_id), |
| + ip_address(ip_address) {} |
| + |
| +NetworkInfo::NetworkInfo(const NetworkInfo&) = default; |
| + |
| +NetworkInfo& NetworkInfo::operator=(const NetworkInfo&) = default; |
| + |
| +DiscoveryNetworkMonitor::DiscoveryNetworkMonitor() |
| + : observers_(new base::ObserverListThreadSafe<Observer>( |
| + base::ObserverListThreadSafe< |
| + Observer>::NotificationType::NOTIFY_EXISTING_ONLY)) { |
| + net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| +} |
| + |
| +DiscoveryNetworkMonitor::~DiscoveryNetworkMonitor() { |
| + net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
| +} |
| + |
| +DiscoveryNetworkMonitor* DiscoveryNetworkMonitor::GetInstance() { |
| + DiscoveryNetworkMonitor* monitor = g_discovery_monitor.Pointer(); |
| + if (!monitor->network_info_strategy_) { |
| + monitor->network_info_strategy_ = base::Bind(&GetNetworkInfo); |
| + } |
| + return monitor; |
| +} |
| + |
| +DiscoveryNetworkMonitor* DiscoveryNetworkMonitor::GetInstanceForTest( |
| + NetworkInfoStrategy strategy) { |
| + DiscoveryNetworkMonitor* monitor = g_discovery_monitor.Pointer(); |
| + monitor->network_info_strategy_ = std::move(strategy); |
| + return monitor; |
| +} |
| + |
| +void DiscoveryNetworkMonitor::RebindNetworkChangeObserverForTest() { |
| + net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| +} |
| + |
| +void DiscoveryNetworkMonitor::AddObserver(Observer* const observer) { |
| + observers_->AddObserver(observer); |
| +} |
| + |
| +void DiscoveryNetworkMonitor::RemoveObserver(Observer* const observer) { |
| + observers_->RemoveObserver(observer); |
| +} |
| + |
| +void DiscoveryNetworkMonitor::ForceNetworkInfoRefresh( |
| + NetworkRefreshCompleteCallback callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&DiscoveryNetworkMonitor::UpdateNetworkInfoWithCallback, |
| + base::Unretained(this), callback)); |
| +} |
| + |
| +void DiscoveryNetworkMonitor::OnNetworkChanged( |
| + net::NetworkChangeNotifier::ConnectionType) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&DiscoveryNetworkMonitor::UpdateNetworkInfoWithObservers, |
| + base::Unretained(this))); |
| +} |
| + |
| +std::string DiscoveryNetworkMonitor::ComputeNetworkId( |
| + const std::vector<NetworkInfo>& network_info_list) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + if (network_info_list.size() == 0) { |
| + return std::string("disconnected"); |
|
mark a. foltz
2017/03/18 19:58:21
Can these special network id constants be defined
btolsch
2017/04/03 10:16:36
Done.
|
| + } |
| + std::string network_ids; |
| + for (const auto& network_info : network_info_list) { |
| + network_ids += network_info.network_id; |
| + } |
| + if (network_ids.size() == 0) { |
| + return std::string("unknown"); |
| + } |
| + int folded_ids = 0; |
| + unsigned long size = network_ids.size(); |
| + for (unsigned long i = 0; i < size; ++i) { |
| + folded_ids ^= network_ids[i] << (8 * (i % 2)); |
|
mark a. foltz
2017/03/18 19:58:21
What is this computing? Maybe you can just comput
btolsch
2017/04/03 10:16:35
Done.
|
| + } |
| + |
| + std::string network_id = "#_____"; |
| + network_id[5] = '0' + (folded_ids % 10); |
| + folded_ids /= 10; |
| + network_id[4] = '0' + (folded_ids % 10); |
| + folded_ids /= 10; |
| + network_id[3] = '0' + (folded_ids % 10); |
| + folded_ids /= 10; |
| + network_id[2] = '0' + (folded_ids % 10); |
| + folded_ids /= 10; |
| + network_id[1] = '0' + (folded_ids % 10); |
| + |
| + return network_id; |
|
imcheng
2017/03/14 22:45:35
Is the purpose of this to mimic the Cast MRP logic
btolsch
2017/04/03 10:16:35
The order shouldn't matter. I added a sort to the
|
| +} |
| + |
| +void DiscoveryNetworkMonitor::UpdateNetworkInfo() { |
|
mark a. foltz
2017/03/18 19:58:21
Will this get called when WiFi SSIDs change?
btolsch
2017/04/03 10:16:35
I guess that depends on whether NetworkChangeNotif
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + auto network_info_list = network_info_strategy_.Run(); |
| + auto network_id = ComputeNetworkId(network_info_list); |
| + |
| + base::AutoLock auto_lock(network_info_lock_); |
| + networks_.swap(network_info_list); |
| + network_id_.swap(network_id); |
| +} |
| + |
| +void DiscoveryNetworkMonitor::UpdateNetworkInfoWithObservers() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + UpdateNetworkInfo(); |
| + |
| + observers_->Notify(FROM_HERE, &Observer::OnNetworksChanged, |
|
mark a. foltz
2017/03/18 19:58:21
Do you only want to do this if the network list /
btolsch
2017/04/03 10:16:35
Yes. Done.
|
| + base::ConstRef(*this)); |
| +} |
| + |
| +void DiscoveryNetworkMonitor::UpdateNetworkInfoWithCallback( |
|
mark a. foltz
2017/03/18 19:58:21
Maybe UpdateNetworkInfo() could always update obse
btolsch
2017/04/03 10:16:35
Done.
|
| + NetworkRefreshCompleteCallback callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + |
| + UpdateNetworkInfo(); |
| + |
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
| +} |