⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 287979 in webkit


Ignore:
Timestamp:
Jan 13, 2022, 8:22:10 AM (5 years ago)
Author:
Patrick Angle
Message:

Web Inspector: Implement frameURL option for devtools.inspectedWindow.eval command
​https://bugs.webkit.org/show_bug.cgi?id=222568

Reviewed by Devin Rousso.

Source/WebInspectorUI:

New test: Tools/TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm

Add support for evaluating script from an extension in a specific frame on the page by referring to it by the
frame's URL. Frame URLs are matched in three steps, first looking for an exact URL match, including query
parameters and fragment identifier. If no match is found and the provided options.frameURL does not have any
fragment identifier or query parameters, a check is then made against each known frame again, this time
excluding their fragment identifier. If that check still fails to find a frame for the URL, we perform one more
pass, this time excluding the fragment identifier and query parameters for each known frame.

  • UserInterface/Controllers/WebInspectorExtensionController.js:

(WI.WebInspectorExtensionController.prototype.evaluateScriptForExtension):
(WI.WebInspectorExtensionController.prototype.reloadForExtension):

  • Drive-by removal of trailing spaces.

(WI.WebInspectorExtensionController.prototype._frameForFrameURL):

Source/WebKit:

New test: Tools/TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm

Correct the API to indicate that frameURL and contextSecurityOrigin are nullable parameters.

  • UIProcess/API/Cocoa/_WKInspectorExtension.h:

Tools:

Add test coverage for evaluating script on an inspected page from an extension, including evaluating on an inner
frame.

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm:

(TEST):

  • TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtensionEvaluateScriptOnPage.html: Added.
  • TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html: Added.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r287956 r287979  
     12022-01-13  Patrick Angle  <pangle@apple.com>
     2
     3        Web Inspector: Implement `frameURL` option for `devtools.inspectedWindow.eval` command
     4        https://bugs.webkit.org/show_bug.cgi?id=222568
     5
     6        Reviewed by Devin Rousso.
     7
     8        New test: Tools/TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm
     9
     10        Add support for evaluating script from an extension in a specific frame on the page by referring to it by the
     11        frame's URL. Frame URLs are matched in three steps, first looking for an exact URL match, including query
     12        parameters and fragment identifier. If no match is found and the provided `options.frameURL` does not have any
     13        fragment identifier or query parameters, a check is then made against each known frame again, this time
     14        excluding their fragment identifier. If that check still fails to find a frame for the URL, we perform one more
     15        pass, this time excluding the fragment identifier and query parameters for each known frame.
     16
     17        * UserInterface/Controllers/WebInspectorExtensionController.js:
     18        (WI.WebInspectorExtensionController.prototype.evaluateScriptForExtension):
     19        (WI.WebInspectorExtensionController.prototype.reloadForExtension):
     20        - Drive-by removal of trailing spaces.
     21        (WI.WebInspectorExtensionController.prototype._frameForFrameURL):
     22
    1232022-01-12  Elliott Williams  <emw@apple.com>
    224
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/WebInspectorExtensionController.js

    r286887 r287979  
    134134        }
    135135
    136         // FIXME: <rdar://problem/74180355> implement execution context selection options
    137         if (frameURL) {
    138             WI.reportInternalError("evaluateScriptForExtension: the 'frameURL' option is not yet implemented.");
    139             return WI.WebInspectorExtension.ErrorCode.NotImplemented;
     136        let frame = this._frameForFrameURL(frameURL);
     137        if (!frame) {
     138            WI.reportInternalError("evaluateScriptForExtension: No frame matched provided frameURL: " + frameURL);
     139            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
    140140        }
    141141
    … …  
    150150        }
    151151
    152         let evaluationContext = WI.runtimeManager.activeExecutionContext;
     152        let evaluationContext = frame.pageExecutionContext;
     153        if (!evaluationContext) {
     154            WI.reportInternalError("evaluateScriptForExtension: No 'pageExecutionContext' was present for frame with URL: " + frame.url);
     155            return WI.WebInspectorExtension.ErrorCode.ContextDestroyed;
     156        }
     157
    153158        return evaluationContext.target.RuntimeAgent.evaluate.invoke({
    154159            expression: scriptSource,
    … …  
    166171        }).catch((error) => error.description);
    167172    }
    168    
     173
    169174    reloadForExtension(extensionID, {ignoreCache, userAgent, injectedScript} = {})
    170175    {
    … …  
    185190            return WI.WebInspectorExtension.ErrorCode.NotImplemented;
    186191        }
    187        
     192
    188193        let target = WI.assumingMainTarget();
    189194        if (!target.hasCommand("Page.reload"))
    190195            return WI.WebInspectorExtension.ErrorCode.InvalidRequest;
    191        
     196
    192197        return target.PageAgent.reload.invoke({ignoreCache});
    193198    }
    194    
     199
    195200    showExtensionTab(extensionTabID, options = {})
    196201    {
    … …  
    394399    }
    395400
     401    _frameForFrameURL(frameURL)
     402    {
     403        if (!frameURL)
     404            return WI.networkManager.mainFrame;
     405
     406        function findFrame(frameURL, adjustKnownFrameURL) {
     407            return WI.networkManager.frames.find((knownFrame) => {
     408                let knownFrameURL = new URL(knownFrame.url);
     409                adjustKnownFrameURL?.(knownFrameURL);
     410                return knownFrameURL.toString() === frameURL;
     411            });
     412        }
     413
     414        let frame = findFrame(frameURL);
     415        if (frame)
     416            return frame;
     417
     418        let frameURLParts = new URL(frameURL);
     419        if (frameURLParts.hash.length)
     420            return null;
     421
     422        frame = findFrame(frameURL, (knownFrameURL) => {
     423            knownFrameURL.hash = "";
     424        });
     425        if (frame)
     426            return frame;
     427
     428        if (frameURLParts.search.length)
     429            return null;
     430
     431        return findFrame(frameURL, (knownFrameURL) => {
     432            knownFrameURL.hash = "";
     433            knownFrameURL.search = "";
     434        });
     435    }
     436
    396437    _handleMainResourceDidChange(event)
    397438    {
  • trunk/Source/WebKit/ChangeLog

    r287970 r287979  
     12022-01-13  Patrick Angle  <pangle@apple.com>
     2
     3        Web Inspector: Implement `frameURL` option for `devtools.inspectedWindow.eval` command
     4        https://bugs.webkit.org/show_bug.cgi?id=222568
     5
     6        Reviewed by Devin Rousso.
     7
     8        New test: Tools/TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm
     9
     10        Correct the API to indicate that `frameURL` and `contextSecurityOrigin` are nullable parameters.
     11
     12        * UIProcess/API/Cocoa/_WKInspectorExtension.h:
     13
    1142022-01-12  John Wilander  <wilander@apple.com>
    215
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.h

    r286497 r287979  
    6464 * The inspected page ultimately controls its execution context and the result of this evaluation. Thus, the result shall be treated as untrusted input.
    6565 */
    66 - (void)evaluateScript:(NSString *)scriptSource frameURL:(NSURL *)frameURL contextSecurityOrigin:(NSURL *)contextSecurityOrigin useContentScriptContext:(BOOL)useContentScriptContext completionHandler:(void(^)(NSError * _Nullable, id result))completionHandler;
     66- (void)evaluateScript:(NSString *)scriptSource frameURL:(NSURL * _Nullable)frameURL contextSecurityOrigin:(NSURL * _Nullable)contextSecurityOrigin useContentScriptContext:(BOOL)useContentScriptContext completionHandler:(void(^)(NSError * _Nullable, id result))completionHandler;
    6767
    6868/**
  • trunk/Tools/ChangeLog

    r287978 r287979  
     12022-01-13  Patrick Angle  <pangle@apple.com>
     2
     3        Web Inspector: Implement `frameURL` option for `devtools.inspectedWindow.eval` command
     4        https://bugs.webkit.org/show_bug.cgi?id=222568
     5
     6        Reviewed by Devin Rousso.
     7
     8        Add test coverage for evaluating script on an inspected page from an extension, including evaluating on an inner
     9        frame.
     10
     11        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     12        * TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm:
     13        (TEST):
     14        * TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtensionEvaluateScriptOnPage.html: Added.
     15        * TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html: Added.
     16
    1172022-01-12  Jonathan Bedard  <jbedard@apple.com>
    218
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r287956 r287979  
    170170                2EBD9D0A2134730D002DA758 /* video.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 07CD32F72065B72A0064A4BE /* video.html */; };
    171171                2EC7034A26AF5E88002B2D37 /* KeyboardEventTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2EC7034926AF5E88002B2D37 /* KeyboardEventTests.mm */; };
     172                2ED88823277125AB00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2ED8882127711F1200DB7E99 /* WKInspectorExtensionEvaluateScriptOnPage.html */; };
     173                2ED88824277125AB00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2ED888222771203A00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html */; };
    172174                2EFF06C31D88621E0004BB30 /* large-video-offscreen.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2EFF06C21D8862120004BB30 /* large-video-offscreen.html */; };
    173175                2EFF06C51D8867760004BB30 /* change-video-source-on-click.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2EFF06C41D8867700004BB30 /* change-video-source-on-click.html */; };
    … …  
    16351637                                468F2F942368DAF100F4B864 /* window-open-then-document-open.html in Copy Resources */,
    16361638                                A5E2027515B21F6E00C13E14 /* WindowlessWebViewWithMedia.html in Copy Resources */,
     1639                                2ED88823277125AB00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPage.html in Copy Resources */,
     1640                                2ED88824277125AB00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html in Copy Resources */,
    16371641                        );
    16381642                        name = "Copy Resources";
    … …  
    18581862                2EC7034926AF5E88002B2D37 /* KeyboardEventTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyboardEventTests.mm; sourceTree = "<group>"; };
    18591863                2ECFF5541D9B12F800B55394 /* NowPlayingControlsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NowPlayingControlsTests.mm; sourceTree = "<group>"; };
     1864                2ED8882127711F1200DB7E99 /* WKInspectorExtensionEvaluateScriptOnPage.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = WKInspectorExtensionEvaluateScriptOnPage.html; sourceTree = "<group>"; };
     1865                2ED888222771203A00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html; sourceTree = "<group>"; };
    18601866                2EFF06C21D8862120004BB30 /* large-video-offscreen.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-offscreen.html"; sourceTree = "<group>"; };
    18611867                2EFF06C41D8867700004BB30 /* change-video-source-on-click.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "change-video-source-on-click.html"; sourceTree = "<group>"; };
    … …  
    42534259                                5120C83B1E674E350025B250 /* WebsiteDataStoreCustomPaths.html */,
    42544260                                2E131C171D83A97E001BA36C /* wide-autoplaying-video-with-audio.html */,
     4261                                2ED8882127711F1200DB7E99 /* WKInspectorExtensionEvaluateScriptOnPage.html */,
     4262                                2ED888222771203A00DB7E99 /* WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html */,
    42554263                        );
    42564264                        name = Resources;
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKInspectorExtension.mm

    r286329 r287979  
    3131#import "TestCocoa.h"
    3232#import "TestInspectorURLSchemeHandler.h"
     33#import "TestNavigationDelegate.h"
    3334#import "Utilities.h"
    3435#import <WebKit/WKPreferencesPrivate.h>
    … …  
    383384}
    384385
     386TEST(WKInspectorExtension, EvaluateScriptOnPage)
     387{
     388    resetGlobalState();
     389
     390    auto webViewConfiguration = adoptNS([WKWebViewConfiguration new]);
     391    webViewConfiguration.get().preferences._developerExtrasEnabled = YES;
     392    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     393    auto uiDelegate = adoptNS([UIDelegateForTestingInspectorExtension new]);
     394    auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]);
     395
     396    auto *testPageFileURL = [NSBundle.mainBundle URLForResource:@"WKInspectorExtensionEvaluateScriptOnPage" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
     397
     398    [webView setUIDelegate:uiDelegate.get()];
     399    [webView setNavigationDelegate:navigationDelegate.get()];
     400    [webView loadFileURL:testPageFileURL allowingReadAccessToURL:testPageFileURL.URLByDeletingLastPathComponent];
     401    [navigationDelegate waitForDidFinishNavigation];
     402
     403    [[webView _inspector] show];
     404    TestWebKitAPI::Util::run(&didAttachLocalInspectorCalled);
     405
     406    auto extensionID = [NSUUID UUID].UUIDString;
     407    auto extensionBundleIdentifier = @"org.webkit.TestWebKitAPI.FourthExtension";
     408    auto extensionDisplayName = @"FourthExtension";
     409
     410    // Register the test extension.
     411    pendingCallbackWasCalled = false;
     412    [[webView _inspector] registerExtensionWithID:extensionID extensionBundleIdentifier:extensionBundleIdentifier displayName:extensionDisplayName completionHandler:^(NSError *error, _WKInspectorExtension *extension) {
     413        EXPECT_NULL(error);
     414        EXPECT_NOT_NULL(extension);
     415        sharedInspectorExtension = extension;
     416
     417        pendingCallbackWasCalled = true;
     418    }];
     419    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     420
     421    auto extensionDelegate = adoptNS([InspectorExtensionDelegateForTestingInspectorExtension new]);
     422    [sharedInspectorExtension setDelegate:extensionDelegate.get()];
     423
     424    // Create and show an extension tab.
     425    auto iconURL = [NSURL URLWithString:@"test-resource://FourthExtension/InspectorExtension-TabIcon-30x30.png"];
     426    auto sourceURL = [NSURL URLWithString:@"test-resource://FourthExtension/InspectorExtension-basic-tab.html"];
     427
     428    pendingCallbackWasCalled = false;
     429    [sharedInspectorExtension createTabWithName:@"FourthExtension-Tab" tabIconURL:iconURL sourceURL:sourceURL completionHandler:^(NSError *error, NSString *extensionTabIdentifier) {
     430        EXPECT_NULL(error);
     431        EXPECT_NOT_NULL(extensionTabIdentifier);
     432        sharedExtensionTabIdentifier = extensionTabIdentifier;
     433
     434        pendingCallbackWasCalled = true;
     435    }];
     436    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     437
     438    pendingCallbackWasCalled = false;
     439    didShowExtensionTabWasCalled = false;
     440    [[webView _inspector] showExtensionTabWithIdentifier:sharedExtensionTabIdentifier.get() completionHandler:^(NSError *error) {
     441        EXPECT_NULL(error);
     442
     443        pendingCallbackWasCalled = true;
     444    }];
     445    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     446    TestWebKitAPI::Util::run(&didShowExtensionTabWasCalled);
     447
     448    auto mainFrameSecretString = @"42-mainFrame";
     449    auto innerFrameSecretString = @"42-innerFrame";
     450    auto scriptSource = @"document.getElementById('secret').innerText";
     451
     452    // Test main frame evaluation.
     453    pendingCallbackWasCalled = false;
     454    [sharedInspectorExtension evaluateScript:scriptSource frameURL:nil contextSecurityOrigin:nil useContentScriptContext:false completionHandler:^(NSError *error, NSDictionary *result) {
     455        EXPECT_NULL(error);
     456        EXPECT_NOT_NULL(result);
     457        EXPECT_NS_EQUAL(result, mainFrameSecretString);
     458
     459        pendingCallbackWasCalled = true;
     460    }];
     461    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     462
     463    // Test main frame evaluation failure.
     464    pendingCallbackWasCalled = false;
     465    [sharedInspectorExtension evaluateScript:@"[].x.x" frameURL:nil contextSecurityOrigin:nil useContentScriptContext:false completionHandler:^(NSError *error, NSDictionary *result) {
     466        EXPECT_NULL(result);
     467        EXPECT_NOT_NULL(error);
     468
     469        pendingCallbackWasCalled = true;
     470    }];
     471    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     472
     473    // Test loose frameURL evaluation.
     474    auto *testPageInnerFrameFileURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@WKInspectorExtensionEvaluateScriptOnPageInnerFrame.html", [[testPageFileURL URLByDeletingLastPathComponent] absoluteString]]];
     475
     476    pendingCallbackWasCalled = false;
     477    [sharedInspectorExtension evaluateScript:scriptSource frameURL:testPageInnerFrameFileURL contextSecurityOrigin:nil useContentScriptContext:false completionHandler:^(NSError *error, NSDictionary *result) {
     478        EXPECT_NULL(error);
     479        EXPECT_NOT_NULL(result);
     480        EXPECT_NS_EQUAL(result, innerFrameSecretString);
     481
     482        pendingCallbackWasCalled = true;
     483    }];
     484    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     485
     486    // Test strict frameURL evaluation.
     487    auto *testPageInnerFrameStrictFileURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@?query=param#fragment", [testPageInnerFrameFileURL absoluteString]]];
     488
     489    pendingCallbackWasCalled = false;
     490    [sharedInspectorExtension evaluateScript:scriptSource frameURL:testPageInnerFrameStrictFileURL contextSecurityOrigin:nil useContentScriptContext:false completionHandler:^(NSError *error, NSDictionary *result) {
     491        EXPECT_NULL(error);
     492        EXPECT_NOT_NULL(result);
     493        EXPECT_NS_EQUAL(result, innerFrameSecretString);
     494
     495        pendingCallbackWasCalled = true;
     496    }];
     497    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     498
     499    // Unregister the test extension.
     500    pendingCallbackWasCalled = false;
     501    [[webView _inspector] unregisterExtension:sharedInspectorExtension.get() completionHandler:^(NSError * error) {
     502        EXPECT_NULL(error);
     503
     504        pendingCallbackWasCalled = true;
     505    }];
     506    TestWebKitAPI::Util::run(&pendingCallbackWasCalled);
     507}
     508
    385509#endif // ENABLE(INSPECTOR_EXTENSIONS)
Note: See TracChangeset for help on using the changeset viewer.