Diff
Modified: trunk/Source/WebKit/ChangeLog (257891 => 257892)
--- trunk/Source/WebKit/ChangeLog 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Source/WebKit/ChangeLog 2020-03-05 01:13:20 UTC (rev 257892)
@@ -1,3 +1,24 @@
+2020-03-04 Alex Christensen <achristen...@webkit.org>
+
+ Call globalObjectIsAvailableForFrame before evaluating _javascript_ in newly created worlds
+ https://bugs.webkit.org/show_bug.cgi?id=208615
+ <rdar://problem/59406743>
+
+ Reviewed by Alex Christensen.
+
+ globalObjectIsAvailableForFrame is often used for initialization code for a content world.
+ If we evaluate _javascript_ in a content world as the first thing we do in that world,
+ globalObjectIsAvailableForFrame hadn't been called, so things were not initialized.
+ So call it when evaluating _javascript_ if we create the world to evaluate in.
+
+ Covered by new API tests.
+
+ * WebProcess/UserContent/WebUserContentController.cpp:
+ (WebKit::WebUserContentController::addContentWorld):
+ * WebProcess/UserContent/WebUserContentController.h:
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::runJavaScriptInFrameInScriptWorld):
+
2020-03-04 Jiewen Tan <jiewen_...@apple.com>
Unreviewed, a build fix after r257877
Modified: trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp (257891 => 257892)
--- trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.cpp 2020-03-05 01:13:20 UTC (rev 257892)
@@ -101,13 +101,13 @@
return iterator == worldMap().end() ? nullptr : iterator->value.first.get();
}
-void WebUserContentController::addContentWorld(const std::pair<ContentWorldIdentifier, String>& world)
+InjectedBundleScriptWorld* WebUserContentController::addContentWorld(const std::pair<ContentWorldIdentifier, String>& world)
{
ASSERT(world.first);
if (world.first == pageContentWorldIdentifier())
- return;
-
- worldMap().ensure(world.first, [&] {
+ return nullptr;
+
+ auto addResult = worldMap().ensure(world.first, [&] {
#if PLATFORM(GTK) || PLATFORM(WPE)
// The GLib API doesn't allow to create script worlds from the UI process. We need to
// use the existing world created by the web extension if any. The world name is used
@@ -117,6 +117,10 @@
#endif
return std::make_pair(InjectedBundleScriptWorld::create(world.second, InjectedBundleScriptWorld::Type::User), 1);
});
+
+ if (addResult.isNewEntry)
+ return addResult.iterator->value.first.get();
+ return nullptr;
}
void WebUserContentController::addContentWorlds(const Vector<std::pair<ContentWorldIdentifier, String>>& worlds)
Modified: trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.h (257891 => 257892)
--- trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.h 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Source/WebKit/WebProcess/UserContent/WebUserContentController.h 2020-03-05 01:13:20 UTC (rev 257892)
@@ -67,7 +67,7 @@
InjectedBundleScriptWorld* worldForIdentifier(ContentWorldIdentifier);
void addContentWorlds(const Vector<std::pair<ContentWorldIdentifier, String>>&);
- void addContentWorld(const std::pair<ContentWorldIdentifier, String>&);
+ InjectedBundleScriptWorld* addContentWorld(const std::pair<ContentWorldIdentifier, String>&);
void addUserScripts(Vector<WebUserScriptData>&&, InjectUserScriptImmediately);
void addUserStyleSheets(const Vector<WebUserStyleSheetData>&);
void addUserScriptMessageHandlers(const Vector<WebScriptMessageHandlerData>&);
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (257891 => 257892)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-03-05 01:13:20 UTC (rev 257892)
@@ -3472,7 +3472,13 @@
void WebPage::runJavaScriptInFrameInScriptWorld(RunJavaScriptParameters&& parameters, Optional<WebCore::FrameIdentifier> frameID, const std::pair<ContentWorldIdentifier, String>& worldData, CallbackID callbackID)
{
auto* webFrame = frameID ? WebProcess::singleton().webFrame(*frameID) : mainWebFrame();
- m_userContentController->addContentWorld(worldData);
+
+ if (auto* newWorld = m_userContentController->addContentWorld(worldData)) {
+ auto& coreWorld = newWorld->coreWorld();
+ for (RefPtr<Frame> frame = mainFrame(); frame; frame = frame->tree().traverseNext())
+ frame->loader().client().dispatchGlobalObjectAvailable(coreWorld);
+ }
+
runJavaScript(webFrame, WTFMove(parameters), worldData.first, callbackID);
}
Modified: trunk/Tools/ChangeLog (257891 => 257892)
--- trunk/Tools/ChangeLog 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Tools/ChangeLog 2020-03-05 01:13:20 UTC (rev 257892)
@@ -1,3 +1,19 @@
+2020-03-04 Alex Christensen <achristen...@webkit.org>
+
+ Call globalObjectIsAvailableForFrame before evaluating _javascript_ in newly created worlds
+ https://bugs.webkit.org/show_bug.cgi?id=208615
+ <rdar://problem/59406743>
+
+ Reviewed by Alex Christensen.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/ContentWorldPlugIn.mm: Added.
+ (-[ContentWorldPlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+ (-[ContentWorldPlugIn webProcessPlugInBrowserContextController:globalObjectIsAvailableForFrame:inScriptWorld:]):
+ * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm:
+ (TEST):
+ Also make a test written in bug 206310 actually run code.
+
2020-03-04 Aakash Jain <aakash_j...@apple.com>
[build.webkit.org] Remove leaks queue
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (257891 => 257892)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2020-03-05 01:13:20 UTC (rev 257892)
@@ -397,6 +397,7 @@
5C0BF8921DD599B600B00328 /* EarlyKVOCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A9FB6CC1CA34BE500966124 /* EarlyKVOCrash.mm */; };
5C0BF8931DD599BD00B00328 /* IsNavigationActionTrusted.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57F10D921C7E7B3800ECDF30 /* IsNavigationActionTrusted.mm */; };
5C0BF8941DD599C900B00328 /* MenuTypesForMouseEvents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */; };
+ 5C121E8D2410704900486F9B /* ContentWorldPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C121E8C2410703200486F9B /* ContentWorldPlugIn.mm */; };
5C16F8FC230C94370074C4A8 /* TextSize.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C16F8FB230C942B0074C4A8 /* TextSize.mm */; };
5C19A5241FD0F60100EEA323 /* CookiePrivateBrowsing.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C19A5231FD0F32600EEA323 /* CookiePrivateBrowsing.mm */; };
5C23DF0B2246015800F454B6 /* Challenge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C23DF0A2245C9D700F454B6 /* Challenge.mm */; };
@@ -2027,6 +2028,7 @@
5C0160C021A132320077FA32 /* JITEnabled.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JITEnabled.mm; sourceTree = "<group>"; };
5C0BF88C1DD5957400B00328 /* MemoryPressureHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryPressureHandler.mm; sourceTree = "<group>"; };
5C0BF88F1DD5999B00B00328 /* WebViewCanPasteZeroPng.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewCanPasteZeroPng.mm; sourceTree = "<group>"; };
+ 5C121E8C2410703200486F9B /* ContentWorldPlugIn.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContentWorldPlugIn.mm; sourceTree = "<group>"; };
5C16F8FB230C942B0074C4A8 /* TextSize.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextSize.mm; sourceTree = "<group>"; };
5C19A5231FD0F32600EEA323 /* CookiePrivateBrowsing.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CookiePrivateBrowsing.mm; sourceTree = "<group>"; };
5C23DF0A2245C9D700F454B6 /* Challenge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Challenge.mm; sourceTree = "<group>"; };
@@ -2977,6 +2979,7 @@
A14FC5861B8991B600D107EB /* ContentFiltering.mm */,
A14FC5891B89927100D107EB /* ContentFilteringPlugIn.mm */,
5CA1DED81F74A87100E71BD3 /* ContentRuleListNotification.mm */,
+ 5C121E8C2410703200486F9B /* ContentWorldPlugIn.mm */,
5C3B1D2522A74EA400BCF4D0 /* ContextMenus.mm */,
5C2936911D5BF63E00DEAB1E /* CookieAcceptPolicy.mm */,
5C19A5231FD0F32600EEA323 /* CookiePrivateBrowsing.mm */,
@@ -5227,6 +5230,7 @@
1C2B81831C891F0900A5529F /* CancelFontSubresourcePlugIn.mm in Sources */,
5CB18BA81F5645E300EE23C4 /* ClickAutoFillButton.mm in Sources */,
A14FC58B1B89927100D107EB /* ContentFilteringPlugIn.mm in Sources */,
+ 5C121E8D2410704900486F9B /* ContentWorldPlugIn.mm in Sources */,
CEA7F57D2089624B0078EF6E /* DidResignInputElementStrongPasswordAppearance.mm in Sources */,
518EE51920A78CE500E024F3 /* DoubleDefersLoadingPlugin.mm in Sources */,
5CB5B3C21FFC55CF00C27BB0 /* FrameHandleSerialization.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentWorldPlugIn.mm (0 => 257892)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentWorldPlugIn.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentWorldPlugIn.mm 2020-03-05 01:13:20 UTC (rev 257892)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 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/WKWebProcessPlugIn.h>
+#import <WebKit/WKWebProcessPlugInBrowserContextController.h>
+#import <WebKit/WKWebProcessPlugInFrame.h>
+#import <WebKit/WKWebProcessPlugInLoadDelegate.h>
+#import <WebKit/WKWebProcessPlugInScriptWorld.h>
+
+@interface ContentWorldPlugIn : NSObject <WKWebProcessPlugIn, WKWebProcessPlugInLoadDelegate>
+@end
+
+@implementation ContentWorldPlugIn
+
+- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
+{
+ browserContextController.loadDelegate = self;
+}
+
+- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller globalObjectIsAvailableForFrame:(WKWebProcessPlugInFrame *)frame inScriptWorld:(WKWebProcessPlugInScriptWorld *)scriptWorld
+{
+ [[frame jsContextForWorld:scriptWorld] setObject:scriptWorld.name forKeyedSubscript:@"worldName"];
+}
+
+@end
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm (257891 => 257892)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm 2020-03-05 01:02:51 UTC (rev 257891)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm 2020-03-05 01:13:20 UTC (rev 257892)
@@ -31,7 +31,9 @@
#import "TCPServer.h"
#import "Test.h"
#import "TestNavigationDelegate.h"
+#import "TestURLSchemeHandler.h"
#import "TestWKWebView.h"
+#import "WKWebViewConfigurationExtras.h"
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKContentWorld.h>
#import <WebKit/WKErrorPrivate.h>
@@ -38,6 +40,7 @@
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKPreferencesRef.h>
#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKFrameTreeNode.h>
#import <wtf/RetainPtr.h>
static bool isDone;
@@ -136,10 +139,12 @@
[webView synchronouslyLoadHTMLString:@"<html></html>"];
// Set a variable in the main world via "normal" evaluateJavaScript
- isDone = false;
+ __block bool isDone = false;
+ __block size_t testsPassed = 0;
[webView evaluateJavaScript:@"var foo = 'bar'" completionHandler:^(id result, NSError *error) {
isDone = true;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify that value is visible when evaluating in the pageWorld
@@ -147,7 +152,9 @@
EXPECT_TRUE([result isKindOfClass:[NSString class]]);
EXPECT_TRUE([result isEqualToString:@"bar"]);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify that value is not visible when evaluating in the defaultClientWorld
@@ -154,38 +161,48 @@
[webView evaluateJavaScript:@"foo" inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify that value is visible when calling a function in the pageWorld
- [webView callAsyncJavaScript:@"return foo" arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
+ [webView callAsyncJavaScript:@"return foo" arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
EXPECT_TRUE([result isKindOfClass:[NSString class]]);
EXPECT_TRUE([result isEqualToString:@"bar"]);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify that value is not visible when calling a function in the defaultClientWorld
- [webView callAsyncJavaScript:@"return foo" arguments:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) {
+ [webView callAsyncJavaScript:@"return foo" arguments:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Set a varibale value in a named world.
RetainPtr<WKContentWorld> namedWorld = [WKContentWorld worldWithName:@"NamedWorld"];
- [webView evaluateJavaScript:@"var bar = baz" inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
+ [webView evaluateJavaScript:@"var bar = 'baz'" inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
- // Set a global varibale value in a named world via a function call.
- [webView callAsyncJavaScript:@"window.baz = bat" arguments:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
+ // Set a global variable value in a named world via a function call.
+ [webView callAsyncJavaScript:@"window.baz = 'bat'" arguments:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
EXPECT_NULL(error);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify they are there in that named world.
@@ -193,7 +210,9 @@
EXPECT_TRUE([result isKindOfClass:[NSString class]]);
EXPECT_TRUE([result isEqualToString:@"baz"]);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
[webView evaluateJavaScript:@"window.baz" inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
@@ -200,7 +219,9 @@
EXPECT_TRUE([result isKindOfClass:[NSString class]]);
EXPECT_TRUE([result isEqualToString:@"bat"]);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify they aren't there in the defaultClientWorld.
@@ -207,13 +228,17 @@
[webView evaluateJavaScript:@"bar" inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
[webView evaluateJavaScript:@"window.baz" inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
// Verify they aren't there in the pageWorld.
@@ -220,16 +245,74 @@
[webView evaluateJavaScript:@"bar" inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
[webView evaluateJavaScript:@"window.baz" inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
EXPECT_NULL(result);
isDone = true;
+ testsPassed++;
}];
+ TestWebKitAPI::Util::run(&isDone);
isDone = false;
+
+ EXPECT_EQ(testsPassed, 12u);
}
+TEST(WKWebView, EvaluateJavaScriptInWorldsWithGlobalObjectAvailable)
+{
+ WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"ContentWorldPlugIn"];
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
+ [webView synchronouslyLoadHTMLString:@"<html></html>"];
+
+ __block bool done = false;
+ [webView evaluateJavaScript:@"window.worldName" inContentWorld:[WKContentWorld worldWithName:@"testName"] completionHandler:^(id result, NSError *error) {
+ EXPECT_WK_STREQ(result, "testName");
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
+TEST(WKWebView, EvaluateJavaScriptInWorldsWithGlobalObjectAvailableInCrossOriginIframe)
+{
+ WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"ContentWorldPlugIn"];
+ auto handler = adoptNS([TestURLSchemeHandler new]);
+ __block bool childFrameLoaded = false;
+ [handler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+ NSString *responseString = nil;
+ if ([task.request.URL.absoluteString isEqualToString:@"frame://host1/"])
+ responseString = @"<iframe src='' _onload_='fetch(\"loadedChildFrame\")'></iframe>";
+ else if ([task.request.URL.absoluteString isEqualToString:@"frame://host2/"])
+ responseString = @"frame content";
+ else if ([task.request.URL.path isEqualToString:@"/loadedChildFrame"]) {
+ responseString = @"fetched content";
+ childFrameLoaded = true;
+ }
+
+ ASSERT(responseString);
+ auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:responseString.length textEncodingName:nil]);
+ [task didReceiveResponse:response.get()];
+ [task didReceiveData:[responseString dataUsingEncoding:NSUTF8StringEncoding]];
+ [task didFinish];
+ }];
+ [configuration setURLSchemeHandler:handler.get() forURLScheme:@"frame"];
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"frame://host1/"]]];
+
+ TestWebKitAPI::Util::run(&childFrameLoaded);
+
+ __block bool done = false;
+ [webView _frames:^(_WKFrameTreeNode *mainFrame) {
+ [webView _evaluateJavaScript:@"window.worldName" inFrame:mainFrame.childFrames[0] inContentWorld:[WKContentWorld worldWithName:@"testName"] completionHandler:^(id result, NSError *error) {
+ EXPECT_WK_STREQ(result, "testName");
+ done = true;
+ }];
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
TEST(WebKit, EvaluateJavaScriptInAttachments)
{
// Attachments displayed inline are in sandboxed documents.