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" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/threading/thread_restrictions.h" 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_cftyperef.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace net { 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace { 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Called back by OS. Calls OnNetworkConfigChange(). 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DynamicStoreCallback(SCDynamicStoreRef /* store */, 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CFArrayRef changed_keys, 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void* config_delegate) { 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NetworkConfigWatcherMac::Delegate* net_config_delegate = 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<NetworkConfigWatcherMac::Delegate*>(config_delegate); 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net_config_delegate->OnNetworkConfigChange(changed_keys); 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass NetworkConfigWatcherMacThread : public base::Thread { 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate); 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual ~NetworkConfigWatcherMacThread(); 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch protected: 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // base::Thread 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void Init(); 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void CleanUp(); 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The SystemConfiguration calls in this function can lead to contention early 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // on, so we invoke this function later on in startup to keep it fast. 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void InitNotifications(); 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_; 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetworkConfigWatcherMac::Delegate* const delegate_; 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ScopedRunnableMethodFactory<NetworkConfigWatcherMacThread> method_factory_; 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMacThread); 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 51513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMacThread::NetworkConfigWatcherMacThread( 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetworkConfigWatcherMac::Delegate* delegate) 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : base::Thread("NetworkConfigWatcher"), 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch delegate_(delegate), 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 57513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() { 5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Allow IO because Stop() calls PlatformThread::Join(), which is a blocking 5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // operation. This is expected during shutdown. 6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::ThreadRestrictions::ScopedAllowIO allow_io; 6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Stop(); 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid NetworkConfigWatcherMacThread::Init() { 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Disallow IO to make sure NetworkConfigWatcherMacThread's helper thread does 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // not perform blocking operations. 6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::ThreadRestrictions::SetIOAllowed(false); 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(willchan): Look to see if there's a better signal for when it's ok to 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // initialize this, rather than just delaying it by a fixed time. 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const int kInitializationDelayMS = 1000; 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch message_loop()->PostDelayedTask( 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FROM_HERE, 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch method_factory_.NewRunnableMethod( 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &NetworkConfigWatcherMacThread::InitNotifications), 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kInitializationDelayMS); 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid NetworkConfigWatcherMacThread::CleanUp() { 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!run_loop_source_.get()) 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_.get(), 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kCFRunLoopCommonModes); 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick run_loop_source_.reset(); 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid NetworkConfigWatcherMacThread::InitNotifications() { 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Add a run loop source for a dynamic store to the current run loop. 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SCDynamicStoreContext context = { 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, // Version 0. 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delegate_, // User data. 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, // This is not reference counted. No retain function. 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, // This is not reference counted. No release function. 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, // No description for this. 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::mac::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate( 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, CFSTR("org.chromium"), DynamicStoreCallback, &context)); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick run_loop_source_.reset(SCDynamicStoreCreateRunLoopSource( 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, store.get(), 0)); 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source_.get(), 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kCFRunLoopCommonModes); 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Set up notifications for interface and IP address changes. 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delegate_->SetDynamicStoreNotificationKeys(store.get()); 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 111513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate) 112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) { 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // We create this notifier thread because the notification implementation 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // needs a thread with a CFRunLoop, and there's no guarantee that 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // MessageLoop::current() meets that criterion. 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch notifier_thread_->StartWithOptions(thread_options); 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 120513209b27ff55e2841eac0e4120199c23acce758Ben MurdochNetworkConfigWatcherMac::~NetworkConfigWatcherMac() {} 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace net 123