[WK2] Notifications clobber each other with multiple processes
authorjonlee@apple.com <jonlee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 May 2013 00:02:46 +0000 (00:02 +0000)
committerjonlee@apple.com <jonlee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 May 2013 00:02:46 +0000 (00:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=116428
<rdar://problem/13935191>

Reviewed by Darin Adler.

.:

* ManualTests/notification-in-multiple-windows.html: Added.

Source/WebKit2:

With multiple processes, the notification IDs, when passed up to the UI process, can clobber
each other. To fix this, we need to maintain a global map of notification IDs. This map is
keyed by its own unique notification ID, and maps to a pair containing the web page ID and that
web page's ID for the notification.

Now that we maintain groups of notifications based on the web page, we no longer send IPC messages
from WebNotificationManager to WebNotificationManagerProxy; instead we send messages to the
WebPageProxy. This removes the need for WebNotificationManagerProxy to be a message receiver.

When a page closes, all of the web notifications are cleared out. However, by the time the
WebPage::close() is called, the connection between WebPage and WebPageProxy is destroyed. Since
the WebPage is told to close from the UI process anyway, we clear out the notifications separately,
instead of waiting for a message from the WebPage.

* UIProcess/Notifications/WebNotificationManagerProxy.h: Update to take into account the
notification's web page. Remove inheritance of CoreIPC::MessageReceiver. Expose the original message
handlers as public functions, since they will be called from WebPageProxy. Add a new map that
associates a global ID with a notification ID that came from a web page.
    There are now two flavors of clearNotifications(). One clears out all notifications associated
with a web page. This is called when the page is closed. The other clears out a subset of
notifications associated with a web page. This is called when notifications associated with a sub-frame
is closed.
* UIProcess/Notifications/WebNotificationManagerProxy.messages.in: Removed. All messages from
the web process go to WebPageProxy now.

* UIProcess/Notifications/WebNotificationManagerProxy.cpp: Update to take into account the
notification's web page.

(WebKit::generateGlobalNotificationID): The manager proxy now maintains its own global notification
ID generator.
(WebKit::WebNotificationManagerProxy::WebNotificationManagerProxy): The proxy is no longer a
message receiver. Remove code that registers it as such.

(WebKit::WebNotificationManagerProxy::show): Refactor to differentiate between the notification ID
that came from the web process, and the global notification ID the proxy maintains. Add the mapping
from the global ID to the (web page ID, notification ID) pair.
(WebKit::WebNotificationManagerProxy::cancel): Refactor to take into consideration the web page.
(WebKit::WebNotificationManagerProxy::didDestroyNotification): Refactor to take into consideration
the web page. Fixes a leak where we did not remove the item from the maps. This function is called
from the web process, when the ScriptExecutionContext is destroyed, so we remove it from our maps
before we pass the message along to the provider.

Helper functions that evaluate when a given notification in the map matches the desired parameters.
(WebKit::pageIDsMatch): The notification is associated with the provided page.
(WebKit::pageAndNotificationIDsMatch): The notification is associated with the provided page and is
contained within the list of provided notifications.

(WebKit::WebNotificationManagerProxy::clearNotifications): Changed to only remove notifications
associated with the provided web page, and could include a specific list of notifications. This latter
situation occurs if notifications were associated with an iframe, and that iframe was removed.
There is an O(n) walk that could be make more efficient using another hash map, but that's overhead
for a map that should be small in size anyway.

(WebKit::WebNotificationManagerProxy::providerDidShowNotification): Refactor to take into
consideration the web page.
(WebKit::WebNotificationManagerProxy::providerDidClickNotification): Refactor to take into
consideration the web page.
(WebKit::WebNotificationManagerProxy::providerDidCloseNotifications): Now we need to comb through
the list of global IDs and put them in buckets based on the notification's web pages. After that
is done we can send the DidCloseNotifications() to those pages' processes. There is a possible
extra optimization here where we group based on the page's process instead, to reduce the number
of messages sent to processes.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::close): When a web page is closed, we clear the notifications associated
with the page.
(WebKit::WebPageProxy::cancelNotification): Forward call to WebNotificationManagerProxy.
(WebKit::WebPageProxy::clearNotifications): Ditto.
(WebKit::WebPageProxy::didDestroyNotification): Ditto.
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:

* WebProcess/Notifications/NotificationPermissionRequestManager.cpp:
* WebProcess/Notifications/WebNotificationManager.cpp:
(WebKit::WebNotificationManager::cancel):
(WebKit::WebNotificationManager::clearNotifications):
(WebKit::WebNotificationManager::didDestroyNotification):
* WebProcess/Notifications/NotificationPermissionRequestManager.cpp: Remove extraneous include.

* CMakeLists.txt: Remove WebNotificationManagerProxy.messages.in and related files.
* DerivedSources.pri: Ditto.
* DerivedSources.make: Ditto.
* GNUmakefile.list.am: Ditto.
* WebKit2.xcodeproj/project.pbxproj: Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@150785 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
ChangeLog
ManualTests/notification-in-multiple-windows.html [new file with mode: 0644]
Source/WebKit2/CMakeLists.txt
Source/WebKit2/ChangeLog
Source/WebKit2/DerivedSources.make
Source/WebKit2/DerivedSources.pri
Source/WebKit2/GNUmakefile.list.am
Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp
Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h
Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in [deleted file]
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/Notifications/NotificationPermissionRequestManager.cpp
Source/WebKit2/WebProcess/Notifications/WebNotificationManager.cpp

index d46fe374094f94aa2f5dadf67780d7f98aba1f4f..33a8b916be1b072c40a84ee8bbef23af0f0ef7b3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-05-26  Jon Lee  <jonlee@apple.com>
+
+        [WK2] Notifications clobber each other with multiple processes
+        https://bugs.webkit.org/show_bug.cgi?id=116428
+        <rdar://problem/13935191>
+
+        Reviewed by Darin Adler.
+
+        * ManualTests/notification-in-multiple-windows.html: Added.
+
 2013-05-27  Patrick Gansterer  <paroga@webkit.org>
 
         Use ICU_INCLUDE_DIRS in BlackBerry CMake files
diff --git a/ManualTests/notification-in-multiple-windows.html b/ManualTests/notification-in-multiple-windows.html
new file mode 100644 (file)
index 0000000..d0fd871
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<body>
+Open this page through a web server in two views. If necessary request permission to post web notifications: <button onclick="requestPermission()">Request permission</button><br/>
+Then post this permission once in each page. <button onclick="postNotification()">Post notification</button><br/>
+Click on the notification. Only the second notification should be closed on the second page.
+<p id="console">
+</p>
+
+<script>
+function requestPermission() {
+    if (Notification.permission == "granted") {
+        log("Notification already granted");
+        return;
+    }
+
+    log("Requesting permission...");
+    Notification.requestPermission(function(permission) {
+        if (Notification.permission == "granted") {
+            log("Notification granted");
+            return;
+        }
+        log("Notification denied");
+    });
+}
+
+function postNotification() {
+    var n = new Notification("Notification title");
+    n.onshow = onShowHandler;
+    n.onclick = onClickHandler;
+    n.onclose = onCloseHandler;
+}
+
+function log(message) {
+    document.getElementById("console").innerHTML += message + "<br/>";
+}
+
+function onShowHandler() {
+    log("onshow handler called");
+}
+
+function onClickHandler() {
+    log("onclick handler called");
+    this.close();
+}
+
+function onCloseHandler() {
+    log("onclose handler called");
+}
+</script>
+</body>
+</html>
\ No newline at end of file
index a1772361bab0555a41ad6d9a63517bb074f550f4..60a4efd1829e96190cd81dd52612d7ee198bdb0f 100644 (file)
@@ -551,8 +551,6 @@ set(WebKit2_MESSAGES_IN_FILES
 
     UIProcess/Downloads/DownloadProxy.messages.in
 
-    UIProcess/Notifications/WebNotificationManagerProxy.messages.in
-
     UIProcess/Plugins/PluginProcessProxy.messages.in
 
     WebProcess/WebProcess.messages.in
index fdc704d53a8b0724051f69dcb8de1cba41611b05..6b06494f5eabe386ba9fc97ca37f04a3a8f4c5bf 100644 (file)
@@ -1,3 +1,96 @@
+2013-05-26  Jon Lee  <jonlee@apple.com>
+
+        [WK2] Notifications clobber each other with multiple processes
+        https://bugs.webkit.org/show_bug.cgi?id=116428
+        <rdar://problem/13935191>
+
+        Reviewed by Darin Adler.
+
+        With multiple processes, the notification IDs, when passed up to the UI process, can clobber
+        each other. To fix this, we need to maintain a global map of notification IDs. This map is
+        keyed by its own unique notification ID, and maps to a pair containing the web page ID and that
+        web page's ID for the notification.
+
+        Now that we maintain groups of notifications based on the web page, we no longer send IPC messages
+        from WebNotificationManager to WebNotificationManagerProxy; instead we send messages to the
+        WebPageProxy. This removes the need for WebNotificationManagerProxy to be a message receiver.
+
+        When a page closes, all of the web notifications are cleared out. However, by the time the
+        WebPage::close() is called, the connection between WebPage and WebPageProxy is destroyed. Since
+        the WebPage is told to close from the UI process anyway, we clear out the notifications separately,
+        instead of waiting for a message from the WebPage.
+
+        * UIProcess/Notifications/WebNotificationManagerProxy.h: Update to take into account the
+        notification's web page. Remove inheritance of CoreIPC::MessageReceiver. Expose the original message
+        handlers as public functions, since they will be called from WebPageProxy. Add a new map that
+        associates a global ID with a notification ID that came from a web page.
+            There are now two flavors of clearNotifications(). One clears out all notifications associated
+        with a web page. This is called when the page is closed. The other clears out a subset of
+        notifications associated with a web page. This is called when notifications associated with a sub-frame
+        is closed.
+        * UIProcess/Notifications/WebNotificationManagerProxy.messages.in: Removed. All messages from
+        the web process go to WebPageProxy now.
+
+        * UIProcess/Notifications/WebNotificationManagerProxy.cpp: Update to take into account the
+        notification's web page.
+
+        (WebKit::generateGlobalNotificationID): The manager proxy now maintains its own global notification
+        ID generator.
+        (WebKit::WebNotificationManagerProxy::WebNotificationManagerProxy): The proxy is no longer a
+        message receiver. Remove code that registers it as such.
+
+        (WebKit::WebNotificationManagerProxy::show): Refactor to differentiate between the notification ID
+        that came from the web process, and the global notification ID the proxy maintains. Add the mapping
+        from the global ID to the (web page ID, notification ID) pair.
+        (WebKit::WebNotificationManagerProxy::cancel): Refactor to take into consideration the web page.
+        (WebKit::WebNotificationManagerProxy::didDestroyNotification): Refactor to take into consideration
+        the web page. Fixes a leak where we did not remove the item from the maps. This function is called
+        from the web process, when the ScriptExecutionContext is destroyed, so we remove it from our maps
+        before we pass the message along to the provider.
+
+        Helper functions that evaluate when a given notification in the map matches the desired parameters.
+        (WebKit::pageIDsMatch): The notification is associated with the provided page.
+        (WebKit::pageAndNotificationIDsMatch): The notification is associated with the provided page and is
+        contained within the list of provided notifications.
+
+        (WebKit::WebNotificationManagerProxy::clearNotifications): Changed to only remove notifications
+        associated with the provided web page, and could include a specific list of notifications. This latter
+        situation occurs if notifications were associated with an iframe, and that iframe was removed.
+        There is an O(n) walk that could be make more efficient using another hash map, but that's overhead
+        for a map that should be small in size anyway.
+
+        (WebKit::WebNotificationManagerProxy::providerDidShowNotification): Refactor to take into
+        consideration the web page.
+        (WebKit::WebNotificationManagerProxy::providerDidClickNotification): Refactor to take into
+        consideration the web page.
+        (WebKit::WebNotificationManagerProxy::providerDidCloseNotifications): Now we need to comb through
+        the list of global IDs and put them in buckets based on the notification's web pages. After that
+        is done we can send the DidCloseNotifications() to those pages' processes. There is a possible
+        extra optimization here where we group based on the page's process instead, to reduce the number
+        of messages sent to processes.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::close): When a web page is closed, we clear the notifications associated
+        with the page.
+        (WebKit::WebPageProxy::cancelNotification): Forward call to WebNotificationManagerProxy.
+        (WebKit::WebPageProxy::clearNotifications): Ditto.
+        (WebKit::WebPageProxy::didDestroyNotification): Ditto.
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+
+        * WebProcess/Notifications/NotificationPermissionRequestManager.cpp:
+        * WebProcess/Notifications/WebNotificationManager.cpp:
+        (WebKit::WebNotificationManager::cancel):
+        (WebKit::WebNotificationManager::clearNotifications):
+        (WebKit::WebNotificationManager::didDestroyNotification):
+        * WebProcess/Notifications/NotificationPermissionRequestManager.cpp: Remove extraneous include.
+
+        * CMakeLists.txt: Remove WebNotificationManagerProxy.messages.in and related files.
+        * DerivedSources.pri: Ditto.
+        * DerivedSources.make: Ditto.
+        * GNUmakefile.list.am: Ditto.
+        * WebKit2.xcodeproj/project.pbxproj: Ditto.
+
 2013-05-27  Tim Horton  <timothy_horton@apple.com>
 
         Unreviewed build fix take 2.
index d284fb38b1b8ffdeda8152346320e40fd92c47d3..dd7ba2334386206b5d40ca6eeacf45d316506c1e 100644 (file)
@@ -104,7 +104,6 @@ MESSAGE_RECEIVERS = \
     WebInspectorProxy \
     WebMediaCacheManager \
     WebMediaCacheManagerProxy \
-    WebNotificationManagerProxy \
     WebNotificationManager \
     WebPage \
     WebPageGroupProxy \
index 9339ee2f371c16c6c152803942e126f414704aae..dc17faaac0b9ccff828b4bcd7614bbaa63f1dd9c 100644 (file)
@@ -97,7 +97,6 @@ MESSAGE_RECEIVERS = \
     WebMediaCacheManagerProxy.messages.in \
     WebNetworkInfoManager.messages.in \
     WebNetworkInfoManagerProxy.messages.in \
-    WebNotificationManagerProxy.messages.in \
     WebNotificationManager.messages.in \
     WebFullScreenManager.messages.in \
     WebFullScreenManagerProxy.messages.in \
index dac0bba154bcfc5a48778f179d38b1fbb321d935..a2e67cd462f7d711bee63029c8b7056d77e1680c 100644 (file)
@@ -214,8 +214,6 @@ webkit2_built_sources += \
        DerivedSources/WebKit2/WebNetworkInfoManagerProxyMessages.h \
        DerivedSources/WebKit2/WebNotificationManagerMessageReceiver.cpp \
        DerivedSources/WebKit2/WebNotificationManagerMessages.h \
-       DerivedSources/WebKit2/WebNotificationManagerProxyMessageReceiver.cpp \
-       DerivedSources/WebKit2/WebNotificationManagerProxyMessages.h \
        DerivedSources/WebKit2/WebPageGroupProxyMessageReceiver.cpp \
        DerivedSources/WebKit2/WebPageGroupProxyMessages.h \
        DerivedSources/WebKit2/WebPageProxyMessageReceiver.cpp \
index a7b0fa6d9b8d792228d617b43b67d384b4971308..9e462af9b3c3b88b9f3e5159a07d003efd9be049 100644 (file)
 #include "WebContext.h"
 #include "WebNotification.h"
 #include "WebNotificationManagerMessages.h"
-#include "WebNotificationManagerProxyMessages.h"
 #include "WebPageProxy.h"
+#include "WebProcessProxy.h"
 #include "WebSecurityOrigin.h"
 
+using namespace std;
 using namespace WTF;
 using namespace WebCore;
 
 namespace WebKit {
 
+static uint64_t generateGlobalNotificationID()
+{
+    static uint64_t uniqueGlobalNotificationID = 1;
+    return uniqueGlobalNotificationID++;
+}
+
 const char* WebNotificationManagerProxy::supplementName()
 {
     return "WebNotificationManagerProxy";
@@ -53,7 +60,6 @@ PassRefPtr<WebNotificationManagerProxy> WebNotificationManagerProxy::create(WebC
 WebNotificationManagerProxy::WebNotificationManagerProxy(WebContext* context)
     : WebContextSupplement(context)
 {
-    WebContextSupplement::context()->addMessageReceiver(Messages::WebNotificationManagerProxy::messageReceiverName(), this);
 }
 
 void WebNotificationManagerProxy::initializeProvider(const WKNotificationProvider *provider)
@@ -79,8 +85,6 @@ void WebNotificationManagerProxy::derefWebContextSupplement()
     APIObject::deref();
 }
 
-// CoreIPC::MessageReceiver
-
 void WebNotificationManagerProxy::populateCopyOfNotificationPermissions(HashMap<String, bool>& permissions)
 {
     RefPtr<ImmutableDictionary> knownPermissions = m_provider.notificationPermissions();
@@ -96,82 +100,136 @@ void WebNotificationManagerProxy::populateCopyOfNotificationPermissions(HashMap<
     }
 }
 
-void WebNotificationManagerProxy::show(WebPageProxy* page, const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t notificationID)
+void WebNotificationManagerProxy::show(WebPageProxy* webPage, const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t pageNotificationID)
 {
-    if (!isNotificationIDValid(notificationID))
-        return;
-    
-    RefPtr<WebNotification> notification = WebNotification::create(title, body, iconURL, tag, lang, dir, originString, notificationID);
-    m_notifications.set(notificationID, notification);
-    m_provider.show(page, notification.get());
+    uint64_t globalNotificationID = generateGlobalNotificationID();
+    RefPtr<WebNotification> notification = WebNotification::create(title, body, iconURL, tag, lang, dir, originString, globalNotificationID);
+    pair<uint64_t, uint64_t> notificationIDPair = make_pair(webPage->pageID(), pageNotificationID);
+    m_globalNotificationMap.set(globalNotificationID, notificationIDPair);
+    m_notifications.set(notificationIDPair, make_pair(globalNotificationID, notification));
+    m_provider.show(webPage, notification.get());
 }
 
-void WebNotificationManagerProxy::cancel(uint64_t notificationID)
+void WebNotificationManagerProxy::cancel(WebPageProxy* webPage, uint64_t pageNotificationID)
 {
-    if (!isNotificationIDValid(notificationID))
-        return;
-
-    RefPtr<WebNotification> notification = m_notifications.get(notificationID);
-    if (!notification)
-        return;
-
-    m_provider.cancel(notification.get());
+    if (WebNotification* notification = m_notifications.get(make_pair(webPage->pageID(), pageNotificationID)).second.get())
+        m_provider.cancel(notification);
 }
     
-void WebNotificationManagerProxy::didDestroyNotification(uint64_t notificationID)
+void WebNotificationManagerProxy::didDestroyNotification(WebPageProxy* webPage, uint64_t pageNotificationID)
 {
-    if (!isNotificationIDValid(notificationID))
-        return;
+    auto globalIDNotificationPair = m_notifications.take(make_pair(webPage->pageID(), pageNotificationID));
+    if (uint64_t globalNotificationID = globalIDNotificationPair.first) {
+        WebNotification* notification = globalIDNotificationPair.second.get();
+        m_globalNotificationMap.remove(globalNotificationID);
+        m_provider.didDestroyNotification(notification);
+    }
+}
 
-    RefPtr<WebNotification> notification = m_notifications.take(notificationID);
-    if (!notification)
-        return;
+static bool pageIDsMatch(uint64_t pageID, uint64_t, uint64_t desiredPageID, const Vector<uint64_t>&)
+{
+    return pageID == desiredPageID;
+}
 
-    m_provider.didDestroyNotification(notification.get());
+static bool pageAndNotificationIDsMatch(uint64_t pageID, uint64_t pageNotificationID, uint64_t desiredPageID, const Vector<uint64_t>& desiredPageNotificationIDs)
+{
+    return pageID == desiredPageID && desiredPageNotificationIDs.contains(pageNotificationID);
 }
 
-void WebNotificationManagerProxy::clearNotifications(const Vector<uint64_t>& notificationIDs)
+void WebNotificationManagerProxy::clearNotifications(WebPageProxy* webPage)
 {
-    m_provider.clearNotifications(notificationIDs);
-    size_t count = notificationIDs.size();
-    for (size_t i = 0; i < count; ++i)
-        m_notifications.remove(notificationIDs[i]);
+    clearNotifications(webPage, Vector<uint64_t>(), pageIDsMatch);
 }
 
-void WebNotificationManagerProxy::providerDidShowNotification(uint64_t notificationID)
+void WebNotificationManagerProxy::clearNotifications(WebPageProxy* webPage, const Vector<uint64_t>& pageNotificationIDs)
 {
-    if (!context())
+    clearNotifications(webPage, pageNotificationIDs, pageAndNotificationIDsMatch);
+}
+
+void WebNotificationManagerProxy::clearNotifications(WebPageProxy* webPage, const Vector<uint64_t>& pageNotificationIDs, NotificationFilterFunction filterFunction)
+{
+    uint64_t targetPageID = webPage->pageID();
+
+    Vector<uint64_t> globalNotificationIDs;
+    globalNotificationIDs.reserveCapacity(m_globalNotificationMap.size());
+
+    for (auto it = m_notifications.begin(), end = m_notifications.end(); it != end; ++it) {
+        uint64_t webPageID = it->key.first;
+        uint64_t pageNotificationID = it->key.second;
+        if (!filterFunction(webPageID, pageNotificationID, targetPageID, pageNotificationIDs))
+            continue;
+
+        uint64_t globalNotificationID = it->value.first;
+        globalNotificationIDs.append(globalNotificationID);
+    }
+
+    for (auto it = globalNotificationIDs.begin(), end = globalNotificationIDs.end(); it != end; ++it) {
+        auto pageNotification = m_globalNotificationMap.take(*it);
+        m_notifications.remove(pageNotification);
+    }
+
+    m_provider.clearNotifications(globalNotificationIDs);
+}
+
+void WebNotificationManagerProxy::providerDidShowNotification(uint64_t globalNotificationID)
+{
+    auto it = m_globalNotificationMap.find(globalNotificationID);
+    if (it == m_globalNotificationMap.end())
         return;
-    
-    context()->sendToAllProcesses(Messages::WebNotificationManager::DidShowNotification(notificationID));
+
+    uint64_t webPageID = it->value.first;
+    WebPageProxy* webPage = WebProcessProxy::webPage(webPageID);
+    if (!webPage)
+        return;
+
+    uint64_t pageNotificationID = it->value.second;
+    webPage->process()->send(Messages::WebNotificationManager::DidShowNotification(pageNotificationID), 0);
 }
 
-void WebNotificationManagerProxy::providerDidClickNotification(uint64_t notificationID)
+void WebNotificationManagerProxy::providerDidClickNotification(uint64_t globalNotificationID)
 {
-    if (!context())
+    auto it = m_globalNotificationMap.find(globalNotificationID);
+    if (it == m_globalNotificationMap.end())
         return;
     
-    context()->sendToAllProcesses(Messages::WebNotificationManager::DidClickNotification(notificationID));
+    uint64_t webPageID = it->value.first;
+    WebPageProxy* webPage = WebProcessProxy::webPage(webPageID);
+    if (!webPage)
+        return;
+
+    uint64_t pageNotificationID = it->value.second;
+    webPage->process()->send(Messages::WebNotificationManager::DidClickNotification(pageNotificationID), 0);
 }
 
 
-void WebNotificationManagerProxy::providerDidCloseNotifications(ImmutableArray* notificationIDs)
+void WebNotificationManagerProxy::providerDidCloseNotifications(ImmutableArray* globalNotificationIDs)
 {
-    if (!context())
-        return;
-    
-    size_t size = notificationIDs->size();
-    
-    Vector<uint64_t> vectorNotificationIDs;
-    vectorNotificationIDs.reserveInitialCapacity(size);
+    HashMap<WebPageProxy*, Vector<uint64_t>> pageNotificationIDs;
     
+    size_t size = globalNotificationIDs->size();
     for (size_t i = 0; i < size; ++i) {
-        uint64_t notificationID = notificationIDs->at<WebUInt64>(i)->value();
-        vectorNotificationIDs.append(notificationID);
+        auto it = m_globalNotificationMap.find(globalNotificationIDs->at<WebUInt64>(i)->value());
+        if (it == m_globalNotificationMap.end())
+            continue;
+
+        if (WebPageProxy* webPage = WebProcessProxy::webPage(it->value.first)) {
+            auto pageIt = pageNotificationIDs.find(webPage);
+            if (pageIt == pageNotificationIDs.end()) {
+                Vector<uint64_t> newVector;
+                newVector.reserveInitialCapacity(size);
+                pageIt = pageNotificationIDs.add(webPage, newVector).iterator;
+            }
+
+            uint64_t pageNotificationID = it->value.second;
+            pageIt->value.append(pageNotificationID);
+        }
+
+        m_notifications.remove(it->value);
+        m_globalNotificationMap.remove(it);
     }
-    
-    if (vectorNotificationIDs.size())
-        context()->sendToAllProcesses(Messages::WebNotificationManager::DidCloseNotifications(vectorNotificationIDs));
+
+    for (auto it = pageNotificationIDs.begin(), end = pageNotificationIDs.end(); it != end; ++it)
+        it->key->process()->send(Messages::WebNotificationManager::DidCloseNotifications(it->value), 0);
 }
 
 void WebNotificationManagerProxy::providerDidUpdateNotificationPolicy(const WebSecurityOrigin* origin, bool allowed)
index 0ffb2b783412a4415291245796e349e2f38cb387..5890b5c1b0e4f5d60c89601cfa686ad1e9e0a0fc 100644 (file)
@@ -43,7 +43,7 @@ class WebContext;
 class WebPageProxy;
 class WebSecurityOrigin;
 
-class WebNotificationManagerProxy : public TypedAPIObject<APIObject::TypeNotificationManager>, public WebContextSupplement, private CoreIPC::MessageReceiver {
+class WebNotificationManagerProxy : public TypedAPIObject<APIObject::TypeNotificationManager>, public WebContextSupplement {
 public:
 
     static const char* supplementName();
@@ -53,7 +53,11 @@ public:
     void initializeProvider(const WKNotificationProvider*);
     void populateCopyOfNotificationPermissions(HashMap<String, bool>&);
 
-    void show(WebPageProxy*, const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t notificationID);
+    void show(WebPageProxy*, const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t pageNotificationID);
+    void cancel(WebPageProxy*, uint64_t pageNotificationID);
+    void clearNotifications(WebPageProxy*);
+    void clearNotifications(WebPageProxy*, const Vector<uint64_t>& pageNotificationIDs);
+    void didDestroyNotification(WebPageProxy*, uint64_t pageNotificationID);
 
     void providerDidShowNotification(uint64_t notificationID);
     void providerDidClickNotification(uint64_t notificationID);
@@ -67,23 +71,19 @@ public:
 private:
     explicit WebNotificationManagerProxy(WebContext*);
 
+    typedef bool (*NotificationFilterFunction)(uint64_t pageID, uint64_t pageNotificationID, uint64_t desiredPageID, const Vector<uint64_t>& desiredPageNotificationIDs);
+    void clearNotifications(WebPageProxy*, const Vector<uint64_t>& pageNotificationIDs, NotificationFilterFunction);
+
     // WebContextSupplement
     virtual void contextDestroyed() OVERRIDE;
     virtual void refWebContextSupplement() OVERRIDE;
     virtual void derefWebContextSupplement() OVERRIDE;
 
-    // CoreIPC::MessageReceiver
-    virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&) OVERRIDE;
-    
-    // Message handlers
-    void cancel(uint64_t notificationID);
-    void didDestroyNotification(uint64_t notificationID);
-    void clearNotifications(const Vector<uint64_t>& notificationIDs);
-
-    typedef HashMap<uint64_t, RefPtr<WebNotification>> WebNotificationMap;
-    
     WebNotificationProvider m_provider;
-    WebNotificationMap m_notifications;
+    // Pair comprised of web page ID and the web process's notification ID
+    HashMap<uint64_t, pair<uint64_t, uint64_t>> m_globalNotificationMap;
+    // Key pair comprised of web page ID and the web process's notification ID; value pair comprised of global notification ID, and notification object
+    HashMap<pair<uint64_t, uint64_t>, pair<uint64_t, RefPtr<WebNotification>>> m_notifications;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in
deleted file mode 100644 (file)
index a06e928..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2011 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1.  Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer.
-# 2.  Redistributions in binary form must reproduce the above copyright
-#     notice, this list of conditions and the following disclaimer in the
-#     documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-messages -> WebNotificationManagerProxy {
-    Cancel(uint64_t notificationID);
-    DidDestroyNotification(uint64_t notificationID);
-    ClearNotifications(Vector<uint64_t> notificationIDs);
-}
index e21487e3e116cb85643eb43218c4edac6e99fdc4..594cfda6813a94ade6fca01e2efbccf5957182a2 100644 (file)
@@ -591,6 +591,7 @@ void WebPageProxy::close()
 #endif
 
     m_notificationPermissionRequestManager.invalidateRequests();
+    m_process->context()->supplement<WebNotificationManagerProxy>()->clearNotifications(this);
 
     m_toolTip = String();
 
@@ -4103,6 +4104,21 @@ void WebPageProxy::showNotification(const String& title, const String& body, con
     m_process->context()->supplement<WebNotificationManagerProxy>()->show(this, title, body, iconURL, tag, lang, dir, originString, notificationID);
 }
 
+void WebPageProxy::cancelNotification(uint64_t notificationID)
+{
+    m_process->context()->supplement<WebNotificationManagerProxy>()->cancel(this, notificationID);
+}
+
+void WebPageProxy::clearNotifications(const Vector<uint64_t>& notificationIDs)
+{
+    m_process->context()->supplement<WebNotificationManagerProxy>()->clearNotifications(this, notificationIDs);
+}
+
+void WebPageProxy::didDestroyNotification(uint64_t notificationID)
+{
+    m_process->context()->supplement<WebNotificationManagerProxy>()->didDestroyNotification(this, notificationID);
+}
+
 float WebPageProxy::headerHeight(WebFrameProxy* frame)
 {
     if (frame->isDisplayingPDFDocument())
index 40473efda4f474101b283dd692c084ebe037843d..532ec3fd1d359a9122eafd3fa3854e093b186e96 100644 (file)
@@ -872,7 +872,10 @@ private:
 
     void requestNotificationPermission(uint64_t notificationID, const String& originString);
     void showNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t notificationID);
-    
+    void cancelNotification(uint64_t notificationID);
+    void clearNotifications(const Vector<uint64_t>& notificationIDs);
+    void didDestroyNotification(uint64_t notificationID);
+
 #if USE(TILED_BACKING_STORE)
     void pageDidRequestScroll(const WebCore::IntPoint&);
     void pageTransitionViewportReady();
index a7eeb5429837c170dcc3d9dec736478846c68710..86213f1ccc70b4038ef9d33a1473d75b927e07a9 100644 (file)
@@ -220,6 +220,9 @@ messages -> WebPageProxy {
     # Notification messages
     RequestNotificationPermission(uint64_t requestID, WTF::String originIdentifier)
     ShowNotification(WTF::String title, WTF::String body, WTF::String iconURL, WTF::String tag, WTF::String lang, WTF::String dir, WTF::String originIdentifier, uint64_t notificationID)
+    CancelNotification(uint64_t notificationID)
+    ClearNotifications(Vector<uint64_t> notificationIDs)
+    DidDestroyNotification(uint64_t notificationID)
 
     # Spelling and grammar messages
 #if USE(UNIFIED_TEXT_CHECKING)  
index 49392a191a446ce97cd0d7357566e9ace78e1e0f..0dad3ad450b35f8d6b439bbf142ed575a82abc77 100644 (file)
                3131261F148FF82C00BA2A39 /* NotificationPermissionRequestManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3131261A148FF82B00BA2A39 /* NotificationPermissionRequestManager.h */; };
                31312620148FF82C00BA2A39 /* WebNotificationManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3131261B148FF82B00BA2A39 /* WebNotificationManager.cpp */; };
                31312621148FF82C00BA2A39 /* WebNotificationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3131261C148FF82B00BA2A39 /* WebNotificationManager.h */; };
-               318BE1671473433700A8FBB2 /* WebNotificationManagerProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 318BE1651473433700A8FBB2 /* WebNotificationManagerProxyMessageReceiver.cpp */; };
-               318BE1681473433700A8FBB2 /* WebNotificationManagerProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 318BE1661473433700A8FBB2 /* WebNotificationManagerProxyMessages.h */; };
                318BE17114743DB100A8FBB2 /* WKNotificationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 318BE17014743DB100A8FBB2 /* WKNotificationManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
                318BE17514743DD700A8FBB2 /* WKNotificationManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 318BE17414743DD600A8FBB2 /* WKNotificationManager.cpp */; };
                318BE17714743E6000A8FBB2 /* WKNotification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 318BE17614743E6000A8FBB2 /* WKNotification.cpp */; };
                3131261B148FF82B00BA2A39 /* WebNotificationManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationManager.cpp; sourceTree = "<group>"; };
                3131261C148FF82B00BA2A39 /* WebNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationManager.h; sourceTree = "<group>"; };
                3131261D148FF82C00BA2A39 /* WebNotificationManager.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebNotificationManager.messages.in; sourceTree = "<group>"; };
-               318BE1651473433700A8FBB2 /* WebNotificationManagerProxyMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationManagerProxyMessageReceiver.cpp; sourceTree = "<group>"; };
-               318BE1661473433700A8FBB2 /* WebNotificationManagerProxyMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationManagerProxyMessages.h; sourceTree = "<group>"; };
                318BE17014743DB100A8FBB2 /* WKNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNotificationManager.h; sourceTree = "<group>"; };
                318BE17414743DD600A8FBB2 /* WKNotificationManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKNotificationManager.cpp; sourceTree = "<group>"; };
                318BE17614743E6000A8FBB2 /* WKNotification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKNotification.cpp; sourceTree = "<group>"; };
                31A2EC42148997BE00810D71 /* WebNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotification.h; sourceTree = "<group>"; };
                31A2EC43148997BE00810D71 /* WebNotificationManagerProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationManagerProxy.cpp; sourceTree = "<group>"; };
                31A2EC44148997BF00810D71 /* WebNotificationManagerProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationManagerProxy.h; sourceTree = "<group>"; };
-               31A2EC45148997BF00810D71 /* WebNotificationManagerProxy.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebNotificationManagerProxy.messages.in; sourceTree = "<group>"; };
                31A2EC46148997C000810D71 /* WebNotificationProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationProvider.cpp; sourceTree = "<group>"; };
                31A2EC47148997C100810D71 /* WebNotificationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationProvider.h; sourceTree = "<group>"; };
                31A2EC4F1489980500810D71 /* NotificationPermissionRequestManagerProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NotificationPermissionRequestManagerProxy.cpp; sourceTree = "<group>"; };
                                31A2EC42148997BE00810D71 /* WebNotification.h */,
                                31A2EC43148997BE00810D71 /* WebNotificationManagerProxy.cpp */,
                                31A2EC44148997BF00810D71 /* WebNotificationManagerProxy.h */,
-                               31A2EC45148997BF00810D71 /* WebNotificationManagerProxy.messages.in */,
                                31A2EC46148997C000810D71 /* WebNotificationProvider.cpp */,
                                31A2EC47148997C100810D71 /* WebNotificationProvider.h */,
                        );
                                33D3A3C71339617900709BE4 /* WebMediaCacheManagerProxyMessages.h */,
                                31BA9248148830810062EDB5 /* WebNotificationManagerMessageReceiver.cpp */,
                                31BA9249148830810062EDB5 /* WebNotificationManagerMessages.h */,
-                               318BE1651473433700A8FBB2 /* WebNotificationManagerProxyMessageReceiver.cpp */,
-                               318BE1661473433700A8FBB2 /* WebNotificationManagerProxyMessages.h */,
                                29D55DEF161BF9F10031A2E3 /* WebPageGroupProxyMessageReceiver.cpp */,
                                29D55DF0161BF9F10031A2E3 /* WebPageGroupProxyMessages.h */,
                                C0CE729E1247E71D00BC0EC4 /* WebPageMessageReceiver.cpp */,
                                31312621148FF82C00BA2A39 /* WebNotificationManager.h in Headers */,
                                31BA924E148831260062EDB5 /* WebNotificationManagerMessages.h in Headers */,
                                31A2EC4B148997C200810D71 /* WebNotificationManagerProxy.h in Headers */,
-                               318BE1681473433700A8FBB2 /* WebNotificationManagerProxyMessages.h in Headers */,
                                31A2EC4E148997C200810D71 /* WebNotificationProvider.h in Headers */,
                                BC33DD681238464600360F3F /* WebNumber.h in Headers */,
                                BC857FB512B830E600EDEB2E /* WebOpenPanelParameters.h in Headers */,
                                31312620148FF82C00BA2A39 /* WebNotificationManager.cpp in Sources */,
                                31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */,
                                31A2EC4A148997C200810D71 /* WebNotificationManagerProxy.cpp in Sources */,
-                               318BE1671473433700A8FBB2 /* WebNotificationManagerProxyMessageReceiver.cpp in Sources */,
                                31A2EC4D148997C200810D71 /* WebNotificationProvider.cpp in Sources */,
                                BC857FB612B830E600EDEB2E /* WebOpenPanelParameters.cpp in Sources */,
                                1A8C728C1738477C000A6554 /* LocalStorageDatabaseTracker.cpp in Sources */,
index bd69f1d48b798ae202a08d395a3f91d032ca236e..71dc82698647b57685a8de7f51ca4b8ad3c699d6 100644 (file)
@@ -27,7 +27,6 @@
 #include "NotificationPermissionRequestManager.h"
 
 #include "WebCoreArgumentCoders.h"
-#include "WebNotificationManagerProxyMessages.h"
 #include "WebPage.h"
 #include "WebPageProxyMessages.h"
 #include "WebProcess.h"
index 5446e84fa9c4ac106260cde683b6bc8e0376e7c0..b558c13c14d936d7f45f2b60769dd40787b870d6 100644 (file)
@@ -33,7 +33,6 @@
 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
 #include "WebNotification.h"
 #include "WebNotificationManagerMessages.h"
-#include "WebNotificationManagerProxyMessages.h"
 #include "WebPageProxyMessages.h"
 #include <WebCore/Document.h>
 #include <WebCore/Notification.h>
@@ -175,7 +174,7 @@ void WebNotificationManager::cancel(Notification* notification, WebPage* page)
     if (!notificationID)
         return;
     
-    m_process->parentProcessConnection()->send(Messages::WebNotificationManagerProxy::Cancel(notificationID), 0);
+    m_process->parentProcessConnection()->send(Messages::WebPageProxy::CancelNotification(notificationID), page->pageID());
 #else
     UNUSED_PARAM(notification);
     UNUSED_PARAM(page);
@@ -188,9 +187,9 @@ void WebNotificationManager::clearNotifications(WebCore::ScriptExecutionContext*
     NotificationContextMap::iterator it = m_notificationContextMap.find(context);
     if (it == m_notificationContextMap.end())
         return;
-    
+
     Vector<uint64_t>& notificationIDs = it->value;
-    m_process->parentProcessConnection()->send(Messages::WebNotificationManagerProxy::ClearNotifications(notificationIDs), 0);
+    m_process->parentProcessConnection()->send(Messages::WebPageProxy::ClearNotifications(notificationIDs), page->pageID());
     size_t count = notificationIDs.size();
     for (size_t i = 0; i < count; ++i) {
         RefPtr<Notification> notification = m_notificationIDMap.take(notificationIDs[i]);
@@ -216,7 +215,7 @@ void WebNotificationManager::didDestroyNotification(Notification* notification,
 
     m_notificationIDMap.remove(notificationID);
     removeNotificationFromContextMap(notificationID, notification);
-    m_process->parentProcessConnection()->send(Messages::WebNotificationManagerProxy::DidDestroyNotification(notificationID), 0);
+    m_process->parentProcessConnection()->send(Messages::WebPageProxy::DidDestroyNotification(notificationID), page->pageID());
 #else
     UNUSED_PARAM(notification);
     UNUSED_PARAM(page);