18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Apple Inc. All Rights Reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NetworkStateNotifier.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <SystemConfiguration/SystemConfiguration.h> 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#ifdef BUILDING_ON_TIGER 32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// This function is available on Tiger, but not declared in the CFRunLoop.h header on Tiger. 33643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockextern "C" CFRunLoopRef CFRunLoopGetMain(); 34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif 35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const double StateChangeTimerInterval = 2.0; 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid NetworkStateNotifier::updateState() 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Assume that we're offline until proven otherwise. 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isOnLine = false; 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFStringRef> str(AdoptCF, SCDynamicStoreKeyCreateNetworkInterface(0, kSCDynamicStoreDomainState)); 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFPropertyListRef> propertyList(AdoptCF, SCDynamicStoreCopyValue(m_store.get(), str.get())); 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!propertyList) 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID()) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFArrayRef netInterfaces = (CFArrayRef)CFDictionaryGetValue((CFDictionaryRef)propertyList.get(), kSCDynamicStorePropNetInterfaces); 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (CFGetTypeID(netInterfaces) != CFArrayGetTypeID()) 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (CFIndex i = 0; i < CFArrayGetCount(netInterfaces); i++) { 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFStringRef interface = (CFStringRef)CFArrayGetValueAtIndex(netInterfaces, i); 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (CFGetTypeID(interface) != CFStringGetTypeID()) 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Ignore the loopback interface. 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (CFStringFind(interface, CFSTR("lo"), kCFCompareAnchored).location != kCFNotFound) 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFStringRef> key(AdoptCF, SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, interface, kSCEntNetIPv4)); 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFArrayRef> keyList(AdoptCF, SCDynamicStoreCopyKeyList(m_store.get(), key.get())); 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (keyList && CFArrayGetCount(keyList.get())) { 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isOnLine = true; 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid NetworkStateNotifier::dynamicStoreCallback(SCDynamicStoreRef, CFArrayRef, void* info) 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NetworkStateNotifier* notifier = static_cast<NetworkStateNotifier*>(info); 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Calling updateState() could be expensive so we schedule a timer that will do it 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // when things have cooled down. 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notifier->m_networkStateChangeTimer.startOneShot(StateChangeTimerInterval); 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid NetworkStateNotifier::networkStateChangeTimerFired(Timer<NetworkStateNotifier>*) 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool oldOnLine = m_isOnLine; 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project updateState(); 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_isOnLine == oldOnLine) 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_networkStateChangedFunction) 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_networkStateChangedFunction(); 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectNetworkStateNotifier::NetworkStateNotifier() 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_isOnLine(false) 103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project , m_networkStateChangedFunction(0) 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_networkStateChangeTimer(this, &NetworkStateNotifier::networkStateChangeTimerFired) 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SCDynamicStoreContext context = { 0, this, 0, 0, 0 }; 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_store.adoptCF(SCDynamicStoreCreate(0, CFSTR("com.apple.WebCore"), dynamicStoreCallback, &context)); 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_store) 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFRunLoopSourceRef> configSource = SCDynamicStoreCreateRunLoopSource(0, m_store.get(), 0); 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!configSource) 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CFRunLoopAddSource(CFRunLoopGetMain(), configSource.get(), kCFRunLoopCommonModes); 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFMutableArrayRef> keys(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFMutableArrayRef> patterns(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFStringRef> key; 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RetainPtr<CFStringRef> pattern; 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project key.adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetIPv4)); 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFArrayAppendValue(keys.get(), key.get()); 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pattern.adoptCF(SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4)); 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFArrayAppendValue(patterns.get(), pattern.get()); 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project key.adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetDNS)); 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CFArrayAppendValue(keys.get(), key.get()); 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SCDynamicStoreSetNotificationKeys(m_store.get(), keys.get(), patterns.get()); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project updateState(); 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 139