Infer Windows network connection type from interface type.

If all active network interfaces have the same network
connection type it's safe to assume this is the type of
the network connection.  Make NetworkChangeNotifier return
this network connection type on Windows.

BUG=160537

Review URL: https://codereview.chromium.org/298023005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278881 0039d316-1c4b-4281-b951-d872f2087c98
parent 1e0d6ebf
...@@ -763,6 +763,36 @@ void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) { ...@@ -763,6 +763,36 @@ void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
NotifyObserversOfDNSChange(); NotifyObserversOfDNSChange();
} }
// static
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifier::ConnectionTypeFromInterfaces() {
NetworkInterfaceList interfaces;
if (!GetNetworkList(&interfaces, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES))
return CONNECTION_UNKNOWN;
return ConnectionTypeFromInterfaceList(interfaces);
}
//static
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifier::ConnectionTypeFromInterfaceList(
const NetworkInterfaceList& interfaces) {
bool first = true;
ConnectionType result = CONNECTION_UNKNOWN;
for (size_t i = 0; i < interfaces.size(); ++i) {
#if defined(OS_WIN)
if (interfaces[i].friendly_name == "Teredo Tunneling Pseudo-Interface")
continue;
#endif
if (first) {
first = false;
result = interfaces[i].type;
} else if (result != interfaces[i].type) {
return CONNECTION_UNKNOWN;
}
}
return result;
}
void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
if (g_network_change_notifier) { if (g_network_change_notifier) {
g_network_change_notifier->connection_type_observer_list_->Notify( g_network_change_notifier->connection_type_observer_list_->Notify(
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_H_ #ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_H_
#define NET_BASE_NETWORK_CHANGE_NOTIFIER_H_ #define NET_BASE_NETWORK_CHANGE_NOTIFIER_H_
#include <vector>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/observer_list_threadsafe.h" #include "base/observer_list_threadsafe.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "net/base/net_export.h" #include "net/base/net_export.h"
...@@ -17,6 +20,8 @@ namespace net { ...@@ -17,6 +20,8 @@ namespace net {
struct DnsConfig; struct DnsConfig;
class HistogramWatcher; class HistogramWatcher;
class NetworkChangeNotifierFactory; class NetworkChangeNotifierFactory;
struct NetworkInterface;
typedef std::vector<NetworkInterface> NetworkInterfaceList;
class URLRequest; class URLRequest;
#if defined(OS_LINUX) #if defined(OS_LINUX)
...@@ -300,15 +305,26 @@ class NET_EXPORT NetworkChangeNotifier { ...@@ -300,15 +305,26 @@ class NET_EXPORT NetworkChangeNotifier {
// Stores |config| in NetworkState and notifies observers. // Stores |config| in NetworkState and notifies observers.
static void SetDnsConfig(const DnsConfig& config); static void SetDnsConfig(const DnsConfig& config);
// Infer connection type from |GetNetworkList|. If all network interfaces have
// the same type, return it, otherwise return CONNECTION_UNKNOWN.
static ConnectionType ConnectionTypeFromInterfaces();
private: private:
friend class HostResolverImplDnsTest; friend class HostResolverImplDnsTest;
friend class NetworkChangeNotifierAndroidTest; friend class NetworkChangeNotifierAndroidTest;
friend class NetworkChangeNotifierLinuxTest; friend class NetworkChangeNotifierLinuxTest;
friend class NetworkChangeNotifierWinTest; friend class NetworkChangeNotifierWinTest;
FRIEND_TEST_ALL_PREFIXES(NetworkChangeNotifierTest,
InterfacesToConnectionType);
class NetworkState; class NetworkState;
class NetworkChangeCalculator; class NetworkChangeCalculator;
// Infer connection type from |interfaces|. If all network interfaces have
// the same type, return it, otherwise return CONNECTION_UNKNOWN.
static ConnectionType ConnectionTypeFromInterfaceList(
const NetworkInterfaceList& interfaces);
const scoped_refptr<ObserverListThreadSafe<IPAddressObserver> > const scoped_refptr<ObserverListThreadSafe<IPAddressObserver> >
ip_address_observer_list_; ip_address_observer_list_;
const scoped_refptr<ObserverListThreadSafe<ConnectionTypeObserver> > const scoped_refptr<ObserverListThreadSafe<ConnectionTypeObserver> >
......
// Copyright 2014 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 "network_change_notifier.h"
#include "net/base/net_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
TEST(NetworkChangeNotifierTest, InterfacesToConnectionType) {
NetworkInterfaceList list;
// Test empty list.
EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
NetworkChangeNotifier::CONNECTION_UNKNOWN);
NetworkInterface interface;
for (int i = NetworkChangeNotifier::CONNECTION_UNKNOWN;
i < NetworkChangeNotifier::CONNECTION_LAST;
i++) {
// Check individual types.
list.clear();
interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(i);
list.push_back(interface);
EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list), i);
// Check two types.
for (int j = NetworkChangeNotifier::CONNECTION_UNKNOWN;
j < NetworkChangeNotifier::CONNECTION_LAST;
j++) {
list.clear();
interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(i);
list.push_back(interface);
interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(j);
list.push_back(interface);
EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
i == j ? i : NetworkChangeNotifier::CONNECTION_UNKNOWN);
}
}
#if defined(OS_WIN)
// Ignore fake Teredo interface.
list.clear();
interface.type = NetworkChangeNotifier::CONNECTION_4G;
interface.friendly_name = "Teredo Tunneling Pseudo-Interface";
list.push_back(interface);
// Verify Teredo interface type ignored.
EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
NetworkChangeNotifier::CONNECTION_UNKNOWN);
// Verify type of non-Teredo interface used.
interface.type = NetworkChangeNotifier::CONNECTION_3G;
interface.friendly_name = "";
list.push_back(interface);
EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
NetworkChangeNotifier::CONNECTION_3G);
// Reverse elements.
list.push_back(list[0]);
list.erase(list.begin());
EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
NetworkChangeNotifier::CONNECTION_3G);
#endif
}
} // namespace net
...@@ -200,8 +200,7 @@ NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const { ...@@ -200,8 +200,7 @@ NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const {
LOG_IF(ERROR, result != 0) LOG_IF(ERROR, result != 0)
<< "WSALookupServiceEnd() failed with: " << result; << "WSALookupServiceEnd() failed with: " << result;
// TODO(droger): Return something more detailed than CONNECTION_UNKNOWN. return found_connection ? ConnectionTypeFromInterfaces() :
return found_connection ? NetworkChangeNotifier::CONNECTION_UNKNOWN :
NetworkChangeNotifier::CONNECTION_NONE; NetworkChangeNotifier::CONNECTION_NONE;
} }
......
...@@ -1242,6 +1242,7 @@ ...@@ -1242,6 +1242,7 @@
'base/net_log_unittest.h', 'base/net_log_unittest.h',
'base/net_util_unittest.cc', 'base/net_util_unittest.cc',
'base/net_util_icu_unittest.cc', 'base/net_util_icu_unittest.cc',
'base/network_change_notifier_unittest.cc',
'base/network_change_notifier_win_unittest.cc', 'base/network_change_notifier_win_unittest.cc',
'base/prioritized_dispatcher_unittest.cc', 'base/prioritized_dispatcher_unittest.cc',
'base/priority_queue_unittest.cc', 'base/priority_queue_unittest.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment