1/*
2 * Copyright (C) 2013 Igalia S.L.
3 * Copyright (C) 2014 Collabora Ltd.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "WebKitNotificationProvider.h"
29
30#include "APIArray.h"
31#include "APINotificationProvider.h"
32#include "WebKitNotificationPrivate.h"
33#include "WebKitWebContextPrivate.h"
34#include "WebKitWebViewPrivate.h"
35#include "WebNotificationManagerProxy.h"
36#include "WebPageProxy.h"
37#include <wtf/text/CString.h>
38
39using namespace WebKit;
40
41
42class NotificationProvider final : public API::NotificationProvider {
43public:
44 explicit NotificationProvider(WebKitNotificationProvider& provider)
45 : m_provider(provider)
46 {
47 }
48
49private:
50 void show(WebPageProxy& page, WebNotification& notification) override
51 {
52 m_provider.show(page, notification);
53 }
54
55 void cancel(WebNotification& notification) override
56 {
57 m_provider.cancel(notification);
58 }
59
60 void clearNotifications(const Vector<uint64_t>& notificationIDs) override
61 {
62 m_provider.clearNotifications(notificationIDs);
63 }
64
65 HashMap<String, bool> notificationPermissions() override
66 {
67 return m_provider.notificationPermissions();
68 }
69
70 WebKitNotificationProvider& m_provider;
71};
72
73WebKitNotificationProvider::WebKitNotificationProvider(WebNotificationManagerProxy* notificationManager, WebKitWebContext* webContext)
74 : m_webContext(webContext)
75 , m_notificationManager(notificationManager)
76{
77 ASSERT(m_notificationManager);
78 m_notificationManager->setProvider(std::make_unique<NotificationProvider>(*this));
79}
80
81WebKitNotificationProvider::~WebKitNotificationProvider()
82{
83 m_notificationManager->setProvider(nullptr);
84}
85
86void WebKitNotificationProvider::notificationCloseCallback(WebKitNotification* notification, WebKitNotificationProvider* provider)
87{
88 uint64_t notificationID = webkit_notification_get_id(notification);
89 Vector<RefPtr<API::Object>> arrayIDs;
90 arrayIDs.append(API::UInt64::create(notificationID));
91 provider->m_notificationManager->providerDidCloseNotifications(API::Array::create(WTFMove(arrayIDs)).ptr());
92 provider->m_notifications.remove(notificationID);
93}
94
95void WebKitNotificationProvider::notificationClickedCallback(WebKitNotification* notification, WebKitNotificationProvider* provider)
96{
97 provider->m_notificationManager->providerDidClickNotification(webkit_notification_get_id(notification));
98}
99
100void WebKitNotificationProvider::withdrawAnyPreviousNotificationMatchingTag(const CString& tag)
101{
102 if (!tag.length())
103 return;
104
105 for (auto& notification : m_notifications.values()) {
106 if (tag == webkit_notification_get_tag(notification.get())) {
107 webkit_notification_close(notification.get());
108 break;
109 }
110 }
111
112#ifndef NDEBUG
113 for (auto& notification : m_notifications.values())
114 ASSERT(tag != webkit_notification_get_tag(notification.get()));
115#endif
116}
117
118void WebKitNotificationProvider::show(WebPageProxy& page, const WebNotification& webNotification)
119{
120 GRefPtr<WebKitNotification> notification = m_notifications.get(webNotification.notificationID());
121 auto* webView = webkitWebContextGetWebViewForPage(m_webContext, &page);
122 ASSERT(webView);
123
124 if (!notification) {
125 withdrawAnyPreviousNotificationMatchingTag(webNotification.tag().utf8());
126 notification = adoptGRef(webkitNotificationCreate(webView, webNotification));
127 g_signal_connect(notification.get(), "closed", G_CALLBACK(notificationCloseCallback), this);
128 g_signal_connect(notification.get(), "clicked", G_CALLBACK(notificationClickedCallback), this);
129 m_notifications.set(webNotification.notificationID(), notification);
130 }
131
132 if (webkitWebViewEmitShowNotification(webView, notification.get()))
133 m_notificationManager->providerDidShowNotification(webNotification.notificationID());
134}
135
136void WebKitNotificationProvider::cancelNotificationByID(uint64_t notificationID)
137{
138 if (GRefPtr<WebKitNotification> notification = m_notifications.get(notificationID))
139 webkit_notification_close(notification.get());
140}
141
142void WebKitNotificationProvider::cancel(const WebNotification& webNotification)
143{
144 cancelNotificationByID(webNotification.notificationID());
145}
146
147void WebKitNotificationProvider::clearNotifications(const Vector<uint64_t>& notificationIDs)
148{
149 for (const auto& item : notificationIDs)
150 cancelNotificationByID(item);
151}
152
153HashMap<WTF::String, bool> WebKitNotificationProvider::notificationPermissions()
154{
155 webkitWebContextInitializeNotificationPermissions(m_webContext);
156 return m_notificationPermissions;
157}
158
159void WebKitNotificationProvider::setNotificationPermissions(HashMap<String, bool>&& permissionsMap)
160{
161 m_notificationPermissions = WTFMove(permissionsMap);
162}
163