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 |
index 7521c90bd649117a2d7b4400e2e29424d652564e..1fb3fb741a66893eff4322a53dc5e1982a6a750e 100644 |
--- a/net/base/network_change_notifier_mac.cc |
+++ b/net/base/network_change_notifier_mac.cc |
@@ -4,7 +4,11 @@ |
#include "net/base/network_change_notifier_mac.h" |
+#include <netinet/in.h> |
Mark Mentovai
2011/06/01 21:05:59
These shouldn’t be in a separate group from the Sy
adamk
2011/06/01 21:42:53
Done.
|
+#include <string.h> |
+ |
#include <SystemConfiguration/SCDynamicStoreKey.h> |
+#include <SystemConfiguration/SCNetworkReachability.h> |
#include <SystemConfiguration/SCSchemaDefinitions.h> |
#include "base/mac/scoped_cftyperef.h" |
@@ -13,12 +17,12 @@ namespace net { |
NetworkChangeNotifierMac::NetworkChangeNotifierMac() |
: forwarder_(this), |
- config_watcher_(&forwarder_) {} |
+ config_watcher_(&forwarder_), |
+ network_reachable_(true) {} |
NetworkChangeNotifierMac::~NetworkChangeNotifierMac() {} |
bool NetworkChangeNotifierMac::IsCurrentlyOffline() const { |
- // TODO(eroman): http://crbug.com/53473 |
- return false; |
+ return !network_reachable_; |
} |
void NetworkChangeNotifierMac::SetDynamicStoreNotificationKeys( |
@@ -42,11 +46,41 @@ void NetworkChangeNotifierMac::SetDynamicStoreNotificationKeys( |
store, notification_keys.get(), NULL); |
// TODO(willchan): Figure out a proper way to handle this rather than crash. |
CHECK(ret); |
+ |
+ // 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; |
Mark Mentovai
2011/06/01 21:05:59
I would just say |struct sockaddr_in addr = { 0 };
adamk
2011/06/01 21:42:53
I don't think the 0 does anything here. I've rewr
Mark Mentovai
2011/06/01 22:02:45
adamk wrote:
adamk
2011/06/01 22:09:34
Sorry, I meant to say "{ 0 }" wouldn't do anything
Mark Mentovai
2011/06/01 22:10:43
adamk wrote:
|
+ memset(&addr, 0, sizeof(addr)); |
+ addr.sin_len = sizeof(addr); |
+ addr.sin_family = AF_INET; |
+ reachability_.reset(SCNetworkReachabilityCreateWithAddress( |
+ kCFAllocatorDefault, reinterpret_cast<struct sockaddr*>(&addr))); |
+ SCNetworkReachabilityContext reachability_context = { |
+ 0, // version |
+ this, // user data |
+ NULL, // retain |
+ NULL, // release |
+ NULL // description |
+ }; |
+ // TODO(adamk): Either of these calls could fail, can we do any better |
+ // in handling this? |
+ ret = SCNetworkReachabilitySetCallback( |
+ reachability_.get(), |
+ &NetworkChangeNotifierMac::ReachabilityCallback, |
+ &reachability_context); |
Mark Mentovai
2011/06/01 21:05:59
I hope SC copies what it needs from this structure
adamk
2011/06/01 21:42:53
I have to imagine they copy what they need...
|
+ DCHECK(ret) << "Could not set network reachability callback"; |
+ ret = SCNetworkReachabilityScheduleWithRunLoop(reachability_.get(), |
Mark Mentovai
2011/06/01 21:05:59
I think you’d want to avoid doing this (and maybe
adamk
2011/06/01 21:42:53
Changed the structure around and added some resets
|
+ CFRunLoopGetCurrent(), |
+ kCFRunLoopCommonModes); |
+ DCHECK(ret) << "Could not schedule network reachability on run loop"; |
} |
void NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) { |
// Called on notifier thread. |
- |
for (CFIndex i = 0; i < CFArrayGetCount(changed_keys); ++i) { |
CFStringRef key = static_cast<CFStringRef>( |
CFArrayGetValueAtIndex(changed_keys, i)); |
@@ -64,4 +98,28 @@ void NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) { |
} |
} |
+// static |
+void NetworkChangeNotifierMac::ReachabilityCallback( |
+ SCNetworkReachabilityRef target, |
+ SCNetworkConnectionFlags flags, |
+ void* notifier) { |
+ // Called on notifier thread. |
+ bool reachable = (flags & kSCNetworkFlagsReachable); |
Mark Mentovai
2011/06/01 21:05:59
No parentheses on this line, the next, or line 111
adamk
2011/06/01 21:42:53
Done.
|
+ bool connection_required = (flags & kSCNetworkFlagsConnectionRequired); |
+ NetworkChangeNotifierMac* notifier_mac = |
+ static_cast<NetworkChangeNotifierMac*>(notifier); |
+ notifier_mac->network_reachable_ = (reachable && !connection_required); |
+ notifier_mac->NotifyObserversOfOnlineStateChange(); |
+} |
+ |
+void NetworkChangeNotifierMac::CleanUp() { |
+ // Called on notifier thread. |
+ if (!reachability_.get()) |
+ return; |
+ SCNetworkReachabilityUnscheduleFromRunLoop(reachability_.get(), |
+ CFRunLoopGetCurrent(), |
+ kCFRunLoopCommonModes); |
+ reachability_.reset(); |
+} |
+ |
} // namespace net |