network_config_watcher_mac.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/network_config_watcher_mac.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <SystemConfiguration/SCDynamicStoreKey.h> 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <SystemConfiguration/SCSchemaDefinitions.h> 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <algorithm> 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/compiler_specific.h" 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_cftyperef.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace net { 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace { 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Called back by OS. Calls OnNetworkConfigChange(). 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DynamicStoreCallback(SCDynamicStoreRef /* store */, 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CFArrayRef changed_keys, 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void* config_delegate) { 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NetworkConfigWatcherMac::Delegate* net_config_delegate = 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<NetworkConfigWatcherMac::Delegate*>(config_delegate); 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net_config_delegate->OnNetworkConfigChange(changed_keys); 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass NetworkConfigWatcherMacThread : public base::Thread { 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate); 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual ~NetworkConfigWatcherMacThread(); 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch protected: 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // base::Thread 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void Init(); 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void CleanUp(); 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The SystemConfiguration calls in this function can lead to contention early 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // on, so we invoke this function later on in startup to keep it fast. 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void InitNotifications(); 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_; 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetworkConfigWatcherMac::Delegate* const delegate_; 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ScopedRunnableMethodFactory<NetworkConfigWatcherMacThread> method_factory_; 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMacThread); 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 50513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMacThread::NetworkConfigWatcherMacThread( 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetworkConfigWatcherMac::Delegate* delegate) 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : base::Thread("NetworkConfigWatcher"), 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch delegate_(delegate), 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 56513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() { 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Stop(); 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid NetworkConfigWatcherMacThread::Init() { 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(willchan): Look to see if there's a better signal for when it's ok to 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // initialize this, rather than just delaying it by a fixed time. 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const int kInitializationDelayMS = 1000; 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch message_loop()->PostDelayedTask( 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FROM_HERE, 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch method_factory_.NewRunnableMethod( 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &NetworkConfigWatcherMacThread::InitNotifications), 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kInitializationDelayMS); 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid NetworkConfigWatcherMacThread::CleanUp() { 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!run_loop_source_.get()) 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_.get(), 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kCFRunLoopCommonModes); 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick run_loop_source_.reset(); 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid NetworkConfigWatcherMacThread::InitNotifications() { 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Add a run loop source for a dynamic store to the current run loop. 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SCDynamicStoreContext context = { 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, // Version 0. 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delegate_, // User data. 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, // This is not reference counted. No retain function. 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, // This is not reference counted. No release function. 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, // No description for this. 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::mac::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate( 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, CFSTR("org.chromium"), DynamicStoreCallback, &context)); 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick run_loop_source_.reset(SCDynamicStoreCreateRunLoopSource( 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, store.get(), 0)); 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source_.get(), 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kCFRunLoopCommonModes); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Set up notifications for interface and IP address changes. 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delegate_->SetDynamicStoreNotificationKeys(store.get()); 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 102513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate) 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) { 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // We create this notifier thread because the notification implementation 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // needs a thread with a CFRunLoop, and there's no guarantee that 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // MessageLoop::current() meets that criterion. 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch notifier_thread_->StartWithOptions(thread_options); 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 111513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMac::~NetworkConfigWatcherMac() {} 112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace net 114