1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/base/network_change_notifier_mac.h"
6
7#include <SystemConfiguration/SCDynamicStoreKey.h>
8#include <SystemConfiguration/SCSchemaDefinitions.h>
9
10#include "base/mac/scoped_cftyperef.h"
11
12namespace net {
13
14NetworkChangeNotifierMac::NetworkChangeNotifierMac()
15    : forwarder_(this),
16      config_watcher_(&forwarder_) {}
17NetworkChangeNotifierMac::~NetworkChangeNotifierMac() {}
18
19bool NetworkChangeNotifierMac::IsCurrentlyOffline() const {
20  // TODO(eroman): http://crbug.com/53473
21  return false;
22}
23
24void NetworkChangeNotifierMac::SetDynamicStoreNotificationKeys(
25    SCDynamicStoreRef store) {
26  // Called on notifier thread.
27  base::mac::ScopedCFTypeRef<CFMutableArrayRef> notification_keys(
28      CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
29  base::mac::ScopedCFTypeRef<CFStringRef> key(
30      SCDynamicStoreKeyCreateNetworkGlobalEntity(
31          NULL, kSCDynamicStoreDomainState, kSCEntNetInterface));
32  CFArrayAppendValue(notification_keys.get(), key.get());
33  key.reset(SCDynamicStoreKeyCreateNetworkGlobalEntity(
34      NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4));
35  CFArrayAppendValue(notification_keys.get(), key.get());
36  key.reset(SCDynamicStoreKeyCreateNetworkGlobalEntity(
37      NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6));
38  CFArrayAppendValue(notification_keys.get(), key.get());
39
40  // Set the notification keys.  This starts us receiving notifications.
41  bool ret = SCDynamicStoreSetNotificationKeys(
42      store, notification_keys.get(), NULL);
43  // TODO(willchan): Figure out a proper way to handle this rather than crash.
44  CHECK(ret);
45}
46
47void NetworkChangeNotifierMac::OnNetworkConfigChange(CFArrayRef changed_keys) {
48  // Called on notifier thread.
49
50  for (CFIndex i = 0; i < CFArrayGetCount(changed_keys); ++i) {
51    CFStringRef key = static_cast<CFStringRef>(
52        CFArrayGetValueAtIndex(changed_keys, i));
53    if (CFStringHasSuffix(key, kSCEntNetIPv4) ||
54        CFStringHasSuffix(key, kSCEntNetIPv6)) {
55      NotifyObserversOfIPAddressChange();
56      return;
57    }
58    if (CFStringHasSuffix(key, kSCEntNetInterface)) {
59      // TODO(willchan): Does not appear to be working.  Look into this.
60      // Perhaps this isn't needed anyway.
61    } else {
62      NOTREACHED();
63    }
64  }
65}
66
67}  // namespace net
68