Improve use of NeverDestroyed
[WebKit-https.git] / Source / WebCore / platform / network / mac / NetworkStateNotifierMac.cpp
1 /*
2  * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "NetworkStateNotifier.h"
28
29 #include <SystemConfiguration/SystemConfiguration.h>
30
31 namespace WebCore {
32
33 void NetworkStateNotifier::updateStateWithoutNotifying()
34 {
35     auto key = adoptCF(SCDynamicStoreKeyCreateNetworkInterface(0, kSCDynamicStoreDomainState));
36     auto propertyList = adoptCF(SCDynamicStoreCopyValue(m_store.get(), key.get()));
37     if (!propertyList || CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID())
38         return;
39
40     auto netInterfaces = CFDictionaryGetValue((CFDictionaryRef)propertyList.get(), kSCDynamicStorePropNetInterfaces);
41     if (!netInterfaces || CFGetTypeID(netInterfaces) != CFArrayGetTypeID())
42         return;
43
44     for (CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)netInterfaces); i++) {
45         auto interface = CFArrayGetValueAtIndex((CFArrayRef)netInterfaces, i);
46         if (CFGetTypeID(interface) != CFStringGetTypeID())
47             continue;
48
49         // Ignore the loopback interface.
50         if (CFStringFind((CFStringRef)interface, CFSTR("lo"), kCFCompareAnchored).location != kCFNotFound)
51             continue;
52
53         auto key = adoptCF(SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, (CFStringRef)interface, kSCEntNetIPv4));
54         auto keyList = adoptCF(SCDynamicStoreCopyKeyList(m_store.get(), key.get()));
55         if (keyList && CFArrayGetCount(keyList.get())) {
56             m_isOnLine = true;
57             return;
58         }
59     }
60
61     m_isOnLine = false;
62 }
63
64 void NetworkStateNotifier::startObserving()
65 {
66     SCDynamicStoreContext context = { 0, this, 0, 0, 0 };
67     m_store = adoptCF(SCDynamicStoreCreate(0, CFSTR("com.apple.WebCore"), [] (SCDynamicStoreRef, CFArrayRef, void*) {
68         // Calling updateState() could be expensive so we coalesce calls with a timer.
69         singleton().updateStateSoon();
70     }, &context));
71     if (!m_store)
72         return;
73
74     auto source = adoptCF(SCDynamicStoreCreateRunLoopSource(0, m_store.get(), 0));
75     if (!source)
76         return;
77
78     CFRunLoopAddSource(CFRunLoopGetMain(), source.get(), kCFRunLoopCommonModes);
79
80     auto keys = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
81     CFArrayAppendValue(keys.get(), adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetIPv4)).get());
82     CFArrayAppendValue(keys.get(), adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetDNS)).get());
83
84     auto patterns = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
85     CFArrayAppendValue(patterns.get(), adoptCF(SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4)).get());
86
87     SCDynamicStoreSetNotificationKeys(m_store.get(), keys.get(), patterns.get());
88 }
89     
90 }