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); |
+} |