Changeset 263727 in webkit
- Timestamp:
- Jun 29, 2020 10:43:19 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r263722 r263727 1 2020-06-29 Brady Eidson <beidson@apple.com> 2 3 JavaScript cannot be injected into iframes 4 <rdar://problem/54168946> and https://bugs.webkit.org/show_bug.cgi?id=213556 5 6 Reviewed by Geoff Garen. 7 8 Covered by API tests. 9 10 * bindings/js/ExceptionDetails.h: Start a collection of "exception types" that will grow quickly, 11 beginning with the specialized "missing frame" type. 12 1 13 2020-06-29 Sam Weinig <weinig@apple.com> 2 14 -
trunk/Source/WebCore/bindings/js/ExceptionDetails.h
r253950 r263727 31 31 32 32 struct ExceptionDetails { 33 enum class Type : uint8_t { 34 Script, 35 InvalidTargetFrame, 36 }; 37 33 38 String message; 34 39 int lineNumber { 0 }; 35 40 int columnNumber { 0 }; 41 Type type { Type::Script }; 42 36 43 // This bizarre explicit initialization of String is because older compilers (like on High Sierra) 37 44 // don't properly handle partial initialization lists unless every struct member has an explicit default value. … … 41 48 42 49 } // namespace WebCore 50 51 namespace WTF { 52 template<> struct EnumTraits<WebCore::ExceptionDetails::Type> { 53 using values = EnumValues< 54 WebCore::ExceptionDetails::Type, 55 WebCore::ExceptionDetails::Type::Script, 56 WebCore::ExceptionDetails::Type::InvalidTargetFrame 57 >; 58 }; 59 } -
trunk/Source/WebKit/ChangeLog
r263724 r263727 1 2020-06-29 Brady Eidson <beidson@apple.com> 2 3 JavaScript cannot be injected into iframes 4 <rdar://problem/54168946> and https://bugs.webkit.org/show_bug.cgi?id=213556 5 6 Reviewed by Geoff Garen. 7 8 This adds a few mechanisms: 9 - Allows for WKUserScripts to have a target content world 10 - Allows "evaluateJavaScript" and "callAsyncJavaScript" to target a specific frame 11 - Allows for the completion handlers of those methods to be able to distinguish 12 failure-due-to-missing-frame. 13 14 * Shared/WebCoreArgumentCoders.cpp: 15 (IPC::ArgumentCoder<ExceptionDetails>::encode): 16 (IPC::ArgumentCoder<ExceptionDetails>::decode): 17 * Shared/WebCoreArgumentCoders.h: 18 19 * UIProcess/API/Cocoa/WKError.h: 20 * UIProcess/API/Cocoa/WKError.mm: 21 (localizedDescriptionForErrorCode): 22 23 * UIProcess/API/Cocoa/WKUserScript.h: 24 * UIProcess/API/Cocoa/WKUserScript.mm: 25 (-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:]): 26 (-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:inContentWorld:]): 27 * UIProcess/API/Cocoa/WKWebView.h: 28 29 * UIProcess/API/Cocoa/WKWebView.mm: 30 (-[WKWebView evaluateJavaScript:inFrame:inContentWorld:completionHandler:]): 31 (-[WKWebView callAsyncJavaScript:arguments:inFrame:inContentWorld:completionHandler:]): 32 (nsErrorFromExceptionDetails): 33 (-[WKWebView _evaluateJavaScript:asAsyncFunction:withSourceURL:withArguments:forceUserGesture:inFrame:inWorld:completionHandler:]): 34 (-[WKWebView callAsyncJavaScript:arguments:inContentWorld:completionHandler:]): Deleted. 35 36 * WebProcess/WebPage/WebPage.cpp: 37 (WebKit::WebPage::runJavaScript): 38 1 39 2020-06-29 Alex Christensen <achristensen@webkit.org> 2 40 -
trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
r262994 r263727 2660 2660 encoder << info.lineNumber; 2661 2661 encoder << info.columnNumber; 2662 encoder << info.type; 2662 2663 encoder << info.sourceURL; 2663 2664 } … … 2672 2673 2673 2674 if (!decoder.decode(result.columnNumber)) 2675 return false; 2676 2677 if (!decoder.decode(result.type)) 2674 2678 return false; 2675 2679 -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKError.h
r252174 r263727 59 59 WKErrorAttributedStringContentFailedToLoad WK_API_AVAILABLE(macos(10.15), ios(13.0)), 60 60 WKErrorAttributedStringContentLoadTimedOut WK_API_AVAILABLE(macos(10.15), ios(13.0)), 61 WKErrorJavaScriptInvalidFrameTarget WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)), 61 62 } WK_API_AVAILABLE(macos(10.10), ios(8.0)); 62 63 -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKError.mm
r243113 r263727 74 74 case WKErrorAttributedStringContentLoadTimedOut: 75 75 return WEB_UI_STRING("Timed out while loading attributed string content", "WKErrorAttributedStringContentLoadTimedOut description"); 76 77 case WKErrorJavaScriptInvalidFrameTarget: 78 return WEB_UI_STRING("JavaScript execution targeted an invalid frame", "WKErrorJavaScriptInvalidFrameTarget description"); 76 79 } 77 80 } -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.h
r243376 r263727 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 58 58 @param injectionTime When the script should be injected. 59 59 @param forMainFrameOnly Whether the script should be injected into all frames or just the main frame. 60 @discussion Calling this method is the same as calling `initWithSource:injectionTime:forMainFrameOnly:inContentWorld:` with a `contentWorld` value of `WKContentWorld.pageWorld` 60 61 */ 61 62 - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly; 63 64 /*! @abstract Returns an initialized user script that can be added to a @link WKUserContentController @/link. 65 @param source The script source. 66 @param injectionTime When the script should be injected. 67 @param forMainFrameOnly Whether the script should be injected into all frames or just the main frame. 68 @param contentWorld The WKContentWorld in which to inject the script. 69 */ 70 - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly inContentWorld:(WKContentWorld *)contentWorld WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 62 71 63 72 @end -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.mm
r263060 r263727 34 34 - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly 35 35 { 36 return [self initWithSource:source injectionTime:injectionTime forMainFrameOnly:forMainFrameOnly inContentWorld:WKContentWorld.pageWorld]; 37 } 38 39 - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly inContentWorld:(WKContentWorld *)contentWorld 40 { 36 41 if (!(self = [super init])) 37 42 return nil; 38 43 39 API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { source, API::UserScript::generateUniqueURL(), { }, { }, API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, API::ContentWorld::pageContentWorld());44 API::Object::constructInWrapper<API::UserScript>(self, WebCore::UserScript { source, API::UserScript::generateUniqueURL(), { }, { }, API::toWebCoreUserScriptInjectionTime(injectionTime), forMainFrameOnly ? WebCore::UserContentInjectedFrames::InjectInTopFrameOnly : WebCore::UserContentInjectedFrames::InjectInAllFrames, WebCore::WaitForNotificationBeforeInjecting::No }, *contentWorld->_contentWorld); 40 45 41 46 return self; -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h
r260334 r263727 39 39 @class WKFindConfiguration; 40 40 @class WKFindResult; 41 @class WKFrameInfo; 41 42 @class WKNavigation; 42 43 @class WKPDFConfiguration; … … 221 222 @param completionHandler A block to invoke when script evaluation completes or fails. 222 223 @discussion The completionHandler is passed the result of the script evaluation or an error. 224 Calling this method is equivalent to calling `evaluateJavaScript:inFrame:inContentWorld:completionHandler:` with: 225 - A `frame` value of `nil` to represent the main frame 226 - A `contentWorld` value of `WKContentWorld.pageWorld` 223 227 */ 224 228 - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler; … … 226 230 /* @abstract Evaluates the given JavaScript string. 227 231 @param javaScriptString The JavaScript string to evaluate. 232 @param frame A WKFrameInfo identifying the frame in which to evaluate the JavaScript string. 228 233 @param contentWorld The WKContentWorld in which to evaluate the JavaScript string. 229 234 @param completionHandler A block to invoke when script evaluation completes or fails. 230 235 @discussion The completionHandler is passed the result of the script evaluation or an error. 236 237 Passing nil is equivalent to targeting the main frame. 238 If the frame argument no longer represents a valid frame by the time WebKit attempts to call the JavaScript function your completion handler will be called with a WKErrorJavaScriptInvalidFrameTarget error. 239 This might happen for a number of reasons, including but not limited to: 240 - The target frame has been removed from the DOM via JavaScript 241 - A parent frame has navigated, destroying all of its previous child frames 242 231 243 No matter which WKContentWorld you use to evaluate your JavaScript string, you can make changes to the underlying web content. (e.g. the Document and its DOM structure) 232 244 Such changes will be visible to script executing in all WKContentWorlds. … … 236 248 Once your global state is set up, consider using callAsyncJavaScript: for more flexible interaction with the JavaScript programming model. 237 249 */ 238 - (void)evaluateJavaScript:(NSString *)javaScriptString in ContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler NS_REFINED_FOR_SWIFT WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));250 - (void)evaluateJavaScript:(NSString *)javaScriptString inFrame:(nullable WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler NS_REFINED_FOR_SWIFT WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 239 251 240 252 /* @abstract Calls the given JavaScript string as an async JavaScript function, passing the given named arguments to that function. 241 253 @param functionBody The JavaScript string to use as the function body. 242 254 @param arguments A dictionary representing the arguments to be passed to the function call. 255 @param frame A WKFrameInfo identifying the frame in which to call the JavaScript function. 243 256 @param contentWorld The WKContentWorld in which to call the JavaScript function. 244 257 @param completionHandler A block to invoke with the return value of the function call, or with the asynchronous resolution of the function's return value. … … 271 284 NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull. 272 285 Any NSArray or NSDictionary containers can only contain objects of those types. 286 287 Passing nil is equivalent to targeting the main frame. 288 If the frame argument no longer represents a valid frame by the time WebKit attempts to call the JavaScript function your completion handler will be called with a WKErrorJavaScriptInvalidFrameTarget error. 289 This might happen for a number of reasons, including but not limited to: 290 - The target frame has been removed from the DOM via JavaScript 291 - A parent frame has navigated, destroying all of its previous child frames 273 292 274 293 No matter which WKContentWorld you use to call your JavaScript function, you can make changes to the underlying web content. (e.g. the Document and its DOM structure) … … 301 320 The above function text will create a promise that will fulfull with the value 42 after a one second delay, wait for it to resolve, then return the fulfillment value of 42. 302 321 */ 303 - (void)callAsyncJavaScript:(NSString *)functionBody arguments:(nullable NSDictionary<NSString *, id> *)arguments in ContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler NS_REFINED_FOR_SWIFT WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));322 - (void)callAsyncJavaScript:(NSString *)functionBody arguments:(nullable NSDictionary<NSString *, id> *)arguments inFrame:(nullable WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler NS_REFINED_FOR_SWIFT WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 304 323 305 324 /*! @abstract Get a snapshot for the visible viewport of WKWebView. -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
r263525 r263727 821 821 } 822 822 823 - (void)evaluateJavaScript:(NSString *)javaScriptString in ContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *))completionHandler824 { 825 [self _evaluateJavaScript:javaScriptString asAsyncFunction:NO withSourceURL:nil withArguments:nil forceUserGesture:YES inFrame: nilinWorld:contentWorld completionHandler:completionHandler];826 } 827 828 - (void)callAsyncJavaScript:(NSString *)javaScriptString arguments:(NSDictionary<NSString *, id> *)arguments in ContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *error))completionHandler829 { 830 [self _evaluateJavaScript:javaScriptString asAsyncFunction:YES withSourceURL:nil withArguments:arguments forceUserGesture:YES inFrame: nilinWorld:contentWorld completionHandler:completionHandler];823 - (void)evaluateJavaScript:(NSString *)javaScriptString inFrame:(WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *))completionHandler 824 { 825 [self _evaluateJavaScript:javaScriptString asAsyncFunction:NO withSourceURL:nil withArguments:nil forceUserGesture:YES inFrame:frame inWorld:contentWorld completionHandler:completionHandler]; 826 } 827 828 - (void)callAsyncJavaScript:(NSString *)javaScriptString arguments:(NSDictionary<NSString *, id> *)arguments inFrame:(WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *error))completionHandler 829 { 830 [self _evaluateJavaScript:javaScriptString asAsyncFunction:YES withSourceURL:nil withArguments:arguments forceUserGesture:YES inFrame:frame inWorld:contentWorld completionHandler:completionHandler]; 831 831 } 832 832 … … 863 863 864 864 return false; 865 } 866 867 static RetainPtr<NSError> nsErrorFromExceptionDetails(const WebCore::ExceptionDetails& details) 868 { 869 auto userInfo = adoptNS([[NSMutableDictionary alloc] init]); 870 871 WKErrorCode errorCode; 872 switch (details.type) { 873 case WebCore::ExceptionDetails::Type::InvalidTargetFrame: 874 errorCode = WKErrorJavaScriptInvalidFrameTarget; 875 break; 876 case WebCore::ExceptionDetails::Type::Script: 877 errorCode = WKErrorJavaScriptExceptionOccurred; 878 break; 879 } 880 881 [userInfo setObject:localizedDescriptionForErrorCode(errorCode) forKey:NSLocalizedDescriptionKey]; 882 [userInfo setObject:details.message forKey:_WKJavaScriptExceptionMessageErrorKey]; 883 [userInfo setObject:@(details.lineNumber) forKey:_WKJavaScriptExceptionLineNumberErrorKey]; 884 [userInfo setObject:@(details.columnNumber) forKey:_WKJavaScriptExceptionColumnNumberErrorKey]; 885 886 if (!details.sourceURL.isEmpty()) 887 [userInfo setObject:[NSURL _web_URLWithWTFString:details.sourceURL] forKey:_WKJavaScriptExceptionSourceURLErrorKey]; 888 889 return adoptNS([[NSError alloc] initWithDomain:WKErrorDomain code:errorCode userInfo:userInfo.get()]); 865 890 } 866 891 … … 931 956 if (details) { 932 957 ASSERT(!serializedScriptValue); 933 934 RetainPtr<NSMutableDictionary> userInfo = adoptNS([[NSMutableDictionary alloc] init]); 935 936 [userInfo setObject:localizedDescriptionForErrorCode(WKErrorJavaScriptExceptionOccurred) forKey:NSLocalizedDescriptionKey]; 937 [userInfo setObject:static_cast<NSString *>(details->message) forKey:_WKJavaScriptExceptionMessageErrorKey]; 938 [userInfo setObject:@(details->lineNumber) forKey:_WKJavaScriptExceptionLineNumberErrorKey]; 939 [userInfo setObject:@(details->columnNumber) forKey:_WKJavaScriptExceptionColumnNumberErrorKey]; 940 941 if (!details->sourceURL.isEmpty()) 942 [userInfo setObject:[NSURL _web_URLWithWTFString:details->sourceURL] forKey:_WKJavaScriptExceptionSourceURLErrorKey]; 943 944 rawHandler(nil, adoptNS([[NSError alloc] initWithDomain:WKErrorDomain code:WKErrorJavaScriptExceptionOccurred userInfo:userInfo.get()]).get()); 958 rawHandler(nil, nsErrorFromExceptionDetails(*details).get()); 945 959 return; 946 960 } -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp
r263428 r263727 3431 3431 3432 3432 if (!frame || !frame->coreFrame()) { 3433 send(Messages::WebPageProxy::ScriptValueCallback({ }, ExceptionDetails { "Unable to execute JavaScript: Page is in invalid state"_s}, callbackID));3433 send(Messages::WebPageProxy::ScriptValueCallback({ }, ExceptionDetails { "Unable to execute JavaScript: Target frame could not be found in the page"_s, 0, 0, ExceptionDetails::Type::InvalidTargetFrame }, callbackID)); 3434 3434 return; 3435 3435 } -
trunk/Tools/ChangeLog
r263714 r263727 1 2020-06-29 Brady Eidson <beidson@apple.com> 2 3 JavaScript cannot be injected into iframes 4 <rdar://problem/54168946> and https://bugs.webkit.org/show_bug.cgi?id=213556 5 6 Reviewed by Geoff Garen. 7 8 * TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm: 9 (TestWebKitAPI::TEST): 10 * TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm: 11 (TEST): 12 * TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm: 13 * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm: 14 (TEST): 15 (-[FramesMessageHandler userContentController:didReceiveScriptMessage:]): 16 * TestWebKitAPI/cocoa/TestWKWebView.mm: 17 (-[WKWebView objectByCallingAsyncFunction:withArguments:error:]): 18 1 19 2020-06-29 Jonathan Bedard <jbedard@apple.com> 2 20 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm
r257876 r263727 184 184 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]); 185 185 186 [webView callAsyncJavaScript:@"shouldn't crash" arguments:@{ @"invalidparameter" : webView.get() } in ContentWorld:WKContentWorld.pageWorld completionHandler:nil];186 [webView callAsyncJavaScript:@"shouldn't crash" arguments:@{ @"invalidparameter" : webView.get() } inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:nil]; 187 187 188 188 NSString *functionBody = @"return new Promise(function(resolve, reject) { setTimeout(function(){ resolve(42) }, 0); })"; 189 189 190 190 bool done = false; 191 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {191 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 192 192 EXPECT_NULL(error); 193 193 EXPECT_TRUE([result isKindOfClass:[NSNumber class]]); … … 201 201 202 202 done = false; 203 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {203 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 204 204 EXPECT_NULL(result); 205 205 EXPECT_TRUE(error != nil); … … 212 212 213 213 done = false; 214 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {214 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 215 215 EXPECT_NULL(error); 216 216 EXPECT_TRUE([result isKindOfClass:[NSNumber class]]); … … 223 223 224 224 done = false; 225 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {225 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 226 226 EXPECT_NULL(result); 227 227 EXPECT_TRUE(error != nil); … … 235 235 236 236 done = false; 237 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {237 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 238 238 EXPECT_NULL(error); 239 239 EXPECT_TRUE([result isKindOfClass:[NSNumber class]]); … … 247 247 248 248 done = false; 249 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {249 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 250 250 EXPECT_NULL(error); 251 251 EXPECT_TRUE([result isKindOfClass:[NSString class]]); … … 259 259 260 260 done = false; 261 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {261 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 262 262 EXPECT_NULL(error); 263 263 EXPECT_TRUE([result isKindOfClass:[NSString class]]); … … 271 271 functionBody = @"return new Promise(function(resolve, reject) { })"; 272 272 for (int i = 0; i < 500; ++i) { 273 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {273 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 274 274 EXPECT_NULL(result); 275 275 EXPECT_TRUE(error != nil); -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm
r263060 r263727 222 222 __block bool done = false; 223 223 // Test that we throw an exception if you try to use a message handler that has been removed. 224 [webView callAsyncJavaScript:@"return handlerToRemove.postMessage('FAIL')" arguments:nil in ContentWorld:[WKContentWorld pageWorld] completionHandler:^ (id value, NSError * error) {224 [webView callAsyncJavaScript:@"return handlerToRemove.postMessage('FAIL')" arguments:nil inFrame:nil inContentWorld:[WKContentWorld pageWorld] completionHandler:^ (id value, NSError * error) { 225 225 EXPECT_NULL(value); 226 226 EXPECT_NOT_NULL(error); … … 1013 1013 1014 1014 // pageWorld is where testhandler1 lives 1015 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler1", @"arg" : @1 } in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {1015 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler1", @"arg" : @1 } inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 1016 1016 EXPECT_NULL(error); 1017 1017 EXPECT_TRUE([result isEqualToNumber:@1]); … … 1022 1022 1023 1023 // Trying to find testHandler1 in the defaultClientWorld should fail 1024 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler1", @"arg" : @1 } in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) {1024 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler1", @"arg" : @1 } inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) { 1025 1025 EXPECT_NULL(result); 1026 1026 EXPECT_NOT_NULL(error); … … 1031 1031 1032 1032 // defaultClientWorld is where testhandler2 lives 1033 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler2", @"arg" : @1 } in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) {1033 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler2", @"arg" : @1 } inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) { 1034 1034 EXPECT_NULL(error); 1035 1035 EXPECT_TRUE([result isEqualToNumber:@1]); … … 1041 1041 // But if we remvoe it, it should no longer live there, and using it should cause an error. 1042 1042 [[configuration userContentController] removeScriptMessageHandlerForName:@"testHandler2" contentWorld:WKContentWorld.defaultClientWorld]; 1043 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler2", @"arg" : @1 } in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) {1043 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler2", @"arg" : @1 } inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[&] (id result, NSError *error) { 1044 1044 EXPECT_NULL(result); 1045 1045 EXPECT_NOT_NULL(error); … … 1050 1050 1051 1051 // Verify handlers 3, 4, and 5 are all in the custom world. 1052 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1052 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1053 1053 EXPECT_NULL(error); 1054 1054 EXPECT_TRUE([result isEqualToNumber:@1]); 1055 1055 }]; 1056 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1056 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1057 1057 EXPECT_NULL(error); 1058 1058 EXPECT_TRUE([result isEqualToNumber:@1]); 1059 1059 }]; 1060 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1060 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1061 1061 EXPECT_NULL(error); 1062 1062 EXPECT_TRUE([result isEqualToNumber:@1]); … … 1068 1068 // Remove 3 from the wrong world, verify it is still there in the custom world. 1069 1069 [[configuration userContentController] removeScriptMessageHandlerForName:@"testHandler3" contentWorld:WKContentWorld.defaultClientWorld]; 1070 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1070 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1071 1071 EXPECT_NULL(error); 1072 1072 EXPECT_TRUE([result isEqualToNumber:@1]); … … 1078 1078 // Remove 3 from the correct world, verify it is gone, but 4 and 5 are still there. 1079 1079 [[configuration userContentController] removeScriptMessageHandlerForName:@"testHandler3" contentWorld:world]; 1080 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1080 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1081 1081 EXPECT_NULL(result); 1082 1082 EXPECT_NOT_NULL(error); 1083 1083 }]; 1084 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1084 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1085 1085 EXPECT_NULL(error); 1086 1086 EXPECT_TRUE([result isEqualToNumber:@1]); 1087 1087 }]; 1088 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1088 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1089 1089 EXPECT_NULL(error); 1090 1090 EXPECT_TRUE([result isEqualToNumber:@1]); … … 1096 1096 // Remove "all" in the custom world, verify 4 and 5 are now gone. 1097 1097 [[configuration userContentController] removeAllScriptMessageHandlersFromContentWorld:world]; 1098 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1098 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1099 1099 EXPECT_NULL(result); 1100 1100 EXPECT_NOT_NULL(error); 1101 1101 }]; 1102 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } in ContentWorld:world completionHandler:[&] (id result, NSError *error) {1102 [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) { 1103 1103 EXPECT_NULL(result); 1104 1104 EXPECT_NOT_NULL(error); … … 1119 1119 bool done = false; 1120 1120 NSString *functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Fulfill'); await p; return p;"; 1121 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {1121 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 1122 1122 EXPECT_NULL(error); 1123 1123 EXPECT_TRUE([result isKindOfClass:[NSString class]]); … … 1130 1130 done = false; 1131 1131 functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Reject'); await p; return p;"; 1132 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {1132 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 1133 1133 EXPECT_NULL(result); 1134 1134 EXPECT_TRUE(!!error); … … 1142 1142 done = false; 1143 1143 functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Undefined'); var result = await p; return result == undefined ? 'Yes' : 'No'"; 1144 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {1144 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 1145 1145 EXPECT_NULL(error); 1146 1146 EXPECT_TRUE([result isKindOfClass:[NSString class]]); … … 1154 1154 done = false; 1155 1155 functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Do nothing'); await p; return p;"; 1156 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {1156 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 1157 1157 EXPECT_NULL(result); 1158 1158 EXPECT_TRUE(!!error); … … 1166 1166 done = false; 1167 1167 functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Invalid reply'); await p; return p;"; 1168 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {1168 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 1169 1169 EXPECT_NULL(result); 1170 1170 EXPECT_TRUE(!!error); … … 1188 1188 // Set a variable in the world. 1189 1189 bool done = false; 1190 [webView evaluateJavaScript:@"var foo = 'bar'" in ContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {1190 [webView evaluateJavaScript:@"var foo = 'bar'" inFrame:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) { 1191 1191 EXPECT_NULL(error); 1192 1192 done = true; … … 1197 1197 // Have the message handler bounce back that value. 1198 1198 NSString *functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage(foo); await p; return p;"; 1199 [webView callAsyncJavaScript:functionBody arguments:nil in ContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {1199 [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) { 1200 1200 EXPECT_NULL(error); 1201 1201 EXPECT_TRUE([result isKindOfClass:[NSString class]]); … … 1209 1209 // But by evaluating JS make sure the value is still there. 1210 1210 [[configuration userContentController] removeAllScriptMessageHandlersFromContentWorld:world.get()]; 1211 [webView evaluateJavaScript:@"foo" in ContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {1211 [webView evaluateJavaScript:@"foo" inFrame:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) { 1212 1212 EXPECT_NULL(error); 1213 1213 EXPECT_TRUE([result isKindOfClass:[NSString class]]); -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm
r261418 r263727 159 159 160 160 // Verify that value is visible when evaluating in the pageWorld 161 [webView evaluateJavaScript:@"foo" in ContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {161 [webView evaluateJavaScript:@"foo" inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) { 162 162 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 163 163 EXPECT_TRUE([result isEqualToString:@"bar"]); … … 169 169 170 170 // Verify that value is not visible when evaluating in the defaultClientWorld 171 [webView evaluateJavaScript:@"foo" in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {171 [webView evaluateJavaScript:@"foo" inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) { 172 172 EXPECT_NULL(result); 173 173 isDone = true; … … 178 178 179 179 // Verify that value is visible when calling a function in the pageWorld 180 [webView callAsyncJavaScript:@"return foo" arguments:nil in ContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {180 [webView callAsyncJavaScript:@"return foo" arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) { 181 181 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 182 182 EXPECT_TRUE([result isEqualToString:@"bar"]); … … 188 188 189 189 // Verify that value is not visible when calling a function in the defaultClientWorld 190 [webView callAsyncJavaScript:@"return foo" arguments:nil in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {190 [webView callAsyncJavaScript:@"return foo" arguments:nil inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) { 191 191 EXPECT_NULL(result); 192 192 isDone = true; … … 202 202 203 203 // Set a variable value in that named world. 204 [webView evaluateJavaScript:@"var bar = 'baz'" in ContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {204 [webView evaluateJavaScript:@"var bar = 'baz'" inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) { 205 205 EXPECT_NULL(result); 206 206 isDone = true; … … 211 211 212 212 // Set a global variable value in that named world via a function call. 213 [webView callAsyncJavaScript:@"window.baz = 'bat'" arguments:nil in ContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {213 [webView callAsyncJavaScript:@"window.baz = 'bat'" arguments:nil inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) { 214 214 EXPECT_NULL(result); 215 215 EXPECT_NULL(error); … … 224 224 225 225 // Verify the variables we set are there in that named world. 226 [webView evaluateJavaScript:@"bar" in ContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {226 [webView evaluateJavaScript:@"bar" inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) { 227 227 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 228 228 EXPECT_TRUE([result isEqualToString:@"baz"]); … … 233 233 isDone = false; 234 234 235 [webView evaluateJavaScript:@"window.baz" in ContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {235 [webView evaluateJavaScript:@"window.baz" inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) { 236 236 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 237 237 EXPECT_TRUE([result isEqualToString:@"bat"]); … … 243 243 244 244 // Verify they aren't there in the defaultClientWorld. 245 [webView evaluateJavaScript:@"bar" in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {246 EXPECT_NULL(result); 247 isDone = true; 248 testsPassed++; 249 }]; 250 TestWebKitAPI::Util::run(&isDone); 251 isDone = false; 252 253 [webView evaluateJavaScript:@"window.baz" in ContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {245 [webView evaluateJavaScript:@"bar" inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) { 246 EXPECT_NULL(result); 247 isDone = true; 248 testsPassed++; 249 }]; 250 TestWebKitAPI::Util::run(&isDone); 251 isDone = false; 252 253 [webView evaluateJavaScript:@"window.baz" inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) { 254 254 EXPECT_NULL(result); 255 255 isDone = true; … … 260 260 261 261 // Verify they aren't there in the pageWorld. 262 [webView evaluateJavaScript:@"bar" in ContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {263 EXPECT_NULL(result); 264 isDone = true; 265 testsPassed++; 266 }]; 267 TestWebKitAPI::Util::run(&isDone); 268 isDone = false; 269 270 [webView evaluateJavaScript:@"window.baz" in ContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {262 [webView evaluateJavaScript:@"bar" inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) { 263 EXPECT_NULL(result); 264 isDone = true; 265 testsPassed++; 266 }]; 267 TestWebKitAPI::Util::run(&isDone); 268 isDone = false; 269 270 [webView evaluateJavaScript:@"window.baz" inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) { 271 271 EXPECT_NULL(result); 272 272 isDone = true; … … 286 286 287 287 __block bool done = false; 288 [webView evaluateJavaScript:@"window.worldName" in ContentWorld:[WKContentWorld worldWithName:@"testName"] completionHandler:^(id result, NSError *error) {288 [webView evaluateJavaScript:@"window.worldName" inFrame:nil inContentWorld:[WKContentWorld worldWithName:@"testName"] completionHandler:^(id result, NSError *error) { 289 289 EXPECT_WK_STREQ(result, "testName"); 290 290 done = true; … … 473 473 474 474 } 475 476 static NSMutableSet<WKFrameInfo *> *allFrames; 477 @interface FramesMessageHandler : NSObject <WKScriptMessageHandler> 478 @end 479 480 @implementation FramesMessageHandler 481 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 482 { 483 EXPECT_TRUE(message.world == WKContentWorld.defaultClientWorld); 484 [allFrames addObject:message.frameInfo]; 485 } 486 @end 487 488 static const char* framesMainResource = R"FRAMESRESOURCE( 489 Hello world<br> 490 <iframe id='theFrame' src='otherprotocol://test/index.html'></iframe> 491 )FRAMESRESOURCE"; 492 493 static NSString *userScriptSource = @"window.webkit.messageHandlers.framesTester.postMessage('hi');"; 494 495 // This test loads a document under one protocol. 496 // That document embeds an iframe under a different protocol 497 // (ensuring they cannot access each other under the cross-origin rules of the web security model) 498 // It uses a WKUserScript to collect all of the frames on the page, and then uses new forms of evaluateJavaScript 499 // and callAsyncJavaScript to confirm that it can execute JS directly in each of those frames. 500 TEST(EvaluateJavaScript, JavaScriptInFramesFromPostMessage) 501 { 502 allFrames = [[NSMutableSet<WKFrameInfo *> alloc] init]; 503 auto messageHandler = adoptNS([[FramesMessageHandler alloc] init]); 504 auto userScript = adoptNS([[WKUserScript alloc] initWithSource:userScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO inContentWorld:WKContentWorld.defaultClientWorld]); 505 506 WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease]; 507 [configuration.userContentController addUserScript:userScript.get()]; 508 [configuration.userContentController addScriptMessageHandler:messageHandler.get() contentWorld:WKContentWorld.defaultClientWorld name:@"framesTester"]; 509 510 auto handler = adoptNS([[TestURLSchemeHandler alloc] init]); 511 [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) { 512 if ([task.request.URL.absoluteString isEqualToString:@"framestest://test/index.html"]) { 513 NSData *data = [[NSString stringWithFormat:@"%s", framesMainResource] dataUsingEncoding:NSUTF8StringEncoding]; 514 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:data.length textEncodingName:nil] autorelease]]; 515 [task didReceiveData:data]; 516 [task didFinish]; 517 } else if ([task.request.URL.absoluteString isEqualToString:@"otherprotocol://test/index.html"]) { 518 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]]; 519 [task didFinish]; 520 } else 521 ASSERT_NOT_REACHED(); 522 }]; 523 524 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"framestest"]; 525 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"otherprotocol"]; 526 527 RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]); 528 [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"framestest://test/index.html"]]]; 529 530 EXPECT_EQ(allFrames.count, 2u); 531 532 static size_t finishedFrames = 0; 533 static bool isDone = false; 534 535 for (WKFrameInfo *frame in allFrames) { 536 bool isMainFrame = frame.isMainFrame; 537 [webView callAsyncJavaScript:@"return location.href;" arguments:nil inFrame:frame inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[isMainFrame] (id result, NSError *error) { 538 EXPECT_NULL(error); 539 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 540 541 if (isMainFrame) 542 EXPECT_TRUE([result isEqualToString:@"framestest://test/index.html"]); 543 else 544 EXPECT_TRUE([result isEqualToString:@"otherprotocol://test/index.html"]); 545 546 if (++finishedFrames == allFrames.count * 2) 547 isDone = true; 548 }]; 549 550 551 [webView evaluateJavaScript:@"location.href;" inFrame:frame inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[isMainFrame] (id result, NSError *error) { 552 EXPECT_NULL(error); 553 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 554 555 if (isMainFrame) 556 EXPECT_TRUE([result isEqualToString:@"framestest://test/index.html"]); 557 else 558 EXPECT_TRUE([result isEqualToString:@"otherprotocol://test/index.html"]); 559 560 if (++finishedFrames == allFrames.count * 2) 561 isDone = true; 562 }]; 563 } 564 565 TestWebKitAPI::Util::run(&isDone); 566 } 567 568 // This test loads a document under one protocol. 569 // That document embeds an iframe under a different protocol 570 // (ensuring they cannot access each other under the cross-origin rules of the web security model) 571 // It collects all the frames seen during navigation delegate callbacks, and then uses new forms of evaluateJavaScript 572 // and callAsyncJavaScript to confirm that it can execute JS directly in each of those frames. 573 TEST(EvaluateJavaScript, JavaScriptInFramesFromNavigationDelegate) 574 { 575 allFrames = [[NSMutableSet<WKFrameInfo *> alloc] init]; 576 577 auto handler = adoptNS([[TestURLSchemeHandler alloc] init]); 578 [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) { 579 if ([task.request.URL.absoluteString isEqualToString:@"framestest://test/index.html"]) { 580 NSData *data = [[NSString stringWithFormat:@"%s", framesMainResource] dataUsingEncoding:NSUTF8StringEncoding]; 581 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:data.length textEncodingName:nil] autorelease]]; 582 [task didReceiveData:data]; 583 [task didFinish]; 584 } else if ([task.request.URL.absoluteString isEqualToString:@"otherprotocol://test/index.html"]) { 585 NSData *data = [@"FooBarBaz" dataUsingEncoding:NSUTF8StringEncoding]; 586 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]]; 587 [task didReceiveData:data]; 588 [task didFinish]; 589 } else 590 ASSERT_NOT_REACHED(); 591 }]; 592 593 WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease]; 594 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"framestest"]; 595 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"otherprotocol"]; 596 597 RetainPtr<WKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]); 598 599 auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]); 600 601 __block bool didFinishNavigation = false; 602 [navigationDelegate setDidFinishNavigation:^(WKWebView *, WKNavigation *) { 603 didFinishNavigation = true; 604 }]; 605 606 [navigationDelegate setDecidePolicyForNavigationAction:[&] (WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) { 607 if (action.targetFrame) 608 [allFrames addObject:action.targetFrame]; 609 610 decisionHandler(WKNavigationActionPolicyAllow); 611 }]; 612 613 [webView setNavigationDelegate:navigationDelegate.get()]; 614 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"framestest://test/index.html"]]]; 615 616 TestWebKitAPI::Util::run(&didFinishNavigation); 617 618 EXPECT_EQ(allFrames.count, 2u); 619 620 static size_t finishedFrames = 0; 621 static bool isDone = false; 622 623 for (WKFrameInfo *frame in allFrames) { 624 bool isMainFrame = frame.isMainFrame; 625 [webView callAsyncJavaScript:@"return location.href;" arguments:nil inFrame:frame inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[isMainFrame] (id result, NSError *error) { 626 EXPECT_NULL(error); 627 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 628 629 if (isMainFrame) 630 EXPECT_TRUE([result isEqualToString:@"framestest://test/index.html"]); 631 else 632 EXPECT_TRUE([result isEqualToString:@"otherprotocol://test/index.html"]); 633 634 if (++finishedFrames == allFrames.count * 2) 635 isDone = true; 636 }]; 637 638 639 [webView evaluateJavaScript:@"location.href;" inFrame:frame inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[isMainFrame] (id result, NSError *error) { 640 EXPECT_NULL(error); 641 EXPECT_TRUE([result isKindOfClass:[NSString class]]); 642 643 if (isMainFrame) 644 EXPECT_TRUE([result isEqualToString:@"framestest://test/index.html"]); 645 else 646 EXPECT_TRUE([result isEqualToString:@"otherprotocol://test/index.html"]); 647 648 if (++finishedFrames == allFrames.count * 2) 649 isDone = true; 650 }]; 651 } 652 653 TestWebKitAPI::Util::run(&isDone); 654 } 655 656 // This test verifies that evaluating JavaScript in a frame that has since gone missing 657 // due to removal from the DOM results in an appropriate error 658 TEST(EvaluateJavaScript, JavaScriptInMissingFrameError) 659 { 660 allFrames = [[NSMutableSet<WKFrameInfo *> alloc] init]; 661 662 auto handler = adoptNS([[TestURLSchemeHandler alloc] init]); 663 [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) { 664 if ([task.request.URL.absoluteString isEqualToString:@"framestest://test/index.html"]) { 665 NSData *data = [[NSString stringWithFormat:@"%s", framesMainResource] dataUsingEncoding:NSUTF8StringEncoding]; 666 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:data.length textEncodingName:nil] autorelease]]; 667 [task didReceiveData:data]; 668 [task didFinish]; 669 } else if ([task.request.URL.absoluteString isEqualToString:@"otherprotocol://test/index.html"]) { 670 NSData *data = [@"FooBarBaz" dataUsingEncoding:NSUTF8StringEncoding]; 671 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]]; 672 [task didReceiveData:data]; 673 [task didFinish]; 674 } else 675 ASSERT_NOT_REACHED(); 676 }]; 677 678 WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease]; 679 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"framestest"]; 680 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"otherprotocol"]; 681 682 RetainPtr<WKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]); 683 684 auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]); 685 686 __block bool didFinishNavigation = false; 687 [navigationDelegate setDidFinishNavigation:^(WKWebView *, WKNavigation *) { 688 didFinishNavigation = true; 689 }]; 690 691 [navigationDelegate setDecidePolicyForNavigationAction:[&] (WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) { 692 if (action.targetFrame) 693 [allFrames addObject:action.targetFrame]; 694 695 decisionHandler(WKNavigationActionPolicyAllow); 696 }]; 697 698 [webView setNavigationDelegate:navigationDelegate.get()]; 699 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"framestest://test/index.html"]]]; 700 701 TestWebKitAPI::Util::run(&didFinishNavigation); 702 703 EXPECT_EQ(allFrames.count, 2u); 704 705 static bool isDone = false; 706 [webView evaluateJavaScript:@"var frame = document.getElementById('theFrame'); frame.parentNode.removeChild(frame);" inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[] (id result, NSError *error) { 707 isDone = true; 708 }]; 709 710 TestWebKitAPI::Util::run(&isDone); 711 isDone = false; 712 713 for (WKFrameInfo *frame in allFrames) { 714 if (frame.isMainFrame) 715 continue; 716 717 [webView callAsyncJavaScript:@"return location.href;" arguments:nil inFrame:frame inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[] (id result, NSError *error) { 718 EXPECT_FALSE(error == nil); 719 EXPECT_TRUE(error.domain == WKErrorDomain); 720 EXPECT_TRUE(error.code == WKErrorJavaScriptInvalidFrameTarget); 721 isDone = true; 722 }]; 723 } 724 725 TestWebKitAPI::Util::run(&isDone); 726 } 727 728 // This test verifies that evaluating JavaScript in a frame from the previous main navigation results in an error 729 TEST(EvaluateJavaScript, JavaScriptInMissingFrameAfterNavigationError) 730 { 731 allFrames = [[NSMutableSet<WKFrameInfo *> alloc] init]; 732 733 auto handler = adoptNS([[TestURLSchemeHandler alloc] init]); 734 [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) { 735 if ([task.request.URL.absoluteString isEqualToString:@"framestest://test/index.html"]) { 736 NSData *data = [[NSString stringWithFormat:@"%s", framesMainResource] dataUsingEncoding:NSUTF8StringEncoding]; 737 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:data.length textEncodingName:nil] autorelease]]; 738 [task didReceiveData:data]; 739 [task didFinish]; 740 } else if ([task.request.URL.absoluteString isEqualToString:@"otherprotocol://test/index.html"]) { 741 NSData *data = [@"FooBarBaz" dataUsingEncoding:NSUTF8StringEncoding]; 742 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]]; 743 [task didReceiveData:data]; 744 [task didFinish]; 745 } else if ([task.request.URL.absoluteString isEqualToString:@"framestest://index2.html"]) { 746 NSData *data = [@"Hi" dataUsingEncoding:NSUTF8StringEncoding]; 747 [task didReceiveResponse:[[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]]; 748 [task didReceiveData:data]; 749 [task didFinish]; 750 } else 751 ASSERT_NOT_REACHED(); 752 }]; 753 754 WKWebViewConfiguration *configuration = [[[WKWebViewConfiguration alloc] init] autorelease]; 755 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"framestest"]; 756 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"otherprotocol"]; 757 758 RetainPtr<WKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]); 759 760 auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]); 761 762 __block bool didFinishNavigation = false; 763 [navigationDelegate setDidFinishNavigation:^(WKWebView *, WKNavigation *) { 764 didFinishNavigation = true; 765 }]; 766 767 [navigationDelegate setDecidePolicyForNavigationAction:[&] (WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) { 768 if (action.targetFrame) 769 [allFrames addObject:action.targetFrame]; 770 771 decisionHandler(WKNavigationActionPolicyAllow); 772 }]; 773 774 [webView setNavigationDelegate:navigationDelegate.get()]; 775 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"framestest://test/index.html"]]]; 776 777 TestWebKitAPI::Util::run(&didFinishNavigation); 778 didFinishNavigation = false; 779 780 EXPECT_EQ(allFrames.count, 2u); 781 782 RetainPtr<WKFrameInfo> iframe; 783 for (WKFrameInfo *frame in allFrames) { 784 if (frame.isMainFrame) 785 continue; 786 iframe = frame; 787 break; 788 } 789 790 EXPECT_NOT_NULL(iframe); 791 792 // Get rid of the frame by navigating 793 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"framestest://index2.html"]]]; 794 TestWebKitAPI::Util::run(&didFinishNavigation); 795 didFinishNavigation = false; 796 797 static bool isDone = false; 798 799 [webView callAsyncJavaScript:@"return location.href;" arguments:nil inFrame:iframe.get() inContentWorld:WKContentWorld.defaultClientWorld completionHandler:[] (id result, NSError *error) { 800 EXPECT_FALSE(error == nil); 801 EXPECT_TRUE(error.domain == WKErrorDomain); 802 EXPECT_TRUE(error.code == WKErrorJavaScriptInvalidFrameTarget); 803 isDone = true; 804 }]; 805 806 TestWebKitAPI::Util::run(&isDone); 807 isDone = false; 808 } -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
r262507 r263727 199 199 200 200 RetainPtr<id> evalResult; 201 [self callAsyncJavaScript:script arguments:arguments in ContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {201 [self callAsyncJavaScript:script arguments:arguments inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) { 202 202 evalResult = result; 203 203 if (errorOut)
Note: See TracChangeset
for help on using the changeset viewer.