[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 d46fe37..33a8b91 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 a177236..60a4efd 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 fdc704d..6b06494 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 d284fb3..dd7ba23 100644 (file)
@@ -104,7 +104,6 @@ MESSAGE_RECEIVERS = \
     WebInspectorProxy \
     WebMediaCacheManager \
     WebMediaCacheManagerProxy \
-    WebNotificationManagerProxy \
     WebNotificationManager \
     WebPage \
     WebPageGroupProxy \
index 9339ee2..dc17faa 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 dac0bba..a2e67cd 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 a7b0fa6..9e462af 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 0ffb2b7..5890b5c 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 e21487e..594cfda 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 40473ef..532ec3f 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 a7eeb54..86213f1 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 49392a1..0dad3ad 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 bd69f1d..71dc826 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 5446e84..b558c13 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);