Changeset 263727 in webkit


Ignore:
Timestamp:
Jun 29, 2020 10:43:19 PM (4 years ago)
Author:
beidson@apple.com
Message:

JavaScript cannot be injected into iframes
<rdar://problem/54168946> and https://bugs.webkit.org/show_bug.cgi?id=213556

Reviewed by Geoff Garen.
Source/WebCore:

Covered by API tests.

  • bindings/js/ExceptionDetails.h: Start a collection of "exception types" that will grow quickly, beginning with the specialized "missing frame" type.

Source/WebKit:

This adds a few mechanisms:

  • Allows for WKUserScripts to have a target content world
  • Allows "evaluateJavaScript" and "callAsyncJavaScript" to target a specific frame
  • Allows for the completion handlers of those methods to be able to distinguish failure-due-to-missing-frame.
  • Shared/WebCoreArgumentCoders.cpp:

(IPC::ArgumentCoder<ExceptionDetails>::encode):
(IPC::ArgumentCoder<ExceptionDetails>::decode):

  • Shared/WebCoreArgumentCoders.h:
  • UIProcess/API/Cocoa/WKError.h:
  • UIProcess/API/Cocoa/WKError.mm:

(localizedDescriptionForErrorCode):

  • UIProcess/API/Cocoa/WKUserScript.h:
  • UIProcess/API/Cocoa/WKUserScript.mm:

(-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:]):
(-[WKUserScript initWithSource:injectionTime:forMainFrameOnly:inContentWorld:]):

  • UIProcess/API/Cocoa/WKWebView.h:
  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView evaluateJavaScript:inFrame:inContentWorld:completionHandler:]):
(-[WKWebView callAsyncJavaScript:arguments:inFrame:inContentWorld:completionHandler:]):
(nsErrorFromExceptionDetails):
(-[WKWebView _evaluateJavaScript:asAsyncFunction:withSourceURL:withArguments:forceUserGesture:inFrame:inWorld:completionHandler:]):
(-[WKWebView callAsyncJavaScript:arguments:inContentWorld:completionHandler:]): Deleted.

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::runJavaScript):

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm:

(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm:

(TEST):

  • TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:
  • TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm:

(TEST):
(-[FramesMessageHandler userContentController:didReceiveScriptMessage:]):

  • TestWebKitAPI/cocoa/TestWKWebView.mm:

(-[WKWebView objectByCallingAsyncFunction:withArguments:error:]):

Location:
trunk
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r263722 r263727  
     12020-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
    1132020-06-29  Sam Weinig  <weinig@apple.com>
    214
  • trunk/Source/WebCore/bindings/js/ExceptionDetails.h

    r253950 r263727  
    3131
    3232struct ExceptionDetails {
     33    enum class Type : uint8_t {
     34        Script,
     35        InvalidTargetFrame,
     36    };
     37
    3338    String message;
    3439    int lineNumber { 0 };
    3540    int columnNumber { 0 };
     41    Type type { Type::Script };
     42
    3643    // This bizarre explicit initialization of String is because older compilers (like on High Sierra)
    3744    // don't properly handle partial initialization lists unless every struct member has an explicit default value.
     
    4148
    4249} // namespace WebCore
     50
     51namespace WTF {
     52template<> 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  
     12020-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
    1392020-06-29  Alex Christensen  <achristensen@webkit.org>
    240
  • trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp

    r262994 r263727  
    26602660    encoder << info.lineNumber;
    26612661    encoder << info.columnNumber;
     2662    encoder << info.type;
    26622663    encoder << info.sourceURL;
    26632664}
     
    26722673
    26732674    if (!decoder.decode(result.columnNumber))
     2675        return false;
     2676
     2677    if (!decoder.decode(result.type))
    26742678        return false;
    26752679
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKError.h

    r252174 r263727  
    5959    WKErrorAttributedStringContentFailedToLoad WK_API_AVAILABLE(macos(10.15), ios(13.0)),
    6060    WKErrorAttributedStringContentLoadTimedOut WK_API_AVAILABLE(macos(10.15), ios(13.0)),
     61    WKErrorJavaScriptInvalidFrameTarget WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)),
    6162} WK_API_AVAILABLE(macos(10.10), ios(8.0));
    6263
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKError.mm

    r243113 r263727  
    7474    case WKErrorAttributedStringContentLoadTimedOut:
    7575        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");
    7679    }
    7780}
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.h

    r243376 r263727  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5858 @param injectionTime When the script should be injected.
    5959 @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`
    6061 */
    6162- (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));
    6271
    6372@end
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKUserScript.mm

    r263060 r263727  
    3434- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly
    3535{
     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{
    3641    if (!(self = [super init]))
    3742        return nil;
    3843
    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);
    4045
    4146    return self;
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h

    r260334 r263727  
    3939@class WKFindConfiguration;
    4040@class WKFindResult;
     41@class WKFrameInfo;
    4142@class WKNavigation;
    4243@class WKPDFConfiguration;
     
    221222 @param completionHandler A block to invoke when script evaluation completes or fails.
    222223 @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`
    223227*/
    224228- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
     
    226230/* @abstract Evaluates the given JavaScript string.
    227231 @param javaScriptString The JavaScript string to evaluate.
     232 @param frame A WKFrameInfo identifying the frame in which to evaluate the JavaScript string.
    228233 @param contentWorld The WKContentWorld in which to evaluate the JavaScript string.
    229234 @param completionHandler A block to invoke when script evaluation completes or fails.
    230235 @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
    231243 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)
    232244 Such changes will be visible to script executing in all WKContentWorlds.
     
    236248 Once your global state is set up, consider using callAsyncJavaScript: for more flexible interaction with the JavaScript programming model.
    237249*/
    238 - (void)evaluateJavaScript:(NSString *)javaScriptString 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));
     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));
    239251
    240252/* @abstract Calls the given JavaScript string as an async JavaScript function, passing the given named arguments to that function.
    241253 @param functionBody The JavaScript string to use as the function body.
    242254 @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.
    243256 @param contentWorld The WKContentWorld in which to call the JavaScript function.
    244257 @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.
     
    271284 NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull.
    272285 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
    273292
    274293 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)
     
    301320 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.
    302321*/
    303 - (void)callAsyncJavaScript:(NSString *)functionBody arguments:(nullable NSDictionary<NSString *, id> *)arguments 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));
     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));
    304323
    305324/*! @abstract Get a snapshot for the visible viewport of WKWebView.
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r263525 r263727  
    821821}
    822822
    823 - (void)evaluateJavaScript:(NSString *)javaScriptString inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *))completionHandler
    824 {
    825     [self _evaluateJavaScript:javaScriptString asAsyncFunction:NO withSourceURL:nil withArguments:nil forceUserGesture:YES inFrame:nil inWorld:contentWorld completionHandler:completionHandler];
    826 }
    827 
    828 - (void)callAsyncJavaScript:(NSString *)javaScriptString arguments:(NSDictionary<NSString *, id> *)arguments inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *error))completionHandler
    829 {
    830     [self _evaluateJavaScript:javaScriptString asAsyncFunction:YES withSourceURL:nil withArguments:arguments forceUserGesture:YES inFrame:nil inWorld: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];
    831831}
    832832
     
    863863
    864864    return false;
     865}
     866
     867static 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()]);
    865890}
    866891
     
    931956        if (details) {
    932957            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());
    945959            return;
    946960        }
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r263428 r263727  
    34313431
    34323432    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));
    34343434        return;
    34353435    }
  • trunk/Tools/ChangeLog

    r263714 r263727  
     12020-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
    1192020-06-29  Jonathan Bedard  <jbedard@apple.com>
    220
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm

    r257876 r263727  
    184184    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
    185185
    186     [webView callAsyncJavaScript:@"shouldn't crash" arguments:@{ @"invalidparameter" : webView.get() } inContentWorld:WKContentWorld.pageWorld completionHandler:nil];
     186    [webView callAsyncJavaScript:@"shouldn't crash" arguments:@{ @"invalidparameter" : webView.get() } inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:nil];
    187187
    188188    NSString *functionBody = @"return new Promise(function(resolve, reject) { setTimeout(function(){ resolve(42) }, 0); })";
    189189
    190190    bool done = false;
    191     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     191    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    192192        EXPECT_NULL(error);
    193193        EXPECT_TRUE([result isKindOfClass:[NSNumber class]]);
     
    201201
    202202    done = false;
    203     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     203    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    204204        EXPECT_NULL(result);
    205205        EXPECT_TRUE(error != nil);
     
    212212
    213213    done = false;
    214     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     214    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    215215        EXPECT_NULL(error);
    216216        EXPECT_TRUE([result isKindOfClass:[NSNumber class]]);
     
    223223
    224224    done = false;
    225     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     225    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    226226        EXPECT_NULL(result);
    227227        EXPECT_TRUE(error != nil);
     
    235235
    236236    done = false;
    237     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     237    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    238238        EXPECT_NULL(error);
    239239        EXPECT_TRUE([result isKindOfClass:[NSNumber class]]);
     
    247247
    248248    done = false;
    249     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     249    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    250250        EXPECT_NULL(error);
    251251        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
     
    259259
    260260    done = false;
    261     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     261    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    262262        EXPECT_NULL(error);
    263263        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
     
    271271    functionBody = @"return new Promise(function(resolve, reject) { })";
    272272    for (int i = 0; i < 500; ++i) {
    273         [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     273        [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    274274            EXPECT_NULL(result);
    275275            EXPECT_TRUE(error != nil);
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserContentController.mm

    r263060 r263727  
    222222    __block bool done = false;
    223223    // 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 inContentWorld:[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) {
    225225        EXPECT_NULL(value);
    226226        EXPECT_NOT_NULL(error);
     
    10131013
    10141014    // pageWorld is where testhandler1 lives
    1015     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler1", @"arg" : @1 } inContentWorld: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) {
    10161016        EXPECT_NULL(error);
    10171017        EXPECT_TRUE([result isEqualToNumber:@1]);
     
    10221022
    10231023    // Trying to find testHandler1 in the defaultClientWorld should fail
    1024     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler1", @"arg" : @1 } inContentWorld: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) {
    10251025        EXPECT_NULL(result);
    10261026        EXPECT_NOT_NULL(error);
     
    10311031
    10321032    // defaultClientWorld is where testhandler2 lives
    1033     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler2", @"arg" : @1 } inContentWorld: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) {
    10341034        EXPECT_NULL(error);
    10351035        EXPECT_TRUE([result isEqualToNumber:@1]);
     
    10411041    // But if we remvoe it, it should no longer live there, and using it should cause an error.
    10421042    [[configuration userContentController] removeScriptMessageHandlerForName:@"testHandler2" contentWorld:WKContentWorld.defaultClientWorld];
    1043     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler2", @"arg" : @1 } inContentWorld: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) {
    10441044        EXPECT_NULL(result);
    10451045        EXPECT_NOT_NULL(error);
     
    10501050
    10511051    // Verify handlers 3, 4, and 5 are all in the custom world.
    1052     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1052    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10531053        EXPECT_NULL(error);
    10541054        EXPECT_TRUE([result isEqualToNumber:@1]);
    10551055    }];
    1056     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1056    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10571057        EXPECT_NULL(error);
    10581058        EXPECT_TRUE([result isEqualToNumber:@1]);
    10591059    }];
    1060     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1060    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10611061        EXPECT_NULL(error);
    10621062        EXPECT_TRUE([result isEqualToNumber:@1]);
     
    10681068    // Remove 3 from the wrong world, verify it is still there in the custom world.
    10691069    [[configuration userContentController] removeScriptMessageHandlerForName:@"testHandler3" contentWorld:WKContentWorld.defaultClientWorld];
    1070     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1070    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10711071        EXPECT_NULL(error);
    10721072        EXPECT_TRUE([result isEqualToNumber:@1]);
     
    10781078    // Remove 3 from the correct world, verify it is gone, but 4 and 5 are still there.
    10791079    [[configuration userContentController] removeScriptMessageHandlerForName:@"testHandler3" contentWorld:world];
    1080     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1080    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler3", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10811081        EXPECT_NULL(result);
    10821082        EXPECT_NOT_NULL(error);
    10831083    }];
    1084     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1084    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10851085        EXPECT_NULL(error);
    10861086        EXPECT_TRUE([result isEqualToNumber:@1]);
    10871087    }];
    1088     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1088    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10891089        EXPECT_NULL(error);
    10901090        EXPECT_TRUE([result isEqualToNumber:@1]);
     
    10961096    // Remove "all" in the custom world, verify 4 and 5 are now gone.
    10971097    [[configuration userContentController] removeAllScriptMessageHandlersFromContentWorld:world];
    1098     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1098    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler4", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    10991099        EXPECT_NULL(result);
    11001100        EXPECT_NOT_NULL(error);
    11011101    }];
    1102     [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inContentWorld:world completionHandler:[&] (id result, NSError *error) {
     1102    [webView callAsyncJavaScript:functionBody arguments:@{ @"handler" : @"testHandler5", @"arg" : @1 } inFrame:nil inContentWorld:world completionHandler:[&] (id result, NSError *error) {
    11031103        EXPECT_NULL(result);
    11041104        EXPECT_NOT_NULL(error);
     
    11191119    bool done = false;
    11201120    NSString *functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Fulfill'); await p; return p;";
    1121     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     1121    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    11221122        EXPECT_NULL(error);
    11231123        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
     
    11301130    done = false;
    11311131    functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Reject'); await p; return p;";
    1132     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     1132    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    11331133        EXPECT_NULL(result);
    11341134        EXPECT_TRUE(!!error);
     
    11421142    done = false;
    11431143    functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Undefined'); var result = await p; return result == undefined ? 'Yes' : 'No'";
    1144     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     1144    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    11451145        EXPECT_NULL(error);
    11461146        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
     
    11541154    done = false;
    11551155    functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Do nothing'); await p; return p;";
    1156     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     1156    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    11571157        EXPECT_NULL(result);
    11581158        EXPECT_TRUE(!!error);
     
    11661166    done = false;
    11671167    functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage('Invalid reply'); await p; return p;";
    1168     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     1168    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    11691169        EXPECT_NULL(result);
    11701170        EXPECT_TRUE(!!error);
     
    11881188    // Set a variable in the world.
    11891189    bool done = false;
    1190     [webView evaluateJavaScript:@"var foo = 'bar'" inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {
     1190    [webView evaluateJavaScript:@"var foo = 'bar'" inFrame:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {
    11911191        EXPECT_NULL(error);
    11921192        done = true;
     
    11971197    // Have the message handler bounce back that value.
    11981198    NSString *functionBody = @"var p = window.webkit.messageHandlers.testHandler.postMessage(foo); await p; return p;";
    1199     [webView callAsyncJavaScript:functionBody arguments:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {
     1199    [webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {
    12001200        EXPECT_NULL(error);
    12011201        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
     
    12091209    // But by evaluating JS make sure the value is still there.
    12101210    [[configuration userContentController] removeAllScriptMessageHandlersFromContentWorld:world.get()];
    1211     [webView evaluateJavaScript:@"foo" inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {
     1211    [webView evaluateJavaScript:@"foo" inFrame:nil inContentWorld:world.get() completionHandler:[&] (id result, NSError *error) {
    12121212        EXPECT_NULL(error);
    12131213        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEvaluateJavaScript.mm

    r261418 r263727  
    159159
    160160    // Verify that value is visible when evaluating in the pageWorld
    161     [webView evaluateJavaScript:@"foo" inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
     161    [webView evaluateJavaScript:@"foo" inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
    162162        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
    163163        EXPECT_TRUE([result isEqualToString:@"bar"]);
     
    169169
    170170    // Verify that value is not visible when evaluating in the defaultClientWorld
    171     [webView evaluateJavaScript:@"foo" inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
     171    [webView evaluateJavaScript:@"foo" inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
    172172        EXPECT_NULL(result);
    173173        isDone = true;
     
    178178
    179179    // Verify that value is visible when calling a function in the pageWorld
    180     [webView callAsyncJavaScript:@"return foo" arguments:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
     180    [webView callAsyncJavaScript:@"return foo" arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:^(id result, NSError *error) {
    181181        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
    182182        EXPECT_TRUE([result isEqualToString:@"bar"]);
     
    188188
    189189    // Verify that value is not visible when calling a function in the defaultClientWorld
    190     [webView callAsyncJavaScript:@"return foo" arguments:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
     190    [webView callAsyncJavaScript:@"return foo" arguments:nil inFrame:nil inContentWorld:WKContentWorld.defaultClientWorld completionHandler:^(id result, NSError *error) {
    191191        EXPECT_NULL(result);
    192192        isDone = true;
     
    202202
    203203    // Set a variable value in that named world.
    204     [webView evaluateJavaScript:@"var bar = 'baz'" inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
     204    [webView evaluateJavaScript:@"var bar = 'baz'" inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
    205205        EXPECT_NULL(result);
    206206        isDone = true;
     
    211211
    212212    // Set a global variable value in that named world via a function call.
    213     [webView callAsyncJavaScript:@"window.baz = 'bat'" arguments:nil inContentWorld: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) {
    214214        EXPECT_NULL(result);
    215215        EXPECT_NULL(error);
     
    224224
    225225    // Verify the variables we set are there in that named world.
    226     [webView evaluateJavaScript:@"bar" inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
     226    [webView evaluateJavaScript:@"bar" inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
    227227        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
    228228        EXPECT_TRUE([result isEqualToString:@"baz"]);
     
    233233    isDone = false;
    234234
    235     [webView evaluateJavaScript:@"window.baz" inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
     235    [webView evaluateJavaScript:@"window.baz" inFrame:nil inContentWorld:namedWorld.get() completionHandler:^(id result, NSError *error) {
    236236        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
    237237        EXPECT_TRUE([result isEqualToString:@"bat"]);
     
    243243
    244244    // Verify they aren't there in the defaultClientWorld.
    245     [webView evaluateJavaScript:@"bar" 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" inContentWorld: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) {
    254254        EXPECT_NULL(result);
    255255        isDone = true;
     
    260260
    261261    // Verify they aren't there in the pageWorld.
    262     [webView evaluateJavaScript:@"bar" 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" inContentWorld: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) {
    271271        EXPECT_NULL(result);
    272272        isDone = true;
     
    286286
    287287    __block bool done = false;
    288     [webView evaluateJavaScript:@"window.worldName" inContentWorld:[WKContentWorld worldWithName:@"testName"] completionHandler:^(id result, NSError *error) {
     288    [webView evaluateJavaScript:@"window.worldName" inFrame:nil inContentWorld:[WKContentWorld worldWithName:@"testName"] completionHandler:^(id result, NSError *error) {
    289289        EXPECT_WK_STREQ(result, "testName");
    290290        done = true;
     
    473473
    474474}
     475
     476static 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
     488static const char* framesMainResource = R"FRAMESRESOURCE(
     489Hello world<br>
     490<iframe id='theFrame' src='otherprotocol://test/index.html'></iframe>
     491)FRAMESRESOURCE";
     492
     493static 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.
     500TEST(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.
     573TEST(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
     658TEST(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
     729TEST(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  
    199199
    200200    RetainPtr<id> evalResult;
    201     [self callAsyncJavaScript:script arguments:arguments inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
     201    [self callAsyncJavaScript:script arguments:arguments inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
    202202        evalResult = result;
    203203        if (errorOut)
Note: See TracChangeset for help on using the changeset viewer.