1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/network_change_notifier_mac.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <SystemConfiguration/SCDynamicStoreKey.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <SystemConfiguration/SCSchemaDefinitions.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_cftyperef.h"
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNetworkChangeNotifierMac::NetworkChangeNotifierMac()
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : forwarder_(this),
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      config_watcher_(&forwarder_) {}
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickNetworkChangeNotifierMac::~NetworkChangeNotifierMac() {}
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool NetworkChangeNotifierMac::IsCurrentlyOffline() const {
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(eroman): http://crbug.com/53473
21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return false;
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid NetworkChangeNotifierMac::SetDynamicStoreNotificationKeys(
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SCDynamicStoreRef store) {
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Called on notifier thread.
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  base::mac::ScopedCFTypeRef<CFMutableArrayRef> notification_keys(
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  base::mac::ScopedCFTypeRef<CFStringRef> key(
30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      SCDynamicStoreKeyCreateNetworkGlobalEntity(
31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          NULL, kSCDynamicStoreDomainState, kSCEntNetInterface));
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CFArrayAppendValue(notification_keys.get(), key.get());
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.reset(SCDynamicStoreKeyCreateNetworkGlobalEntity(
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4));
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CFArrayAppendValue(notification_keys.get(), key.get());
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  key.reset(SCDynamicStoreKeyCreateNetworkGlobalEntity(
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6));
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CFArrayAppendValue(notification_keys.get(), key.get());
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the notification keys.  This starts us receiving notifications.
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ret = SCDynamicStoreSetNotificationKeys(
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      store, notification_keys.get(), NULL);
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(willchan): Figure out a proper way to handle this rather than crash.
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(ret);
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) {
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Called on notifier thread.
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (CFIndex i = 0; i < CFArrayGetCount(changed_keys); ++i) {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CFStringRef key = static_cast<CFStringRef>(
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        CFArrayGetValueAtIndex(changed_keys, i));
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (CFStringHasSuffix(key, kSCEntNetIPv4) ||
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        CFStringHasSuffix(key, kSCEntNetIPv6)) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotifyObserversOfIPAddressChange();
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (CFStringHasSuffix(key, kSCEntNetInterface)) {
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // TODO(willchan): Does not appear to be working.  Look into this.
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Perhaps this isn't needed anyway.
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
68