Add SPI to allow install script message handlers in isolated worlds
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Apr 2016 21:03:28 +0000 (21:03 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 4 Apr 2016 21:03:28 +0000 (21:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=156153

Reviewed by Anders Carlsson.

Source/WebCore:

Added API Test: WKUserContentController.ScriptMessageHandlerBasicPostIsolatedWorld

- Changes the signature of the method in UserContentProvider to get UserMessageHandlerDescriptors
  to match that of UserScripts and UserStyleSheets.
- Removes the need for UserMessageHandlerDescriptor::Client by making UserMessageHandlerDescriptor
  directly subclassable.
- Changes invalidation model of UserMessageHandlersNamespace to be more direct by allowing it to
  register for invalidation notifications, rather than always checking if handler has been removed
  on each invocation.

* loader/EmptyClients.cpp:
Update for new signature.

* page/DOMWindow.cpp:
(WebCore::DOMWindow::shouldHaveWebKitNamespaceForWorld):
Switch to using forEachUserMessageHandler.

(WebCore::DOMWindow::webkitNamespace):
Pass the UserContentProvider to the namespace on creation, so the UserMessageHandlersNamespace
can use it to register to listen for UserMessageHandler changes.

* page/UserContentController.h:
* page/UserContentController.cpp:
(WebCore::UserContentController::forEachUserStyleSheet):
(WebCore::UserContentController::forEachUserMessageHandler):
(WebCore::UserContentController::addUserScript):
(WebCore::UserContentController::removeUserStyleSheets):
(WebCore::UserContentController::removeAllUserContent):
(WebCore::UserContentController::addUserMessageHandlerDescriptor): Deleted.
(WebCore::UserContentController::removeUserMessageHandlerDescriptor): Deleted.
(WebCore::UserContentController::addUserContentExtension): Deleted.
(WebCore::UserContentController::removeUserContentExtension): Deleted.
(WebCore::UserContentController::removeAllUserContentExtensions): Deleted.
Removed unused functions, all the UserMessageHandler and UserContentExtension ones. UserContentController
is only used for Legacy WebKit where those features are not exposed.

* page/UserContentProvider.h:
* page/UserContentProvider.cpp:
(WebCore::UserContentProvider::registerForUserMessageHandlerInvalidation):
(WebCore::UserContentProvider::unregisterForUserMessageHandlerInvalidation):
(WebCore::UserContentProvider::invalidateAllRegisteredUserMessageHandlerInvalidationClients):
(WebCore::UserContentProviderInvalidationClient::~UserContentProviderInvalidationClient):
Update signature for UserMessageHandlerDescriptor access to match UserScript and UserStyleSheet.
Adds explicit invalidation for UserMessageHandlers.

* page/UserMessageHandler.cpp:
(WebCore::UserMessageHandler::UserMessageHandler):
(WebCore::UserMessageHandler::postMessage):
(WebCore::UserMessageHandler::name): Deleted.
(WebCore::UserMessageHandler::world): Deleted.
* page/UserMessageHandler.h:
(WebCore::UserMessageHandler::descriptor):
(WebCore::UserMessageHandler::invalidateDescriptor):
* page/UserMessageHandlerDescriptor.cpp:
(WebCore::UserMessageHandlerDescriptor::UserMessageHandlerDescriptor):
(WebCore::UserMessageHandlerDescriptor::~UserMessageHandlerDescriptor):
(WebCore::UserMessageHandlerDescriptor::name):
(WebCore::UserMessageHandlerDescriptor::world):
* page/UserMessageHandlerDescriptor.h:
(WebCore::UserMessageHandlerDescriptor::Client::~Client): Deleted.
(WebCore::UserMessageHandlerDescriptor::create): Deleted.
(WebCore::UserMessageHandlerDescriptor::client): Deleted.
(WebCore::UserMessageHandlerDescriptor::invalidateClient): Deleted.
Simplify by removing the Client. Now, when the UserMessageHandlerDescriptor is no longer
active, it gets nulled out in the UserMessageHandler.

* page/UserMessageHandlersNamespace.cpp:
(WebCore::UserMessageHandlersNamespace::UserMessageHandlersNamespace):
(WebCore::UserMessageHandlersNamespace::~UserMessageHandlersNamespace):
(WebCore::UserMessageHandlersNamespace::didInvalidate):
(WebCore::UserMessageHandlersNamespace::handler):
* page/UserMessageHandlersNamespace.h:
Change the logic to listen for invalidations of the UserMessageHandlerDescriptor map. When it
is invalidated, re-build the map of cached UserMessageHandlers from the UserContentProvider,
and invalidate any remaining UserMessageHandlers that no longer exist in the UserContentProvider.

* page/WebKitNamespace.cpp:
(WebCore::WebKitNamespace::WebKitNamespace):
* page/WebKitNamespace.h:
(WebCore::WebKitNamespace::create):
Pass through the UserContentProvider.

Source/WebKit2:

* Scripts/webkit/messages.py:
(headers_for_type):
* Shared/WebUserContentControllerDataTypes.cpp:
(WebKit::WebScriptMessageHandlerData::encode):
(WebKit::WebScriptMessageHandlerData::decode):
* Shared/WebUserContentControllerDataTypes.h:
Add WebKit::WebScriptMessageHandlerData, matching WebKit::WebUserScriptData and
WebKit::WebUserStyleSheetData.

* UIProcess/API/Cocoa/WKUserContentController.mm:
(-[WKUserContentController addScriptMessageHandler:name:]):
(-[WKUserContentController removeScriptMessageHandlerForName:]):
(-[WKUserContentController _removeAllUserStyleSheetsAssociatedWithUserContentWorld:]):
(-[WKUserContentController _addScriptMessageHandler:name:userContentWorld:]):
(-[WKUserContentController _removeScriptMessageHandlerForName:userContentWorld:]):
(-[WKUserContentController _removeAllScriptMessageHandlersAssociatedWithUserContentWorld:]):
* UIProcess/API/Cocoa/WKUserContentControllerPrivate.h:
Add SPI for adding and removing ScriptMessageHandlers associated with a world.

* UIProcess/UserContent/WebScriptMessageHandler.cpp:
(WebKit::WebScriptMessageHandler::create):
(WebKit::WebScriptMessageHandler::WebScriptMessageHandler):
(WebKit::WebScriptMessageHandlerHandle::encode): Deleted.
(WebKit::WebScriptMessageHandlerHandle::decode): Deleted.
* UIProcess/UserContent/WebScriptMessageHandler.h:
(WebKit::WebScriptMessageHandler::identifier):
(WebKit::WebScriptMessageHandler::name):
(WebKit::WebScriptMessageHandler::userContentWorld):
(WebKit::WebScriptMessageHandler::client):
(WebKit::WebScriptMessageHandler::handle): Deleted.
Add the world and move the data object to WebUserContentControllerDataTypes.h

* UIProcess/UserContent/WebUserContentControllerProxy.cpp:
(WebKit::WebUserContentControllerProxy::addProcess):
(WebKit::WebUserContentControllerProxy::addUserScriptMessageHandler):
(WebKit::WebUserContentControllerProxy::removeUserMessageHandlerForName):
(WebKit::WebUserContentControllerProxy::removeAllUserMessageHandlers):
* UIProcess/UserContent/WebUserContentControllerProxy.h:
Update for worlds, matching UserScript/UserStyleSheet model.

* WebProcess/UserContent/WebUserContentController.h:
* WebProcess/UserContent/WebUserContentController.cpp:
(WebKit::WebUserMessageHandlerDescriptorProxy::WebUserMessageHandlerDescriptorProxy):
Change to inherit directly from WebCore::UserMessageHandlerDescriptor.

(WebKit::WebUserContentController::addUserScriptMessageHandlers):
(WebKit::WebUserContentController::removeUserScriptMessageHandler):
(WebKit::WebUserContentController::removeAllUserScriptMessageHandlers):
(WebKit::WebUserContentController::addUserScriptMessageHandlerInternal):
(WebKit::WebUserContentController::removeUserScriptMessageHandlerInternal):
Add support for worlds, matching UserScript/UserStyleSheet model.

(WebKit::WebUserContentController::addUserStyleSheets):
Add missing call to invalidateInjectedStyleSheetCacheInAllFramesInAllPages()

(WebKit::WebUserContentController::removeAllUserStyleSheets):
Switch to only calling invalidateInjectedStyleSheetCacheInAllFramesInAllPages() once
after the loop and only if any stylesheets were removed.

(WebKit::WebUserContentController::addUserStyleSheetInternal):
Remove call to invalidateInjectedStyleSheetCacheInAllFramesInAllPages(), make
callers call it. This allows us to avoid calling it repeatedly in removeAllUserStyleSheets().

(WebKit::WebUserContentController::addUserStyleSheet):
Call invalidateInjectedStyleSheetCacheInAllFramesInAllPages() explicitly since it
is no longer called in addUserStyleSheetInternal().

(WebKit::WebUserContentController::forEachUserMessageHandler):
Implement by iterating the m_userMessageHandlers map.

* WebProcess/UserContent/WebUserContentController.messages.in:
Update for worlds, matching UserScript/UserStyleSheet model.

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm:
Add new test, WKUserContentController.ScriptMessageHandlerBasicPostIsolatedWorld

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

30 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/EmptyClients.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/UserContentController.cpp
Source/WebCore/page/UserContentController.h
Source/WebCore/page/UserContentProvider.cpp
Source/WebCore/page/UserContentProvider.h
Source/WebCore/page/UserMessageHandler.cpp
Source/WebCore/page/UserMessageHandler.h
Source/WebCore/page/UserMessageHandlerDescriptor.cpp
Source/WebCore/page/UserMessageHandlerDescriptor.h
Source/WebCore/page/UserMessageHandlersNamespace.cpp
Source/WebCore/page/UserMessageHandlersNamespace.h
Source/WebCore/page/WebKitNamespace.cpp
Source/WebCore/page/WebKitNamespace.h
Source/WebKit2/ChangeLog
Source/WebKit2/Scripts/webkit/messages.py
Source/WebKit2/Shared/WebUserContentControllerDataTypes.cpp
Source/WebKit2/Shared/WebUserContentControllerDataTypes.h
Source/WebKit2/UIProcess/API/Cocoa/WKUserContentController.mm
Source/WebKit2/UIProcess/API/Cocoa/WKUserContentControllerPrivate.h
Source/WebKit2/UIProcess/UserContent/WebScriptMessageHandler.cpp
Source/WebKit2/UIProcess/UserContent/WebScriptMessageHandler.h
Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.cpp
Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.h
Source/WebKit2/WebProcess/UserContent/WebUserContentController.cpp
Source/WebKit2/WebProcess/UserContent/WebUserContentController.h
Source/WebKit2/WebProcess/UserContent/WebUserContentController.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm

index 83e88ed..2a9cc41 100644 (file)
@@ -1,3 +1,92 @@
+2016-04-03  Sam Weinig  <sam@webkit.org>
+
+        Add SPI to allow install script message handlers in isolated worlds
+        https://bugs.webkit.org/show_bug.cgi?id=156153
+
+        Reviewed by Anders Carlsson.
+
+        Added API Test: WKUserContentController.ScriptMessageHandlerBasicPostIsolatedWorld
+
+        - Changes the signature of the method in UserContentProvider to get UserMessageHandlerDescriptors
+          to match that of UserScripts and UserStyleSheets.
+        - Removes the need for UserMessageHandlerDescriptor::Client by making UserMessageHandlerDescriptor
+          directly subclassable.
+        - Changes invalidation model of UserMessageHandlersNamespace to be more direct by allowing it to
+          register for invalidation notifications, rather than always checking if handler has been removed
+          on each invocation.
+
+        * loader/EmptyClients.cpp:
+        Update for new signature.
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::shouldHaveWebKitNamespaceForWorld):
+        Switch to using forEachUserMessageHandler.
+
+        (WebCore::DOMWindow::webkitNamespace):
+        Pass the UserContentProvider to the namespace on creation, so the UserMessageHandlersNamespace
+        can use it to register to listen for UserMessageHandler changes.
+
+        * page/UserContentController.h:
+        * page/UserContentController.cpp:
+        (WebCore::UserContentController::forEachUserStyleSheet):
+        (WebCore::UserContentController::forEachUserMessageHandler):
+        (WebCore::UserContentController::addUserScript):
+        (WebCore::UserContentController::removeUserStyleSheets):
+        (WebCore::UserContentController::removeAllUserContent):
+        (WebCore::UserContentController::addUserMessageHandlerDescriptor): Deleted.
+        (WebCore::UserContentController::removeUserMessageHandlerDescriptor): Deleted.
+        (WebCore::UserContentController::addUserContentExtension): Deleted.
+        (WebCore::UserContentController::removeUserContentExtension): Deleted.
+        (WebCore::UserContentController::removeAllUserContentExtensions): Deleted.
+        Removed unused functions, all the UserMessageHandler and UserContentExtension ones. UserContentController
+        is only used for Legacy WebKit where those features are not exposed.
+
+        * page/UserContentProvider.h:
+        * page/UserContentProvider.cpp:
+        (WebCore::UserContentProvider::registerForUserMessageHandlerInvalidation):
+        (WebCore::UserContentProvider::unregisterForUserMessageHandlerInvalidation):
+        (WebCore::UserContentProvider::invalidateAllRegisteredUserMessageHandlerInvalidationClients):
+        (WebCore::UserContentProviderInvalidationClient::~UserContentProviderInvalidationClient):
+        Update signature for UserMessageHandlerDescriptor access to match UserScript and UserStyleSheet.
+        Adds explicit invalidation for UserMessageHandlers.
+
+        * page/UserMessageHandler.cpp:
+        (WebCore::UserMessageHandler::UserMessageHandler):
+        (WebCore::UserMessageHandler::postMessage):
+        (WebCore::UserMessageHandler::name): Deleted.
+        (WebCore::UserMessageHandler::world): Deleted.
+        * page/UserMessageHandler.h:
+        (WebCore::UserMessageHandler::descriptor):
+        (WebCore::UserMessageHandler::invalidateDescriptor):
+        * page/UserMessageHandlerDescriptor.cpp:
+        (WebCore::UserMessageHandlerDescriptor::UserMessageHandlerDescriptor):
+        (WebCore::UserMessageHandlerDescriptor::~UserMessageHandlerDescriptor):
+        (WebCore::UserMessageHandlerDescriptor::name):
+        (WebCore::UserMessageHandlerDescriptor::world):
+        * page/UserMessageHandlerDescriptor.h:
+        (WebCore::UserMessageHandlerDescriptor::Client::~Client): Deleted.
+        (WebCore::UserMessageHandlerDescriptor::create): Deleted.
+        (WebCore::UserMessageHandlerDescriptor::client): Deleted.
+        (WebCore::UserMessageHandlerDescriptor::invalidateClient): Deleted.
+        Simplify by removing the Client. Now, when the UserMessageHandlerDescriptor is no longer
+        active, it gets nulled out in the UserMessageHandler.
+
+        * page/UserMessageHandlersNamespace.cpp:
+        (WebCore::UserMessageHandlersNamespace::UserMessageHandlersNamespace):
+        (WebCore::UserMessageHandlersNamespace::~UserMessageHandlersNamespace):
+        (WebCore::UserMessageHandlersNamespace::didInvalidate):
+        (WebCore::UserMessageHandlersNamespace::handler):
+        * page/UserMessageHandlersNamespace.h:
+        Change the logic to listen for invalidations of the UserMessageHandlerDescriptor map. When it
+        is invalidated, re-build the map of cached UserMessageHandlers from the UserContentProvider,
+        and invalidate any remaining UserMessageHandlers that no longer exist in the UserContentProvider.
+
+        * page/WebKitNamespace.cpp:
+        (WebCore::WebKitNamespace::WebKitNamespace):
+        * page/WebKitNamespace.h:
+        (WebCore::WebKitNamespace::create):
+        Pass through the UserContentProvider.
+
 2016-04-04  Chris Dumez  <cdumez@apple.com>
 
         Regression(r196145): Crash in getOwnPropertyDescriptor on http://www.history.com/shows/vikings
index 75e73df..bf19745 100644 (file)
@@ -101,7 +101,7 @@ class EmptyUserContentProvider final : public UserContentProvider {
     void forEachUserScript(const std::function<void(DOMWrapperWorld&, const UserScript&)>&) const override { }
     void forEachUserStyleSheet(const std::function<void(const UserStyleSheet&)>&) const override { }
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    const UserMessageHandlerDescriptorMap& userMessageHandlerDescriptors() const override { static NeverDestroyed<UserMessageHandlerDescriptorMap> map; return map.get(); }
+    void forEachUserMessageHandler(const std::function<void(const UserMessageHandlerDescriptor&)>&) const override { }
 #endif
 #if ENABLE(CONTENT_EXTENSIONS)
     ContentExtensions::ContentExtensionsBackend& userContentExtensionBackend() override { static NeverDestroyed<ContentExtensions::ContentExtensionsBackend> backend; return backend.get(); };
index c42eba6..6ca2000 100644 (file)
@@ -761,20 +761,26 @@ bool DOMWindow::shouldHaveWebKitNamespaceForWorld(DOMWrapperWorld& world)
     if (!page)
         return false;
 
-    for (auto& descriptor : page->userContentProvider().userMessageHandlerDescriptors().values()) {
-        if (&descriptor->world() == &world)
-            return true;
-    }
+    bool hasUserMessageHandler = false;
+    page->userContentProvider().forEachUserMessageHandler([&](const UserMessageHandlerDescriptor& descriptor) {
+        if (&descriptor.world() == &world) {
+            hasUserMessageHandler = true;
+            return;
+        }
+    });
 
-    return false;
+    return hasUserMessageHandler;
 }
 
 WebKitNamespace* DOMWindow::webkitNamespace() const
 {
     if (!isCurrentlyDisplayedInFrame())
         return nullptr;
+    auto* page = m_frame->page();
+    if (!page)
+        return nullptr;
     if (!m_webkitNamespace)
-        m_webkitNamespace = WebKitNamespace::create(*m_frame);
+        m_webkitNamespace = WebKitNamespace::create(*m_frame, page->userContentProvider());
     return m_webkitNamespace.get();
 }
 #endif
index b7a3844..4ec8953 100644 (file)
 #include <runtime/JSCellInlines.h>
 #include <runtime/StructureInlines.h>
 
-#if ENABLE(USER_MESSAGE_HANDLERS)
-#include "UserMessageHandlerDescriptor.h"
-#endif
-
 #if ENABLE(CONTENT_EXTENSIONS)
 #include "CompiledContentExtension.h"
 #endif
@@ -72,6 +68,12 @@ void UserContentController::forEachUserStyleSheet(const std::function<void(const
     }
 }
 
+#if ENABLE(USER_MESSAGE_HANDLERS)
+void UserContentController::forEachUserMessageHandler(const std::function<void(const UserMessageHandlerDescriptor&)>&) const
+{
+}
+#endif
+
 void UserContentController::addUserScript(DOMWrapperWorld& world, std::unique_ptr<UserScript> userScript)
 {
     auto& scriptsInWorld = m_userScripts.ensure(&world, [&] { return std::make_unique<UserScriptVector>(); }).iterator->value;
@@ -141,35 +143,6 @@ void UserContentController::removeUserStyleSheets(DOMWrapperWorld& world)
     invalidateInjectedStyleSheetCacheInAllFramesInAllPages();
 }
 
-#if ENABLE(USER_MESSAGE_HANDLERS)
-void UserContentController::addUserMessageHandlerDescriptor(UserMessageHandlerDescriptor& descriptor)
-{
-    m_userMessageHandlerDescriptors.add(std::make_pair(descriptor.name(), &descriptor.world()), &descriptor);
-}
-
-void UserContentController::removeUserMessageHandlerDescriptor(UserMessageHandlerDescriptor& descriptor)
-{
-    m_userMessageHandlerDescriptors.remove(std::make_pair(descriptor.name(), &descriptor.world()));
-}
-#endif
-
-#if ENABLE(CONTENT_EXTENSIONS)
-void UserContentController::addUserContentExtension(const String& name, RefPtr<ContentExtensions::CompiledContentExtension> contentExtension)
-{
-    m_contentExtensionBackend.addContentExtension(name, contentExtension);
-}
-
-void UserContentController::removeUserContentExtension(const String& name)
-{
-    m_contentExtensionBackend.removeContentExtension(name);
-}
-
-void UserContentController::removeAllUserContentExtensions()
-{
-    m_contentExtensionBackend.removeAllContentExtensions();
-}
-#endif
-
 void UserContentController::removeAllUserContent()
 {
     m_userScripts.clear();
index 97cfcff..6582a14 100644 (file)
@@ -45,17 +45,6 @@ public:
 
     WEBCORE_EXPORT void removeAllUserContent();
 
-#if ENABLE(USER_MESSAGE_HANDLERS)
-    WEBCORE_EXPORT void addUserMessageHandlerDescriptor(UserMessageHandlerDescriptor&);
-    WEBCORE_EXPORT void removeUserMessageHandlerDescriptor(UserMessageHandlerDescriptor&);
-#endif
-
-#if ENABLE(CONTENT_EXTENSIONS)
-    WEBCORE_EXPORT void addUserContentExtension(const String& name, RefPtr<ContentExtensions::CompiledContentExtension>);
-    WEBCORE_EXPORT void removeUserContentExtension(const String& name);
-    WEBCORE_EXPORT void removeAllUserContentExtensions();
-#endif
-
 private:
     UserContentController();
 
@@ -63,7 +52,7 @@ private:
     void forEachUserScript(const std::function<void(DOMWrapperWorld&, const UserScript&)>&) const override;
     void forEachUserStyleSheet(const std::function<void(const UserStyleSheet&)>&) const override;
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    const UserMessageHandlerDescriptorMap& userMessageHandlerDescriptors() const override { return m_userMessageHandlerDescriptors; }
+    void forEachUserMessageHandler(const std::function<void(const UserMessageHandlerDescriptor&)>&) const override;
 #endif
 #if ENABLE(CONTENT_EXTENSIONS)
     ContentExtensions::ContentExtensionsBackend& userContentExtensionBackend() override { return m_contentExtensionBackend; }
@@ -71,9 +60,6 @@ private:
 
     UserScriptMap m_userScripts;
     UserStyleSheetMap m_userStyleSheets;
-#if ENABLE(USER_MESSAGE_HANDLERS)
-    UserMessageHandlerDescriptorMap m_userMessageHandlerDescriptors;
-#endif
 #if ENABLE(CONTENT_EXTENSIONS)
     ContentExtensions::ContentExtensionsBackend m_contentExtensionBackend;
 #endif
index 0026c50..3175e74 100644 (file)
@@ -61,6 +61,26 @@ void UserContentProvider::removePage(Page& page)
     m_pages.remove(&page);
 }
 
+void UserContentProvider::registerForUserMessageHandlerInvalidation(UserContentProviderInvalidationClient& invalidationClient)
+{
+    ASSERT(!m_userMessageHandlerInvalidationClients.contains(&invalidationClient));
+
+    m_userMessageHandlerInvalidationClients.add(&invalidationClient);
+}
+
+void UserContentProvider::unregisterForUserMessageHandlerInvalidation(UserContentProviderInvalidationClient& invalidationClient)
+{
+    ASSERT(m_userMessageHandlerInvalidationClients.contains(&invalidationClient));
+
+    m_userMessageHandlerInvalidationClients.remove(&invalidationClient);
+}
+
+void UserContentProvider::invalidateAllRegisteredUserMessageHandlerInvalidationClients()
+{
+    for (auto& client : m_userMessageHandlerInvalidationClients)
+        client->didInvalidate(*this);
+}
+
 void UserContentProvider::invalidateInjectedStyleSheetCacheInAllFramesInAllPages()
 {
     for (auto& page : m_pages)
index bd56522..3113d84 100644 (file)
@@ -58,6 +58,17 @@ class ContentExtensionsBackend;
 struct Action;
 }
 
+class UserContentProvider;
+
+class UserContentProviderInvalidationClient {
+public:
+    virtual ~UserContentProviderInvalidationClient()
+    {
+    }
+    
+    virtual void didInvalidate(UserContentProvider&) = 0;
+};
+
 class UserContentProvider : public RefCounted<UserContentProvider> {
 public:
     WEBCORE_EXPORT UserContentProvider();
@@ -65,19 +76,19 @@ public:
 
     virtual void forEachUserScript(const std::function<void(DOMWrapperWorld&, const UserScript&)>&) const = 0;
     virtual void forEachUserStyleSheet(const std::function<void(const UserStyleSheet&)>&) const = 0;
-
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    virtual const UserMessageHandlerDescriptorMap& userMessageHandlerDescriptors() const = 0;
+    virtual void forEachUserMessageHandler(const std::function<void(const UserMessageHandlerDescriptor&)>&) const = 0;
 #endif
-
 #if ENABLE(CONTENT_EXTENSIONS)
     virtual ContentExtensions::ContentExtensionsBackend& userContentExtensionBackend() = 0;
 #endif
 
+    void registerForUserMessageHandlerInvalidation(UserContentProviderInvalidationClient&);
+    void unregisterForUserMessageHandlerInvalidation(UserContentProviderInvalidationClient&);
+
     void addPage(Page&);
     void removePage(Page&);
 
-
 #if ENABLE(CONTENT_EXTENSIONS)
     // FIXME: These don't really belong here. They should probably bundled up in the ContentExtensionsBackend
     // which should always exist.
@@ -86,10 +97,12 @@ public:
 #endif
 
 protected:
+    WEBCORE_EXPORT void invalidateAllRegisteredUserMessageHandlerInvalidationClients();
     WEBCORE_EXPORT void invalidateInjectedStyleSheetCacheInAllFramesInAllPages();
 
 private:
     HashSet<Page*> m_pages;
+    HashSet<UserContentProviderInvalidationClient*> m_userMessageHandlerInvalidationClients;
 };
 
 } // namespace WebCore
index 05c5a76..9a52d60 100644 (file)
@@ -36,7 +36,7 @@ namespace WebCore {
 
 UserMessageHandler::UserMessageHandler(Frame& frame, UserMessageHandlerDescriptor& descriptor)
     : FrameDestructionObserver(&frame)
-    , m_descriptor(descriptor)
+    , m_descriptor(&descriptor)
 {
 }
 
@@ -48,22 +48,12 @@ void UserMessageHandler::postMessage(PassRefPtr<SerializedScriptValue> value, Ex
 {
     // Check to see if the descriptor has been removed. This can happen if the host application has
     // removed the named message handler at the WebKit2 API level.
-    if (!m_descriptor->client()) {
+    if (!m_descriptor) {
         ec = INVALID_ACCESS_ERR;
         return;
     }
 
-    m_descriptor->client()->didPostMessage(*this, value.get());
-}
-
-const AtomicString& UserMessageHandler::name()
-{
-    return m_descriptor->name();
-}
-
-DOMWrapperWorld& UserMessageHandler::world()
-{
-    return m_descriptor->world();
+    m_descriptor->didPostMessage(*this, value.get());
 }
 
 } // namespace WebCore
index e9a8814..512a114 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "FrameDestructionObserver.h"
 #include "UserMessageHandlerDescriptor.h"
-#include <bindings/ScriptValue.h>
 
 namespace WebCore {
 
@@ -46,14 +45,13 @@ public:
 
     void postMessage(PassRefPtr<SerializedScriptValue>, ExceptionCode&);
 
-    const AtomicString& name();
-    DOMWrapperWorld& world();
-    const UserMessageHandlerDescriptor& descriptor() const { return m_descriptor.get(); }
+    UserMessageHandlerDescriptor* descriptor() { return m_descriptor.get(); }
+    void invalidateDescriptor() { m_descriptor = nullptr; }
 
 private:
     UserMessageHandler(Frame&, UserMessageHandlerDescriptor&);
     
-    Ref<UserMessageHandlerDescriptor> m_descriptor;
+    RefPtr<UserMessageHandlerDescriptor> m_descriptor;
 };
 
 } // namespace WebCore
index 72f02be..723782c 100644 (file)
 
 namespace WebCore {
 
-UserMessageHandlerDescriptor::UserMessageHandlerDescriptor(const AtomicString& name, DOMWrapperWorld& world, Client& client)
+UserMessageHandlerDescriptor::UserMessageHandlerDescriptor(const AtomicString& name, DOMWrapperWorld& world)
     : m_name(name)
     , m_world(world)
-    , m_client(&client)
 {
 }
 
@@ -43,7 +42,7 @@ UserMessageHandlerDescriptor::~UserMessageHandlerDescriptor()
 {
 }
 
-const AtomicString& UserMessageHandlerDescriptor::name()
+const AtomicString& UserMessageHandlerDescriptor::name() const
 {
     return m_name;
 }
@@ -53,6 +52,11 @@ DOMWrapperWorld& UserMessageHandlerDescriptor::world()
     return m_world.get();
 }
 
+const DOMWrapperWorld& UserMessageHandlerDescriptor::world() const
+{
+    return m_world.get();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(USER_MESSAGE_HANDLERS)
index d202ec6..161403e 100644 (file)
 
 #if ENABLE(USER_MESSAGE_HANDLERS)
 
-#include <wtf/PassRefPtr.h>
+#include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
 #include <wtf/text/AtomicString.h>
 
 namespace WebCore {
 
-class Frame;
 class DOMWrapperWorld;
-class UserMessageHandler;
 class SerializedScriptValue;
+class UserMessageHandler;
 
 class UserMessageHandlerDescriptor : public RefCounted<UserMessageHandlerDescriptor> {
 public:
-    class Client {
-    public:
-        virtual ~Client() { }
-        virtual void didPostMessage(UserMessageHandler&, SerializedScriptValue*) = 0;
-    };
+    WEBCORE_EXPORT explicit UserMessageHandlerDescriptor(const AtomicString&, DOMWrapperWorld&);
+    WEBCORE_EXPORT virtual ~UserMessageHandlerDescriptor();
 
-    static Ref<UserMessageHandlerDescriptor> create(const AtomicString& name, DOMWrapperWorld& world, Client& client)
-    {
-        return adoptRef(*new UserMessageHandlerDescriptor(name, world, client));
-    }
-    WEBCORE_EXPORT ~UserMessageHandlerDescriptor();
-
-    WEBCORE_EXPORT const AtomicString& name();
+    WEBCORE_EXPORT const AtomicString& name() const;
     WEBCORE_EXPORT DOMWrapperWorld& world();
+    WEBCORE_EXPORT const DOMWrapperWorld& world() const;
 
-    Client* client() const { return m_client; }
-    void invalidateClient() { m_client = nullptr; }
+    virtual void didPostMessage(UserMessageHandler&, SerializedScriptValue*) = 0;
 
 private:
-    WEBCORE_EXPORT explicit UserMessageHandlerDescriptor(const AtomicString&, DOMWrapperWorld&, Client&);
-
     AtomicString m_name;
     Ref<DOMWrapperWorld> m_world;
-    Client* m_client;
 };
 
 } // namespace WebCore
index 0e0e3a1..7cef10c 100644 (file)
 #include "Frame.h"
 #include "Page.h"
 #include "UserContentController.h"
+#include "UserMessageHandler.h"
 
 namespace WebCore {
 
-UserMessageHandlersNamespace::UserMessageHandlersNamespace(Frame& frame)
+UserMessageHandlersNamespace::UserMessageHandlersNamespace(Frame& frame, UserContentProvider& userContentProvider)
     : FrameDestructionObserver(&frame)
+    , m_userContentProvider(userContentProvider)
 {
+    m_userContentProvider->registerForUserMessageHandlerInvalidation(*this);
 }
 
 UserMessageHandlersNamespace::~UserMessageHandlersNamespace()
 {
+    m_userContentProvider->unregisterForUserMessageHandlerInvalidation(*this);
+}
+
+void UserMessageHandlersNamespace::didInvalidate(UserContentProvider& provider)
+{
+    auto oldMap = WTFMove(m_messageHandlers);
+
+    provider.forEachUserMessageHandler([&](const UserMessageHandlerDescriptor& descriptor) {
+        auto userMessageHandler = oldMap.take(std::make_pair(descriptor.name(), const_cast<DOMWrapperWorld*>(&descriptor.world())));
+        if (userMessageHandler) {
+            m_messageHandlers.add(std::make_pair(descriptor.name(), const_cast<DOMWrapperWorld*>(&descriptor.world())), userMessageHandler);
+            return;
+        }
+    });
+
+    for (auto& userMessageHandler : oldMap.values())
+        userMessageHandler->invalidateDescriptor();
 }
 
 UserMessageHandler* UserMessageHandlersNamespace::handler(const AtomicString& name, DOMWrapperWorld& world)
 {
-    if (!frame())
+    Frame* frame = this->frame();
+    if (!frame)
         return nullptr;
 
-    Page* page = frame()->page();
+    Page* page = frame->page();
     if (!page)
         return nullptr;
-    
-    auto& descriptors = page->userContentProvider().userMessageHandlerDescriptors();
-    
-    RefPtr<UserMessageHandlerDescriptor> descriptor = descriptors.get(std::make_pair(name, &world));
-    if (!descriptor)
-        return nullptr;
 
-    for (auto& handler : m_messageHandlers) {
-        if (&handler->descriptor() == descriptor.get())
-            return &handler.get();
-    }
+    UserMessageHandler* handler = m_messageHandlers.get(std::pair<AtomicString, RefPtr<DOMWrapperWorld>>(name, &world));
+    if (handler)
+        return handler;
 
-    auto liveHandlers = descriptors.values();
-    m_messageHandlers.removeAllMatching([liveHandlers](const Ref<UserMessageHandler>& handler) {
-        for (const auto& liveHandler : liveHandlers) {
-            if (liveHandler.get() == &handler->descriptor())
-                return true;
-        }
-        return false;
+    page->userContentProvider().forEachUserMessageHandler([&](const UserMessageHandlerDescriptor& descriptor) {
+        if (descriptor.name() != name || &descriptor.world() != &world)
+            return;
+        
+        ASSERT(!handler);
+
+        auto addResult = m_messageHandlers.add(std::make_pair(descriptor.name(), const_cast<DOMWrapperWorld*>(&descriptor.world())), UserMessageHandler::create(*frame, const_cast<UserMessageHandlerDescriptor&>(descriptor)));
+        handler = addResult.iterator->value.get();
     });
 
-    m_messageHandlers.append(UserMessageHandler::create(*frame(), *descriptor));
-    return &m_messageHandlers.last().get();
+    return handler;
 }
 
 } // namespace WebCore
index 4eecb50..3403475 100644 (file)
 #if ENABLE(USER_MESSAGE_HANDLERS)
 
 #include "FrameDestructionObserver.h"
+#include "UserContentProvider.h"
 #include "UserMessageHandler.h"
+#include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
 #include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
 
 namespace WebCore {
 
@@ -41,11 +43,11 @@ class Frame;
 class UserMessageHandler;
 class DOMWrapperWorld;
 
-class UserMessageHandlersNamespace : public RefCounted<UserMessageHandlersNamespace>, public FrameDestructionObserver {
+class UserMessageHandlersNamespace : public RefCounted<UserMessageHandlersNamespace>, public FrameDestructionObserver, public UserContentProviderInvalidationClient {
 public:
-    static Ref<UserMessageHandlersNamespace> create(Frame& frame)
+    static Ref<UserMessageHandlersNamespace> create(Frame& frame, UserContentProvider& userContentProvider)
     {
-        return adoptRef(*new UserMessageHandlersNamespace(frame));
+        return adoptRef(*new UserMessageHandlersNamespace(frame, userContentProvider));
     }
 
     virtual ~UserMessageHandlersNamespace();
@@ -53,9 +55,13 @@ public:
     UserMessageHandler* handler(const AtomicString&, DOMWrapperWorld&);
 
 private:
-    explicit UserMessageHandlersNamespace(Frame&);
+    explicit UserMessageHandlersNamespace(Frame&, UserContentProvider&);
 
-    Vector<Ref<UserMessageHandler>> m_messageHandlers;
+    // UserContentProviderInvalidationClient
+    void didInvalidate(UserContentProvider&) override;
+
+    Ref<UserContentProvider> m_userContentProvider;
+    HashMap<std::pair<AtomicString, RefPtr<DOMWrapperWorld>>, RefPtr<UserMessageHandler>> m_messageHandlers;
 };
 
 } // namespace WebCore
index 2abd0ad..a1c6e14 100644 (file)
@@ -33,9 +33,9 @@
 
 namespace WebCore {
 
-WebKitNamespace::WebKitNamespace(Frame& frame)
+WebKitNamespace::WebKitNamespace(Frame& frame, UserContentProvider& userContentProvider)
     : DOMWindowProperty(&frame)
-    , m_messageHandlerNamespace(UserMessageHandlersNamespace::create(frame))
+    , m_messageHandlerNamespace(UserMessageHandlersNamespace::create(frame, userContentProvider))
 {
 }
 
index f85f419..fd02c64 100644 (file)
 namespace WebCore {
 
 class Frame;
+class UserContentProvider;
 class UserMessageHandlersNamespace;
 
 class WebKitNamespace : public DOMWindowProperty, public RefCounted<WebKitNamespace> {
 public:
-    static Ref<WebKitNamespace> create(Frame& frame)
+    static Ref<WebKitNamespace> create(Frame& frame, UserContentProvider& userContentProvider)
     {
-        return adoptRef(*new WebKitNamespace(frame));
+        return adoptRef(*new WebKitNamespace(frame, userContentProvider));
     }
 
     virtual ~WebKitNamespace();
@@ -49,7 +50,7 @@ public:
     UserMessageHandlersNamespace* messageHandlers();
 
 private:
-    explicit WebKitNamespace(Frame&);
+    explicit WebKitNamespace(Frame&, UserContentProvider&);
 
     Ref<UserMessageHandlersNamespace> m_messageHandlerNamespace;
 };
index 3e9663c..ad6a5bf 100644 (file)
@@ -1,3 +1,83 @@
+2016-04-03  Sam Weinig  <sam@webkit.org>
+
+        Add SPI to allow install script message handlers in isolated worlds
+        https://bugs.webkit.org/show_bug.cgi?id=156153
+
+        Reviewed by Anders Carlsson.
+
+        * Scripts/webkit/messages.py:
+        (headers_for_type):
+        * Shared/WebUserContentControllerDataTypes.cpp:
+        (WebKit::WebScriptMessageHandlerData::encode):
+        (WebKit::WebScriptMessageHandlerData::decode):
+        * Shared/WebUserContentControllerDataTypes.h:
+        Add WebKit::WebScriptMessageHandlerData, matching WebKit::WebUserScriptData and
+        WebKit::WebUserStyleSheetData.
+
+        * UIProcess/API/Cocoa/WKUserContentController.mm:
+        (-[WKUserContentController addScriptMessageHandler:name:]):
+        (-[WKUserContentController removeScriptMessageHandlerForName:]):
+        (-[WKUserContentController _removeAllUserStyleSheetsAssociatedWithUserContentWorld:]):
+        (-[WKUserContentController _addScriptMessageHandler:name:userContentWorld:]):
+        (-[WKUserContentController _removeScriptMessageHandlerForName:userContentWorld:]):
+        (-[WKUserContentController _removeAllScriptMessageHandlersAssociatedWithUserContentWorld:]):
+        * UIProcess/API/Cocoa/WKUserContentControllerPrivate.h:
+        Add SPI for adding and removing ScriptMessageHandlers associated with a world.
+
+        * UIProcess/UserContent/WebScriptMessageHandler.cpp:
+        (WebKit::WebScriptMessageHandler::create):
+        (WebKit::WebScriptMessageHandler::WebScriptMessageHandler):
+        (WebKit::WebScriptMessageHandlerHandle::encode): Deleted.
+        (WebKit::WebScriptMessageHandlerHandle::decode): Deleted.
+        * UIProcess/UserContent/WebScriptMessageHandler.h:
+        (WebKit::WebScriptMessageHandler::identifier):
+        (WebKit::WebScriptMessageHandler::name):
+        (WebKit::WebScriptMessageHandler::userContentWorld):
+        (WebKit::WebScriptMessageHandler::client):
+        (WebKit::WebScriptMessageHandler::handle): Deleted.
+        Add the world and move the data object to WebUserContentControllerDataTypes.h
+
+        * UIProcess/UserContent/WebUserContentControllerProxy.cpp:
+        (WebKit::WebUserContentControllerProxy::addProcess):
+        (WebKit::WebUserContentControllerProxy::addUserScriptMessageHandler):
+        (WebKit::WebUserContentControllerProxy::removeUserMessageHandlerForName):
+        (WebKit::WebUserContentControllerProxy::removeAllUserMessageHandlers):
+        * UIProcess/UserContent/WebUserContentControllerProxy.h:
+        Update for worlds, matching UserScript/UserStyleSheet model.
+
+        * WebProcess/UserContent/WebUserContentController.h:
+        * WebProcess/UserContent/WebUserContentController.cpp:
+        (WebKit::WebUserMessageHandlerDescriptorProxy::WebUserMessageHandlerDescriptorProxy):
+        Change to inherit directly from WebCore::UserMessageHandlerDescriptor.
+
+        (WebKit::WebUserContentController::addUserScriptMessageHandlers):
+        (WebKit::WebUserContentController::removeUserScriptMessageHandler):
+        (WebKit::WebUserContentController::removeAllUserScriptMessageHandlers):
+        (WebKit::WebUserContentController::addUserScriptMessageHandlerInternal):
+        (WebKit::WebUserContentController::removeUserScriptMessageHandlerInternal):
+        Add support for worlds, matching UserScript/UserStyleSheet model.
+
+        (WebKit::WebUserContentController::addUserStyleSheets):
+        Add missing call to invalidateInjectedStyleSheetCacheInAllFramesInAllPages()
+
+        (WebKit::WebUserContentController::removeAllUserStyleSheets):
+        Switch to only calling invalidateInjectedStyleSheetCacheInAllFramesInAllPages() once
+        after the loop and only if any stylesheets were removed.
+        
+        (WebKit::WebUserContentController::addUserStyleSheetInternal):
+        Remove call to invalidateInjectedStyleSheetCacheInAllFramesInAllPages(), make
+        callers call it. This allows us to avoid calling it repeatedly in removeAllUserStyleSheets().
+
+        (WebKit::WebUserContentController::addUserStyleSheet):
+        Call invalidateInjectedStyleSheetCacheInAllFramesInAllPages() explicitly since it
+        is no longer called in addUserStyleSheetInternal().
+
+        (WebKit::WebUserContentController::forEachUserMessageHandler):
+        Implement by iterating the m_userMessageHandlers map.
+
+        * WebProcess/UserContent/WebUserContentController.messages.in:
+        Update for worlds, matching UserScript/UserStyleSheet model.
+
 2016-04-04  Joonghun Park  <jh718.park@samsung.com>
 
         [EFL] Fix build break since r198800
index 902926e..c42144e 100644 (file)
@@ -377,9 +377,9 @@ def headers_for_type(type):
         'WebKit::WebMouseEvent': ['"WebEvent.h"'],
         'WebKit::WebTouchEvent': ['"WebEvent.h"'],
         'WebKit::WebWheelEvent': ['"WebEvent.h"'],
-        'WebKit::WebScriptMessageHandlerHandle': ['"WebScriptMessageHandler.h"'],
         'struct WebKit::WebUserScriptData': ['"WebUserContentControllerDataTypes.h"'],
         'struct WebKit::WebUserStyleSheetData': ['"WebUserContentControllerDataTypes.h"'],
+        'struct WebKit::WebScriptMessageHandlerData': ['"WebUserContentControllerDataTypes.h"'],
         'std::chrono::system_clock::time_point': ['<chrono>'],
     }
 
index 262ca81..f6542bb 100644 (file)
@@ -66,4 +66,24 @@ bool WebUserStyleSheetData::decode(IPC::ArgumentDecoder& decoder, WebUserStyleSh
     return true;
 }
 
+
+void WebScriptMessageHandlerData::encode(IPC::ArgumentEncoder& encoder) const
+{
+    encoder << identifier;
+    encoder << worldIdentifier;
+    encoder << name;
+}
+
+bool WebScriptMessageHandlerData::decode(IPC::ArgumentDecoder& decoder, WebScriptMessageHandlerData& data)
+{
+    if (!decoder.decode(data.identifier))
+        return false;
+    if (!decoder.decode(data.worldIdentifier))
+        return false;
+    if (!decoder.decode(data.name))
+        return false;
+
+    return true;
+}
+
 } // namespace WebKit
index 36b4ac6..0b75419 100644 (file)
@@ -54,6 +54,15 @@ struct WebUserStyleSheetData {
     WebCore::UserStyleSheet userStyleSheet;
 };
 
+struct WebScriptMessageHandlerData {
+    void encode(IPC::ArgumentEncoder&) const;
+    static bool decode(IPC::ArgumentDecoder&, WebScriptMessageHandlerData&);
+
+    uint64_t identifier;
+    uint64_t worldIdentifier;
+    String name;
+};
+
 } // namespace WebKit
 
 #endif // WebUserContentControllerDataTypes_h
index c20f59e..566814c 100644 (file)
@@ -29,6 +29,7 @@
 #if WK_API_ENABLED
 
 #import "APISerializedScriptValue.h"
+#import "APIUserContentWorld.h"
 #import "WKFrameInfoInternal.h"
 #import "WKNSArray.h"
 #import "WKScriptMessageHandler.h"
@@ -118,14 +119,14 @@ private:
 
 - (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name
 {
-    RefPtr<WebKit::WebScriptMessageHandler> handler = WebKit::WebScriptMessageHandler::create(std::make_unique<ScriptMessageHandlerDelegate>(self, scriptMessageHandler, name), name);
+    auto handler = WebKit::WebScriptMessageHandler::create(std::make_unique<ScriptMessageHandlerDelegate>(self, scriptMessageHandler, name), name, API::UserContentWorld::normalWorld());
     if (!_userContentControllerProxy->addUserScriptMessageHandler(handler.get()))
         [NSException raise:NSInvalidArgumentException format:@"Attempt to add script message handler with name '%@' when one already exists.", name];
 }
 
 - (void)removeScriptMessageHandlerForName:(NSString *)name
 {
-    _userContentControllerProxy->removeUserMessageHandlerForName(name);
+    _userContentControllerProxy->removeUserMessageHandlerForName(name, API::UserContentWorld::normalWorld());
 }
 
 #pragma mark WKObject protocol implementation
@@ -195,6 +196,23 @@ private:
     _userContentControllerProxy->removeAllUserStyleSheets(*userContentWorld->_userContentWorld);
 }
 
+- (void)_addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name userContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    auto handler = WebKit::WebScriptMessageHandler::create(std::make_unique<ScriptMessageHandlerDelegate>(self, scriptMessageHandler, name), name, *userContentWorld->_userContentWorld);
+    if (!_userContentControllerProxy->addUserScriptMessageHandler(handler.get()))
+        [NSException raise:NSInvalidArgumentException format:@"Attempt to add script message handler with name '%@' when one already exists.", name];
+}
+
+- (void)_removeScriptMessageHandlerForName:(NSString *)name userContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    _userContentControllerProxy->removeUserMessageHandlerForName(name, *userContentWorld->_userContentWorld);
+}
+
+- (void)_removeAllScriptMessageHandlersAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    _userContentControllerProxy->removeAllUserMessageHandlers(*userContentWorld->_userContentWorld);
+}
+
 @end
 
 #endif
index cd0e994..ed94da3 100644 (file)
 - (void)_removeAllUserStyleSheets WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
 - (void)_removeAllUserStyleSheetsAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
 
+- (void)_addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name userContentWorld:(_WKUserContentWorld *)userContentWorld;
+- (void)_removeScriptMessageHandlerForName:(NSString *)name userContentWorld:(_WKUserContentWorld *)userContentWorld;
+- (void)_removeAllScriptMessageHandlersAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld;
+
 @end
 
 #endif
index bfacf04..91e5cea 100644 (file)
 #include "config.h"
 #include "WebScriptMessageHandler.h"
 
-#include "ArgumentCoders.h"
+#include "APIUserContentWorld.h"
 
 namespace WebKit {
 
-void WebScriptMessageHandlerHandle::encode(IPC::ArgumentEncoder& encoder) const
-{
-    encoder << identifier;
-    encoder << name;
-}
-
-bool WebScriptMessageHandlerHandle::decode(IPC::ArgumentDecoder& decoder, WebScriptMessageHandlerHandle& handle)
-{
-    if (!decoder.decode(handle.identifier))
-        return false;
-
-    if (!decoder.decode(handle.name))
-        return false;
-
-    return true;
-}
-
 static uint64_t generateIdentifier()
 {
     static uint64_t identifier;
@@ -54,15 +37,16 @@ static uint64_t generateIdentifier()
     return ++identifier;
 }
 
-PassRefPtr<WebScriptMessageHandler> WebScriptMessageHandler::create(std::unique_ptr<Client> client, const String& name)
+Ref<WebScriptMessageHandler> WebScriptMessageHandler::create(std::unique_ptr<Client> client, const String& name, API::UserContentWorld& world)
 {
-    return adoptRef(new WebScriptMessageHandler(WTFMove(client), name));
+    return adoptRef(*new WebScriptMessageHandler(WTFMove(client), name, world));
 }
 
-WebScriptMessageHandler::WebScriptMessageHandler(std::unique_ptr<Client> client, const String& name)
+WebScriptMessageHandler::WebScriptMessageHandler(std::unique_ptr<Client> client, const String& name, API::UserContentWorld& world)
     : m_identifier(generateIdentifier())
     , m_client(WTFMove(client))
     , m_name(name)
+    , m_world(world)
 {
 }
 
index 22d73bb..96959a8 100644 (file)
 #ifndef WebScriptMessageHandler_h
 #define WebScriptMessageHandler_h
 
-#include <wtf/PassRefPtr.h>
+#include "WebUserContentControllerDataTypes.h"
+#include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/WTFString.h>
 
-namespace IPC {
-class ArgumentDecoder;
-class ArgumentEncoder;
-}
-
 namespace WebCore {
 struct SecurityOriginData;
 class SerializedScriptValue;
 }
 
+namespace API {
+class UserContentWorld;
+}
+
 namespace WebKit {
 
 class WebPageProxy;
 class WebFrameProxy;
 
-struct WebScriptMessageHandlerHandle {
-    void encode(IPC::ArgumentEncoder&) const;
-    static bool decode(IPC::ArgumentDecoder&, WebScriptMessageHandlerHandle&);
-
-    uint64_t identifier;
-    String name;
-};
-
 class WebScriptMessageHandler : public RefCounted<WebScriptMessageHandler> {
 public:
     class Client {
@@ -61,23 +53,25 @@ public:
         virtual void didPostMessage(WebPageProxy&, WebFrameProxy&, const WebCore::SecurityOriginData&, WebCore::SerializedScriptValue&) = 0;
     };
 
-    static PassRefPtr<WebScriptMessageHandler> create(std::unique_ptr<Client>, const String& name);    
+    static Ref<WebScriptMessageHandler> create(std::unique_ptr<Client>, const String& name, API::UserContentWorld&);
     virtual ~WebScriptMessageHandler();
 
-    WebScriptMessageHandlerHandle handle() { return { m_identifier, m_name }; }
-
     uint64_t identifier() const { return m_identifier; }
     String name() const { return m_name; }
 
+    const API::UserContentWorld& userContentWorld() const { return m_world; }
+    API::UserContentWorld& userContentWorld() { return m_world; }
+
     Client& client() const { return *m_client; }
 
 private:
-    WebScriptMessageHandler(std::unique_ptr<Client>, const String&);
+    WebScriptMessageHandler(std::unique_ptr<Client>, const String&, API::UserContentWorld&);
     
     uint64_t m_identifier;
 
     std::unique_ptr<Client> m_client;
     String m_name;
+    Ref<API::UserContentWorld> m_world;
 };
 
 } // namespace API
index 3434716..b0a933c 100644 (file)
@@ -91,10 +91,10 @@ void WebUserContentControllerProxy::addProcess(WebProcessProxy& webProcessProxy)
         userStyleSheets.append({ userStyleSheet->identifier(), userStyleSheet->userContentWorld().identifier(), userStyleSheet->userStyleSheet() });
     webProcessProxy.connection()->send(Messages::WebUserContentController::AddUserStyleSheets(userStyleSheets), m_identifier);
 
-    Vector<WebScriptMessageHandlerHandle> messageHandlerHandles;
+    Vector<WebScriptMessageHandlerData> messageHandlers;
     for (auto& handler : m_scriptMessageHandlers.values())
-        messageHandlerHandles.append(handler->handle());
-    webProcessProxy.connection()->send(Messages::WebUserContentController::AddUserScriptMessageHandlers(messageHandlerHandles), m_identifier);
+        messageHandlers.append({ handler->identifier(), handler->userContentWorld().identifier(), handler->name() });
+    webProcessProxy.connection()->send(Messages::WebUserContentController::AddUserScriptMessageHandlers(messageHandlers), m_identifier);
 
 #if ENABLE(CONTENT_EXTENSIONS)
     Vector<std::pair<String, WebCompiledContentExtensionData>> userContentExtensions;
@@ -270,33 +270,57 @@ void WebUserContentControllerProxy::removeAllUserStyleSheets()
     removeUserContentWorldUses(worlds);
 }
 
-bool WebUserContentControllerProxy::addUserScriptMessageHandler(WebScriptMessageHandler* handler)
+bool WebUserContentControllerProxy::addUserScriptMessageHandler(WebScriptMessageHandler& handler)
 {
+    Ref<API::UserContentWorld> world = handler.userContentWorld();
+
     for (auto& existingHandler : m_scriptMessageHandlers.values()) {
-        if (existingHandler->name() == handler->name())
+        if (existingHandler->name() == handler.name() && &existingHandler->userContentWorld() == world.ptr())
             return false;
     }
 
-    m_scriptMessageHandlers.add(handler->identifier(), handler);
+    addUserContentWorldUse(world.get());
+
+    m_scriptMessageHandlers.add(handler.identifier(), &handler);
 
     for (WebProcessProxy* process : m_processes)
-        process->connection()->send(Messages::WebUserContentController::AddUserScriptMessageHandlers({ handler->handle() }), m_identifier);
+        process->connection()->send(Messages::WebUserContentController::AddUserScriptMessageHandlers({ { handler.identifier(), world->identifier(), handler.name() } }), m_identifier);
     
     return true;
 }
 
-void WebUserContentControllerProxy::removeUserMessageHandlerForName(const String& name)
+void WebUserContentControllerProxy::removeUserMessageHandlerForName(const String& name, API::UserContentWorld& world)
 {
     for (auto it = m_scriptMessageHandlers.begin(), end = m_scriptMessageHandlers.end(); it != end; ++it) {
-        if (it->value->name() == name) {
+        if (it->value->name() == name && &it->value->userContentWorld() == &world) {
             for (WebProcessProxy* process : m_processes)
-                process->connection()->send(Messages::WebUserContentController::RemoveUserScriptMessageHandler(it->value->identifier()), m_identifier);
+                process->connection()->send(Messages::WebUserContentController::RemoveUserScriptMessageHandler(world.identifier(), it->value->identifier()), m_identifier);
+
             m_scriptMessageHandlers.remove(it);
+
+            removeUserContentWorldUses(world, 1);
             return;
         }
     }
 }
 
+void WebUserContentControllerProxy::removeAllUserMessageHandlers(API::UserContentWorld& world)
+{
+    for (WebProcessProxy* process : m_processes)
+        process->connection()->send(Messages::WebUserContentController::RemoveAllUserScriptMessageHandlers({ world.identifier() }), m_identifier);
+
+    unsigned numberRemoved = 0;
+    m_scriptMessageHandlers.removeIf([&](HashMap<uint64_t, RefPtr<WebScriptMessageHandler>>::KeyValuePairType& entry) {
+        if (&entry.value->userContentWorld() == &world) {
+            ++numberRemoved;
+            return true;
+        }
+        return false;
+    });
+
+    removeUserContentWorldUses(world, numberRemoved);
+}
+
 void WebUserContentControllerProxy::didPostMessage(IPC::Connection& connection, uint64_t pageID, uint64_t frameID, const WebCore::SecurityOriginData& securityOrigin, uint64_t messageHandlerID, const IPC::DataReference& dataReference)
 {
     WebPageProxy* page = WebProcessProxy::webPage(pageID);
@@ -315,8 +339,7 @@ void WebUserContentControllerProxy::didPostMessage(IPC::Connection& connection,
     if (!handler)
         return;
 
-    handler->client().didPostMessage(*page, *frame, securityOrigin,
-        WebCore::SerializedScriptValue::adopt(dataReference.vector()));
+    handler->client().didPostMessage(*page, *frame, securityOrigin, WebCore::SerializedScriptValue::adopt(dataReference.vector()));
 }
 
 #if ENABLE(CONTENT_EXTENSIONS)
index 60c8de0..0ca35eb 100644 (file)
@@ -88,8 +88,9 @@ public:
     void removeAllUserContent(API::UserContentWorld&);
 
     // Returns false if there was a name conflict.
-    bool addUserScriptMessageHandler(WebScriptMessageHandler*);
-    void removeUserMessageHandlerForName(const String&);
+    bool addUserScriptMessageHandler(WebScriptMessageHandler&);
+    void removeUserMessageHandlerForName(const String&, API::UserContentWorld&);
+    void removeAllUserMessageHandlers(API::UserContentWorld&);
 
 #if ENABLE(CONTENT_EXTENSIONS)
     void addUserContentExtension(API::UserContentExtension&);
index 3e4006f..3dd20a2 100644 (file)
@@ -171,6 +171,8 @@ void WebUserContentController::addUserStyleSheets(const Vector<WebUserStyleSheet
         UserStyleSheet sheet = userStyleSheetData.userStyleSheet;
         addUserStyleSheetInternal(*it->value.first, userStyleSheetData.identifier, WTFMove(sheet));
     }
+
+    invalidateInjectedStyleSheetCacheInAllFramesInAllPages();
 }
 
 void WebUserContentController::removeUserStyleSheet(uint64_t worldIdentifier, uint64_t userStyleSheetIdentifier)
@@ -186,6 +188,7 @@ void WebUserContentController::removeUserStyleSheet(uint64_t worldIdentifier, ui
 
 void WebUserContentController::removeAllUserStyleSheets(const Vector<uint64_t>& worldIdentifiers)
 {
+    bool sheetsChanged = false;
     for (auto& worldIdentifier : worldIdentifiers) {
         auto it = worldMap().find(worldIdentifier);
         if (it == worldMap().end()) {
@@ -193,25 +196,38 @@ void WebUserContentController::removeAllUserStyleSheets(const Vector<uint64_t>&
             return;
         }
 
-        removeUserStyleSheets(*it->value.first);
+        if (m_userStyleSheets.remove(it->value.first.get()))
+            sheetsChanged = true;
     }
+
+    if (sheetsChanged)
+        invalidateInjectedStyleSheetCacheInAllFramesInAllPages();
 }
 
 #if ENABLE(USER_MESSAGE_HANDLERS)
-class WebUserMessageHandlerDescriptorProxy : public RefCounted<WebUserMessageHandlerDescriptorProxy>, public WebCore::UserMessageHandlerDescriptor::Client {
+class WebUserMessageHandlerDescriptorProxy : public WebCore::UserMessageHandlerDescriptor {
 public:
-    static PassRefPtr<WebUserMessageHandlerDescriptorProxy> create(WebUserContentController* controller, const String& name, uint64_t identifier)
+    static PassRefPtr<WebUserMessageHandlerDescriptorProxy> create(WebUserContentController* controller, const String& name, InjectedBundleScriptWorld& world, uint64_t identifier)
     {
-        return adoptRef(new WebUserMessageHandlerDescriptorProxy(controller, name, identifier));
+        return adoptRef(new WebUserMessageHandlerDescriptorProxy(controller, name, world, identifier));
     }
 
     virtual ~WebUserMessageHandlerDescriptorProxy()
     {
-        m_descriptor->invalidateClient();
     }
 
-    // WebCore::UserMessageHandlerDescriptor::Client
-    virtual void didPostMessage(WebCore::UserMessageHandler& handler, WebCore::SerializedScriptValue* value)
+    uint64_t identifier() { return m_identifier; }
+
+private:
+    WebUserMessageHandlerDescriptorProxy(WebUserContentController* controller, const String& name, InjectedBundleScriptWorld& world, uint64_t identifier)
+        : WebCore::UserMessageHandlerDescriptor(name, world.coreWorld())
+        , m_controller(controller)
+        , m_identifier(identifier)
+    {
+    }
+
+    // WebCore::UserMessageHandlerDescriptor
+    void didPostMessage(WebCore::UserMessageHandler& handler, WebCore::SerializedScriptValue* value) override
     {
         WebCore::Frame* frame = handler.frame();
         if (!frame)
@@ -228,54 +244,99 @@ public:
         WebProcess::singleton().parentProcessConnection()->send(Messages::WebUserContentControllerProxy::DidPostMessage(webPage->pageID(), webFrame->frameID(), SecurityOriginData::fromFrame(frame), m_identifier, IPC::DataReference(value->data())), m_controller->identifier());
     }
 
-    WebCore::UserMessageHandlerDescriptor& descriptor() { return *m_descriptor; }
-    uint64_t identifier() { return m_identifier; }
-
-private:
-    WebUserMessageHandlerDescriptorProxy(WebUserContentController* controller, const String& name, uint64_t identifier)
-        : m_controller(controller)
-        , m_descriptor(UserMessageHandlerDescriptor::create(name, mainThreadNormalWorld(), *this))
-        , m_identifier(identifier)
-    {
-    }
-
     RefPtr<WebUserContentController> m_controller;
-    RefPtr<WebCore::UserMessageHandlerDescriptor> m_descriptor;
     uint64_t m_identifier;
 };
 #endif
 
-void WebUserContentController::addUserScriptMessageHandlers(const Vector<WebScriptMessageHandlerHandle>& scriptMessageHandlers)
+void WebUserContentController::addUserScriptMessageHandlers(const Vector<WebScriptMessageHandlerData>& scriptMessageHandlers)
 {
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    for (auto& handle : scriptMessageHandlers) {
-        RefPtr<WebUserMessageHandlerDescriptorProxy> descriptor = WebUserMessageHandlerDescriptorProxy::create(this, handle.name, handle.identifier);
-
-        m_userMessageHandlerDescriptors.add(descriptor->identifier(), descriptor);
+    for (auto& handler : scriptMessageHandlers) {
+        auto it = worldMap().find(handler.worldIdentifier);
+        if (it == worldMap().end()) {
+            WTFLogAlways("Trying to add a UserScriptMessageHandler to a UserContentWorld (id=%" PRIu64 ") that does not exist.", handler.worldIdentifier);
+            continue;
+        }
 
-        auto& coreDescriptor = descriptor->descriptor();
-        m_userMessageHandlerDescriptorsMap.add(std::make_pair(coreDescriptor.name(), &coreDescriptor.world()), &coreDescriptor);
+        addUserScriptMessageHandlerInternal(*it->value.first, handler.identifier, handler.name);
     }
 #else
     UNUSED_PARAM(scriptMessageHandlers);
 #endif
 }
 
-void WebUserContentController::removeUserScriptMessageHandler(uint64_t identifier)
+void WebUserContentController::removeUserScriptMessageHandler(uint64_t worldIdentifier, uint64_t userScriptMessageHandlerIdentifier)
 {
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    auto it = m_userMessageHandlerDescriptors.find(identifier);
-    ASSERT(it != m_userMessageHandlerDescriptors.end());
+    auto it = worldMap().find(worldIdentifier);
+    if (it == worldMap().end()) {
+        WTFLogAlways("Trying to remove a UserScriptMessageHandler from a UserContentWorld (id=%" PRIu64 ") that does not exist.", worldIdentifier);
+        return;
+    }
 
-    auto& coreDescriptor = it->value->descriptor();
-    m_userMessageHandlerDescriptorsMap.remove(std::make_pair(coreDescriptor.name(), &coreDescriptor.world()));
+    removeUserScriptMessageHandlerInternal(*it->value.first, userScriptMessageHandlerIdentifier);
+#else
+    UNUSED_PARAM(worldIdentifier);
+    UNUSED_PARAM(userScriptMessageHandlerIdentifier);
+#endif
+}
 
-    m_userMessageHandlerDescriptors.remove(it);
+void WebUserContentController::removeAllUserScriptMessageHandlers(const Vector<uint64_t>& worldIdentifiers)
+{
+#if ENABLE(USER_MESSAGE_HANDLERS)
+    bool userMessageHandlersChanged = false;
+    for (auto& worldIdentifier : worldIdentifiers) {
+        auto it = worldMap().find(worldIdentifier);
+        if (it == worldMap().end()) {
+            WTFLogAlways("Trying to remove all UserScriptMessageHandler from a UserContentWorld (id=%" PRIu64 ") that does not exist.", worldIdentifier);
+            return;
+        }
+
+        if (m_userMessageHandlers.remove(it->value.first.get()))
+            userMessageHandlersChanged = true;
+    }
+
+    if (userMessageHandlersChanged)
+        invalidateAllRegisteredUserMessageHandlerInvalidationClients();
 #else
-    UNUSED_PARAM(identifier);
+    UNUSED_PARAM(worldIdentifiers);
 #endif
 }
 
+#if ENABLE(USER_MESSAGE_HANDLERS)
+void WebUserContentController::addUserScriptMessageHandlerInternal(InjectedBundleScriptWorld& world, uint64_t userScriptMessageHandlerIdentifier, const String& name)
+{
+    auto& messageHandlersInWorld = m_userMessageHandlers.ensure(&world, [] { return Vector<RefPtr<WebUserMessageHandlerDescriptorProxy>>(); }).iterator->value;
+    messageHandlersInWorld.append(WebUserMessageHandlerDescriptorProxy::create(this, name, world, userScriptMessageHandlerIdentifier));
+}
+
+void WebUserContentController::removeUserScriptMessageHandlerInternal(InjectedBundleScriptWorld& world, uint64_t userScriptMessageHandlerIdentifier)
+{
+    auto it = m_userMessageHandlers.find(&world);
+    if (it == m_userMessageHandlers.end())
+        return;
+
+    auto& userMessageHandlers = it->value;
+
+    bool userMessageHandlersChanged = false;
+    for (int i = userMessageHandlers.size() - 1; i >= 0; --i) {
+        if (userMessageHandlers[i]->identifier() == userScriptMessageHandlerIdentifier) {
+            userMessageHandlers.remove(i);
+            userMessageHandlersChanged = true;
+        }
+    }
+
+    if (!userMessageHandlersChanged)
+        return;
+
+    if (userMessageHandlers.isEmpty())
+        m_userMessageHandlers.remove(it);
+
+    invalidateAllRegisteredUserMessageHandlerInvalidationClients();
+}
+#endif
+
 #if ENABLE(CONTENT_EXTENSIONS)
 void WebUserContentController::addUserContentExtensions(const Vector<std::pair<String, WebCompiledContentExtensionData>>& userContentExtensions)
 {
@@ -298,8 +359,6 @@ void WebUserContentController::removeAllUserContentExtensions()
 }
 #endif
 
-
-
 void WebUserContentController::addUserScriptInternal(InjectedBundleScriptWorld& world, uint64_t userScriptIdentifier, UserScript&& userScript)
 {
     auto& scriptsInWorld = m_userScripts.ensure(&world, [] { return Vector<std::pair<uint64_t, WebCore::UserScript>>(); }).iterator->value;
@@ -352,13 +411,12 @@ void WebUserContentController::addUserStyleSheetInternal(InjectedBundleScriptWor
 {
     auto& styleSheetsInWorld = m_userStyleSheets.ensure(&world, [] { return Vector<std::pair<uint64_t, WebCore::UserStyleSheet>>(); }).iterator->value;
     styleSheetsInWorld.append(std::make_pair(userStyleSheetIdentifier, WTFMove(userStyleSheet)));
-
-    invalidateInjectedStyleSheetCacheInAllFramesInAllPages();
 }
 
 void WebUserContentController::addUserStyleSheet(InjectedBundleScriptWorld& world, UserStyleSheet&& userStyleSheet)
 {
     addUserStyleSheetInternal(world, 0, WTFMove(userStyleSheet));
+    invalidateInjectedStyleSheetCacheInAllFramesInAllPages();
 }
 
 void WebUserContentController::removeUserStyleSheetWithURL(InjectedBundleScriptWorld& world, const URL& url)
@@ -446,4 +504,14 @@ void WebUserContentController::forEachUserStyleSheet(const std::function<void(co
     }
 }
 
+#if ENABLE(USER_MESSAGE_HANDLERS)
+void WebUserContentController::forEachUserMessageHandler(const std::function<void(const WebCore::UserMessageHandlerDescriptor&)>& functor) const
+{
+    for (const auto& userMessageHandlerVector : m_userMessageHandlers.values()) {
+        for (const auto& userMessageHandler : userMessageHandlerVector)
+            functor(*userMessageHandler.get());
+    }
+}
+#endif
+
 } // namespace WebKit
index 90525b4..dab0cd0 100644 (file)
@@ -46,10 +46,7 @@ namespace WebKit {
 
 class InjectedBundleScriptWorld;
 class WebCompiledContentExtensionData;
-
-#if ENABLE(USER_MESSAGE_HANDLERS)
 class WebUserMessageHandlerDescriptorProxy;
-#endif
 
 class WebUserContentController final : public WebCore::UserContentProvider, private IPC::MessageReceiver {
 public:
@@ -73,7 +70,7 @@ private:
     void forEachUserScript(const std::function<void(WebCore::DOMWrapperWorld&, const WebCore::UserScript&)>&) const override;
     void forEachUserStyleSheet(const std::function<void(const WebCore::UserStyleSheet&)>&) const override;
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    const WebCore::UserMessageHandlerDescriptorMap& userMessageHandlerDescriptors() const override { return m_userMessageHandlerDescriptorsMap; }
+    void forEachUserMessageHandler(const std::function<void(const WebCore::UserMessageHandlerDescriptor&)>&) const override;
 #endif
 #if ENABLE(CONTENT_EXTENSIONS)
     WebCore::ContentExtensions::ContentExtensionsBackend& userContentExtensionBackend() override { return m_contentExtensionBackend; }
@@ -93,8 +90,9 @@ private:
     void removeUserStyleSheet(uint64_t worldIdentifier, uint64_t userScriptIdentifier);
     void removeAllUserStyleSheets(const Vector<uint64_t>&);
 
-    void addUserScriptMessageHandlers(const Vector<WebScriptMessageHandlerHandle>&);
-    void removeUserScriptMessageHandler(uint64_t);
+    void addUserScriptMessageHandlers(const Vector<WebScriptMessageHandlerData>&);
+    void removeUserScriptMessageHandler(uint64_t worldIdentifier, uint64_t userScriptIdentifier);
+    void removeAllUserScriptMessageHandlers(const Vector<uint64_t>&);
 
 #if ENABLE(CONTENT_EXTENSIONS)
     void addUserContentExtensions(const Vector<std::pair<String, WebCompiledContentExtensionData>>&);
@@ -102,12 +100,14 @@ private:
     void removeAllUserContentExtensions();
 #endif
 
-
     void addUserScriptInternal(InjectedBundleScriptWorld&, uint64_t userScriptIdentifier, WebCore::UserScript&&);
     void removeUserScriptInternal(InjectedBundleScriptWorld&, uint64_t userScriptIdentifier);
     void addUserStyleSheetInternal(InjectedBundleScriptWorld&, uint64_t userStyleSheetIdentifier, WebCore::UserStyleSheet&&);
     void removeUserStyleSheetInternal(InjectedBundleScriptWorld&, uint64_t userStyleSheetIdentifier);
-
+#if ENABLE(USER_MESSAGE_HANDLERS)
+    void addUserScriptMessageHandlerInternal(InjectedBundleScriptWorld&, uint64_t userScriptMessageHandlerIdentifier, const String& name);
+    void removeUserScriptMessageHandlerInternal(InjectedBundleScriptWorld&, uint64_t userScriptMessageHandlerIdentifier);
+#endif
 
     uint64_t m_identifier;
 
@@ -118,8 +118,8 @@ private:
     WorldToUserStyleSheetMap m_userStyleSheets;
 
 #if ENABLE(USER_MESSAGE_HANDLERS)
-    HashMap<uint64_t, RefPtr<WebUserMessageHandlerDescriptorProxy>> m_userMessageHandlerDescriptors;
-    WebCore::UserMessageHandlerDescriptorMap m_userMessageHandlerDescriptorsMap;
+    typedef HashMap<RefPtr<InjectedBundleScriptWorld>, Vector<RefPtr<WebUserMessageHandlerDescriptorProxy>>> WorldToUserMessageHandlerVectorMap;
+    WorldToUserMessageHandlerVectorMap m_userMessageHandlers;
 #endif
 #if ENABLE(CONTENT_EXTENSIONS)
     WebCore::ContentExtensions::ContentExtensionsBackend m_contentExtensionBackend;
index fa25c7a..e434e20 100644 (file)
@@ -35,8 +35,9 @@ messages -> WebUserContentController {
     RemoveUserStyleSheet(uint64_t worldIdentifier, uint64_t identifier);
     RemoveAllUserStyleSheets(Vector<uint64_t> worldIdentifiers);
 
-    AddUserScriptMessageHandlers(Vector<WebKit::WebScriptMessageHandlerHandle> scriptMessageHandlers);
-    RemoveUserScriptMessageHandler(uint64_t identifier);
+    AddUserScriptMessageHandlers(Vector<struct WebKit::WebScriptMessageHandlerData> scriptMessageHandlers);
+    RemoveUserScriptMessageHandler(uint64_t worldIdentifier, uint64_t identifier);
+    RemoveAllUserScriptMessageHandlers(Vector<uint64_t> worldIdentifiers);
 
 #if ENABLE(CONTENT_EXTENSIONS)
     AddUserContentExtensions(Vector<std::pair<String, WebKit::WebCompiledContentExtensionData>> userContentFilters);
index f0adc9d..df56fe6 100644 (file)
@@ -1,3 +1,13 @@
+2016-04-03  Sam Weinig  <sam@webkit.org>
+
+        Add SPI to allow install script message handlers in isolated worlds
+        https://bugs.webkit.org/show_bug.cgi?id=156153
+
+        Reviewed by Anders Carlsson.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm:
+        Add new test, WKUserContentController.ScriptMessageHandlerBasicPostIsolatedWorld
+
 2016-04-04  Jiewen Tan  <jiewen_tan@apple.com>
 
         Build fix for r198956.
index 095f6e7..0b0c733 100644 (file)
@@ -95,6 +95,55 @@ TEST(WKUserContentController, ScriptMessageHandlerBasicPost)
     EXPECT_WK_STREQ(@"Hello", (NSString *)[lastScriptMessage body]);
 }
 
+TEST(WKUserContentController, ScriptMessageHandlerBasicPostIsolatedWorld)
+{
+    RetainPtr<_WKUserContentWorld> world = adoptNS([_WKUserContentWorld worldWithName:@"TestWorld"]);
+
+    RetainPtr<ScriptMessageHandler> handler = adoptNS([[ScriptMessageHandler alloc] init]);
+    RetainPtr<WKUserScript> userScript = adoptNS([[WKUserScript alloc] _initWithSource:@"window.webkit.messageHandlers.testHandler.postMessage('Hello')" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [[configuration userContentController] _addScriptMessageHandler:handler.get() name:@"testHandler" userContentWorld:world.get()];
+    [[configuration userContentController] addUserScript:userScript.get()];
+
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    RetainPtr<SimpleNavigationDelegate> delegate = adoptNS([[SimpleNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+
+    isDoneWithNavigation = false;
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&receivedScriptMessage);
+    receivedScriptMessage = false;
+
+    EXPECT_WK_STREQ(@"Hello", (NSString *)[lastScriptMessage body]);
+
+    if (!isDoneWithNavigation)
+        TestWebKitAPI::Util::run(&isDoneWithNavigation);
+
+    __block bool isDoneEvaluatingScript = false;
+    __block NSString *resultValue = @"";
+    [webView evaluateJavaScript:
+        @"var result;"
+         "if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.testHandler) {"
+         "    result = { 'result': 'FAIL' };"
+         "} else {"
+         "    result = { 'result': 'PASS' };"
+         "} " 
+         "result;"
+         completionHandler:^(id value, NSError *error) {
+            resultValue = [((NSDictionary *)value)[@"result"] copy];
+            isDoneEvaluatingScript = true;
+        }];
+
+    TestWebKitAPI::Util::run(&isDoneEvaluatingScript);
+
+    EXPECT_WK_STREQ(@"PASS", resultValue);
+}
+
 TEST(WKUserContentController, ScriptMessageHandlerBasicRemove)
 {
     RetainPtr<ScriptMessageHandler> handler = adoptNS([[ScriptMessageHandler alloc] init]);