<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197302] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197302">197302</a></dd>
<dt>Author</dt> <dd>weinig@apple.com</dd>
<dt>Date</dt> <dd>2016-02-28 13:56:44 -0800 (Sun, 28 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Source/WebKit2:
Bind _WKUserStyleSheets to _WKUserContentWorlds to allow for grouping of user content by associating to a world
https://bugs.webkit.org/show_bug.cgi?id=154798

Reviewed by Dan Bernstein.

Treat _WKUserStyleSheets like WKUserScripts and allow them to be bound to a _WKUserContentWorld.
The immediate benefit of this is allowing a client to bind a set of user content (scripts and stylesheets
for now) to a world and have them easily remove all user content associated with that world easily.

* Shared/API/APIArray.h:
Add helpers removeAllMatching and removeAllOfTypeMatching.

* UIProcess/API/APIUserStyleSheet.h:
Add API::UserContentWorld member.

* UIProcess/API/Cocoa/WKUserContentController.mm:
(-[WKUserContentController _removeAllUserScriptsAssociatedWithUserContentWorld:]):
(-[WKUserContentController _removeAllUserStyleSheetsAssociatedWithUserContentWorld:]):
* UIProcess/API/Cocoa/WKUserContentControllerPrivate.h:
Add _removeAllUserScriptsAssociatedWithUserContentWorld and _removeAllUserStyleSheetsAssociatedWithUserContentWorld.

* UIProcess/API/Cocoa/WKUserScript.mm:
(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
(toStringVector): Deleted.
* UIProcess/API/Cocoa/_WKUserContentWorldInternal.h:
(API::toStringVector):
Move toStringVector to a location where it can be shared.

* UIProcess/API/Cocoa/_WKUserStyleSheet.h:
* UIProcess/API/Cocoa/_WKUserStyleSheet.mm:
(-[_WKUserStyleSheet initWithSource:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
Add new initializer which has a world to be bound to. While here, match WKUserScript and add support for the 
legacy whitelist and blacklists.

* UIProcess/UserContent/WebUserContentControllerProxy.cpp:
(WebKit::WebUserContentControllerProxy::addProcess):
(WebKit::WebUserContentControllerProxy::removeProcess):
(WebKit::WebUserContentControllerProxy::addUserContentWorldUse):
(WebKit::WebUserContentControllerProxy::shouldSendRemoveUserContentWorldsMessage):
(WebKit::WebUserContentControllerProxy::removeUserContentWorldUses):
(WebKit::WebUserContentControllerProxy::addUserScript):
(WebKit::WebUserContentControllerProxy::removeUserScript):
(WebKit::WebUserContentControllerProxy::removeAllUserScripts):
(WebKit::WebUserContentControllerProxy::addUserStyleSheet):
(WebKit::WebUserContentControllerProxy::removeUserStyleSheet):
(WebKit::WebUserContentControllerProxy::removeAllUserStyleSheets):
* UIProcess/UserContent/WebUserContentControllerProxy.h:
Refactor to share the code which decides whether to send AddUserContentWorlds/RemoveUserContentWorlds
messages.

* WebProcess/UserContent/WebUserContentController.cpp:
(WebKit::WebUserContentController::addUserContentWorlds):
(WebKit::WebUserContentController::removeUserContentWorlds):
(WebKit::WebUserContentController::addUserScripts):
(WebKit::WebUserContentController::removeUserScript):
(WebKit::WebUserContentController::removeAllUserScripts):
(WebKit::WebUserContentController::addUserStyleSheets):
(WebKit::WebUserContentController::removeUserStyleSheet):
(WebKit::WebUserContentController::removeAllUserStyleSheets):
* WebProcess/UserContent/WebUserContentController.h:
* WebProcess/UserContent/WebUserContentController.messages.in:
Add support for binding stylesheets to worlds and allow removing all the scripts/stylesheets from a 
set of worlds at once by passing Vectors of world identifiers in the remove messages.

Tools:
Bind _WKUserStyleSheets to WKUserContentWorlds to allow for grouping of user content by associating to a world
https://bugs.webkit.org/show_bug.cgi?id=154798

Reviewed by Dan Bernstein.

* TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm:
Add tests for removing _WKUserStyleSheets and WKUserScripts</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedAPIAPIArrayh">trunk/Source/WebKit2/Shared/API/APIArray.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIAPIUserStyleSheeth">trunk/Source/WebKit2/UIProcess/API/APIUserStyleSheet.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKUserContentControllermm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentController.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKUserContentControllerPrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentControllerPrivate.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKUserScriptmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserScript.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserContentWorldInternalh">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserStyleSheeth">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserStyleSheetmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitUserContentcpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitUserContent.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessUserContentWebUserContentControllerProxycpp">trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessUserContentWebUserContentControllerProxyh">trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessUserContentWebUserContentControllercpp">trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessUserContentWebUserContentControllerh">trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessUserContentWebUserContentControllermessagesin">trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.messages.in</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2CocoaUserContentControllermm">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/ChangeLog        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -1,3 +1,69 @@
</span><ins>+2016-02-28  Sam Weinig  &lt;sam@webkit.org&gt;
+
+        Bind _WKUserStyleSheets to _WKUserContentWorlds to allow for grouping of user content by associating to a world
+        https://bugs.webkit.org/show_bug.cgi?id=154798
+
+        Reviewed by Dan Bernstein.
+
+        Treat _WKUserStyleSheets like WKUserScripts and allow them to be bound to a _WKUserContentWorld.
+        The immediate benefit of this is allowing a client to bind a set of user content (scripts and stylesheets
+        for now) to a world and have them easily remove all user content associated with that world easily.
+
+        * Shared/API/APIArray.h:
+        Add helpers removeAllMatching and removeAllOfTypeMatching.
+
+        * UIProcess/API/APIUserStyleSheet.h:
+        Add API::UserContentWorld member.
+
+        * UIProcess/API/Cocoa/WKUserContentController.mm:
+        (-[WKUserContentController _removeAllUserScriptsAssociatedWithUserContentWorld:]):
+        (-[WKUserContentController _removeAllUserStyleSheetsAssociatedWithUserContentWorld:]):
+        * UIProcess/API/Cocoa/WKUserContentControllerPrivate.h:
+        Add _removeAllUserScriptsAssociatedWithUserContentWorld and _removeAllUserStyleSheetsAssociatedWithUserContentWorld.
+
+        * UIProcess/API/Cocoa/WKUserScript.mm:
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
+        (toStringVector): Deleted.
+        * UIProcess/API/Cocoa/_WKUserContentWorldInternal.h:
+        (API::toStringVector):
+        Move toStringVector to a location where it can be shared.
+
+        * UIProcess/API/Cocoa/_WKUserStyleSheet.h:
+        * UIProcess/API/Cocoa/_WKUserStyleSheet.mm:
+        (-[_WKUserStyleSheet initWithSource:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
+        Add new initializer which has a world to be bound to. While here, match WKUserScript and add support for the 
+        legacy whitelist and blacklists.
+
+        * UIProcess/UserContent/WebUserContentControllerProxy.cpp:
+        (WebKit::WebUserContentControllerProxy::addProcess):
+        (WebKit::WebUserContentControllerProxy::removeProcess):
+        (WebKit::WebUserContentControllerProxy::addUserContentWorldUse):
+        (WebKit::WebUserContentControllerProxy::shouldSendRemoveUserContentWorldsMessage):
+        (WebKit::WebUserContentControllerProxy::removeUserContentWorldUses):
+        (WebKit::WebUserContentControllerProxy::addUserScript):
+        (WebKit::WebUserContentControllerProxy::removeUserScript):
+        (WebKit::WebUserContentControllerProxy::removeAllUserScripts):
+        (WebKit::WebUserContentControllerProxy::addUserStyleSheet):
+        (WebKit::WebUserContentControllerProxy::removeUserStyleSheet):
+        (WebKit::WebUserContentControllerProxy::removeAllUserStyleSheets):
+        * UIProcess/UserContent/WebUserContentControllerProxy.h:
+        Refactor to share the code which decides whether to send AddUserContentWorlds/RemoveUserContentWorlds
+        messages.
+
+        * WebProcess/UserContent/WebUserContentController.cpp:
+        (WebKit::WebUserContentController::addUserContentWorlds):
+        (WebKit::WebUserContentController::removeUserContentWorlds):
+        (WebKit::WebUserContentController::addUserScripts):
+        (WebKit::WebUserContentController::removeUserScript):
+        (WebKit::WebUserContentController::removeAllUserScripts):
+        (WebKit::WebUserContentController::addUserStyleSheets):
+        (WebKit::WebUserContentController::removeUserStyleSheet):
+        (WebKit::WebUserContentController::removeAllUserStyleSheets):
+        * WebProcess/UserContent/WebUserContentController.h:
+        * WebProcess/UserContent/WebUserContentController.messages.in:
+        Add support for binding stylesheets to worlds and allow removing all the scripts/stylesheets from a 
+        set of worlds at once by passing Vectors of world identifiers in the remove messages.
+
</ins><span class="cx"> 2016-02-27  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r197204, r197207, r197211, r197217,
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedAPIAPIArrayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/API/APIArray.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/API/APIArray.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/Shared/API/APIArray.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -82,7 +82,22 @@
</span><span class="cx">         );
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template&lt;typename MatchFunction&gt;
+    unsigned removeAllMatching(const MatchFunction&amp; matchFunction)
+    {
+        return m_elements.removeAllMatching(matchFunction);
+    }
</ins><span class="cx"> 
</span><ins>+    template&lt;typename T, typename MatchFunction&gt;
+    unsigned removeAllOfTypeMatching(const MatchFunction&amp; matchFunction)
+    {
+        return m_elements.removeAllMatching([&amp;] (const RefPtr&lt;Object&gt;&amp; object) -&gt; bool {
+            if (object-&gt;type() != T::APIType)
+                return false;
+            return matchFunction(static_pointer_cast&lt;T&gt;(object));
+        });
+    }
+
</ins><span class="cx"> private:
</span><span class="cx">     explicit Array(Vector&lt;RefPtr&lt;Object&gt;&gt;&amp;&amp; elements)
</span><span class="cx">         : m_elements(WTFMove(elements))
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIAPIUserStyleSheeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/APIUserStyleSheet.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/APIUserStyleSheet.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/APIUserStyleSheet.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #define APIUserStyleSheet_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;APIObject.h&quot;
</span><ins>+#include &quot;APIUserContentWorld.h&quot;
</ins><span class="cx"> #include &lt;WebCore/UserStyleSheet.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace API {
</span><span class="lines">@@ -35,15 +36,25 @@
</span><span class="cx"> public:
</span><span class="cx">     static WebCore::URL generateUniqueURL();
</span><span class="cx"> 
</span><del>-    UserStyleSheet(WebCore::UserStyleSheet userStyleSheet)
</del><ins>+    static Ref&lt;UserStyleSheet&gt; create(WebCore::UserStyleSheet userStyleSheet, API::UserContentWorld&amp; world)
+    {
+        return adoptRef(*new UserStyleSheet(WTFMove(userStyleSheet), world));
+    }
+
+    UserStyleSheet(WebCore::UserStyleSheet userStyleSheet, API::UserContentWorld&amp; world)
</ins><span class="cx">         : m_userStyleSheet(userStyleSheet)
</span><ins>+        , m_world(world)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     const WebCore::UserStyleSheet&amp; userStyleSheet() const { return m_userStyleSheet; }
</span><span class="cx"> 
</span><ins>+    UserContentWorld&amp; userContentWorld() { return m_world; }
+    const UserContentWorld&amp; userContentWorld() const { return m_world; }
+
</ins><span class="cx"> private:
</span><span class="cx">     WebCore::UserStyleSheet m_userStyleSheet;
</span><ins>+    Ref&lt;UserContentWorld&gt; m_world;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace API
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKUserContentControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentController.mm (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentController.mm        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentController.mm        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #import &quot;WebScriptMessageHandler.h&quot;
</span><span class="cx"> #import &quot;WebUserContentControllerProxy.h&quot;
</span><span class="cx"> #import &quot;_WKUserContentFilterInternal.h&quot;
</span><ins>+#import &quot;_WKUserContentWorldInternal.h&quot;
</ins><span class="cx"> #import &quot;_WKUserStyleSheetInternal.h&quot;
</span><span class="cx"> #import &lt;WebCore/SecurityOrigin.h&gt;
</span><span class="cx"> #import &lt;WebCore/SecurityOriginData.h&gt;
</span><span class="lines">@@ -143,6 +144,11 @@
</span><span class="cx">     _userContentControllerProxy-&gt;removeUserScript(*userScript-&gt;_userScript);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_removeAllUserScriptsAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    _userContentControllerProxy-&gt;removeAllUserScripts(*userContentWorld-&gt;_userContentWorld);
+}
+
</ins><span class="cx"> - (void)_addUserContentFilter:(_WKUserContentFilter *)userContentFilter
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(CONTENT_EXTENSIONS)
</span><span class="lines">@@ -184,6 +190,11 @@
</span><span class="cx">     _userContentControllerProxy-&gt;removeAllUserStyleSheets();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_removeAllUserStyleSheetsAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    _userContentControllerProxy-&gt;removeAllUserStyleSheets(*userContentWorld-&gt;_userContentWorld);
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKUserContentControllerPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentControllerPrivate.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentControllerPrivate.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserContentControllerPrivate.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -29,11 +29,13 @@
</span><span class="cx"> 
</span><span class="cx"> @class WKUserScript;
</span><span class="cx"> @class _WKUserContentFilter;
</span><ins>+@class _WKUserContentWorld;
</ins><span class="cx"> @class _WKUserStyleSheet;
</span><span class="cx"> 
</span><span class="cx"> @interface WKUserContentController (WKPrivate)
</span><span class="cx"> 
</span><span class="cx"> - (void)_removeUserScript:(WKUserScript *)userScript WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
</span><ins>+- (void)_removeAllUserScriptsAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
</ins><span class="cx"> 
</span><span class="cx"> - (void)_addUserContentFilter:(_WKUserContentFilter *)userContentFilter WK_AVAILABLE(10_11, 9_0);
</span><span class="cx"> - (void)_removeUserContentFilter:(NSString *)userContentFilterName WK_AVAILABLE(10_11, 9_0);
</span><span class="lines">@@ -43,6 +45,7 @@
</span><span class="cx"> - (void)_addUserStyleSheet:(_WKUserStyleSheet *)userStyleSheet WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
</span><span class="cx"> - (void)_removeUserStyleSheet:(_WKUserStyleSheet *)userStyleSheet WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
</span><span class="cx"> - (void)_removeAllUserStyleSheets WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
</span><ins>+- (void)_removeAllUserStyleSheetsAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
</ins><span class="cx"> 
</span><span class="cx"> @end
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKUserScriptmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserScript.mm (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserScript.mm        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKUserScript.mm        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -73,28 +73,12 @@
</span><span class="cx"> 
</span><span class="cx"> @implementation WKUserScript (WKPrivate)
</span><span class="cx"> 
</span><del>-static Vector&lt;WTF::String&gt; toStringVector(NSArray *input)
-{
-    Vector&lt;WTF::String&gt; vector;
-
-    NSUInteger size = input.count;
-    if (!size)
-        return vector;
-
-    vector.reserveInitialCapacity(size);
-    for (id string : input) {
-        if ([string isKindOfClass:[NSString class]])
-            vector.uncheckedAppend(string);
-    }
-    return vector;
-}
-
</del><span class="cx"> - (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray *)legacyWhitelist legacyBlacklist:(NSArray *)legacyBlacklist userContentWorld:(_WKUserContentWorld *)userContentWorld
</span><span class="cx"> {
</span><span class="cx">     if (!(self = [super init]))
</span><span class="cx">         return nil;
</span><span class="cx"> 
</span><del>-    API::Object::constructInWrapper&lt;API::UserScript&gt;(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), toStringVector(legacyWhitelist), toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *userContentWorld-&gt;_userContentWorld);
</del><ins>+    API::Object::constructInWrapper&lt;API::UserScript&gt;(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *userContentWorld-&gt;_userContentWorld);
</ins><span class="cx"> 
</span><span class="cx">     return self;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserContentWorldInternalh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -29,6 +29,8 @@
</span><span class="cx"> 
</span><span class="cx"> #import &quot;APIUserContentWorld.h&quot;
</span><span class="cx"> #import &quot;WKObject.h&quot;
</span><ins>+#import &lt;wtf/Vector.h&gt;
+#import &lt;wtf/text/WTFString.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace API {
</span><span class="cx"> 
</span><span class="lines">@@ -38,8 +40,24 @@
</span><span class="cx">     return (_WKUserContentWorld *)userContentWorld.wrapper();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline Vector&lt;WTF::String&gt; toStringVector(NSArray *input)
+{
+    Vector&lt;WTF::String&gt; vector;
+
+    NSUInteger size = input.count;
+    if (!size)
+        return vector;
+
+    vector.reserveInitialCapacity(size);
+    for (id string : input) {
+        if ([string isKindOfClass:[NSString class]])
+            vector.uncheckedAppend(string);
+    }
+    return vector;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> @interface _WKUserContentWorld () &lt;WKObject&gt; {
</span><span class="cx"> @package
</span><span class="cx">     API::ObjectStorage&lt;API::UserContentWorld&gt; _userContentWorld;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserStyleSheeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -31,6 +31,8 @@
</span><span class="cx"> 
</span><span class="cx"> NS_ASSUME_NONNULL_BEGIN
</span><span class="cx"> 
</span><ins>+@class _WKUserContentWorld;
+
</ins><span class="cx"> WK_CLASS_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA)
</span><span class="cx"> @interface _WKUserStyleSheet : NSObject &lt;NSCopying&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -40,6 +42,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (instancetype)initWithSource:(NSString *)source forMainFrameOnly:(BOOL)forMainFrameOnly;
</span><span class="cx"> 
</span><ins>+- (instancetype)initWithSource:(NSString *)source forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(WK_ARRAY(NSString *) *)legacyWhitelist legacyBlacklist:(WK_ARRAY(NSString *) *)legacyBlacklist userContentWorld:(_WKUserContentWorld *)userContentWorld;
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> NS_ASSUME_NONNULL_END
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserStyleSheetmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.mm (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.mm        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserStyleSheet.mm        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #import &quot;APIArray.h&quot;
</span><span class="cx"> #import &quot;WKNSArray.h&quot;
</span><span class="cx"> #import &quot;WebKit2Initialize.h&quot;
</span><ins>+#import &quot;_WKUserContentWorldInternal.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #if WK_API_ENABLED
</span><span class="cx"> 
</span><span class="lines">@@ -42,11 +43,24 @@
</span><span class="cx">     // FIXME: In the API test, we can use generateUniqueURL below before the API::Object constructor has done this... where should this really be?
</span><span class="cx">     WebKit::InitializeWebKit2();
</span><span class="cx"> 
</span><del>-    API::Object::constructInWrapper&lt;API::UserStyleSheet&gt;(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), { }, { }, forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel });
</del><ins>+    API::Object::constructInWrapper&lt;API::UserStyleSheet&gt;(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), { }, { }, forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel }, API::UserContentWorld::normalWorld());
</ins><span class="cx"> 
</span><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (instancetype)initWithSource:(NSString *)source forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(WK_ARRAY(NSString *) *)legacyWhitelist legacyBlacklist:(WK_ARRAY(NSString *) *)legacyBlacklist userContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    if (!(self = [super init]))
+        return nil;
+
+    // FIXME: In the API test, we can use generateUniqueURL below before the API::Object constructor has done this... where should this really be?
+    WebKit::InitializeWebKit2();
+
+    API::Object::constructInWrapper&lt;API::UserStyleSheet&gt;(self, WebCore::UserStyleSheet { WTF::String(source), API::UserStyleSheet::generateUniqueURL(), API::toStringVector(legacyWhitelist), API::toStringVector(legacyBlacklist), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames, WebCore::UserStyleUserLevel }, *userContentWorld-&gt;_userContentWorld);
+
+    return self;
+}
+
</ins><span class="cx"> - (NSString *)source
</span><span class="cx"> {
</span><span class="cx">     return _userStyleSheet-&gt;userStyleSheet().source();
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitUserContentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitUserContent.cpp (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitUserContent.cpp        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitUserContent.cpp        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -93,7 +93,7 @@
</span><span class="cx">             String::fromUTF8(source), URL { },
</span><span class="cx">             toStringVector(whitelist), toStringVector(blacklist),
</span><span class="cx">             toUserContentInjectedFrames(injectedFrames),
</span><del>-            toUserStyleLevel(level) })))
</del><ins>+            toUserStyleLevel(level) }, API::UserContentWorld::normalWorld())))
</ins><span class="cx">         , referenceCount(1)
</span><span class="cx">     {
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessUserContentWebUserContentControllerProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.cpp (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.cpp        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.cpp        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -85,9 +85,9 @@
</span><span class="cx">         userScripts.append(std::make_pair(userScript-&gt;userContentWorld().identifier(), userScript-&gt;userScript()));
</span><span class="cx">     webProcessProxy.connection()-&gt;send(Messages::WebUserContentController::AddUserScripts(userScripts), m_identifier);
</span><span class="cx"> 
</span><del>-    Vector&lt;WebCore::UserStyleSheet&gt; userStyleSheets;
</del><ins>+    Vector&lt;std::pair&lt;uint64_t, WebCore::UserStyleSheet&gt;&gt; userStyleSheets;
</ins><span class="cx">     for (const auto&amp; userStyleSheet : m_userStyleSheets-&gt;elementsOfType&lt;API::UserStyleSheet&gt;())
</span><del>-        userStyleSheets.append(userStyleSheet-&gt;userStyleSheet());
</del><ins>+        userStyleSheets.append(std::make_pair(userStyleSheet-&gt;userContentWorld().identifier(), userStyleSheet-&gt;userStyleSheet()));
</ins><span class="cx">     webProcessProxy.connection()-&gt;send(Messages::WebUserContentController::AddUserStyleSheets(userStyleSheets), m_identifier);
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;WebScriptMessageHandlerHandle&gt; messageHandlerHandles;
</span><span class="lines">@@ -111,18 +111,60 @@
</span><span class="cx">     webProcessProxy.removeMessageReceiver(Messages::WebUserContentControllerProxy::messageReceiverName(), m_identifier);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentControllerProxy::addUserScript(API::UserScript&amp; userScript)
</del><ins>+void WebUserContentControllerProxy::addUserContentWorldUse(API::UserContentWorld&amp; world)
</ins><span class="cx"> {
</span><del>-    Ref&lt;API::UserContentWorld&gt; world = userScript.userContentWorld();
</del><ins>+    if (&amp;world == &amp;API::UserContentWorld::normalWorld())
+        return;
</ins><span class="cx"> 
</span><del>-    if (world.ptr() != &amp;API::UserContentWorld::normalWorld()) {
-        auto addResult = m_userContentWorlds.add(world.ptr());
-        if (addResult.isNewEntry) {
-            for (WebProcessProxy* process : m_processes)
-                process-&gt;connection()-&gt;send(Messages::WebUserContentController::AddUserContentWorlds({ std::make_pair(world-&gt;identifier(), world-&gt;name()) }), m_identifier);
</del><ins>+    auto addResult = m_userContentWorlds.add(&amp;world);
+    if (addResult.isNewEntry) {
+        for (WebProcessProxy* process : m_processes)
+            process-&gt;connection()-&gt;send(Messages::WebUserContentController::AddUserContentWorlds({ std::make_pair(world.identifier(), world.name()) }), m_identifier);
+    }
+}
+
+bool WebUserContentControllerProxy::shouldSendRemoveUserContentWorldsMessage(API::UserContentWorld&amp; world, unsigned numberOfUsesToRemove)
+{
+    if (&amp;world == &amp;API::UserContentWorld::normalWorld())
+        return false;
+
+    auto it = m_userContentWorlds.find(&amp;world);
+    for (unsigned i = 0; i &lt; numberOfUsesToRemove; ++i) {
+        if (m_userContentWorlds.remove(it)) {
+            ASSERT(i == (numberOfUsesToRemove - 1));
+            return true;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    
+    return false;
+}
</ins><span class="cx"> 
</span><ins>+void WebUserContentControllerProxy::removeUserContentWorldUses(API::UserContentWorld&amp; world, unsigned numberOfUsesToRemove)
+{
+    if (shouldSendRemoveUserContentWorldsMessage(world, numberOfUsesToRemove)) {
+        for (WebProcessProxy* process : m_processes)
+            process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveUserContentWorlds({ world.identifier() }), m_identifier);
+    }
+}
+
+void WebUserContentControllerProxy::removeUserContentWorldUses(HashCountedSet&lt;RefPtr&lt;API::UserContentWorld&gt;&gt;&amp; worlds)
+{
+    Vector&lt;uint64_t&gt; worldsToRemove;
+    for (auto&amp; worldUsePair : worlds) {
+        if (shouldSendRemoveUserContentWorldsMessage(*worldUsePair.key.get(), worldUsePair.value))
+            worldsToRemove.append(worldUsePair.key-&gt;identifier());
+    }
+
+    for (WebProcessProxy* process : m_processes)
+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveUserContentWorlds(worldsToRemove), m_identifier);
+}
+
+void WebUserContentControllerProxy::addUserScript(API::UserScript&amp; userScript)
+{
+    Ref&lt;API::UserContentWorld&gt; world = userScript.userContentWorld();
+
+    addUserContentWorldUse(world.get());
+
</ins><span class="cx">     m_userScripts-&gt;elements().append(&amp;userScript);
</span><span class="cx"> 
</span><span class="cx">     for (WebProcessProxy* process : m_processes)
</span><span class="lines">@@ -138,44 +180,93 @@
</span><span class="cx"> 
</span><span class="cx">     m_userScripts-&gt;elements().removeAll(&amp;userScript);
</span><span class="cx"> 
</span><del>-    if (world.ptr() != &amp;API::UserContentWorld::normalWorld()) {
-        if (m_userContentWorlds.remove(&amp;userScript.userContentWorld())) {
-            for (WebProcessProxy* process : m_processes)
-                process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveUserContentWorld(world-&gt;identifier()), m_identifier);
-        }
-    }
</del><ins>+    removeUserContentWorldUses(world.get(), 1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebUserContentControllerProxy::removeAllUserScripts(API::UserContentWorld&amp; world)
+{
+    for (WebProcessProxy* process : m_processes)
+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveAllUserScripts({ world.identifier() }), m_identifier);
+
+    unsigned userScriptsRemoved = m_userScripts-&gt;removeAllOfTypeMatching&lt;API::UserScript&gt;([&amp;] (const RefPtr&lt;API::UserScript&gt;&amp; userScript) -&gt; bool {
+        return &amp;userScript-&gt;userContentWorld() == &amp;world;
+    });
+
+    removeUserContentWorldUses(world, userScriptsRemoved);
+}
+
</ins><span class="cx"> void WebUserContentControllerProxy::removeAllUserScripts()
</span><span class="cx"> {
</span><ins>+    HashCountedSet&lt;RefPtr&lt;API::UserContentWorld&gt;&gt; worlds;
+    for (const auto&amp; userScript : m_userScripts-&gt;elementsOfType&lt;API::UserScript&gt;())
+        worlds.add(const_cast&lt;API::UserContentWorld*&gt;(&amp;userScript-&gt;userContentWorld()));
+
+    Vector&lt;uint64_t&gt; worldIdentifiers;
+    worldIdentifiers.reserveInitialCapacity(worlds.size());
+    for (const auto&amp; worldCountPair : worlds)
+        worldIdentifiers.uncheckedAppend(worldCountPair.key-&gt;identifier());
+
</ins><span class="cx">     for (WebProcessProxy* process : m_processes)
</span><del>-        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveAllUserScripts(API::UserContentWorld::normalWorld().identifier()), m_identifier);
</del><ins>+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveAllUserScripts(worldIdentifiers), m_identifier);
</ins><span class="cx"> 
</span><span class="cx">     m_userScripts-&gt;elements().clear();
</span><ins>+
+    removeUserContentWorldUses(worlds);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebUserContentControllerProxy::addUserStyleSheet(API::UserStyleSheet&amp; userStyleSheet)
</span><span class="cx"> {
</span><ins>+    Ref&lt;API::UserContentWorld&gt; world = userStyleSheet.userContentWorld();
+
+    addUserContentWorldUse(world.get());
+
</ins><span class="cx">     m_userStyleSheets-&gt;elements().append(&amp;userStyleSheet);
</span><span class="cx"> 
</span><span class="cx">     for (WebProcessProxy* process : m_processes)
</span><del>-        process-&gt;connection()-&gt;send(Messages::WebUserContentController::AddUserStyleSheets({ userStyleSheet.userStyleSheet() }), m_identifier);
</del><ins>+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::AddUserStyleSheets({ std::make_pair(world-&gt;identifier(), userStyleSheet.userStyleSheet()) }), m_identifier);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentControllerProxy::removeUserStyleSheet(const API::UserStyleSheet&amp; userStyleSheet)
</del><ins>+void WebUserContentControllerProxy::removeUserStyleSheet(API::UserStyleSheet&amp; userStyleSheet)
</ins><span class="cx"> {
</span><ins>+    Ref&lt;API::UserContentWorld&gt; world = userStyleSheet.userContentWorld();
+
</ins><span class="cx">     for (WebProcessProxy* process : m_processes)
</span><del>-        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveUserStyleSheet({ userStyleSheet.userStyleSheet().url().string() }), m_identifier);
</del><ins>+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveUserStyleSheet(world-&gt;identifier(), userStyleSheet.userStyleSheet().url().string()), m_identifier);
</ins><span class="cx"> 
</span><span class="cx">     m_userStyleSheets-&gt;elements().removeAll(&amp;userStyleSheet);
</span><ins>+
+    removeUserContentWorldUses(world.get(), 1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebUserContentControllerProxy::removeAllUserStyleSheets(API::UserContentWorld&amp; world)
+{
+    for (WebProcessProxy* process : m_processes)
+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveAllUserStyleSheets({ world.identifier() }), m_identifier);
+
+    unsigned userStyleSheetsRemoved = m_userStyleSheets-&gt;removeAllOfTypeMatching&lt;API::UserStyleSheet&gt;([&amp;] (const RefPtr&lt;API::UserStyleSheet&gt;&amp; userStyleSheet) -&gt; bool {
+        return &amp;userStyleSheet-&gt;userContentWorld() == &amp;world;
+    });
+
+    removeUserContentWorldUses(world, userStyleSheetsRemoved);
+}
+
</ins><span class="cx"> void WebUserContentControllerProxy::removeAllUserStyleSheets()
</span><span class="cx"> {
</span><ins>+    HashCountedSet&lt;RefPtr&lt;API::UserContentWorld&gt;&gt; worlds;
+    for (const auto&amp; userStyleSheet : m_userStyleSheets-&gt;elementsOfType&lt;API::UserStyleSheet&gt;())
+        worlds.add(const_cast&lt;API::UserContentWorld*&gt;(&amp;userStyleSheet-&gt;userContentWorld()));
+
+    Vector&lt;uint64_t&gt; worldIdentifiers;
+    worldIdentifiers.reserveInitialCapacity(worlds.size());
+    for (const auto&amp; worldCountPair : worlds)
+        worldIdentifiers.uncheckedAppend(worldCountPair.key-&gt;identifier());
+
+    for (WebProcessProxy* process : m_processes)
+        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveAllUserStyleSheets(worldIdentifiers), m_identifier);
+
</ins><span class="cx">     m_userStyleSheets-&gt;elements().clear();
</span><span class="cx"> 
</span><del>-    for (WebProcessProxy* process : m_processes)
-        process-&gt;connection()-&gt;send(Messages::WebUserContentController::RemoveAllUserStyleSheets(), m_identifier);
</del><ins>+    removeUserContentWorldUses(worlds);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool WebUserContentControllerProxy::addUserScriptMessageHandler(WebScriptMessageHandler* handler)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessUserContentWebUserContentControllerProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -76,13 +76,17 @@
</span><span class="cx">     API::Array&amp; userScripts() { return m_userScripts.get(); }
</span><span class="cx">     void addUserScript(API::UserScript&amp;);
</span><span class="cx">     void removeUserScript(API::UserScript&amp;);
</span><ins>+    void removeAllUserScripts(API::UserContentWorld&amp;);
</ins><span class="cx">     void removeAllUserScripts();
</span><span class="cx"> 
</span><span class="cx">     API::Array&amp; userStyleSheets() { return m_userStyleSheets.get(); }
</span><span class="cx">     void addUserStyleSheet(API::UserStyleSheet&amp;);
</span><del>-    void removeUserStyleSheet(const API::UserStyleSheet&amp;);
</del><ins>+    void removeUserStyleSheet(API::UserStyleSheet&amp;);
+    void removeAllUserStyleSheets(API::UserContentWorld&amp;);
</ins><span class="cx">     void removeAllUserStyleSheets();
</span><span class="cx"> 
</span><ins>+    void removeAllUserContent(API::UserContentWorld&amp;);
+
</ins><span class="cx">     // Returns false if there was a name conflict.
</span><span class="cx">     bool addUserScriptMessageHandler(WebScriptMessageHandler*);
</span><span class="cx">     void removeUserMessageHandlerForName(const String&amp;);
</span><span class="lines">@@ -99,6 +103,11 @@
</span><span class="cx"> 
</span><span class="cx">     void didPostMessage(IPC::Connection&amp;, uint64_t pageID, uint64_t frameID, const WebCore::SecurityOriginData&amp;, uint64_t messageHandlerID, const IPC::DataReference&amp;);
</span><span class="cx"> 
</span><ins>+    void addUserContentWorldUse(API::UserContentWorld&amp;);
+    void removeUserContentWorldUses(API::UserContentWorld&amp;, unsigned numberOfUsesToRemove);
+    void removeUserContentWorldUses(HashCountedSet&lt;RefPtr&lt;API::UserContentWorld&gt;&gt;&amp;);
+    bool shouldSendRemoveUserContentWorldsMessage(API::UserContentWorld&amp;, unsigned numberOfUsesToRemove);
+
</ins><span class="cx">     uint64_t m_identifier;
</span><span class="cx">     HashSet&lt;WebProcessProxy*&gt; m_processes;    
</span><span class="cx">     Ref&lt;API::Array&gt; m_userScripts;
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessUserContentWebUserContentControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.cpp (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.cpp        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.cpp        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -105,21 +105,23 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentController::removeUserContentWorld(uint64_t worldIdentifier)
</del><ins>+void WebUserContentController::removeUserContentWorlds(const Vector&lt;uint64_t&gt;&amp; worldIdentifiers)
</ins><span class="cx"> {
</span><del>-    ASSERT(worldIdentifier);
-    ASSERT(worldIdentifier != 1);
</del><ins>+    for (auto&amp; worldIdentifier : worldIdentifiers) {
+        ASSERT(worldIdentifier);
+        ASSERT(worldIdentifier != 1);
</ins><span class="cx"> 
</span><del>-    auto it = worldMap().find(worldIdentifier);
-    if (it == worldMap().end()) {
-        WTFLogAlways(&quot;Trying to remove a UserContentWorld (id=%&quot; PRIu64 &quot;) that does not exist.&quot;, worldIdentifier);
-        return;
</del><ins>+        auto it = worldMap().find(worldIdentifier);
+        if (it == worldMap().end()) {
+            WTFLogAlways(&quot;Trying to remove a UserContentWorld (id=%&quot; PRIu64 &quot;) that is does not exist.&quot;, worldIdentifier);
+            return;
+        }
+
+        it-&gt;value.second--;
+        
+        if (!it-&gt;value.second)
+            worldMap().remove(it);
</ins><span class="cx">     }
</span><del>-
-    it-&gt;value.second--;
-    
-    if (!it-&gt;value.second)
-        worldMap().remove(it);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebUserContentController::addUserScripts(const Vector&lt;std::pair&lt;uint64_t, WebCore::UserScript&gt;&gt;&amp; userScripts)
</span><span class="lines">@@ -146,33 +148,54 @@
</span><span class="cx">     m_userContentController-&gt;removeUserScript(it-&gt;value.first-&gt;coreWorld(), URL(URL(), urlString));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentController::removeAllUserScripts(uint64_t worldIdentifier)
</del><ins>+void WebUserContentController::removeAllUserScripts(const Vector&lt;uint64_t&gt;&amp; worldIdentifiers)
</ins><span class="cx"> {
</span><del>-    auto it = worldMap().find(worldIdentifier);
-    if (it == worldMap().end()) {
-        WTFLogAlways(&quot;Trying to remove all UserScripts from a UserContentWorld (id=%&quot; PRIu64 &quot;) that does not exist.&quot;, worldIdentifier);
-        return;
</del><ins>+    for (auto&amp; worldIdentifier : worldIdentifiers) {
+        auto it = worldMap().find(worldIdentifier);
+        if (it == worldMap().end()) {
+            WTFLogAlways(&quot;Trying to remove all UserScripts from a UserContentWorld (id=%&quot; PRIu64 &quot;) that does not exist.&quot;, worldIdentifier);
+            return;
+        }
+
+        m_userContentController-&gt;removeUserScripts(it-&gt;value.first-&gt;coreWorld());
</ins><span class="cx">     }
</span><del>-
-    m_userContentController-&gt;removeUserScripts(it-&gt;value.first-&gt;coreWorld());
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentController::addUserStyleSheets(const Vector&lt;WebCore::UserStyleSheet&gt;&amp; userStyleSheets)
</del><ins>+void WebUserContentController::addUserStyleSheets(const Vector&lt;std::pair&lt;uint64_t, WebCore::UserStyleSheet&gt;&gt;&amp; userStyleSheets)
</ins><span class="cx"> {
</span><del>-    for (const auto&amp; userStyleSheet : userStyleSheets) {
-        m_userContentController-&gt;addUserStyleSheet(mainThreadNormalWorld(),
-            std::make_unique&lt;WebCore::UserStyleSheet&gt;(userStyleSheet), InjectInExistingDocuments);
</del><ins>+    for (const auto&amp; userStyleSheetWorldPair : userStyleSheets) {
+        auto it = worldMap().find(userStyleSheetWorldPair.first);
+        if (it == worldMap().end()) {
+            WTFLogAlways(&quot;Trying to add a UserStyleSheet to a UserContentWorld (id=%&quot; PRIu64 &quot;) that does not exist.&quot;, userStyleSheetWorldPair.first);
+            continue;
+        }
+
+        m_userContentController-&gt;addUserStyleSheet(it-&gt;value.first-&gt;coreWorld(), std::make_unique&lt;WebCore::UserStyleSheet&gt;(userStyleSheetWorldPair.second), InjectInExistingDocuments);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentController::removeUserStyleSheet(const String&amp; urlString)
</del><ins>+void WebUserContentController::removeUserStyleSheet(uint64_t worldIdentifier, const String&amp; urlString)
</ins><span class="cx"> {
</span><del>-    m_userContentController-&gt;removeUserStyleSheet(mainThreadNormalWorld(), URL(URL(), urlString));
</del><ins>+    auto it = worldMap().find(worldIdentifier);
+    if (it == worldMap().end()) {
+        WTFLogAlways(&quot;Trying to remove a UserStyleSheet from a UserContentWorld (id=%&quot; PRIu64 &quot;) that does not exist.&quot;, worldIdentifier);
+        return;
+    }
+
+    m_userContentController-&gt;removeUserStyleSheet(it-&gt;value.first-&gt;coreWorld(), URL(URL(), urlString));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebUserContentController::removeAllUserStyleSheets()
</del><ins>+void WebUserContentController::removeAllUserStyleSheets(const Vector&lt;uint64_t&gt;&amp; worldIdentifiers)
</ins><span class="cx"> {
</span><del>-    m_userContentController-&gt;removeUserStyleSheets(mainThreadNormalWorld());
</del><ins>+    for (auto&amp; worldIdentifier : worldIdentifiers) {
+        auto it = worldMap().find(worldIdentifier);
+        if (it == worldMap().end()) {
+            WTFLogAlways(&quot;Trying to remove all UserStyleSheets from a UserContentWorld (id=%&quot; PRIu64 &quot;) that does not exist.&quot;, worldIdentifier);
+            return;
+        }
+
+        m_userContentController-&gt;removeUserStyleSheets(it-&gt;value.first-&gt;coreWorld());
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(USER_MESSAGE_HANDLERS)
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessUserContentWebUserContentControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.h (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.h        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.h        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -54,15 +54,15 @@
</span><span class="cx">     virtual void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;) override;
</span><span class="cx"> 
</span><span class="cx">     void addUserContentWorlds(const Vector&lt;std::pair&lt;uint64_t, String&gt;&gt;&amp;);
</span><del>-    void removeUserContentWorld(uint64_t);
</del><ins>+    void removeUserContentWorlds(const Vector&lt;uint64_t&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void addUserScripts(const Vector&lt;std::pair&lt;uint64_t, WebCore::UserScript&gt;&gt;&amp;);
</span><span class="cx">     void removeUserScript(uint64_t worldIdentifier, const String&amp; urlString);
</span><del>-    void removeAllUserScripts(uint64_t worldIdentifier);
</del><ins>+    void removeAllUserScripts(const Vector&lt;uint64_t&gt;&amp;);
</ins><span class="cx"> 
</span><del>-    void addUserStyleSheets(const Vector&lt;WebCore::UserStyleSheet&gt;&amp;);
-    void removeUserStyleSheet(const String&amp; urlString);
-    void removeAllUserStyleSheets();
</del><ins>+    void addUserStyleSheets(const Vector&lt;std::pair&lt;uint64_t, WebCore::UserStyleSheet&gt;&gt;&amp;);
+    void removeUserStyleSheet(uint64_t worldIdentifier, const String&amp; urlString);
+    void removeAllUserStyleSheets(const Vector&lt;uint64_t&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void addUserScriptMessageHandlers(const Vector&lt;WebScriptMessageHandlerHandle&gt;&amp;);
</span><span class="cx">     void removeUserScriptMessageHandler(uint64_t);
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessUserContentWebUserContentControllermessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.messages.in (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.messages.in        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Source/WebKit2/WebProcess/UserContent/WebUserContentController.messages.in        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -25,15 +25,15 @@
</span><span class="cx"> 
</span><span class="cx"> messages -&gt; WebUserContentController {
</span><span class="cx">     AddUserContentWorlds(Vector&lt;std::pair&lt;uint64_t, String&gt;&gt; worlds);
</span><del>-    RemoveUserContentWorld(uint64_t worldIdentifier);
</del><ins>+    RemoveUserContentWorlds(Vector&lt;uint64_t&gt; worldIdentifiers);
</ins><span class="cx"> 
</span><span class="cx">     AddUserScripts(Vector&lt;std::pair&lt;uint64_t, WebCore::UserScript&gt;&gt; userScripts);
</span><span class="cx">     RemoveUserScript(uint64_t worldIdentifier, String url);
</span><del>-    RemoveAllUserScripts(uint64_t worldIdentifier);
</del><ins>+    RemoveAllUserScripts(Vector&lt;uint64_t&gt; worldIdentifiers);
</ins><span class="cx"> 
</span><del>-    AddUserStyleSheets(Vector&lt;WebCore::UserStyleSheet&gt; userStyleSheets);
-    RemoveUserStyleSheet(String url);
-    RemoveAllUserStyleSheets();
</del><ins>+    AddUserStyleSheets(Vector&lt;std::pair&lt;uint64_t, WebCore::UserStyleSheet&gt;&gt; userStyleSheets);
+    RemoveUserStyleSheet(uint64_t worldIdentifier, String url);
+    RemoveAllUserStyleSheets(Vector&lt;uint64_t&gt; worldIdentifiers);
</ins><span class="cx"> 
</span><span class="cx">     AddUserScriptMessageHandlers(Vector&lt;WebKit::WebScriptMessageHandlerHandle&gt; scriptMessageHandlers);
</span><span class="cx">     RemoveUserScriptMessageHandler(uint64_t identifier);
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Tools/ChangeLog        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-02-28  Sam Weinig  &lt;sam@webkit.org&gt;
+
+        Bind _WKUserStyleSheets to WKUserContentWorlds to allow for grouping of user content by associating to a world
+        https://bugs.webkit.org/show_bug.cgi?id=154798
+
+        Reviewed by Dan Bernstein.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm:
+        Add tests for removing _WKUserStyleSheets and WKUserScripts
+
</ins><span class="cx"> 2016-02-27  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Silence leaks under TextCodecICU::registerCodecs
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2CocoaUserContentControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm (197301 => 197302)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm        2016-02-28 21:00:15 UTC (rev 197301)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentController.mm        2016-02-28 21:56:44 UTC (rev 197302)
</span><span class="lines">@@ -27,11 +27,15 @@
</span><span class="cx"> 
</span><span class="cx"> #import &quot;PlatformUtilities.h&quot;
</span><span class="cx"> #import &quot;Test.h&quot;
</span><del>-#import &lt;WebKit/WebKit.h&gt;
</del><span class="cx"> #import &lt;WebKit/WKProcessPoolPrivate.h&gt;
</span><span class="cx"> #import &lt;WebKit/WKUserContentControllerPrivate.h&gt;
</span><ins>+#import &lt;WebKit/WKUserScript.h&gt;
+#import &lt;WebKit/WKUserScriptPrivate.h&gt;
+#import &lt;WebKit/WebKit.h&gt;
</ins><span class="cx"> #import &lt;WebKit/_WKProcessPoolConfiguration.h&gt;
</span><ins>+#import &lt;WebKit/_WKUserContentWorld.h&gt;
</ins><span class="cx"> #import &lt;WebKit/_WKUserStyleSheet.h&gt;
</span><ins>+#import &lt;WebKit/_WKUserStyleSheet.h&gt;
</ins><span class="cx"> #import &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if WK_API_ENABLED
</span><span class="lines">@@ -365,4 +369,176 @@
</span><span class="cx">     expectScriptEvaluatesToColor(webView.get(), frameBackgroundColorScript, greenInRGB);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(WKUserContentController, UserStyleSheetRemove)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO]);
+    [userContentController _addUserStyleSheet:styleSheet.get()];
+    
+    EXPECT_EQ(1u, [userContentController _userStyleSheets].count);
+    EXPECT_EQ(styleSheet.get(), [userContentController _userStyleSheets][0]);
+
+    [userContentController _removeUserStyleSheet:styleSheet.get()];
+
+    EXPECT_EQ(0u, [userContentController _userStyleSheets].count);
+}
+
+TEST(WKUserContentController, UserStyleSheetRemoveAll)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+
+    RetainPtr&lt;_WKUserContentWorld&gt; world = adoptNS([_WKUserContentWorld worldWithName:@&quot;TestWorld&quot;]);
+
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO]);
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheetAssociatedWithWorld = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    
+    [userContentController _addUserStyleSheet:styleSheet.get()];
+    [userContentController _addUserStyleSheet:styleSheetAssociatedWithWorld.get()];
+    
+    EXPECT_EQ(2u, [userContentController _userStyleSheets].count);
+    EXPECT_EQ(styleSheet.get(), [userContentController _userStyleSheets][0]);
+    EXPECT_EQ(styleSheetAssociatedWithWorld.get(), [userContentController _userStyleSheets][1]);
+
+    [userContentController _removeAllUserStyleSheets];
+
+    EXPECT_EQ(0u, [userContentController _userStyleSheets].count);
+}
+
+TEST(WKUserContentController, UserStyleSheetRemoveAllByWorld)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+
+    RetainPtr&lt;_WKUserContentWorld&gt; world = adoptNS([_WKUserContentWorld worldWithName:@&quot;TestWorld&quot;]);
+
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO]);
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheetAssociatedWithWorld = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheetAssociatedWithWorld2 = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    
+    [userContentController _addUserStyleSheet:styleSheet.get()];
+    [userContentController _addUserStyleSheet:styleSheetAssociatedWithWorld.get()];
+    [userContentController _addUserStyleSheet:styleSheetAssociatedWithWorld2.get()];
+    
+    EXPECT_EQ(3u, [userContentController _userStyleSheets].count);
+    EXPECT_EQ(styleSheet.get(), [userContentController _userStyleSheets][0]);
+    EXPECT_EQ(styleSheetAssociatedWithWorld.get(), [userContentController _userStyleSheets][1]);
+    EXPECT_EQ(styleSheetAssociatedWithWorld2.get(), [userContentController _userStyleSheets][2]);
+
+    [userContentController _removeAllUserStyleSheetsAssociatedWithUserContentWorld:world.get()];
+
+    EXPECT_EQ(1u, [userContentController _userStyleSheets].count);
+    EXPECT_EQ(styleSheet.get(), [userContentController _userStyleSheets][0]);
+}
+
+TEST(WKUserContentController, UserStyleSheetRemoveAllByNormalWorld)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+
+    RetainPtr&lt;_WKUserContentWorld&gt; world = adoptNS([_WKUserContentWorld worldWithName:@&quot;TestWorld&quot;]);
+
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheet = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO]);
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheetAssociatedWithWorld = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    RetainPtr&lt;_WKUserStyleSheet&gt; styleSheetAssociatedWithWorld2 = adoptNS([[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    
+    [userContentController _addUserStyleSheet:styleSheet.get()];
+    [userContentController _addUserStyleSheet:styleSheetAssociatedWithWorld.get()];
+    [userContentController _addUserStyleSheet:styleSheetAssociatedWithWorld2.get()];
+    
+    EXPECT_EQ(3u, [userContentController _userStyleSheets].count);
+    EXPECT_EQ(styleSheet.get(), [userContentController _userStyleSheets][0]);
+    EXPECT_EQ(styleSheetAssociatedWithWorld.get(), [userContentController _userStyleSheets][1]);
+    EXPECT_EQ(styleSheetAssociatedWithWorld2.get(), [userContentController _userStyleSheets][2]);
+
+    [userContentController _removeAllUserStyleSheetsAssociatedWithUserContentWorld:[_WKUserContentWorld normalWorld]];
+
+    EXPECT_EQ(2u, [userContentController _userStyleSheets].count);
+    EXPECT_EQ(styleSheetAssociatedWithWorld.get(), [userContentController _userStyleSheets][0]);
+    EXPECT_EQ(styleSheetAssociatedWithWorld2.get(), [userContentController _userStyleSheets][1]);
+}
+
+TEST(WKUserContentController, UserScriptRemove)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+    RetainPtr&lt;WKUserScript&gt; userScript = adoptNS([[WKUserScript alloc] initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]);
+    [userContentController addUserScript:userScript.get()];
+    
+    EXPECT_EQ(1u, [userContentController userScripts].count);
+    EXPECT_EQ(userScript.get(), [userContentController userScripts][0]);
+
+    [userContentController _removeUserScript:userScript.get()];
+
+    EXPECT_EQ(0u, [userContentController userScripts].count);
+}
+
+TEST(WKUserContentController, UserScriptRemoveAll)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+
+    RetainPtr&lt;_WKUserContentWorld&gt; world = adoptNS([_WKUserContentWorld worldWithName:@&quot;TestWorld&quot;]);
+
+    RetainPtr&lt;WKUserScript&gt; userScript = adoptNS([[WKUserScript alloc] initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]);
+    RetainPtr&lt;WKUserScript&gt; userScriptAssociatedWithWorld = adoptNS([[WKUserScript alloc] _initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    
+    [userContentController addUserScript:userScript.get()];
+    [userContentController addUserScript:userScriptAssociatedWithWorld.get()];
+    
+    EXPECT_EQ(2u, [userContentController userScripts].count);
+    EXPECT_EQ(userScript.get(), [userContentController userScripts][0]);
+    EXPECT_EQ(userScriptAssociatedWithWorld.get(), [userContentController userScripts][1]);
+
+    [userContentController removeAllUserScripts];
+
+    EXPECT_EQ(0u, [userContentController userScripts].count);
+}
+
+TEST(WKUserContentController, UserScriptRemoveAllByWorld)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+
+    RetainPtr&lt;_WKUserContentWorld&gt; world = adoptNS([_WKUserContentWorld worldWithName:@&quot;TestWorld&quot;]);
+
+    RetainPtr&lt;WKUserScript&gt; userScript = adoptNS([[WKUserScript alloc] initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]);
+    RetainPtr&lt;WKUserScript&gt; userScriptAssociatedWithWorld = adoptNS([[WKUserScript alloc] _initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    RetainPtr&lt;WKUserScript&gt; userScriptAssociatedWithWorld2 = adoptNS([[WKUserScript alloc] _initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    
+    [userContentController addUserScript:userScript.get()];
+    [userContentController addUserScript:userScriptAssociatedWithWorld.get()];
+    [userContentController addUserScript:userScriptAssociatedWithWorld2.get()];
+    
+    EXPECT_EQ(3u, [userContentController userScripts].count);
+    EXPECT_EQ(userScript.get(), [userContentController userScripts][0]);
+    EXPECT_EQ(userScriptAssociatedWithWorld.get(), [userContentController userScripts][1]);
+    EXPECT_EQ(userScriptAssociatedWithWorld2.get(), [userContentController userScripts][2]);
+
+    [userContentController _removeAllUserScriptsAssociatedWithUserContentWorld:world.get()];
+
+    EXPECT_EQ(1u, [userContentController userScripts].count);
+    EXPECT_EQ(userScript.get(), [userContentController userScripts][0]);
+}
+
+TEST(WKUserContentController, UserScriptRemoveAllByNormalWorld)
+{
+    RetainPtr&lt;WKUserContentController&gt; userContentController = adoptNS([[WKUserContentController alloc] init]);
+
+    RetainPtr&lt;_WKUserContentWorld&gt; world = adoptNS([_WKUserContentWorld worldWithName:@&quot;TestWorld&quot;]);
+
+    RetainPtr&lt;WKUserScript&gt; userScript = adoptNS([[WKUserScript alloc] initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]);
+    RetainPtr&lt;WKUserScript&gt; userScriptAssociatedWithWorld = adoptNS([[WKUserScript alloc] _initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    RetainPtr&lt;WKUserScript&gt; userScriptAssociatedWithWorld2 = adoptNS([[WKUserScript alloc] _initWithSource:@&quot;&quot; injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:world.get()]);
+    
+    [userContentController addUserScript:userScript.get()];
+    [userContentController addUserScript:userScriptAssociatedWithWorld.get()];
+    [userContentController addUserScript:userScriptAssociatedWithWorld2.get()];
+    
+    EXPECT_EQ(3u, [userContentController userScripts].count);
+    EXPECT_EQ(userScript.get(), [userContentController userScripts][0]);
+    EXPECT_EQ(userScriptAssociatedWithWorld.get(), [userContentController userScripts][1]);
+    EXPECT_EQ(userScriptAssociatedWithWorld2.get(), [userContentController userScripts][2]);
+
+    [userContentController _removeAllUserScriptsAssociatedWithUserContentWorld:[_WKUserContentWorld normalWorld]];
+
+    EXPECT_EQ(2u, [userContentController userScripts].count);
+    EXPECT_EQ(userScriptAssociatedWithWorld.get(), [userContentController userScripts][0]);
+    EXPECT_EQ(userScriptAssociatedWithWorld2.get(), [userContentController userScripts][1]);
+}
+
</ins><span class="cx"> #endif
</span></span></pre>
</div>
</div>

</body>
</html>