Title: [197868] trunk
Revision
197868
Author
[email protected]
Date
2016-03-09 11:56:41 -0800 (Wed, 09 Mar 2016)

Log Message

Removing and re-adding a script message handler with the same name results in an unusable message handler
https://bugs.webkit.org/show_bug.cgi?id=155223

Reviewed by Sam Weinig.
Source/WebCore:


New API test: WKUserContentController.ScriptMessageHandlerReplaceWithSameName.

* page/UserMessageHandler.h:
(WebCore::UserMessageHandler::descriptor):
* page/UserMessageHandlersNamespace.cpp:
(WebCore::UserMessageHandlersNamespace::handler):
This lazy removal mechanism combined with the fact that we only compare
handler name and world makes it such that m_messageHandlers could have
a stale UserMessageHandler with a UserMessageHandlerDescriptor that differed
only in client.

It is safe to compare the descriptors by pointer instead because m_messageHandler
holds a strong reference to its UserMessageHandlerDescriptors, and this will ensure
that the add-remove-add path (with identical name and world) causes a new
UserContentController to be created.

We also now clean up any stale UserMessageHandlers whenever we're about to
add a new one, by removing any which the UserContentController no longer knows about.

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm:
(TEST):
Add a test ensuring that it is possible to remove and re-add a script message handler
with the same name and still dispatch messages to it.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (197867 => 197868)


--- trunk/Source/WebCore/ChangeLog	2016-03-09 19:36:21 UTC (rev 197867)
+++ trunk/Source/WebCore/ChangeLog	2016-03-09 19:56:41 UTC (rev 197868)
@@ -1,3 +1,30 @@
+2016-03-09  Tim Horton  <[email protected]>
+
+        Removing and re-adding a script message handler with the same name results in an unusable message handler
+        https://bugs.webkit.org/show_bug.cgi?id=155223
+
+        Reviewed by Sam Weinig.
+        Patch by Geoff Garen and myself.
+
+        New API test: WKUserContentController.ScriptMessageHandlerReplaceWithSameName.
+
+        * page/UserMessageHandler.h:
+        (WebCore::UserMessageHandler::descriptor):
+        * page/UserMessageHandlersNamespace.cpp:
+        (WebCore::UserMessageHandlersNamespace::handler):
+        This lazy removal mechanism combined with the fact that we only compare
+        handler name and world makes it such that m_messageHandlers could have
+        a stale UserMessageHandler with a UserMessageHandlerDescriptor that differed
+        only in client.
+
+        It is safe to compare the descriptors by pointer instead because m_messageHandler
+        holds a strong reference to its UserMessageHandlerDescriptors, and this will ensure
+        that the add-remove-add path (with identical name and world) causes a new
+        UserContentController to be created.
+
+        We also now clean up any stale UserMessageHandlers whenever we're about to
+        add a new one, by removing any which the UserContentController no longer knows about.
+
 2016-03-09  Chris Dumez  <[email protected]>
 
         Align HTMLKeygenElement.keytype with the specification

Modified: trunk/Source/WebCore/page/UserMessageHandler.h (197867 => 197868)


--- trunk/Source/WebCore/page/UserMessageHandler.h	2016-03-09 19:36:21 UTC (rev 197867)
+++ trunk/Source/WebCore/page/UserMessageHandler.h	2016-03-09 19:56:41 UTC (rev 197868)
@@ -48,6 +48,7 @@
 
     const AtomicString& name();
     DOMWrapperWorld& world();
+    const UserMessageHandlerDescriptor& descriptor() const { return m_descriptor.get(); }
 
 private:
     UserMessageHandler(Frame&, UserMessageHandlerDescriptor&);

Modified: trunk/Source/WebCore/page/UserMessageHandlersNamespace.cpp (197867 => 197868)


--- trunk/Source/WebCore/page/UserMessageHandlersNamespace.cpp	2016-03-09 19:36:21 UTC (rev 197867)
+++ trunk/Source/WebCore/page/UserMessageHandlersNamespace.cpp	2016-03-09 19:56:41 UTC (rev 197868)
@@ -62,18 +62,23 @@
         return nullptr;
 
     RefPtr<UserMessageHandlerDescriptor> descriptor = userMessageHandlerDescriptors->get(std::make_pair(name, &world));
-    if (!descriptor) {
-        m_messageHandlers.removeFirstMatching([&name, &world](Ref<UserMessageHandler>& handler) {
-            return handler->name() == name && &handler->world() == &world;
-        });
+    if (!descriptor)
         return nullptr;
-    }
 
     for (auto& handler : m_messageHandlers) {
-        if (handler->name() == name && &handler->world() == &world)
+        if (&handler->descriptor() == descriptor.get())
             return &handler.get();
     }
 
+    auto liveHandlers = userMessageHandlerDescriptors->values();
+    m_messageHandlers.removeAllMatching([liveHandlers](const Ref<UserMessageHandler>& handler) {
+        for (const auto& liveHandler : liveHandlers) {
+            if (liveHandler.get() == &handler->descriptor())
+                return true;
+        }
+        return false;
+    });
+
     m_messageHandlers.append(UserMessageHandler::create(*frame(), *descriptor));
     return &m_messageHandlers.last().get();
 }

Modified: trunk/Tools/ChangeLog (197867 => 197868)


--- trunk/Tools/ChangeLog	2016-03-09 19:36:21 UTC (rev 197867)
+++ trunk/Tools/ChangeLog	2016-03-09 19:56:41 UTC (rev 197868)
@@ -1,3 +1,15 @@
+2016-03-09  Tim Horton  <[email protected]>
+
+        Removing and re-adding a script message handler with the same name results in an unusable message handler
+        https://bugs.webkit.org/show_bug.cgi?id=155223
+
+        Reviewed by Sam Weinig.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm:
+        (TEST):
+        Add a test ensuring that it is possible to remove and re-add a script message handler
+        with the same name and still dispatch messages to it.
+
 2016-03-08  Alexey Proskuryakov  <[email protected]>
 
         Fix iOS Simulator EWS.

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm (197867 => 197868)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm	2016-03-09 19:36:21 UTC (rev 197867)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm	2016-03-09 19:56:41 UTC (rev 197868)
@@ -264,6 +264,44 @@
 }
 #endif
 
+TEST(WKUserContentController, ScriptMessageHandlerReplaceWithSameName)
+{
+    RetainPtr<ScriptMessageHandler> handler = adoptNS([[ScriptMessageHandler alloc] init]);
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    RetainPtr<WKUserContentController> userContentController = [configuration userContentController];
+    [userContentController addScriptMessageHandler:handler.get() name:@"handlerToReplace"];
+
+    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"]];
+
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&isDoneWithNavigation);
+
+    // Test that handlerToReplace was succesfully added.
+    [webView evaluateJavaScript:@"window.webkit.messageHandlers.handlerToReplace.postMessage('PASS1');" completionHandler:nil];
+
+    TestWebKitAPI::Util::run(&receivedScriptMessage);
+    receivedScriptMessage = false;
+
+    EXPECT_WK_STREQ(@"PASS1", (NSString *)[lastScriptMessage body]);
+
+    [userContentController removeScriptMessageHandlerForName:@"handlerToReplace"];
+    [userContentController addScriptMessageHandler:handler.get() name:@"handlerToReplace"];
+
+    // Test that handlerToReplace still works.
+    [webView evaluateJavaScript:@"window.webkit.messageHandlers.handlerToReplace.postMessage('PASS2');" completionHandler:nil];
+
+    TestWebKitAPI::Util::run(&receivedScriptMessage);
+    receivedScriptMessage = false;
+
+    EXPECT_WK_STREQ(@"PASS2", (NSString *)[lastScriptMessage body]);
+}
+
 static NSString *styleSheetSource = @"body { background-color: green !important; }";
 static NSString *backgroundColorScript = @"window.getComputedStyle(document.body, null).getPropertyValue('background-color')";
 static NSString *frameBackgroundColorScript = @"window.getComputedStyle(document.getElementsByTagName('iframe')[0].contentDocument.body, null).getPropertyValue('background-color')";
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to