diff options
author | adamk@google.com <adamk@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 21:56:44 +0000 |
---|---|---|
committer | adamk@google.com <adamk@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-02 21:56:44 +0000 |
commit | 12bd2c0a9f57cc8bf52d5e50f51f3eeb42a7658b (patch) | |
tree | fb9843c803b5392abdedea5b7b48c9d1149e22b4 /net/base/network_change_notifier_mac.cc | |
parent | dd9e545394846524143668315d73e57d2412c625 (diff) | |
download | chromium_src-12bd2c0a9f57cc8bf52d5e50f51f3eeb42a7658b.zip chromium_src-12bd2c0a9f57cc8bf52d5e50f51f3eeb42a7658b.tar.gz chromium_src-12bd2c0a9f57cc8bf52d5e50f51f3eeb42a7658b.tar.bz2 |
Implement NetworkChangeNotifier::IsCurrentlyOffline() for Mac.
R=willchan@chromium.org
BUG=7469,53473
TEST=load onlineTest.html attachment on bug 7469; disconnect/connect network cable
Review URL: http://codereview.chromium.org/7006015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87699 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/network_change_notifier_mac.cc')
-rw-r--r-- | net/base/network_change_notifier_mac.cc | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc index 7521c90..a4c4d2d 100644 --- a/net/base/network_change_notifier_mac.cc +++ b/net/base/network_change_notifier_mac.cc @@ -1,10 +1,12 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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 <SystemConfiguration/SCDynamicStoreKey.h> +#include <SystemConfiguration/SCNetworkReachability.h> #include <SystemConfiguration/SCSchemaDefinitions.h> #include "base/mac/scoped_cftyperef.h" @@ -13,17 +15,27 @@ namespace net { NetworkChangeNotifierMac::NetworkChangeNotifierMac() : forwarder_(this), - config_watcher_(&forwarder_) {} -NetworkChangeNotifierMac::~NetworkChangeNotifierMac() {} + config_watcher_(&forwarder_), + network_reachable_(true) {} + +NetworkChangeNotifierMac::~NetworkChangeNotifierMac() { + if (reachability_.get() && run_loop_.get()) { + SCNetworkReachabilityUnscheduleFromRunLoop(reachability_.get(), + run_loop_.get(), + kCFRunLoopCommonModes); + } +} bool NetworkChangeNotifierMac::IsCurrentlyOffline() const { - // TODO(eroman): http://crbug.com/53473 - return false; + return !network_reachable_; } void NetworkChangeNotifierMac::SetDynamicStoreNotificationKeys( SCDynamicStoreRef store) { // Called on notifier thread. + run_loop_.reset(CFRunLoopGetCurrent()); + CFRetain(run_loop_.get()); + base::mac::ScopedCFTypeRef<CFMutableArrayRef> notification_keys( CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); base::mac::ScopedCFTypeRef<CFStringRef> key( @@ -42,10 +54,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 = {0}; + 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 + }; + if (!SCNetworkReachabilitySetCallback( + reachability_.get(), + &NetworkChangeNotifierMac::ReachabilityCallback, + &reachability_context)) { + LOG(DFATAL) << "Could not set network reachability callback"; + reachability_.reset(); + } else if (!SCNetworkReachabilityScheduleWithRunLoop(reachability_.get(), + run_loop_, + kCFRunLoopCommonModes)) { + LOG(DFATAL) << "Could not schedule network reachability on run loop"; + reachability_.reset(); + } } void NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) { - // Called on notifier thread. + DCHECK_EQ(run_loop_.get(), CFRunLoopGetCurrent()); for (CFIndex i = 0; i < CFArrayGetCount(changed_keys); ++i) { CFStringRef key = static_cast<CFStringRef>( @@ -64,4 +107,22 @@ void NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) { } } +// 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()); + + bool reachable = flags & kSCNetworkFlagsReachable; + bool connection_required = flags & kSCNetworkFlagsConnectionRequired; + bool old_reachability = notifier_mac->network_reachable_; + notifier_mac->network_reachable_ = reachable && !connection_required; + if (old_reachability != notifier_mac->network_reachable_) + notifier_mac->NotifyObserversOfOnlineStateChange(); +} + } // namespace net |