Index: net/base/network_change_notifier_mac.cc |
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc |
deleted file mode 100644 |
index 14ec5542c51cfa0f479e65192f8ab217f0c344c3..0000000000000000000000000000000000000000 |
--- a/net/base/network_change_notifier_mac.cc |
+++ /dev/null |
@@ -1,268 +0,0 @@ |
-// Copyright (c) 2012 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 "net/base/network_change_notifier_mac.h" |
- |
-#include <netinet/in.h> |
-#include <resolv.h> |
- |
-#include "base/basictypes.h" |
-#include "base/threading/thread.h" |
-#include "net/dns/dns_config_service.h" |
- |
-namespace net { |
- |
-static bool CalculateReachability(SCNetworkConnectionFlags flags) { |
- bool reachable = flags & kSCNetworkFlagsReachable; |
- bool connection_required = flags & kSCNetworkFlagsConnectionRequired; |
- return reachable && !connection_required; |
-} |
- |
-NetworkChangeNotifier::ConnectionType CalculateConnectionType( |
- SCNetworkConnectionFlags flags) { |
- bool reachable = CalculateReachability(flags); |
- if (reachable) { |
-#if defined(OS_IOS) |
- return (flags & kSCNetworkReachabilityFlagsIsWWAN) ? |
- NetworkChangeNotifier::CONNECTION_3G : |
- NetworkChangeNotifier::CONNECTION_WIFI; |
-#else |
- // TODO(droger): Get something more detailed than CONNECTION_UNKNOWN. |
- // http://crbug.com/112937 |
- return NetworkChangeNotifier::CONNECTION_UNKNOWN; |
-#endif // defined(OS_IOS) |
- } else { |
- return NetworkChangeNotifier::CONNECTION_NONE; |
- } |
-} |
- |
-// Thread on which we can run DnsConfigService, which requires a TYPE_IO |
-// message loop. |
-class NetworkChangeNotifierMac::DnsConfigServiceThread : public base::Thread { |
- public: |
- DnsConfigServiceThread() : base::Thread("DnsConfigService") {} |
- |
- ~DnsConfigServiceThread() override { Stop(); } |
- |
- void Init() override { |
- service_ = DnsConfigService::CreateSystemService(); |
- service_->WatchConfig(base::Bind(&NetworkChangeNotifier::SetDnsConfig)); |
- } |
- |
- void CleanUp() override { service_.reset(); } |
- |
- private: |
- scoped_ptr<DnsConfigService> service_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DnsConfigServiceThread); |
-}; |
- |
-NetworkChangeNotifierMac::NetworkChangeNotifierMac() |
- : NetworkChangeNotifier(NetworkChangeCalculatorParamsMac()), |
- connection_type_(CONNECTION_UNKNOWN), |
- connection_type_initialized_(false), |
- initial_connection_type_cv_(&connection_type_lock_), |
- forwarder_(this), |
- dns_config_service_thread_(new DnsConfigServiceThread()) { |
- // Must be initialized after the rest of this object, as it may call back into |
- // SetInitialConnectionType(). |
- config_watcher_.reset(new NetworkConfigWatcherMac(&forwarder_)); |
- dns_config_service_thread_->StartWithOptions( |
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
-} |
- |
-NetworkChangeNotifierMac::~NetworkChangeNotifierMac() { |
- // Delete the ConfigWatcher to join the notifier thread, ensuring that |
- // StartReachabilityNotifications() has an opportunity to run to completion. |
- config_watcher_.reset(); |
- |
- // Now that StartReachabilityNotifications() has either run to completion or |
- // never run at all, unschedule reachability_ if it was previously scheduled. |
- if (reachability_.get() && run_loop_.get()) { |
- SCNetworkReachabilityUnscheduleFromRunLoop(reachability_.get(), |
- run_loop_.get(), |
- kCFRunLoopCommonModes); |
- } |
-} |
- |
-// static |
-NetworkChangeNotifier::NetworkChangeCalculatorParams |
-NetworkChangeNotifierMac::NetworkChangeCalculatorParamsMac() { |
- NetworkChangeCalculatorParams params; |
- // Delay values arrived at by simple experimentation and adjusted so as to |
- // produce a single signal when switching between network connections. |
- params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(500); |
- params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(500); |
- params.connection_type_offline_delay_ = |
- base::TimeDelta::FromMilliseconds(1000); |
- params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500); |
- return params; |
-} |
- |
-NetworkChangeNotifier::ConnectionType |
-NetworkChangeNotifierMac::GetCurrentConnectionType() const { |
- base::AutoLock lock(connection_type_lock_); |
- // Make sure the initial connection type is set before returning. |
- while (!connection_type_initialized_) { |
- initial_connection_type_cv_.Wait(); |
- } |
- return connection_type_; |
-} |
- |
-void NetworkChangeNotifierMac::Forwarder::Init() { |
- net_config_watcher_->SetInitialConnectionType(); |
-} |
- |
-void NetworkChangeNotifierMac::Forwarder::StartReachabilityNotifications() { |
- net_config_watcher_->StartReachabilityNotifications(); |
-} |
- |
-void NetworkChangeNotifierMac::Forwarder::SetDynamicStoreNotificationKeys( |
- SCDynamicStoreRef store) { |
- net_config_watcher_->SetDynamicStoreNotificationKeys(store); |
-} |
- |
-void NetworkChangeNotifierMac::Forwarder::OnNetworkConfigChange( |
- CFArrayRef changed_keys) { |
- net_config_watcher_->OnNetworkConfigChange(changed_keys); |
-} |
- |
-void NetworkChangeNotifierMac::SetInitialConnectionType() { |
- // Called on notifier thread. |
- |
- // Try to reach 0.0.0.0. This is the approach taken by Firefox: |
- // |
- // http://mxr.mozilla.org/mozilla2.0/source/netwerk/system/mac/nsNetworkLinkService.mm |
- // |
- // From my (adamk) testing on Snow Leopard, 0.0.0.0 |
- // seems to be reachable if any network connection is available. |
- struct sockaddr_in addr = {0}; |
- addr.sin_len = sizeof(addr); |
- addr.sin_family = AF_INET; |
- reachability_.reset(SCNetworkReachabilityCreateWithAddress( |
- kCFAllocatorDefault, reinterpret_cast<struct sockaddr*>(&addr))); |
- |
- SCNetworkConnectionFlags flags; |
- ConnectionType connection_type = CONNECTION_UNKNOWN; |
- if (SCNetworkReachabilityGetFlags(reachability_, &flags)) { |
- connection_type = CalculateConnectionType(flags); |
- } else { |
- LOG(ERROR) << "Could not get initial network connection type," |
- << "assuming online."; |
- } |
- { |
- base::AutoLock lock(connection_type_lock_); |
- connection_type_ = connection_type; |
- connection_type_initialized_ = true; |
- initial_connection_type_cv_.Signal(); |
- } |
-} |
- |
-void NetworkChangeNotifierMac::StartReachabilityNotifications() { |
- // Called on notifier thread. |
- run_loop_.reset(CFRunLoopGetCurrent()); |
- CFRetain(run_loop_.get()); |
- |
- DCHECK(reachability_); |
- SCNetworkReachabilityContext reachability_context = { |
- 0, // version |
- this, // user data |
- NULL, // retain |
- NULL, // release |
- NULL // description |
- }; |
- if (!SCNetworkReachabilitySetCallback( |
- reachability_, |
- &NetworkChangeNotifierMac::ReachabilityCallback, |
- &reachability_context)) { |
- LOG(DFATAL) << "Could not set network reachability callback"; |
- reachability_.reset(); |
- } else if (!SCNetworkReachabilityScheduleWithRunLoop(reachability_, |
- run_loop_, |
- kCFRunLoopCommonModes)) { |
- LOG(DFATAL) << "Could not schedule network reachability on run loop"; |
- reachability_.reset(); |
- } |
-} |
- |
-void NetworkChangeNotifierMac::SetDynamicStoreNotificationKeys( |
- SCDynamicStoreRef store) { |
-#if defined(OS_IOS) |
- // SCDynamicStore API does not exist on iOS. |
- NOTREACHED(); |
-#else |
- base::ScopedCFTypeRef<CFMutableArrayRef> notification_keys( |
- CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); |
- base::ScopedCFTypeRef<CFStringRef> key( |
- SCDynamicStoreKeyCreateNetworkGlobalEntity( |
- NULL, kSCDynamicStoreDomainState, kSCEntNetInterface)); |
- CFArrayAppendValue(notification_keys.get(), key.get()); |
- key.reset(SCDynamicStoreKeyCreateNetworkGlobalEntity( |
- NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4)); |
- CFArrayAppendValue(notification_keys.get(), key.get()); |
- key.reset(SCDynamicStoreKeyCreateNetworkGlobalEntity( |
- NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6)); |
- CFArrayAppendValue(notification_keys.get(), key.get()); |
- |
- // Set the notification keys. This starts us receiving notifications. |
- bool ret = SCDynamicStoreSetNotificationKeys( |
- store, notification_keys.get(), NULL); |
- // TODO(willchan): Figure out a proper way to handle this rather than crash. |
- CHECK(ret); |
-#endif // defined(OS_IOS) |
-} |
- |
-void NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) { |
-#if defined(OS_IOS) |
- // SCDynamicStore API does not exist on iOS. |
- NOTREACHED(); |
-#else |
- DCHECK_EQ(run_loop_.get(), CFRunLoopGetCurrent()); |
- |
- for (CFIndex i = 0; i < CFArrayGetCount(changed_keys); ++i) { |
- CFStringRef key = static_cast<CFStringRef>( |
- CFArrayGetValueAtIndex(changed_keys, i)); |
- if (CFStringHasSuffix(key, kSCEntNetIPv4) || |
- CFStringHasSuffix(key, kSCEntNetIPv6)) { |
- NotifyObserversOfIPAddressChange(); |
- return; |
- } |
- if (CFStringHasSuffix(key, kSCEntNetInterface)) { |
- // TODO(willchan): Does not appear to be working. Look into this. |
- // Perhaps this isn't needed anyway. |
- } else { |
- NOTREACHED(); |
- } |
- } |
-#endif // defined(OS_IOS) |
-} |
- |
-// static |
-void NetworkChangeNotifierMac::ReachabilityCallback( |
- SCNetworkReachabilityRef target, |
- SCNetworkConnectionFlags flags, |
- void* notifier) { |
- NetworkChangeNotifierMac* notifier_mac = |
- static_cast<NetworkChangeNotifierMac*>(notifier); |
- |
- DCHECK_EQ(notifier_mac->run_loop_.get(), CFRunLoopGetCurrent()); |
- |
- ConnectionType new_type = CalculateConnectionType(flags); |
- ConnectionType old_type; |
- { |
- base::AutoLock lock(notifier_mac->connection_type_lock_); |
- old_type = notifier_mac->connection_type_; |
- notifier_mac->connection_type_ = new_type; |
- } |
- if (old_type != new_type) |
- NotifyObserversOfConnectionTypeChange(); |
- |
-#if defined(OS_IOS) |
- // On iOS, the SCDynamicStore API does not exist, and we use the reachability |
- // API to detect IP address changes instead. |
- NotifyObserversOfIPAddressChange(); |
-#endif // defined(OS_IOS) |
-} |
- |
-} // namespace net |