Remove support for legacy Notifications
[WebKit-https.git] / Source / WebKit2 / WebProcess / Notifications / WebNotificationManager.cpp
1 /*
2  * Copyright (C) 2011, 2012, 2013 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 "WebNotificationManager.h"
28
29 #include "WebPage.h"
30 #include "WebProcess.h"
31 #include "WebProcessCreationParameters.h"
32
33 #if ENABLE(NOTIFICATIONS)
34 #include "WebNotification.h"
35 #include "WebNotificationManagerMessages.h"
36 #include "WebPageProxyMessages.h"
37 #include <WebCore/Document.h>
38 #include <WebCore/Notification.h>
39 #include <WebCore/Page.h>
40 #include <WebCore/ScriptExecutionContext.h>
41 #include <WebCore/SecurityOrigin.h>
42 #include <WebCore/Settings.h>
43 #include <WebCore/UserGestureIndicator.h>
44 #endif
45
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 #if ENABLE(NOTIFICATIONS)
51 static uint64_t generateNotificationID()
52 {
53     static uint64_t uniqueNotificationID = 1;
54     return uniqueNotificationID++;
55 }
56 #endif
57
58 const char* WebNotificationManager::supplementName()
59 {
60     return "WebNotificationManager";
61 }
62
63 WebNotificationManager::WebNotificationManager(WebProcess* process)
64     : m_process(process)
65 {
66 #if ENABLE(NOTIFICATIONS)
67     m_process->addMessageReceiver(Messages::WebNotificationManager::messageReceiverName(), *this);
68 #endif
69 }
70
71 WebNotificationManager::~WebNotificationManager()
72 {
73 }
74
75 void WebNotificationManager::initialize(const WebProcessCreationParameters& parameters)
76 {
77 #if ENABLE(NOTIFICATIONS)
78     m_permissionsMap = parameters.notificationPermissions;
79 #else
80     UNUSED_PARAM(parameters);
81 #endif
82 }
83
84 void WebNotificationManager::didUpdateNotificationDecision(const String& originString, bool allowed)
85 {
86 #if ENABLE(NOTIFICATIONS)
87     m_permissionsMap.set(originString, allowed);
88 #else
89     UNUSED_PARAM(originString);
90     UNUSED_PARAM(allowed);
91 #endif
92 }
93
94 void WebNotificationManager::didRemoveNotificationDecisions(const Vector<String>& originStrings)
95 {
96 #if ENABLE(NOTIFICATIONS)
97     for (auto& originString : originStrings)
98         m_permissionsMap.remove(originString);
99 #else
100     UNUSED_PARAM(originStrings);
101 #endif
102 }
103
104 NotificationClient::Permission WebNotificationManager::policyForOrigin(WebCore::SecurityOrigin* origin) const
105 {
106 #if ENABLE(NOTIFICATIONS)
107     if (!origin)
108         return NotificationClient::PermissionNotAllowed;
109
110     ASSERT(!origin->isUnique());
111     auto it = m_permissionsMap.find(origin->toRawString());
112     if (it != m_permissionsMap.end())
113         return it->value ? NotificationClient::PermissionAllowed : NotificationClient::PermissionDenied;
114 #else
115     UNUSED_PARAM(origin);
116 #endif
117     
118     return NotificationClient::PermissionNotAllowed;
119 }
120
121 void WebNotificationManager::removeAllPermissionsForTesting()
122 {
123 #if ENABLE(NOTIFICATIONS)
124     m_permissionsMap.clear();
125 #endif
126 }
127
128 uint64_t WebNotificationManager::notificationIDForTesting(Notification* notification)
129 {
130 #if ENABLE(NOTIFICATIONS)
131     if (!notification)
132         return 0;
133     return m_notificationMap.get(notification);
134 #else
135     UNUSED_PARAM(notification);
136     return 0;
137 #endif
138 }
139
140 bool WebNotificationManager::show(Notification* notification, WebPage* page)
141 {
142 #if ENABLE(NOTIFICATIONS)
143     if (!notification || !page->corePage()->settings().notificationsEnabled())
144         return false;
145     
146     uint64_t notificationID = generateNotificationID();
147     m_notificationMap.set(notification, notificationID);
148     m_notificationIDMap.set(notificationID, notification);
149     
150     auto it = m_notificationContextMap.add(notification->scriptExecutionContext(), Vector<uint64_t>()).iterator;
151     it->value.append(notificationID);
152
153     m_process->parentProcessConnection()->send(Messages::WebPageProxy::ShowNotification(notification->title(), notification->body(), notification->iconURL().string(), notification->tag(), notification->lang(), notification->dir(), notification->scriptExecutionContext()->securityOrigin()->toString(), notificationID), page->pageID());
154     return true;
155 #else
156     UNUSED_PARAM(notification);
157     UNUSED_PARAM(page);
158     return false;
159 #endif
160 }
161
162 void WebNotificationManager::cancel(Notification* notification, WebPage* page)
163 {
164 #if ENABLE(NOTIFICATIONS)
165     if (!notification || !page->corePage()->settings().notificationsEnabled())
166         return;
167     
168     uint64_t notificationID = m_notificationMap.get(notification);
169     if (!notificationID)
170         return;
171     
172     m_process->parentProcessConnection()->send(Messages::WebPageProxy::CancelNotification(notificationID), page->pageID());
173 #else
174     UNUSED_PARAM(notification);
175     UNUSED_PARAM(page);
176 #endif
177 }
178
179 void WebNotificationManager::clearNotifications(WebCore::ScriptExecutionContext* context, WebPage* page)
180 {
181 #if ENABLE(NOTIFICATIONS)
182     NotificationContextMap::iterator it = m_notificationContextMap.find(context);
183     if (it == m_notificationContextMap.end())
184         return;
185
186     Vector<uint64_t>& notificationIDs = it->value;
187     m_process->parentProcessConnection()->send(Messages::WebPageProxy::ClearNotifications(notificationIDs), page->pageID());
188     size_t count = notificationIDs.size();
189     for (size_t i = 0; i < count; ++i) {
190         RefPtr<Notification> notification = m_notificationIDMap.take(notificationIDs[i]);
191         if (!notification)
192             continue;
193         notification->finalize();
194         m_notificationMap.remove(notification);
195     }
196     
197     m_notificationContextMap.remove(it);
198 #else
199     UNUSED_PARAM(context);
200     UNUSED_PARAM(page);
201 #endif
202 }
203
204 void WebNotificationManager::didDestroyNotification(Notification* notification, WebPage* page)
205 {
206 #if ENABLE(NOTIFICATIONS)
207     uint64_t notificationID = m_notificationMap.take(notification);
208     if (!notificationID)
209         return;
210
211     m_notificationIDMap.remove(notificationID);
212     removeNotificationFromContextMap(notificationID, notification);
213     m_process->parentProcessConnection()->send(Messages::WebPageProxy::DidDestroyNotification(notificationID), page->pageID());
214 #else
215     UNUSED_PARAM(notification);
216     UNUSED_PARAM(page);
217 #endif
218 }
219
220 void WebNotificationManager::didShowNotification(uint64_t notificationID)
221 {
222 #if ENABLE(NOTIFICATIONS)
223     if (!isNotificationIDValid(notificationID))
224         return;
225     
226     RefPtr<Notification> notification = m_notificationIDMap.get(notificationID);
227     if (!notification)
228         return;
229
230     notification->dispatchShowEvent();
231 #else
232     UNUSED_PARAM(notificationID);
233 #endif
234 }
235
236 void WebNotificationManager::didClickNotification(uint64_t notificationID)
237 {
238 #if ENABLE(NOTIFICATIONS)
239     if (!isNotificationIDValid(notificationID))
240         return;
241
242     RefPtr<Notification> notification = m_notificationIDMap.get(notificationID);
243     if (!notification)
244         return;
245
246     // Indicate that this event is being dispatched in reaction to a user's interaction with a platform notification.
247     UserGestureIndicator indicator(ProcessingUserGesture);
248     notification->dispatchClickEvent();
249 #else
250     UNUSED_PARAM(notificationID);
251 #endif
252 }
253
254 void WebNotificationManager::didCloseNotifications(const Vector<uint64_t>& notificationIDs)
255 {
256 #if ENABLE(NOTIFICATIONS)
257     size_t count = notificationIDs.size();
258     for (size_t i = 0; i < count; ++i) {
259         uint64_t notificationID = notificationIDs[i];
260         if (!isNotificationIDValid(notificationID))
261             continue;
262
263         RefPtr<Notification> notification = m_notificationIDMap.take(notificationID);
264         if (!notification)
265             continue;
266
267         m_notificationMap.remove(notification);
268         removeNotificationFromContextMap(notificationID, notification.get());
269
270         notification->dispatchCloseEvent();
271     }
272 #else
273     UNUSED_PARAM(notificationIDs);
274 #endif
275 }
276
277 #if ENABLE(NOTIFICATIONS)
278 void WebNotificationManager::removeNotificationFromContextMap(uint64_t notificationID, Notification* notification)
279 {
280     // This is a helper function for managing the hash maps.
281     NotificationContextMap::iterator it = m_notificationContextMap.find(notification->scriptExecutionContext());
282     ASSERT(it != m_notificationContextMap.end());
283     size_t index = it->value.find(notificationID);
284     ASSERT(index != notFound);
285     it->value.remove(index);
286     if (it->value.isEmpty())
287         m_notificationContextMap.remove(it);
288 }
289 #endif
290
291 } // namespace WebKit