[Web Animations] Expose Web Animations CSS integration as an experimental feature
[WebKit-https.git] / Tools / WebKitTestRunner / WebNotificationProvider.cpp
1 /*
2  * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebNotificationProvider.h"
28
29 #include <WebKit/WKMutableArray.h>
30 #include <WebKit/WKNotification.h>
31 #include <WebKit/WKNotificationManager.h>
32 #include <WebKit/WKNumber.h>
33 #include <WebKit/WKSecurityOriginRef.h>
34 #include <wtf/Assertions.h>
35
36 namespace WTR {
37
38 static void showWebNotification(WKPageRef page, WKNotificationRef notification, const void* clientInfo)
39 {
40     static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->showWebNotification(page, notification);
41 }
42
43 static void closeWebNotification(WKNotificationRef notification, const void* clientInfo)
44 {
45     static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->closeWebNotification(notification);
46 }
47
48 static void addNotificationManager(WKNotificationManagerRef manager, const void* clientInfo)
49 {
50     static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->addNotificationManager(manager);
51 }
52
53 static void removeNotificationManager(WKNotificationManagerRef manager, const void* clientInfo)
54 {
55     static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->removeNotificationManager(manager);
56 }
57
58 static WKDictionaryRef notificationPermissions(const void* clientInfo)
59 {
60     return static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->notificationPermissions();
61 }
62
63 WebNotificationProvider::WebNotificationProvider()
64 {
65 }
66
67 WebNotificationProvider::~WebNotificationProvider()
68 {
69     for (auto& manager : m_ownedNotifications)
70         WKNotificationManagerSetProvider(manager.key.get(), nullptr);
71 }
72
73 WKNotificationProviderV0 WebNotificationProvider::provider()
74 {
75     WKNotificationProviderV0 notificationProvider = {
76         { 0, this },
77         WTR::showWebNotification,
78         WTR::closeWebNotification,
79         0, // didDestroyNotification
80         WTR::addNotificationManager,
81         WTR::removeNotificationManager,
82         WTR::notificationPermissions,
83         0, // clearNotifications
84     };
85     return notificationProvider;
86 }
87
88 void WebNotificationProvider::showWebNotification(WKPageRef page, WKNotificationRef notification)
89 {
90     auto context = WKPageGetContext(page);
91     auto notificationManager = WKContextGetNotificationManager(context);
92     uint64_t id = WKNotificationGetID(notification);
93
94     ASSERT(m_ownedNotifications.contains(notificationManager));
95     auto addResult = m_ownedNotifications.find(notificationManager)->value.add(id);
96     ASSERT_UNUSED(addResult, addResult.isNewEntry);
97     auto addResult2 = m_owningManager.set(id, notificationManager);
98     ASSERT_UNUSED(addResult2, addResult2.isNewEntry);
99     auto addResult3 = m_localToGlobalNotificationIDMap.add(std::make_pair(page, WKNotificationManagerGetLocalIDForTesting(notificationManager, notification)), id);
100     ASSERT_UNUSED(addResult3, addResult3.isNewEntry);
101
102     WKNotificationManagerProviderDidShowNotification(notificationManager, id);
103 }
104
105 static void removeGlobalIDFromIDMap(HashMap<std::pair<WKPageRef, uint64_t>, uint64_t>& map, uint64_t id)
106 {
107     for (auto iter = map.begin(); iter != map.end(); ++iter) {
108         if (iter->value == id) {
109             map.remove(iter);
110             return;
111         }
112     }
113     ASSERT_NOT_REACHED();
114 }
115
116 void WebNotificationProvider::closeWebNotification(WKNotificationRef notification)
117 {
118     uint64_t id = WKNotificationGetID(notification);
119     ASSERT(m_owningManager.contains(id));
120     auto notificationManager = m_owningManager.get(id);
121
122     ASSERT(m_ownedNotifications.contains(notificationManager));
123     bool success = m_ownedNotifications.find(notificationManager)->value.remove(id);
124     ASSERT_UNUSED(success, success);
125     m_owningManager.remove(id);
126
127     removeGlobalIDFromIDMap(m_localToGlobalNotificationIDMap, id);
128
129     WKRetainPtr<WKUInt64Ref> wkID = WKUInt64Create(id);
130     WKRetainPtr<WKMutableArrayRef> array(AdoptWK, WKMutableArrayCreate());
131     WKArrayAppendItem(array.get(), wkID.get());
132     WKNotificationManagerProviderDidCloseNotifications(notificationManager, array.get());
133 }
134
135 void WebNotificationProvider::addNotificationManager(WKNotificationManagerRef manager)
136 {
137     m_ownedNotifications.add(manager, HashSet<uint64_t>());
138 }
139
140 void WebNotificationProvider::removeNotificationManager(WKNotificationManagerRef manager)
141 {
142     auto iterator = m_ownedNotifications.find(manager);
143     ASSERT(iterator != m_ownedNotifications.end());
144     auto toRemove = iterator->value;
145     WKRetainPtr<WKNotificationManagerRef> guard(manager);
146     m_ownedNotifications.remove(iterator);
147     WKRetainPtr<WKMutableArrayRef> array = adoptWK(WKMutableArrayCreate());
148     for (uint64_t notificationID : toRemove) {
149         bool success = m_owningManager.remove(notificationID);
150         ASSERT_UNUSED(success, success);
151         removeGlobalIDFromIDMap(m_localToGlobalNotificationIDMap, notificationID);
152         WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get());
153     }
154     WKNotificationManagerProviderDidCloseNotifications(manager, array.get());
155 }
156
157 WKDictionaryRef WebNotificationProvider::notificationPermissions()
158 {
159     // Initial permissions are always empty.
160     return WKMutableDictionaryCreate();
161 }
162
163 void WebNotificationProvider::simulateWebNotificationClick(WKPageRef page, uint64_t notificationID)
164 {
165     ASSERT(m_localToGlobalNotificationIDMap.contains(std::make_pair(page, notificationID)));
166     auto globalID = m_localToGlobalNotificationIDMap.get(std::make_pair(page, notificationID));
167     ASSERT(m_owningManager.contains(globalID));
168     WKNotificationManagerProviderDidClickNotification(m_owningManager.get(globalID), globalID);
169 }
170
171 void WebNotificationProvider::reset()
172 {
173     for (auto& notificationPair : m_ownedNotifications) {
174         if (notificationPair.value.isEmpty())
175             continue;
176         WKRetainPtr<WKMutableArrayRef> array = adoptWK(WKMutableArrayCreate());
177         for (uint64_t notificationID : notificationPair.value)
178             WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get());
179
180         notificationPair.value.clear();
181         WKNotificationManagerProviderDidCloseNotifications(notificationPair.key.get(), array.get());
182     }
183     m_owningManager.clear();
184     m_localToGlobalNotificationIDMap.clear();
185 }
186
187 } // namespace WTR