Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/network_change_notifier_mac.h" | 5 #include "net/base/network_change_notifier_mac.h" |
| 6 | 6 |
| 7 #include <netinet/in.h> | 7 #include <netinet/in.h> |
| 8 | 8 |
| 9 namespace net { | 9 namespace net { |
| 10 | 10 |
| 11 static bool CalculateReachability(SCNetworkConnectionFlags flags) { | 11 static NetworkChangeNotifier::ConnectionType |
|
wtc
2012/05/11 01:35:05
Nit: NetworkChangeNotifier::ConnectionType is very
| |
| 12 CalculateReachability(SCNetworkConnectionFlags flags) { | |
|
wtc
2012/05/11 01:35:05
IMPORTANT: It seems wrong for a function named
Cal
| |
| 12 bool reachable = flags & kSCNetworkFlagsReachable; | 13 bool reachable = flags & kSCNetworkFlagsReachable; |
| 13 bool connection_required = flags & kSCNetworkFlagsConnectionRequired; | 14 bool connection_required = flags & kSCNetworkFlagsConnectionRequired; |
| 14 return reachable && !connection_required; | 15 // TODO: Return something more detailed than CONNECTION_UNKNOWN. |
| 16 return (reachable && !connection_required) ? | |
| 17 NetworkChangeNotifier::CONNECTION_UNKNOWN : | |
| 18 NetworkChangeNotifier::CONNECTION_NONE; | |
| 15 } | 19 } |
| 16 | 20 |
| 17 NetworkChangeNotifierMac::NetworkChangeNotifierMac() | 21 NetworkChangeNotifierMac::NetworkChangeNotifierMac() |
| 18 : online_state_(UNINITIALIZED), | 22 : connection_type_(CONNECTION_UNKNOWN), |
| 19 initial_state_cv_(&online_state_lock_), | 23 initialized_(false), |
| 24 initial_state_cv_(&connection_type_lock_), | |
| 20 forwarder_(this) { | 25 forwarder_(this) { |
| 21 // Must be initialized after the rest of this object, as it may call back into | 26 // Must be initialized after the rest of this object, as it may call back into |
| 22 // SetInitialState(). | 27 // SetInitialState(). |
| 23 config_watcher_.reset(new NetworkConfigWatcherMac(&forwarder_)); | 28 config_watcher_.reset(new NetworkConfigWatcherMac(&forwarder_)); |
| 24 } | 29 } |
| 25 | 30 |
| 26 NetworkChangeNotifierMac::~NetworkChangeNotifierMac() { | 31 NetworkChangeNotifierMac::~NetworkChangeNotifierMac() { |
| 27 // Delete the ConfigWatcher to join the notifier thread, ensuring that | 32 // Delete the ConfigWatcher to join the notifier thread, ensuring that |
| 28 // StartReachabilityNotifications() has an opportunity to run to completion. | 33 // StartReachabilityNotifications() has an opportunity to run to completion. |
| 29 config_watcher_.reset(); | 34 config_watcher_.reset(); |
| 30 | 35 |
| 31 // Now that StartReachabilityNotifications() has either run to completion or | 36 // Now that StartReachabilityNotifications() has either run to completion or |
| 32 // never run at all, unschedule reachability_ if it was previously scheduled. | 37 // never run at all, unschedule reachability_ if it was previously scheduled. |
| 33 if (reachability_.get() && run_loop_.get()) { | 38 if (reachability_.get() && run_loop_.get()) { |
| 34 SCNetworkReachabilityUnscheduleFromRunLoop(reachability_.get(), | 39 SCNetworkReachabilityUnscheduleFromRunLoop(reachability_.get(), |
| 35 run_loop_.get(), | 40 run_loop_.get(), |
| 36 kCFRunLoopCommonModes); | 41 kCFRunLoopCommonModes); |
| 37 } | 42 } |
| 38 } | 43 } |
| 39 | 44 |
| 40 bool NetworkChangeNotifierMac::IsCurrentlyOffline() const { | 45 NetworkChangeNotifier::ConnectionType |
| 41 base::AutoLock lock(online_state_lock_); | 46 NetworkChangeNotifierMac::GetCurrentConnectionType() const { |
| 47 base::AutoLock lock(connection_type_lock_); | |
| 42 // Make sure the initial state is set before returning. | 48 // Make sure the initial state is set before returning. |
| 43 while (online_state_ == UNINITIALIZED) { | 49 while (!initialized_) { |
| 44 initial_state_cv_.Wait(); | 50 initial_state_cv_.Wait(); |
| 45 } | 51 } |
| 46 return online_state_ == OFFLINE; | 52 return connection_type_; |
| 47 } | 53 } |
| 48 | 54 |
| 49 void NetworkChangeNotifierMac::SetInitialState() { | 55 void NetworkChangeNotifierMac::SetInitialState() { |
| 50 // Called on notifier thread. | 56 // Called on notifier thread. |
| 51 | 57 |
| 52 // Try to reach 0.0.0.0. This is the approach taken by Firefox: | 58 // Try to reach 0.0.0.0. This is the approach taken by Firefox: |
| 53 // | 59 // |
| 54 // http://mxr.mozilla.org/mozilla2.0/source/netwerk/system/mac/nsNetworkLinkSe rvice.mm | 60 // http://mxr.mozilla.org/mozilla2.0/source/netwerk/system/mac/nsNetworkLinkSe rvice.mm |
| 55 // | 61 // |
| 56 // From my (adamk) testing on Snow Leopard, 0.0.0.0 | 62 // From my (adamk) testing on Snow Leopard, 0.0.0.0 |
| 57 // seems to be reachable if any network connection is available. | 63 // seems to be reachable if any network connection is available. |
| 58 struct sockaddr_in addr = {0}; | 64 struct sockaddr_in addr = {0}; |
| 59 addr.sin_len = sizeof(addr); | 65 addr.sin_len = sizeof(addr); |
| 60 addr.sin_family = AF_INET; | 66 addr.sin_family = AF_INET; |
| 61 reachability_.reset(SCNetworkReachabilityCreateWithAddress( | 67 reachability_.reset(SCNetworkReachabilityCreateWithAddress( |
| 62 kCFAllocatorDefault, reinterpret_cast<struct sockaddr*>(&addr))); | 68 kCFAllocatorDefault, reinterpret_cast<struct sockaddr*>(&addr))); |
| 63 | 69 |
| 64 SCNetworkConnectionFlags flags; | 70 SCNetworkConnectionFlags flags; |
| 65 bool reachable = true; | 71 ConnectionType reachable = CONNECTION_UNKNOWN; |
| 66 if (SCNetworkReachabilityGetFlags(reachability_, &flags)) | 72 if (SCNetworkReachabilityGetFlags(reachability_, &flags)) |
| 67 reachable = CalculateReachability(flags); | 73 reachable = CalculateReachability(flags); |
| 68 else | 74 else |
| 69 LOG(ERROR) << "Could not get initial network state, assuming online."; | 75 LOG(ERROR) << "Could not get initial network state, assuming online."; |
| 70 { | 76 { |
| 71 base::AutoLock lock(online_state_lock_); | 77 base::AutoLock lock(connection_type_lock_); |
| 72 online_state_ = reachable ? ONLINE : OFFLINE; | 78 connection_type_ = reachable; |
| 79 initialized_ = true; | |
| 73 initial_state_cv_.Signal(); | 80 initial_state_cv_.Signal(); |
| 74 } | 81 } |
| 75 } | 82 } |
| 76 | 83 |
| 77 void NetworkChangeNotifierMac::StartReachabilityNotifications() { | 84 void NetworkChangeNotifierMac::StartReachabilityNotifications() { |
| 78 // Called on notifier thread. | 85 // Called on notifier thread. |
| 79 run_loop_.reset(CFRunLoopGetCurrent()); | 86 run_loop_.reset(CFRunLoopGetCurrent()); |
| 80 CFRetain(run_loop_.get()); | 87 CFRetain(run_loop_.get()); |
| 81 | 88 |
| 82 DCHECK(reachability_); | 89 DCHECK(reachability_); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 // static | 153 // static |
| 147 void NetworkChangeNotifierMac::ReachabilityCallback( | 154 void NetworkChangeNotifierMac::ReachabilityCallback( |
| 148 SCNetworkReachabilityRef target, | 155 SCNetworkReachabilityRef target, |
| 149 SCNetworkConnectionFlags flags, | 156 SCNetworkConnectionFlags flags, |
| 150 void* notifier) { | 157 void* notifier) { |
| 151 NetworkChangeNotifierMac* notifier_mac = | 158 NetworkChangeNotifierMac* notifier_mac = |
| 152 static_cast<NetworkChangeNotifierMac*>(notifier); | 159 static_cast<NetworkChangeNotifierMac*>(notifier); |
| 153 | 160 |
| 154 DCHECK_EQ(notifier_mac->run_loop_.get(), CFRunLoopGetCurrent()); | 161 DCHECK_EQ(notifier_mac->run_loop_.get(), CFRunLoopGetCurrent()); |
| 155 | 162 |
| 156 OnlineState new_state = CalculateReachability(flags) ? ONLINE : OFFLINE; | 163 ConnectionType new_type = CalculateReachability(flags); |
| 157 OnlineState old_state; | 164 ConnectionType old_type; |
| 158 { | 165 { |
| 159 base::AutoLock lock(notifier_mac->online_state_lock_); | 166 base::AutoLock lock(notifier_mac->connection_type_lock_); |
| 160 old_state = notifier_mac->online_state_; | 167 old_type = notifier_mac->connection_type_; |
| 161 notifier_mac->online_state_ = new_state; | 168 notifier_mac->connection_type_ = new_type; |
| 162 } | 169 } |
| 163 if (old_state != new_state) | 170 if (old_type != new_type) |
| 164 NotifyObserversOfOnlineStateChange(); | 171 NotifyObserversOfConnectionTypeChange(); |
| 165 } | 172 } |
| 166 | 173 |
| 167 } // namespace net | 174 } // namespace net |
| OLD | NEW |