Allow WKUserScripts to be run in isolated worlds
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Feb 2016 17:50:50 +0000 (17:50 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Feb 2016 17:50:50 +0000 (17:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=154701

Reviewed by Anders Carlsson.

Source/WebKit2:

Adds support for using isolated worlds, called _WKUserContentWorlds in the SPI,
from the UIProcess.

* Shared/API/APIObject.h:
* Shared/Cocoa/APIObject.mm:
* UIProcess/API/APIUserContentWorld.cpp: Added.
(API::generateIdentifier):
(API::UserContentWorld::worldWithName):
(API::UserContentWorld::normalWorld):
(API::UserContentWorld::UserContentWorld):
(API::UserContentWorld::~UserContentWorld):
* UIProcess/API/APIUserContentWorld.h: Added.
Add new UserContentWorld type.

* UIProcess/API/APIUserScript.h:
Bind each user script to a particular _WKUserContentWorld.

* UIProcess/API/C/WKUserScriptRef.cpp:
(WKUserScriptCreateWithSource):
(WKUserScriptCopySource):
Existing APIs create user scripts for the normal world, preserving existing behavior.

* UIProcess/API/Cocoa/WKUserScript.mm:
(-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:]):
Existing APIs create user scripts for the normal world, preserving existing behavior.

(-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
Add a new initializer which takes a world to bind to.  Also add support for the legacy whitelist/blacklist mechanism
while we are here, as the expected client needs these as well.

(-[WKUserScript _userContentWorld]):
Add accessor for the bound world.

* UIProcess/API/Cocoa/WKUserScriptInternal.h:
* UIProcess/API/Cocoa/WKUserScriptPrivate.h: Added.
Add new private header.

* UIProcess/API/Cocoa/_WKUserContentWorld.h: Added.
* UIProcess/API/Cocoa/_WKUserContentWorld.mm: Added.
(+[_WKUserContentWorld worldWithName:]):
(+[_WKUserContentWorld normalWorld]):
(-[_WKUserContentWorld dealloc]):
(-[_WKUserContentWorld name]):
(-[_WKUserContentWorld _apiObject]):
* UIProcess/API/Cocoa/_WKUserContentWorldInternal.h: Added.
Add SPI wrapper.

* UIProcess/UserContent/WebUserContentControllerProxy.cpp:
(WebKit::WebUserContentControllerProxy::addProcess):
(WebKit::WebUserContentControllerProxy::addUserScript):
(WebKit::WebUserContentControllerProxy::removeUserScript):
(WebKit::WebUserContentControllerProxy::removeAllUserScripts):
(WebKit::WebUserContentControllerProxy::addUserStyleSheet):
* UIProcess/UserContent/WebUserContentControllerProxy.h:
(WebKit::WebUserContentControllerProxy::userScripts):
(WebKit::WebUserContentControllerProxy::userStyleSheets):
Add support for registering the worlds with the associated WebContentProcesses and then using
their identifiers to map user scripts to the correct world.

* WebKit2.xcodeproj/project.pbxproj:
Add new files.

* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInScriptWorld.h:
* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInScriptWorld.mm:
(-[WKWebProcessPlugInScriptWorld name]):
Expose the name property.

* WebProcess/InjectedBundle/API/c/WKBundleScriptWorld.cpp:
(WKBundleScriptWorldCopyName):
* WebProcess/InjectedBundle/API/c/WKBundleScriptWorld.h:
Expose the name property.

* WebProcess/InjectedBundle/InjectedBundleScriptWorld.cpp:
(WebKit::allWorlds):
(WebKit::InjectedBundleScriptWorld::create):
(WebKit::InjectedBundleScriptWorld::getOrCreate):
(WebKit::InjectedBundleScriptWorld::normalWorld):
(WebKit::InjectedBundleScriptWorld::InjectedBundleScriptWorld):
(WebKit::InjectedBundleScriptWorld::~InjectedBundleScriptWorld):
(WebKit::InjectedBundleScriptWorld::coreWorld):
(WebKit::InjectedBundleScriptWorld::clearWrappers):
* WebProcess/InjectedBundle/InjectedBundleScriptWorld.h:
(WebKit::InjectedBundleScriptWorld::name):
Add the name property and do some drive-by RefPtr -> Ref conversions.

* WebProcess/UserContent/WebUserContentController.cpp:
(WebKit::userContentControllers):
(WebKit::worldMap):
(WebKit::WebUserContentController::getOrCreate):
(WebKit::WebUserContentController::~WebUserContentController):
(WebKit::WebUserContentController::addUserContentWorlds):
(WebKit::WebUserContentController::removeUserContentWorld):
(WebKit::WebUserContentController::addUserScripts):
(WebKit::WebUserContentController::removeUserScript):
(WebKit::WebUserContentController::removeAllUserScripts):
(WebKit::WebUserContentController::addUserStyleSheets):
* WebProcess/UserContent/WebUserContentController.h:
* WebProcess/UserContent/WebUserContentController.messages.in:
Track and use worlds passed from the UIProcess.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentWorld.mm: Added.
(-[SimpleDelegate webView:didFinishNavigation:]):
(-[UserContentWorldRemoteObject didObserveNormalWorld]):
(-[UserContentWorldRemoteObject didObserveWorldWithName:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentWorldPlugIn.mm: Added.
(-[_WKUserContentWorldPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
(-[_WKUserContentWorldPlugIn webProcessPlugInBrowserContextController:globalObjectIsAvailableForFrame:inScriptWorld:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentWorldProtocol.h: Added.

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

30 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/API/APIObject.h
Source/WebKit2/Shared/Cocoa/APIObject.mm
Source/WebKit2/UIProcess/API/APIUserContentWorld.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/API/APIUserContentWorld.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/APIUserScript.h
Source/WebKit2/UIProcess/API/C/WKUserScriptRef.cpp
Source/WebKit2/UIProcess/API/Cocoa/WKUserScript.mm
Source/WebKit2/UIProcess/API/Cocoa/WKUserScriptInternal.h
Source/WebKit2/UIProcess/API/Cocoa/WKUserScriptPrivate.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorld.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorld.mm [new file with mode: 0644]
Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h [new file with mode: 0644]
Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.cpp
Source/WebKit2/UIProcess/UserContent/WebUserContentControllerProxy.h
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInScriptWorld.h
Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInScriptWorld.mm
Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundleScriptWorld.cpp
Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundleScriptWorld.h
Source/WebKit2/WebProcess/InjectedBundle/InjectedBundleScriptWorld.cpp
Source/WebKit2/WebProcess/InjectedBundle/InjectedBundleScriptWorld.h
Source/WebKit2/WebProcess/UserContent/WebUserContentController.cpp
Source/WebKit2/WebProcess/UserContent/WebUserContentController.h
Source/WebKit2/WebProcess/UserContent/WebUserContentController.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorld.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldPlugIn.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h [new file with mode: 0644]

index 4784db5..0c6581d 100644 (file)
@@ -1,3 +1,110 @@
+2016-02-25  Sam Weinig  <sam@webkit.org>
+
+        Allow WKUserScripts to be run in isolated worlds
+        https://bugs.webkit.org/show_bug.cgi?id=154701
+
+        Reviewed by Anders Carlsson.
+
+        Adds support for using isolated worlds, called _WKUserContentWorlds in the SPI,
+        from the UIProcess.
+
+        * Shared/API/APIObject.h:
+        * Shared/Cocoa/APIObject.mm:
+        * UIProcess/API/APIUserContentWorld.cpp: Added.
+        (API::generateIdentifier):
+        (API::UserContentWorld::worldWithName):
+        (API::UserContentWorld::normalWorld):
+        (API::UserContentWorld::UserContentWorld):
+        (API::UserContentWorld::~UserContentWorld):
+        * UIProcess/API/APIUserContentWorld.h: Added.
+        Add new UserContentWorld type.
+
+        * UIProcess/API/APIUserScript.h:
+        Bind each user script to a particular _WKUserContentWorld.
+
+        * UIProcess/API/C/WKUserScriptRef.cpp:
+        (WKUserScriptCreateWithSource):
+        (WKUserScriptCopySource):
+        Existing APIs create user scripts for the normal world, preserving existing behavior.
+
+        * UIProcess/API/Cocoa/WKUserScript.mm:
+        (-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:]):
+        Existing APIs create user scripts for the normal world, preserving existing behavior.
+
+        (-[WKUserScript _initWithSource:injectionTime:forMainFrameOnly:legacyWhitelist:legacyBlacklist:userContentWorld:]):
+        Add a new initializer which takes a world to bind to.  Also add support for the legacy whitelist/blacklist mechanism
+        while we are here, as the expected client needs these as well.
+
+        (-[WKUserScript _userContentWorld]):
+        Add accessor for the bound world.
+
+        * UIProcess/API/Cocoa/WKUserScriptInternal.h:
+        * UIProcess/API/Cocoa/WKUserScriptPrivate.h: Added.
+        Add new private header.
+
+        * UIProcess/API/Cocoa/_WKUserContentWorld.h: Added.
+        * UIProcess/API/Cocoa/_WKUserContentWorld.mm: Added.
+        (+[_WKUserContentWorld worldWithName:]):
+        (+[_WKUserContentWorld normalWorld]):
+        (-[_WKUserContentWorld dealloc]):
+        (-[_WKUserContentWorld name]):
+        (-[_WKUserContentWorld _apiObject]):
+        * UIProcess/API/Cocoa/_WKUserContentWorldInternal.h: Added.
+        Add SPI wrapper.
+
+        * UIProcess/UserContent/WebUserContentControllerProxy.cpp:
+        (WebKit::WebUserContentControllerProxy::addProcess):
+        (WebKit::WebUserContentControllerProxy::addUserScript):
+        (WebKit::WebUserContentControllerProxy::removeUserScript):
+        (WebKit::WebUserContentControllerProxy::removeAllUserScripts):
+        (WebKit::WebUserContentControllerProxy::addUserStyleSheet):
+        * UIProcess/UserContent/WebUserContentControllerProxy.h:
+        (WebKit::WebUserContentControllerProxy::userScripts):
+        (WebKit::WebUserContentControllerProxy::userStyleSheets):
+        Add support for registering the worlds with the associated WebContentProcesses and then using
+        their identifiers to map user scripts to the correct world.
+        
+        * WebKit2.xcodeproj/project.pbxproj:
+        Add new files.
+
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInScriptWorld.h:
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInScriptWorld.mm:
+        (-[WKWebProcessPlugInScriptWorld name]):
+        Expose the name property.
+
+        * WebProcess/InjectedBundle/API/c/WKBundleScriptWorld.cpp:
+        (WKBundleScriptWorldCopyName):
+        * WebProcess/InjectedBundle/API/c/WKBundleScriptWorld.h:
+        Expose the name property.
+
+        * WebProcess/InjectedBundle/InjectedBundleScriptWorld.cpp:
+        (WebKit::allWorlds):
+        (WebKit::InjectedBundleScriptWorld::create):
+        (WebKit::InjectedBundleScriptWorld::getOrCreate):
+        (WebKit::InjectedBundleScriptWorld::normalWorld):
+        (WebKit::InjectedBundleScriptWorld::InjectedBundleScriptWorld):
+        (WebKit::InjectedBundleScriptWorld::~InjectedBundleScriptWorld):
+        (WebKit::InjectedBundleScriptWorld::coreWorld):
+        (WebKit::InjectedBundleScriptWorld::clearWrappers):
+        * WebProcess/InjectedBundle/InjectedBundleScriptWorld.h:
+        (WebKit::InjectedBundleScriptWorld::name):
+        Add the name property and do some drive-by RefPtr -> Ref conversions.
+
+        * WebProcess/UserContent/WebUserContentController.cpp:
+        (WebKit::userContentControllers):
+        (WebKit::worldMap):
+        (WebKit::WebUserContentController::getOrCreate):
+        (WebKit::WebUserContentController::~WebUserContentController):
+        (WebKit::WebUserContentController::addUserContentWorlds):
+        (WebKit::WebUserContentController::removeUserContentWorld):
+        (WebKit::WebUserContentController::addUserScripts):
+        (WebKit::WebUserContentController::removeUserScript):
+        (WebKit::WebUserContentController::removeAllUserScripts):
+        (WebKit::WebUserContentController::addUserStyleSheets):
+        * WebProcess/UserContent/WebUserContentController.h:
+        * WebProcess/UserContent/WebUserContentController.messages.in:
+        Track and use worlds passed from the UIProcess.
+
 2016-02-26  Andreas Kling  <akling@apple.com>
 
         [Darwin] Use vm_kernel_page_size for WTF::pageSize().
index 676c583..cf0079b 100644 (file)
@@ -147,6 +147,7 @@ public:
         UserContentController,
         UserContentExtension,
         UserContentExtensionStore,
+        UserContentWorld,
         UserMediaPermissionCheck,
         UserMediaPermissionRequest,
         Vibration,
index a2f0416..b2f6a64 100644 (file)
@@ -68,6 +68,7 @@
 #import "_WKProcessPoolConfigurationInternal.h"
 #import "_WKUserContentExtensionStoreInternal.h"
 #import "_WKUserContentFilterInternal.h"
+#import "_WKUserContentWorldInternal.h"
 #import "_WKUserStyleSheetInternal.h"
 #import "_WKVisitedLinkStoreInternal.h"
 
@@ -212,6 +213,10 @@ void* Object::newObject(size_t size, Type type)
         wrapper = [_WKUserContentExtensionStore alloc];
         break;
 
+    case Type::UserContentWorld:
+        wrapper = [_WKUserContentWorld alloc];
+        break;
+
     case Type::UserScript:
         wrapper = [WKUserScript alloc];
         break;
diff --git a/Source/WebKit2/UIProcess/API/APIUserContentWorld.cpp b/Source/WebKit2/UIProcess/API/APIUserContentWorld.cpp
new file mode 100644 (file)
index 0000000..ee2c380
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "APIUserContentWorld.h"
+
+#include <wtf/NeverDestroyed.h>
+
+namespace API {
+
+static const uint64_t normalWorldIdentifer = 1;
+
+static uint64_t generateIdentifier()
+{
+    static uint64_t identifier = normalWorldIdentifer;
+
+    return ++identifier;
+}
+
+Ref<UserContentWorld> UserContentWorld::worldWithName(const WTF::String& name)
+{
+    return adoptRef(*new UserContentWorld(name));
+}
+
+UserContentWorld& UserContentWorld::normalWorld()
+{
+    static UserContentWorld* world = new UserContentWorld(ForNormalWorldOnly::NormalWorld);
+    return *world;
+}
+
+UserContentWorld::UserContentWorld(const WTF::String& name)
+    : m_identifier(generateIdentifier())
+    , m_name(name)
+{
+}
+
+UserContentWorld::UserContentWorld(ForNormalWorldOnly)
+    : m_identifier(normalWorldIdentifer)
+{
+}
+
+UserContentWorld::~UserContentWorld()
+{
+}
+
+} // namespace API
diff --git a/Source/WebKit2/UIProcess/API/APIUserContentWorld.h b/Source/WebKit2/UIProcess/API/APIUserContentWorld.h
new file mode 100644 (file)
index 0000000..840fe1c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef APIUserContentWorld_h
+#define APIUserContentWorld_h
+
+#include "APIObject.h"
+#include <wtf/text/WTFString.h>
+
+namespace API {
+
+class UserContentWorld final : public API::ObjectImpl<API::Object::Type::UserContentWorld> {
+public:
+    static Ref<UserContentWorld> worldWithName(const WTF::String&);
+    static UserContentWorld& normalWorld();
+
+    virtual ~UserContentWorld();
+
+    const WTF::String& name() const { return m_name; }
+    uint64_t identifier() const { return m_identifier; }
+
+private:
+    UserContentWorld(const WTF::String&);
+
+    enum class ForNormalWorldOnly { NormalWorld };
+    UserContentWorld(ForNormalWorldOnly);
+
+    uint64_t m_identifier;
+    WTF::String m_name;
+};
+
+} // namespace API
+
+#endif // APIUserContentWorld_h
index 03e2f62..d6d3222 100644 (file)
@@ -27,6 +27,7 @@
 #define APIUserScript_h
 
 #include "APIObject.h"
+#include "APIUserContentWorld.h"
 #include <WebCore/UserScript.h>
 
 namespace API {
@@ -35,20 +36,25 @@ class UserScript final : public ObjectImpl<Object::Type::UserScript> {
 public:
     static WebCore::URL generateUniqueURL();
 
-    static Ref<UserScript> create(WebCore::UserScript userScript)
+    static Ref<UserScript> create(WebCore::UserScript userScript, API::UserContentWorld& world)
     {
-        return adoptRef(*new UserScript(WTFMove(userScript)));
+        return adoptRef(*new UserScript(WTFMove(userScript), world));
     }
 
-    UserScript(WebCore::UserScript userScript)
+    UserScript(WebCore::UserScript userScript, API::UserContentWorld& world)
         : m_userScript(userScript)
+        , m_world(world)
     {
     }
 
     const WebCore::UserScript& userScript() const { return m_userScript; }
-
+    
+    UserContentWorld& userContentWorld() { return m_world; }
+    const UserContentWorld& userContentWorld() const { return m_world; }
+    
 private:
     WebCore::UserScript m_userScript;
+    Ref<UserContentWorld> m_world;
 };
 
 } // namespace API
index ad71b01..17e7629 100644 (file)
@@ -38,7 +38,7 @@ WKTypeID WKUserScriptGetTypeID()
 
 WKUserScriptRef WKUserScriptCreateWithSource(WKStringRef sourceRef, _WKUserScriptInjectionTime injectionTime, bool forMainFrameOnly)
 {
-    return toAPI(&API::UserScript::create(WebCore::UserScript { toWTFString(sourceRef), API::UserScript::generateUniqueURL(), { }, { }, toUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }).leakRef());
+    return toAPI(&API::UserScript::create(WebCore::UserScript { toWTFString(sourceRef), API::UserScript::generateUniqueURL(), { }, { }, toUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, API::UserContentWorld::normalWorld()).leakRef());
 }
 
 WKStringRef WKUserScriptCopySource(WKUserScriptRef userScriptRef)
index 4c2716c..386d268 100644 (file)
@@ -26,6 +26,8 @@
 #import "config.h"
 #import "WKUserScriptInternal.h"
 
+#import "_WKUserContentWorldInternal.h"
+
 #if WK_API_ENABLED
 
 @implementation WKUserScript
@@ -35,7 +37,7 @@
     if (!(self = [super init]))
         return nil;
 
-    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), { }, { }, API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames });
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), { }, { }, API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, API::UserContentWorld::normalWorld());
 
     return self;
 }
 
 @end
 
+@implementation WKUserScript (WKPrivate)
+
+static Vector<WTF::String> toStringVector(NSArray<NSString *> *input)
+{
+    Vector<WTF::String> vector;
+
+    NSUInteger size = input.count;
+    if (!size)
+        return vector;
+
+    vector.reserveInitialCapacity(size);
+    for (NSString *string : input)
+        vector.uncheckedAppend(string);
+    return vector;
+}
+
+- (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray<NSString *> *)legacyWhitelist legacyBlacklist:(NSArray<NSString *> *)legacyBlacklist userContentWorld:(_WKUserContentWorld *)userContentWorld
+{
+    if (!(self = [super init]))
+        return nil;
+
+    API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { WTF::String(source), API::UserScript::generateUniqueURL(), toStringVector(legacyWhitelist), toStringVector(legacyBlacklist), API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::InjectInTopFrameOnly : WebCore::InjectInAllFrames }, *userContentWorld->_userContentWorld);
+
+    return self;
+}
+
+- (_WKUserContentWorld *)_userContentWorld
+{
+    return API::wrapper(_userScript->userContentWorld());
+}
+
+@end
+
 #endif
index 65f30c6..99a291f 100644 (file)
@@ -23,7 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "WKUserScript.h"
+#import "WKUserScriptPrivate.h"
 
 #if WK_API_ENABLED
 
diff --git a/Source/WebKit2/UIProcess/API/Cocoa/WKUserScriptPrivate.h b/Source/WebKit2/UIProcess/API/Cocoa/WKUserScriptPrivate.h
new file mode 100644 (file)
index 0000000..28385ef
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKUserScript.h>
+
+#if WK_API_ENABLED
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class _WKUserContentWorld;
+
+@interface WKUserScript (WKPrivate)
+
+- (instancetype)_initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly legacyWhitelist:(NSArray<NSString *> *)legacyWhitelist legacyBlacklist:(NSArray<NSString *> *)legacyBlacklist userContentWorld:(_WKUserContentWorld *)userContentWorld WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
+
+@property (nonatomic, readonly) _WKUserContentWorld *_userContentWorld WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorld.h b/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorld.h
new file mode 100644 (file)
index 0000000..3df59de
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+NS_ASSUME_NONNULL_BEGIN
+
+WK_CLASS_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA)
+@interface _WKUserContentWorld : NSObject
+
++ (_WKUserContentWorld *)worldWithName:(NSString *)name;
++ (_WKUserContentWorld *)normalWorld;
+
+@property (nullable, nonatomic, readonly, copy) NSString *name;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // WK_API_ENABLED
diff --git a/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorld.mm b/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorld.mm
new file mode 100644 (file)
index 0000000..4fd17f3
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "_WKUserContentWorldInternal.h"
+
+#if WK_API_ENABLED
+
+@implementation _WKUserContentWorld
+
++ (_WKUserContentWorld *)worldWithName:(NSString *)name
+{
+    return [wrapper(API::UserContentWorld::worldWithName(name).leakRef()) autorelease];
+}
+
++ (_WKUserContentWorld *)normalWorld
+{
+    return wrapper(API::UserContentWorld::normalWorld());
+}
+
+- (void)dealloc
+{
+    _userContentWorld->~UserContentWorld();
+
+    [super dealloc];
+}
+
+- (NSString *)name
+{
+    if (_userContentWorld.get() == &API::UserContentWorld::normalWorld())
+        return nil;
+    return _userContentWorld->name();
+}
+
+#pragma mark WKObject protocol implementation
+
+- (API::Object&)_apiObject
+{
+    return *_userContentWorld;
+}
+
+@end
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h b/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentWorldInternal.h
new file mode 100644 (file)
index 0000000..5fb23b2
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "_WKUserContentWorld.h"
+
+#if WK_API_ENABLED
+
+#import "APIUserContentWorld.h"
+#import "WKObject.h"
+
+namespace API {
+
+inline _WKUserContentWorld *wrapper(UserContentWorld& userContentWorld)
+{
+    ASSERT([userContentWorld.wrapper() isKindOfClass:[_WKUserContentWorld class]]);
+    return (_WKUserContentWorld *)userContentWorld.wrapper();
+}
+
+}
+
+@interface _WKUserContentWorld () <WKObject> {
+@package
+    API::ObjectStorage<API::UserContentWorld> _userContentWorld;
+}
+@end
+
+#endif
index b40662f..fedff0a 100644 (file)
@@ -27,6 +27,7 @@
 #include "WebUserContentControllerProxy.h"
 
 #include "APIArray.h"
+#include "APIUserContentWorld.h"
 #include "APIUserScript.h"
 #include "APIUserStyleSheet.h"
 #include "DataReference.h"
@@ -74,9 +75,14 @@ void WebUserContentControllerProxy::addProcess(WebProcessProxy& webProcessProxy)
 
     webProcessProxy.addMessageReceiver(Messages::WebUserContentControllerProxy::messageReceiverName(), m_identifier, *this);
 
-    Vector<WebCore::UserScript> userScripts;
+    Vector<std::pair<uint64_t, String>> userContentWorlds;
+    for (const auto& world : m_userContentWorlds)
+        userContentWorlds.append(std::make_pair(world.key->identifier(), world.key->name()));
+    webProcessProxy.connection()->send(Messages::WebUserContentController::AddUserContentWorlds(userContentWorlds), m_identifier);
+
+    Vector<std::pair<uint64_t, WebCore::UserScript>> userScripts;
     for (const auto& userScript : m_userScripts->elementsOfType<API::UserScript>())
-        userScripts.append(userScript->userScript());
+        userScripts.append(std::make_pair(userScript->userContentWorld().identifier(), userScript->userScript()));
     webProcessProxy.connection()->send(Messages::WebUserContentController::AddUserScripts(userScripts), m_identifier);
 
     Vector<WebCore::UserStyleSheet> userStyleSheets;
@@ -107,26 +113,45 @@ void WebUserContentControllerProxy::removeProcess(WebProcessProxy& webProcessPro
 
 void WebUserContentControllerProxy::addUserScript(API::UserScript& userScript)
 {
+    Ref<API::UserContentWorld> world = userScript.userContentWorld();
+
+    if (world.ptr() != &API::UserContentWorld::normalWorld()) {
+        auto addResult = m_userContentWorlds.add(world.ptr());
+        if (addResult.isNewEntry) {
+            for (WebProcessProxy* process : m_processes)
+                process->connection()->send(Messages::WebUserContentController::AddUserContentWorlds({ std::make_pair(world->identifier(), world->name()) }), m_identifier);
+        }
+    }
+
     m_userScripts->elements().append(&userScript);
 
     for (WebProcessProxy* process : m_processes)
-        process->connection()->send(Messages::WebUserContentController::AddUserScripts({ userScript.userScript() }), m_identifier);
+        process->connection()->send(Messages::WebUserContentController::AddUserScripts({ std::make_pair(world->identifier(), userScript.userScript()) }), m_identifier);
 }
 
-void WebUserContentControllerProxy::removeUserScript(const API::UserScript& userScript)
+void WebUserContentControllerProxy::removeUserScript(API::UserScript& userScript)
 {
+    Ref<API::UserContentWorld> world = userScript.userContentWorld();
+
     for (WebProcessProxy* process : m_processes)
-        process->connection()->send(Messages::WebUserContentController::RemoveUserScript({ userScript.userScript().url().string() }), m_identifier);
+        process->connection()->send(Messages::WebUserContentController::RemoveUserScript(world->identifier(), userScript.userScript().url().string()), m_identifier);
 
     m_userScripts->elements().removeAll(&userScript);
+
+    if (world.ptr() != &API::UserContentWorld::normalWorld()) {
+        if (m_userContentWorlds.remove(&userScript.userContentWorld())) {
+            for (WebProcessProxy* process : m_processes)
+                process->connection()->send(Messages::WebUserContentController::RemoveUserContentWorld(world->identifier()), m_identifier);
+        }
+    }
 }
 
 void WebUserContentControllerProxy::removeAllUserScripts()
 {
-    m_userScripts->elements().clear();
-
     for (WebProcessProxy* process : m_processes)
-        process->connection()->send(Messages::WebUserContentController::RemoveAllUserScripts(), m_identifier);
+        process->connection()->send(Messages::WebUserContentController::RemoveAllUserScripts(API::UserContentWorld::normalWorld().identifier()), m_identifier);
+
+    m_userScripts->elements().clear();
 }
 
 void WebUserContentControllerProxy::addUserStyleSheet(API::UserStyleSheet& userStyleSheet)
index e9ff9a9..ca1418c 100644 (file)
@@ -29,6 +29,7 @@
 #include "APIObject.h"
 #include "MessageReceiver.h"
 #include <wtf/Forward.h>
+#include <wtf/HashCountedSet.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/PassRefPtr.h>
@@ -39,6 +40,7 @@
 
 namespace API {
 class Array;
+class UserContentWorld;
 class UserContentExtension;
 class UserScript;
 class UserStyleSheet;
@@ -73,7 +75,7 @@ public:
 
     API::Array& userScripts() { return m_userScripts.get(); }
     void addUserScript(API::UserScript&);
-    void removeUserScript(const API::UserScript&);
+    void removeUserScript(API::UserScript&);
     void removeAllUserScripts();
 
     API::Array& userStyleSheets() { return m_userStyleSheets.get(); }
@@ -102,6 +104,7 @@ private:
     Ref<API::Array> m_userScripts;
     Ref<API::Array> m_userStyleSheets;
     HashMap<uint64_t, RefPtr<WebScriptMessageHandler>> m_scriptMessageHandlers;
+    HashCountedSet<RefPtr<API::UserContentWorld>> m_userContentWorlds;
 
 #if ENABLE(CONTENT_EXTENSIONS)
     HashMap<String, RefPtr<API::UserContentExtension>> m_userContentExtensions;
index a311eb6..a25a0ee 100644 (file)
                7C85FD7C193415A8000177C4 /* WebPreferencesDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C85FD7B193415A8000177C4 /* WebPreferencesDefinitions.h */; };
                7C85FD7F19341665000177C4 /* WebPreferencesKeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C85FD7D19341665000177C4 /* WebPreferencesKeys.cpp */; };
                7C85FD8019341665000177C4 /* WebPreferencesKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C85FD7E19341665000177C4 /* WebPreferencesKeys.h */; };
+               7C882DF71C7E9965006BF731 /* _WKUserContentWorld.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C882DF31C7E995E006BF731 /* _WKUserContentWorld.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               7C882DF81C7E996C006BF731 /* _WKUserContentWorld.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7C882DF41C7E995E006BF731 /* _WKUserContentWorld.mm */; };
+               7C882DF91C7E996F006BF731 /* _WKUserContentWorldInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C882DF51C7E995E006BF731 /* _WKUserContentWorldInternal.h */; };
+               7C882DFA1C7E9973006BF731 /* WKUserScriptPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C882DF61C7E995E006BF731 /* WKUserScriptPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               7C882DFD1C7E99A8006BF731 /* APIUserContentWorld.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C882DFC1C7E99A6006BF731 /* APIUserContentWorld.h */; };
+               7C882DFE1C7E99AC006BF731 /* APIUserContentWorld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C882DFB1C7E99A6006BF731 /* APIUserContentWorld.cpp */; };
                7C89D2941A67122F003A5FDE /* APIUserScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C89D2921A67122F003A5FDE /* APIUserScript.h */; };
                7C89D2971A6753B2003A5FDE /* APIPageConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89D2951A6753B2003A5FDE /* APIPageConfiguration.cpp */; };
                7C89D2981A6753B2003A5FDE /* APIPageConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C89D2961A6753B2003A5FDE /* APIPageConfiguration.h */; };
                7C85FD7B193415A8000177C4 /* WebPreferencesDefinitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPreferencesDefinitions.h; sourceTree = "<group>"; };
                7C85FD7D19341665000177C4 /* WebPreferencesKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPreferencesKeys.cpp; sourceTree = "<group>"; };
                7C85FD7E19341665000177C4 /* WebPreferencesKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPreferencesKeys.h; sourceTree = "<group>"; };
+               7C882DF31C7E995E006BF731 /* _WKUserContentWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUserContentWorld.h; sourceTree = "<group>"; };
+               7C882DF41C7E995E006BF731 /* _WKUserContentWorld.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKUserContentWorld.mm; sourceTree = "<group>"; };
+               7C882DF51C7E995E006BF731 /* _WKUserContentWorldInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUserContentWorldInternal.h; sourceTree = "<group>"; };
+               7C882DF61C7E995E006BF731 /* WKUserScriptPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKUserScriptPrivate.h; sourceTree = "<group>"; };
+               7C882DFB1C7E99A6006BF731 /* APIUserContentWorld.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIUserContentWorld.cpp; sourceTree = "<group>"; };
+               7C882DFC1C7E99A6006BF731 /* APIUserContentWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIUserContentWorld.h; sourceTree = "<group>"; };
                7C89D2921A67122F003A5FDE /* APIUserScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIUserScript.h; sourceTree = "<group>"; };
                7C89D2951A6753B2003A5FDE /* APIPageConfiguration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIPageConfiguration.cpp; sourceTree = "<group>"; };
                7C89D2961A6753B2003A5FDE /* APIPageConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIPageConfiguration.h; sourceTree = "<group>"; };
                                7C89D2B81A6B0F2C003A5FDE /* _WKUserContentFilter.h */,
                                7C89D2B71A6B0F2C003A5FDE /* _WKUserContentFilter.mm */,
                                7C89D2BB1A6B0F5B003A5FDE /* _WKUserContentFilterInternal.h */,
+                               7C882DF31C7E995E006BF731 /* _WKUserContentWorld.h */,
+                               7C882DF41C7E995E006BF731 /* _WKUserContentWorld.mm */,
+                               7C882DF51C7E995E006BF731 /* _WKUserContentWorldInternal.h */,
                                2D87861B1BDB54BF00D02ABB /* _WKUserStyleSheet.h */,
                                2D87861C1BDB54BF00D02ABB /* _WKUserStyleSheet.mm */,
                                2D87861F1BDB57F500D02ABB /* _WKUserStyleSheetInternal.h */,
                                1AAF089919267EE500B6390C /* WKUserScript.h */,
                                1AAF089819267EE500B6390C /* WKUserScript.mm */,
                                1AAF089C19267FC800B6390C /* WKUserScriptInternal.h */,
+                               7C882DF61C7E995E006BF731 /* WKUserScriptPrivate.h */,
                                1A4832CA1A9BC465008B4DFE /* WKWebsiteDataRecord.h */,
                                1A4832C91A9BC465008B4DFE /* WKWebsiteDataRecord.mm */,
                                1A4832CD1A9BC484008B4DFE /* WKWebsiteDataRecordInternal.h */,
                                7C89D2B21A6B068C003A5FDE /* APIUserContentExtension.h */,
                                7C3A06A51AAB903E009D74BA /* APIUserContentExtensionStore.cpp */,
                                7C3A06A61AAB903E009D74BA /* APIUserContentExtensionStore.h */,
+                               7C882DFB1C7E99A6006BF731 /* APIUserContentWorld.cpp */,
+                               7C882DFC1C7E99A6006BF731 /* APIUserContentWorld.h */,
                                7C89D2A51A6789EA003A5FDE /* APIUserScript.cpp */,
                                7C89D2921A67122F003A5FDE /* APIUserScript.h */,
                                2D8786211BDB58FF00D02ABB /* APIUserStyleSheet.cpp */,
                                1A3DD206125E5A2F004515E6 /* APIClient.h in Headers */,
                                076E884E1A13CADF005E90FC /* APIContextMenuClient.h in Headers */,
                                51578B831209ECEF00A37C4A /* APIData.h in Headers */,
+                               7C882DF91C7E996F006BF731 /* _WKUserContentWorldInternal.h in Headers */,
                                83891B631A68B3420030F386 /* APIDiagnosticLoggingClient.h in Headers */,
                                7C1BA33E1A4A0E600043E249 /* APIDictionary.h in Headers */,
                                1F7D36C118DA513F00D9D659 /* APIDownloadClient.h in Headers */,
                                CEDA12E3152CD1B300D9E08D /* WebAlternativeTextClient.h in Headers */,
                                BC72BA1E11E64907001EB4EA /* WebBackForwardList.h in Headers */,
                                518D2CAE12D5153B003BB93B /* WebBackForwardListItem.h in Headers */,
+                               7C882DFD1C7E99A8006BF731 /* APIUserContentWorld.h in Headers */,
                                BC72B9FB11E6476B001EB4EA /* WebBackForwardListProxy.h in Headers */,
                                BCF50728124329AA005955AE /* WebCertificateInfo.h in Headers */,
                                BC032D7510F4378D0058C15A /* WebChromeClient.h in Headers */,
                                512F589D12A8838800629530 /* WebProtectionSpace.h in Headers */,
                                A1C512C9190656E500448914 /* WebQuickLookHandleClient.h in Headers */,
                                37948404150C350600E52CE9 /* WebRenderLayer.h in Headers */,
+                               7C882DF71C7E9965006BF731 /* _WKUserContentWorld.h in Headers */,
                                3760881F150413E900FC82C7 /* WebRenderObject.h in Headers */,
                                510AFFBA16542048001BA05E /* WebResourceLoader.h in Headers */,
                                51F060E01654317F00F3281B /* WebResourceLoaderMessages.h in Headers */,
                                37C4C08D1814AC5C003688B9 /* WKBackForwardList.h in Headers */,
                                37C4C0951814B9E6003688B9 /* WKBackForwardListInternal.h in Headers */,
                                510523701C739D42007993CB /* WebIDBConnectionToClient.h in Headers */,
+                               7C882DFA1C7E9973006BF731 /* WKUserScriptPrivate.h in Headers */,
                                37C4C08718149C5B003688B9 /* WKBackForwardListItem.h in Headers */,
                                37C4C08918149F23003688B9 /* WKBackForwardListItemInternal.h in Headers */,
                                BC646C1D11DD399F006455B0 /* WKBackForwardListItemRef.h in Headers */,
                                31A67E0C165B2A99006CBA66 /* PlugInAutoStartProvider.cpp in Sources */,
                                1A8EF4CC1252403700F7067F /* PluginControllerProxy.cpp in Sources */,
                                1A2D91A61281D739001EB962 /* PluginControllerProxyMac.mm in Sources */,
+                               7C882DFE1C7E99AC006BF731 /* APIUserContentWorld.cpp in Sources */,
                                1A8EF96E1252AF6B00F7067F /* PluginControllerProxyMessageReceiver.cpp in Sources */,
                                1A17977F137EE82C00F97D45 /* PluginCreationParameters.cpp in Sources */,
                                7C3F8C90173AF52D007B7F39 /* PluginInformation.cpp in Sources */,
                                1AB16AE11648656D00290D62 /* RemoteLayerTreeDrawingAreaProxy.mm in Sources */,
                                0FF24A2D1879E4BC003ABF0C /* RemoteLayerTreeDrawingAreaProxyMessageReceiver.cpp in Sources */,
                                1AA3D75B1651B44F008713D0 /* RemoteLayerTreeHost.mm in Sources */,
+                               7C882DF81C7E996C006BF731 /* _WKUserContentWorld.mm in Sources */,
                                0F0C365818C051BA00F607D7 /* RemoteLayerTreeHostIOS.mm in Sources */,
                                2DDE0AFB18298CC900F97EAA /* RemoteLayerTreePropertyApplier.mm in Sources */,
                                0FF2649F1A1FF9C6001FE759 /* RemoteLayerTreeScrollingPerformanceData.mm in Sources */,
index ec5a55e..ea30e3c 100644 (file)
@@ -35,6 +35,8 @@ WK_CLASS_AVAILABLE(10_10, 8_0)
 + (WKWebProcessPlugInScriptWorld *)world;
 + (WKWebProcessPlugInScriptWorld *)normalWorld;
 
+@property (nonatomic, readonly, copy) NSString *name;
+
 - (void)clearWrappers;
 
 @end
index dcbbdfb..2a2ded8 100644 (file)
@@ -56,6 +56,11 @@ using namespace WebKit;
     _world->clearWrappers();
 }
 
+- (NSString *)name
+{
+    return _world->name();
+}
+
 - (InjectedBundleScriptWorld&)_scriptWorld
 {
     return *_world;
index 3ae8712..6da0cc0 100644 (file)
@@ -57,3 +57,8 @@ void WKBundleScriptWorldMakeAllShadowRootsOpen(WKBundleScriptWorldRef scriptWorl
 {
     toImpl(scriptWorldRef)->makeAllShadowRootsOpen();
 }
+
+WKStringRef WKBundleScriptWorldCopyName(WKBundleScriptWorldRef scriptWorldRef)
+{
+    return toCopiedAPI(toImpl(scriptWorldRef)->name());
+}
index f1fb5d3..325359d 100644 (file)
@@ -38,6 +38,7 @@ WK_EXPORT WKBundleScriptWorldRef WKBundleScriptWorldCreateWorld();
 WK_EXPORT WKBundleScriptWorldRef WKBundleScriptWorldNormalWorld();
 WK_EXPORT void WKBundleScriptWorldClearWrappers(WKBundleScriptWorldRef scriptWorld);
 WK_EXPORT void WKBundleScriptWorldMakeAllShadowRootsOpen(WKBundleScriptWorldRef scriptWorld);
+WK_EXPORT WKStringRef WKBundleScriptWorldCopyName(WKBundleScriptWorldRef scriptWorld);
 
 #ifdef __cplusplus
 }
index 347ea7b..9e11a76 100644 (file)
@@ -30,6 +30,8 @@
 #include <WebCore/ScriptController.h>
 #include <wtf/HashMap.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/text/StringConcatenate.h>
+#include <wtf/text/WTFString.h>
 
 using namespace WebCore;
 
@@ -43,9 +45,20 @@ static WorldMap& allWorlds()
     return map;
 }
 
+static String uniqueWorldName()
+{
+    static uint64_t uniqueWorldNameNumber = 0;
+    return makeString(ASCIILiteral("UniqueWorld_"), String::number(uniqueWorldNameNumber++));
+}
+
 Ref<InjectedBundleScriptWorld> InjectedBundleScriptWorld::create()
 {
-    return adoptRef(*new InjectedBundleScriptWorld(ScriptController::createWorld()));
+    return adoptRef(*new InjectedBundleScriptWorld(ScriptController::createWorld(), uniqueWorldName()));
+}
+
+Ref<InjectedBundleScriptWorld> InjectedBundleScriptWorld::create(const String& name)
+{
+    return adoptRef(*new InjectedBundleScriptWorld(ScriptController::createWorld(), name));
 }
 
 PassRefPtr<InjectedBundleScriptWorld> InjectedBundleScriptWorld::getOrCreate(DOMWrapperWorld& world)
@@ -56,31 +69,37 @@ PassRefPtr<InjectedBundleScriptWorld> InjectedBundleScriptWorld::getOrCreate(DOM
     if (InjectedBundleScriptWorld* existingWorld = allWorlds().get(&world))
         return existingWorld;
 
-    return adoptRef(new InjectedBundleScriptWorld(&world));
+    return adoptRef(new InjectedBundleScriptWorld(world, uniqueWorldName()));
 }
 
 InjectedBundleScriptWorld* InjectedBundleScriptWorld::normalWorld()
 {
-    static InjectedBundleScriptWorld* world = adoptRef(new InjectedBundleScriptWorld(&mainThreadNormalWorld())).leakRef();
+    static InjectedBundleScriptWorld* world = adoptRef(new InjectedBundleScriptWorld(mainThreadNormalWorld(), String())).leakRef();
     return world;
 }
 
-InjectedBundleScriptWorld::InjectedBundleScriptWorld(PassRefPtr<DOMWrapperWorld> world)
+InjectedBundleScriptWorld::InjectedBundleScriptWorld(DOMWrapperWorld& world, const String& name)
     : m_world(world)
+    , m_name(name)
 {
-    ASSERT(!allWorlds().contains(m_world.get()));
-    allWorlds().add(m_world.get(), this);
+    ASSERT(!allWorlds().contains(m_world.ptr()));
+    allWorlds().add(m_world.ptr(), this);
 }
 
 InjectedBundleScriptWorld::~InjectedBundleScriptWorld()
 {
-    ASSERT(allWorlds().contains(m_world.get()));
-    allWorlds().remove(m_world.get());
+    ASSERT(allWorlds().contains(m_world.ptr()));
+    allWorlds().remove(m_world.ptr());
+}
+
+const DOMWrapperWorld& InjectedBundleScriptWorld::coreWorld() const
+{
+    return m_world;
 }
 
-DOMWrapperWorld& InjectedBundleScriptWorld::coreWorld() const
+DOMWrapperWorld& InjectedBundleScriptWorld::coreWorld()
 {
-    return *m_world.get();
+    return m_world;
 }
     
 void InjectedBundleScriptWorld::clearWrappers()
index b3e07f4..fe796f6 100644 (file)
@@ -29,6 +29,7 @@
 #include "APIObject.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
     class DOMWrapperWorld;
@@ -39,20 +40,25 @@ namespace WebKit {
 class InjectedBundleScriptWorld : public API::ObjectImpl<API::Object::Type::BundleScriptWorld> {
 public:
     static Ref<InjectedBundleScriptWorld> create();
+    static Ref<InjectedBundleScriptWorld> create(const String&);
     static PassRefPtr<InjectedBundleScriptWorld> getOrCreate(WebCore::DOMWrapperWorld&);
     static InjectedBundleScriptWorld* normalWorld();
 
     virtual ~InjectedBundleScriptWorld();
 
-    WebCore::DOMWrapperWorld& coreWorld() const;
+    const WebCore::DOMWrapperWorld& coreWorld() const;
+    WebCore::DOMWrapperWorld& coreWorld();
 
     void clearWrappers();
     void makeAllShadowRootsOpen();
 
+    const String& name() const { return m_name; }
+
 private:
-    InjectedBundleScriptWorld(PassRefPtr<WebCore::DOMWrapperWorld>);
+    InjectedBundleScriptWorld(WebCore::DOMWrapperWorld&, const String&);
 
-    RefPtr<WebCore::DOMWrapperWorld> m_world;
+    Ref<WebCore::DOMWrapperWorld> m_world;
+    String m_name;
 };
 
 } // namespace WebKit
index 67a5422..0d9ed0c 100644 (file)
@@ -27,6 +27,7 @@
 #include "WebUserContentController.h"
 
 #include "DataReference.h"
+#include "InjectedBundleScriptWorld.h"
 #include "WebCompiledContentExtension.h"
 #include "WebFrame.h"
 #include "WebPage.h"
@@ -56,6 +57,15 @@ static HashMap<uint64_t, WebUserContentController*>& userContentControllers()
     return userContentControllers;
 }
 
+typedef HashMap<uint64_t, std::pair<RefPtr<InjectedBundleScriptWorld>, unsigned>> WorldMap;
+
+static WorldMap& worldMap()
+{
+    static NeverDestroyed<WorldMap> map(std::initializer_list<WorldMap::KeyValuePairType> { { 1, std::make_pair(InjectedBundleScriptWorld::normalWorld(), 1) } });
+
+    return map;
+}
+
 PassRefPtr<WebUserContentController> WebUserContentController::getOrCreate(uint64_t identifier)
 {
     auto& userContentControllerPtr = userContentControllers().add(identifier, nullptr).iterator->value;
@@ -84,20 +94,67 @@ WebUserContentController::~WebUserContentController()
     userContentControllers().remove(m_identifier);
 }
 
-void WebUserContentController::addUserScripts(const Vector<WebCore::UserScript>& userScripts)
+
+void WebUserContentController::addUserContentWorlds(const Vector<std::pair<uint64_t, String>>& worlds)
 {
-    for (const auto& userScript : userScripts)
-        m_userContentController->addUserScript(mainThreadNormalWorld(), std::make_unique<WebCore::UserScript>(userScript));
+    for (auto& world : worlds) {
+        ASSERT(world.first);
+        ASSERT(world.first != 1);
+
+        worldMap().ensure(world.first, [&] { return std::make_pair(InjectedBundleScriptWorld::create(world.second), 1); });
+    }
 }
 
-void WebUserContentController::removeUserScript(const String& urlString)
+void WebUserContentController::removeUserContentWorld(uint64_t worldIdentifier)
 {
-    m_userContentController->removeUserScript(mainThreadNormalWorld(), URL(URL(), urlString));
+    ASSERT(worldIdentifier);
+    ASSERT(worldIdentifier != 1);
+
+    auto it = worldMap().find(worldIdentifier);
+    if (it == worldMap().end()) {
+        WTFLogAlways("Trying to remove a UserContentWorld (id=%llu) that is does not exist.", worldIdentifier);
+        return;
+    }
+
+    it->value.second--;
+    
+    if (!it->value.second)
+        worldMap().remove(it);
 }
 
-void WebUserContentController::removeAllUserScripts()
+void WebUserContentController::addUserScripts(const Vector<std::pair<uint64_t, WebCore::UserScript>>& userScripts)
 {
-    m_userContentController->removeUserScripts(mainThreadNormalWorld());
+    for (const auto& userScriptWorldPair : userScripts) {
+        auto it = worldMap().find(userScriptWorldPair.first);
+        if (it == worldMap().end()) {
+            WTFLogAlways("Trying to add a UserScript to a UserContentWorld (id=%llu) that does not exist.", userScriptWorldPair.first);
+            continue;
+        }
+
+        m_userContentController->addUserScript(it->value.first->coreWorld(), std::make_unique<WebCore::UserScript>(userScriptWorldPair.second));
+    }
+}
+
+void WebUserContentController::removeUserScript(uint64_t worldIdentifier, const String& urlString)
+{
+    auto it = worldMap().find(worldIdentifier);
+    if (it == worldMap().end()) {
+        WTFLogAlways("Trying to remove a UserScript from a UserContentWorld (id=%llu) that does not exist.", worldIdentifier);
+        return;
+    }
+
+    m_userContentController->removeUserScript(it->value.first->coreWorld(), URL(URL(), urlString));
+}
+
+void WebUserContentController::removeAllUserScripts(uint64_t worldIdentifier)
+{
+    auto it = worldMap().find(worldIdentifier);
+    if (it == worldMap().end()) {
+        WTFLogAlways("Trying to remove all UserScripts from a UserContentWorld (id=%llu) that does not exist.", worldIdentifier);
+        return;
+    }
+
+    m_userContentController->removeUserScripts(it->value.first->coreWorld());
 }
 
 void WebUserContentController::addUserStyleSheets(const Vector<WebCore::UserStyleSheet>& userStyleSheets)
index 9b47be2..8fb43f3 100644 (file)
@@ -34,6 +34,7 @@
 
 namespace WebKit {
 
+class InjectedBundleScriptWorld;
 class WebCompiledContentExtensionData;
 class WebUserMessageHandlerDescriptorProxy;
 
@@ -52,9 +53,12 @@ private:
     // IPC::MessageReceiver.
     virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override;
 
-    void addUserScripts(const Vector<WebCore::UserScript>&);
-    void removeUserScript(const String& urlString);
-    void removeAllUserScripts();
+    void addUserContentWorlds(const Vector<std::pair<uint64_t, String>>&);
+    void removeUserContentWorld(uint64_t);
+
+    void addUserScripts(const Vector<std::pair<uint64_t, WebCore::UserScript>>&);
+    void removeUserScript(uint64_t worldIdentifier, const String& urlString);
+    void removeAllUserScripts(uint64_t worldIdentifier);
 
     void addUserStyleSheets(const Vector<WebCore::UserStyleSheet>&);
     void removeUserStyleSheet(const String& urlString);
index bc9f94f..43df820 100644 (file)
  */
 
 messages -> WebUserContentController {
-    AddUserScripts(Vector<WebCore::UserScript> userScripts);
-    RemoveUserScript(String url);
-    RemoveAllUserScripts();
+    AddUserContentWorlds(Vector<std::pair<uint64_t, String>> worlds);
+    RemoveUserContentWorld(uint64_t worldIdentifier);
+
+    AddUserScripts(Vector<std::pair<uint64_t, WebCore::UserScript>> userScripts);
+    RemoveUserScript(uint64_t worldIdentifier, String url);
+    RemoveAllUserScripts(uint64_t worldIdentifier);
 
     AddUserStyleSheets(Vector<WebCore::UserStyleSheet> userStyleSheets);
     RemoveUserStyleSheet(String url);
index e6f1192..d02ab40 100644 (file)
@@ -1,3 +1,20 @@
+2016-02-25  Sam Weinig  <sam@webkit.org>
+
+        Allow WKUserScripts to be run in isolated worlds
+        https://bugs.webkit.org/show_bug.cgi?id=154701
+
+        Reviewed by Anders Carlsson.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentWorld.mm: Added.
+        (-[SimpleDelegate webView:didFinishNavigation:]):
+        (-[UserContentWorldRemoteObject didObserveNormalWorld]):
+        (-[UserContentWorldRemoteObject didObserveWorldWithName:]):
+        * TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentWorldPlugIn.mm: Added.
+        (-[_WKUserContentWorldPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+        (-[_WKUserContentWorldPlugIn webProcessPlugInBrowserContextController:globalObjectIsAvailableForFrame:inScriptWorld:]):
+        * TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentWorldProtocol.h: Added.
+
 2016-02-26  Youenn Fablet  <youenn.fablet@crf.canon.fr>
 
         W3C test importer should have an option to clean the destination directory
index d398fa9..da11ec4 100644 (file)
@@ -91,6 +91,8 @@
                7C486BA11AA12567003F6F9B /* bundle-file.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7C486BA01AA1254B003F6F9B /* bundle-file.html */; };
                7C54A4BE1AA11CCA00380F78 /* WKBundleFileHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C54A4BC1AA11CCA00380F78 /* WKBundleFileHandle.cpp */; };
                7C54A4C11AA11CE400380F78 /* WKBundleFileHandle_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C54A4BF1AA11CE400380F78 /* WKBundleFileHandle_Bundle.cpp */; };
+               7C882E091C80C630006BF731 /* UserContentWorldPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7C882E041C80C624006BF731 /* UserContentWorldPlugIn.mm */; };
+               7C882E0A1C80C764006BF731 /* UserContentWorld.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7C882E031C80C624006BF731 /* UserContentWorld.mm */; };
                7C89D2AC1A69B80D003A5FDE /* WKPageConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89D2AA1A69B80D003A5FDE /* WKPageConfiguration.cpp */; };
                7C9ED98B17A19F4B00E4DC33 /* attributedStringStrikethrough.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7C9ED98A17A19D0600E4DC33 /* attributedStringStrikethrough.html */; };
                7CB184C61AA3F2100066EDFD /* ContentExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CB184C41AA3F2100066EDFD /* ContentExtensions.cpp */; };
                7C6BBD8A19CEA54300C1F5E0 /* Counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Counters.h; sourceTree = "<group>"; };
                7C6BBD8B19CEA63000C1F5E0 /* Counters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Counters.cpp; sourceTree = "<group>"; };
                7C74D42D188228F300E5ED57 /* StringView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringView.cpp; sourceTree = "<group>"; };
+               7C882E031C80C624006BF731 /* UserContentWorld.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserContentWorld.mm; sourceTree = "<group>"; };
+               7C882E041C80C624006BF731 /* UserContentWorldPlugIn.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserContentWorldPlugIn.mm; sourceTree = "<group>"; };
+               7C882E051C80C624006BF731 /* UserContentWorldProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserContentWorldProtocol.h; sourceTree = "<group>"; };
                7C89D2AA1A69B80D003A5FDE /* WKPageConfiguration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKPageConfiguration.cpp; sourceTree = "<group>"; };
                7C8DDAA91735DE1D00EA5AC0 /* CloseThenTerminate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CloseThenTerminate.cpp; sourceTree = "<group>"; };
                7C9ED98A17A19D0600E4DC33 /* attributedStringStrikethrough.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = attributedStringStrikethrough.html; sourceTree = "<group>"; };
                                37BCA61B1B596BA9002012CA /* ShouldOpenExternalURLsInNewWindowActions.mm */,
                                2D9A53AE1B31FA8D0074D5AA /* ShrinkToFit.mm */,
                                7CC3E1FA197E234100BE6252 /* UserContentController.mm */,
+                               7C882E031C80C624006BF731 /* UserContentWorld.mm */,
+                               7C882E041C80C624006BF731 /* UserContentWorldPlugIn.mm */,
+                               7C882E051C80C624006BF731 /* UserContentWorldProtocol.h */,
                                2D00065D1C1F58940088E6A7 /* WKPDFViewResizeCrash.mm */,
                                0F3B94A51A77266C00DE3272 /* WKWebViewEvaluateJavaScript.mm */,
                        );
                                7CCE7ED31A411A7E00447C4C /* TypingStyleCrash.mm in Sources */,
                                7CCE7EDE1A411A9200447C4C /* URL.cpp in Sources */,
                                7CCE7EB01A411A4400447C4C /* URLExtras.mm in Sources */,
+                               7C882E0A1C80C764006BF731 /* UserContentWorld.mm in Sources */,
                                7CCE7F271A411AF600447C4C /* UserContentController.mm in Sources */,
                                7CCE7F2D1A411B1000447C4C /* UserContentTest.mm in Sources */,
                                7CCE7F171A411AE600447C4C /* UserMedia.cpp in Sources */,
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               7C882E091C80C630006BF731 /* UserContentWorldPlugIn.mm in Sources */,
                                A13EBBAA1B87428D00097110 /* WebProcessPlugIn.mm in Sources */,
                                1A4F81CF1BDFFD53004E672E /* RemoteObjectRegistryPlugIn.mm in Sources */,
                                A13EBBB01B87436F00097110 /* BundleParametersPlugIn.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorld.mm b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorld.mm
new file mode 100644 (file)
index 0000000..9eb7016
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "UserContentWorldProtocol.h"
+#import "WKWebViewConfigurationExtras.h"
+#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKUserContentControllerPrivate.h>
+#import <WebKit/WKUserScriptPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <WebKit/_WKRemoteObjectInterface.h>
+#import <WebKit/_WKRemoteObjectRegistry.h>
+#import <WebKit/_WKUserContentWorld.h>
+#import <WebKit/_WKUserStyleSheet.h>
+#import <wtf/RetainPtr.h>
+
+static bool isDoneWithNavigation;
+
+@interface SimpleDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation SimpleDelegate
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
+{
+    isDoneWithNavigation = true;
+}
+@end
+
+
+TEST(UserContentWorld, NormalWorld)
+{
+    RetainPtr<WKUserScript> basicUserScript = adoptNS([[WKUserScript alloc] initWithSource:@"" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
+    EXPECT_EQ([basicUserScript _userContentWorld], [_WKUserContentWorld normalWorld]);
+    EXPECT_NULL([basicUserScript _userContentWorld].name);
+}
+
+TEST(UserContentWorld, NormalWorldUserScript)
+{
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+    RetainPtr<WKUserScript> userScript = adoptNS([[WKUserScript alloc] initWithSource:@"window.setFromUserScript = true;" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
+    [[configuration userContentController] addUserScript:userScript.get()];
+
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    RetainPtr<SimpleDelegate> delegate = adoptNS([[SimpleDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    [webView loadHTMLString:@"<body style='background-color: red;'></body>" baseURL:nil];
+    TestWebKitAPI::Util::run(&isDoneWithNavigation);
+    isDoneWithNavigation = false;
+
+    __block bool isDone = false;
+    [webView evaluateJavaScript:@"window.setFromUserScript ? 'variable accessible' : 'variable inaccessible';" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
+        EXPECT_WK_STREQ(result, @"variable accessible");
+
+        isDone = true;
+    }];
+
+    isDone = false;
+    TestWebKitAPI::Util::run(&isDone);
+}
+
+TEST(UserContentWorld, IsolatedWorld)
+{
+    RetainPtr<_WKUserContentWorld> isolatedWorld = [_WKUserContentWorld worldWithName:@"TestWorld"];
+    EXPECT_WK_STREQ([isolatedWorld name], @"TestWorld");
+
+    RetainPtr<WKUserScript> userScript = adoptNS([[WKUserScript alloc] _initWithSource:@"" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:isolatedWorld.get()]);
+    EXPECT_EQ([userScript _userContentWorld], isolatedWorld.get());
+}
+
+TEST(UserContentWorld, IsolatedWorldUserScript)
+{
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+    RetainPtr<_WKUserContentWorld> isolatedWorld = [_WKUserContentWorld worldWithName:@"TestWorld"];
+    RetainPtr<WKUserScript> userScript = adoptNS([[WKUserScript alloc] _initWithSource:@"window.setFromUserScript = true;" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:isolatedWorld.get()]);
+    [[configuration userContentController] addUserScript:userScript.get()];
+
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    RetainPtr<SimpleDelegate> delegate = adoptNS([[SimpleDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    [webView loadHTMLString:@"<body style='background-color: red;'></body>" baseURL:nil];
+    TestWebKitAPI::Util::run(&isDoneWithNavigation);
+    isDoneWithNavigation = false;
+
+    __block bool isDone = false;
+    [webView evaluateJavaScript:@"window.setFromUserScript ? 'variable accessible' : 'variable inaccessible';" completionHandler:^(id result, NSError *error) {
+        EXPECT_NULL(error);
+        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
+        EXPECT_WK_STREQ(result, @"variable inaccessible");
+
+        isDone = true;
+    }];
+
+    isDone = false;
+    TestWebKitAPI::Util::run(&isDone);
+}
+
+static bool didObserveNormalWorld;
+static bool didObserveWorldWithName;
+
+@interface UserContentWorldRemoteObject : NSObject <UserContentWorldProtocol>
+@end
+
+@implementation UserContentWorldRemoteObject
+
+- (void)didObserveNormalWorld
+{
+    didObserveNormalWorld = true;
+}
+
+- (void)didObserveWorldWithName:(NSString *)name
+{
+    EXPECT_WK_STREQ(@"TestWorld", name);
+    didObserveWorldWithName = true;
+}
+
+@end
+
+TEST(UserContentWorld, IsolatedWorldPlugIn)
+{
+    NSString * const testPlugInClassName = @"UserContentWorldPlugIn";
+
+    RetainPtr<WKWebViewConfiguration> configuration = retainPtr([WKWebViewConfiguration testwebkitapi_configurationWithTestPlugInClassName:testPlugInClassName]);
+    
+    RetainPtr<_WKUserContentWorld> isolatedWorld = [_WKUserContentWorld worldWithName:@"TestWorld"];
+    RetainPtr<WKUserScript> userScript = adoptNS([[WKUserScript alloc] _initWithSource:@"window.setFromUserScript = true;" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES legacyWhitelist:@[] legacyBlacklist:@[] userContentWorld:isolatedWorld.get()]);
+    [[configuration userContentController] addUserScript:userScript.get()];
+
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    RetainPtr<UserContentWorldRemoteObject> object = adoptNS([[UserContentWorldRemoteObject alloc] init]);
+    _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(UserContentWorldProtocol)];
+    [[webView _remoteObjectRegistry] registerExportedObject:object.get() interface:interface];
+
+    [webView loadHTMLString:@"<body style='background-color: red;'></body>" baseURL:nil];
+
+    TestWebKitAPI::Util::run(&didObserveNormalWorld);
+    TestWebKitAPI::Util::run(&didObserveWorldWithName);
+}
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldPlugIn.mm b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldPlugIn.mm
new file mode 100644 (file)
index 0000000..68f8bd9
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if WK_API_ENABLED
+
+#import "PlatformUtilities.h"
+#import "UserContentWorldProtocol.h"
+#import <WebKit/WKConnection.h>
+#import <WebKit/WKWebProcessPlugIn.h>
+#import <WebKit/WKWebProcessPlugInBrowserContextController.h>
+#import <WebKit/WKWebProcessPlugInBrowserContextControllerPrivate.h>
+#import <WebKit/WKWebProcessPlugInFrame.h>
+#import <WebKit/WKWebProcessPlugInLoadDelegate.h>
+#import <WebKit/WKWebProcessPlugInScriptWorld.h>
+#import <WebKit/_WKRemoteObjectInterface.h>
+#import <WebKit/_WKRemoteObjectRegistry.h>
+#import <wtf/RetainPtr.h>
+
+@interface UserContentWorldPlugIn : NSObject <WKWebProcessPlugIn, WKWebProcessPlugInLoadDelegate>
+@end
+
+@implementation UserContentWorldPlugIn {
+    RetainPtr<WKWebProcessPlugInBrowserContextController> _browserContextController;
+    RetainPtr<WKWebProcessPlugInController> _plugInController;
+    RetainPtr<id <UserContentWorldProtocol>> _remoteObject;
+}
+
+- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
+{
+    ASSERT(!_browserContextController);
+    ASSERT(!_plugInController);
+    _browserContextController = browserContextController;
+    _plugInController = plugInController;
+
+    _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(UserContentWorldProtocol)];
+    _remoteObject = [[browserContextController _remoteObjectRegistry] remoteObjectProxyWithInterface:interface];
+
+    [_browserContextController setLoadDelegate:self];
+}
+
+- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller globalObjectIsAvailableForFrame:(WKWebProcessPlugInFrame *)frame inScriptWorld:(WKWebProcessPlugInScriptWorld *)scriptWorld
+{
+    if (scriptWorld == [WKWebProcessPlugInScriptWorld normalWorld]) {
+        [_remoteObject didObserveNormalWorld];
+        return;
+    }
+
+    [_remoteObject didObserveWorldWithName:scriptWorld.name];
+}
+
+@end
+
+#endif // WK_API_ENABLED
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h
new file mode 100644 (file)
index 0000000..0b33579
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+@protocol UserContentWorldProtocol <NSObject>
+
+- (void)didObserveNormalWorld;
+- (void)didObserveWorldWithName:(NSString *)name;
+
+@end
+
+#endif