1/* 2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. 3 * Copyright (C) 2012 Research In Motion Limited. All rights reserved. 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 "NotificationManager.h" 29 30#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 31#include "UUID.h" 32#include "UserGestureIndicator.h" 33#include "WebPage_p.h" 34 35#include <BlackBerryPlatformString.h> 36 37#include <vector> 38 39using namespace WebCore; 40 41namespace BlackBerry { 42namespace WebKit { 43 44NotificationManager::NotificationManager(WebPagePrivate* webPagePrivate) 45 : m_webPagePrivate(webPagePrivate) 46{ 47} 48 49NotificationManager::~NotificationManager() 50{ 51} 52 53bool NotificationManager::show(Notification* notification) 54{ 55 String notificationID = createCanonicalUUIDString(); 56 m_notificationMap.set(notification, notificationID); 57 m_notificationIDMap.set(notificationID, notification); 58 59 NotificationContextMap::iterator it = m_notificationContextMap.add(notification->scriptExecutionContext(), Vector<String>()).iterator; 60 it->value.append(notificationID); 61 62 m_webPagePrivate->client()->showNotification(notificationID, notification->title(), notification->body(), notification->iconURL().string(), notification->tag(), notification->scriptExecutionContext()->securityOrigin()->toString()); 63 return true; 64} 65 66void NotificationManager::cancel(Notification* notification) 67{ 68 String notificationID = m_notificationMap.get(notification); 69 if (!notificationID) 70 return; 71 72 m_webPagePrivate->client()->cancelNotification(notificationID); 73} 74 75void NotificationManager::clearNotifications(ScriptExecutionContext* context) 76{ 77 NotificationContextMap::iterator it = m_notificationContextMap.find(context); 78 if (it == m_notificationContextMap.end()) 79 return; 80 81 Vector<String>& notificationIDs = it->value; 82 std::vector<BlackBerry::Platform::String> ids; 83 size_t count = notificationIDs.size(); 84 for (size_t i = 0; i < count; ++i) { 85 ids.push_back(notificationIDs[i]); 86 RefPtr<Notification> notification = m_notificationIDMap.take(notificationIDs[i]); 87 if (!notification) 88 continue; 89 90 notification->finalize(); 91 m_notificationMap.remove(notification); 92 } 93 94 m_webPagePrivate->client()->clearNotifications(ids); 95 m_notificationContextMap.remove(it); 96} 97 98void NotificationManager::notificationObjectDestroyed(Notification* notification) 99{ 100 String notificationID = m_notificationMap.take(notification); 101 if (!notificationID) 102 return; 103 104 m_notificationIDMap.remove(notificationID); 105 removeNotificationFromContextMap(notificationID, notification); 106 m_webPagePrivate->client()->notificationDestroyed(notificationID); 107} 108 109#if ENABLE(LEGACY_NOTIFICATIONS) 110void NotificationManager::requestPermission(ScriptExecutionContext* context, PassRefPtr<VoidCallback> callback) 111{ 112 SecurityOrigin* origin = context->securityOrigin(); 113 String requestID = createCanonicalUUIDString(); 114 m_originToIDMap.set(origin, requestID); 115 m_idToOriginMap.set(requestID, origin); 116 m_idToVoidCallbackMap.set(requestID, callback); 117 m_webPagePrivate->client()->requestNotificationPermission(requestID, origin->toString()); 118} 119#endif 120 121#if ENABLE(NOTIFICATIONS) 122void NotificationManager::requestPermission(ScriptExecutionContext* context, PassRefPtr<NotificationPermissionCallback> callback) 123{ 124 SecurityOrigin* origin = context->securityOrigin(); 125 String requestID = createCanonicalUUIDString(); 126 m_originToIDMap.set(origin, requestID); 127 m_idToOriginMap.set(requestID, origin); 128 m_idToCallbackMap.set(requestID, callback); 129 m_webPagePrivate->client()->requestNotificationPermission(requestID, origin->toString()); 130} 131#endif 132 133void NotificationManager::cancelRequestsForPermission(ScriptExecutionContext* context) 134{ 135 SecurityOrigin* origin = context->securityOrigin(); 136 String requestID = m_originToIDMap.take(origin); 137 if (!requestID) 138 return; 139 140 m_idToOriginMap.remove(requestID); 141#if ENABLE(LEGACY_NOTIFICATIONS) 142 m_idToVoidCallbackMap.remove(requestID); 143#endif 144#if ENABLE(NOTIFICATIONS) 145 m_idToCallbackMap.remove(requestID); 146#endif 147} 148 149NotificationClient::Permission NotificationManager::checkPermission(ScriptExecutionContext* context) 150{ 151 return static_cast<NotificationClient::Permission>(m_webPagePrivate->client()->checkNotificationPermission(context->securityOrigin()->toString())); 152} 153 154void NotificationManager::updatePermission(const String& requestID, bool allowed) 155{ 156 RefPtr<WebCore::SecurityOrigin> origin = m_idToOriginMap.take(requestID); 157 m_originToIDMap.remove(origin); 158 159#if ENABLE(LEGACY_NOTIFICATIONS) 160 RefPtr<VoidCallback> voidCallback = m_idToVoidCallbackMap.take(requestID); 161 if (voidCallback) { 162 voidCallback->handleEvent(); 163 return; 164 } 165#endif 166 167#if ENABLE(NOTIFICATIONS) 168 RefPtr<NotificationPermissionCallback> callback = m_idToCallbackMap.take(requestID); 169 if (!callback) 170 return; 171 172 callback->handleEvent(Notification::permissionString(allowed ? NotificationClient::PermissionAllowed : NotificationClient::PermissionDenied)); 173#endif 174} 175 176void NotificationManager::notificationClicked(const String& notificationID) 177{ 178 RefPtr<Notification> notification = m_notificationIDMap.get(notificationID); 179 if (!notification) 180 return; 181 182 // Indicate that this event is being dispatched in reaction to a user's interaction with a platform notification. 183 UserGestureIndicator indicator(DefinitelyProcessingNewUserGesture); 184 notification->dispatchClickEvent(); 185} 186 187void NotificationManager::notificationClosed(const String& notificationID) 188{ 189 RefPtr<Notification> notification = m_notificationIDMap.take(notificationID); 190 if (!notification) 191 return; 192 193 m_notificationMap.remove(notification); 194 removeNotificationFromContextMap(notificationID, notification.get()); 195 notification->dispatchCloseEvent(); 196} 197 198void NotificationManager::notificationError(const String& notificationID) 199{ 200 RefPtr<Notification> notification = m_notificationIDMap.take(notificationID); 201 if (!notification) 202 return; 203 204 notification->dispatchErrorEvent(); 205} 206 207void NotificationManager::notificationShown(const String& notificationID) 208{ 209 RefPtr<Notification> notification = m_notificationIDMap.get(notificationID); 210 if (!notification) 211 return; 212 213 notification->dispatchShowEvent(); 214} 215 216void NotificationManager::removeNotificationFromContextMap(const String& notificationID, Notification* notification) 217{ 218 // This is a helper function for managing the hash maps. 219 NotificationContextMap::iterator it = m_notificationContextMap.find(notification->scriptExecutionContext()); 220 ASSERT(it != m_notificationContextMap.end()); 221 size_t index = it->value.find(notificationID); 222 ASSERT(index != notFound); 223 it->value.remove(index); 224 if (it->value.isEmpty()) 225 m_notificationContextMap.remove(it); 226} 227 228} 229} 230 231#endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 232