Changeset 223856 in webkit


Ignore:
Timestamp:
Oct 23, 2017 2:34:59 PM (7 years ago)
Author:
Joseph Pecoraro
Message:

Web Inspector: Please support HAR Export for network traffic
https://bugs.webkit.org/show_bug.cgi?id=146692
<rdar://problem/7463672>

Reviewed by Brian Burg.

Source/JavaScriptCore:

  • inspector/protocol/Network.json:

Add a walltime to each send request.

Source/WebCore:

Tests: http/tests/inspector/network/har/har-basic.html

http/tests/inspector/network/har/har-page.html

  • inspector/InspectorNetworkAgent.cpp:

(WebCore::InspectorNetworkAgent::willSendRequest):
Include the wall time when sending a request. This is needed for HAR to
include a wall time, and can be used for Cookie expiration time calculation
as well.

Source/WebInspectorUI:

  • UserInterface/Main.html:
  • UserInterface/Test.html:

New resources.

  • UserInterface/Base/Platform.js:

Include a build number as well.

  • UserInterface/Base/URLUtilities.js:

(parseLocationQueryParameters): Deleted.
Remove unused function.

  • UserInterface/Controllers/FrameResourceManager.js:

(WI.FrameResourceManager.prototype.frameDidNavigate):
(WI.FrameResourceManager.prototype.resourceRequestWillBeSent):
(WI.FrameResourceManager.prototype.resourceRequestWasServedFromMemoryCache):
(WI.FrameResourceManager.prototype.resourceRequestDidReceiveResponse):
(WI.FrameResourceManager.prototype._addNewResourceToFrameOrTarget):
Pass along a walltime.

  • UserInterface/Protocol/NetworkObserver.js:

(WI.NetworkObserver.prototype.requestWillBeSent):
Pass along a walltime. This new parameter shifts old parameters.

  • UserInterface/Controllers/HARBuilder.js: Added.

(WI.HARBuilder.async.buildArchive):
(WI.HARBuilder.creator):
(WI.HARBuilder.pages):
(WI.HARBuilder.pageTimings):
(WI.HARBuilder.entry):
(WI.HARBuilder.request):
(WI.HARBuilder.response):
(WI.HARBuilder.cookies):
(WI.HARBuilder.headers):
(WI.HARBuilder.content):
(WI.HARBuilder.postData):
(WI.HARBuilder.cache):
(WI.HARBuilder.timings):
(WI.HARBuilder.ipAddress):
(WI.HARBuilder.date):
(WI.HARBuilder.fetchType):
HAR construction and helpers.

  • UserInterface/Models/Cookie.js:

(WI.Cookie.prototype.expirationDate):

  • UserInterface/Models/Resource.js:

(WI.Resource.prototype.get queryStringParameters):
(WI.Resource.prototype.get requestFormParameters):
(WI.Resource.prototype.get requestSentWalltime):
(WI.Resource.prototype.get requestSentDate):
(WI.Resource.prototype.hasRequestFormParameters):
Helpers for HAR generation and sub-sets of data.

  • UserInterface/Models/SourceCode.js:

(WI.SourceCode.prototype._processContent):
Capture the raw, unmodified, base64 encoded flag and content. This ends
up getting used by HAR generation and is otherwise lost.

  • UserInterface/Test/TestHarness.js:

(TestHarness.prototype.json):
Helper for just logging JSON data with a filter. This defaults to
a reasonable 2 space indent for JSON logs in our test output.

  • UserInterface/Views/DOMTreeContentView.js:

(WI.DOMTreeContentView.prototype.get saveData):
(WI.DOMTreeContentView.get saveData.saveHandler): Deleted.
Drive-by simplify while looking at other save handlers.

  • UserInterface/Views/NetworkTableContentView.js:

(WI.NetworkTableContentView.prototype.get supportsSave):
(WI.NetworkTableContentView.prototype.get saveData):
(WI.NetworkTableContentView.prototype.tableCellContextMenuClicked):
(WI.NetworkTableContentView.prototype._HARResources):
(WI.NetworkTableContentView.prototype._exportHAR):
Provide a context menu and save keyboard handler to export a HAR.
This matches other browsers.

  • UserInterface/Views/ResourceClusterContentView.js:

(WI.ResourceClusterContentView.prototype._canShowRequestContentView):
Use code that is now available in Resource.

LayoutTests:

  • http/tests/inspector/network/har/har-basic-expected.txt: Added.
  • http/tests/inspector/network/har/har-basic.html: Added.
  • http/tests/inspector/network/har/har-page-expected.txt: Added.
  • http/tests/inspector/network/har/har-page.html: Added.

Tests with mock resources / data and real resources.

  • platform/mac-wk1/TestExpectations:
  • platform/mac/TestExpectations:
  • platform/win/TestExpectations:

Skip on platforms that cannot provide complete metrics, so some optional
fields may be missing.

Location:
trunk
Files:
6 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r223855 r223856  
     12017-10-23  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Please support HAR Export for network traffic
     4        https://bugs.webkit.org/show_bug.cgi?id=146692
     5        <rdar://problem/7463672>
     6
     7        Reviewed by Brian Burg.
     8
     9        * http/tests/inspector/network/har/har-basic-expected.txt: Added.
     10        * http/tests/inspector/network/har/har-basic.html: Added.
     11        * http/tests/inspector/network/har/har-page-expected.txt: Added.
     12        * http/tests/inspector/network/har/har-page.html: Added.
     13        Tests with mock resources / data and real resources.
     14
     15        * platform/mac-wk1/TestExpectations:
     16        * platform/mac/TestExpectations:
     17        * platform/win/TestExpectations:
     18        Skip on platforms that cannot provide complete metrics, so some optional
     19        fields may be missing.
     20
    1212017-10-23  Andy Estes  <aestes@apple.com>
    222
  • trunk/LayoutTests/platform/mac-wk1/TestExpectations

    r223678 r223856  
    341341http/tests/inspector/network/resource-sizes-network.html [ Failure ]
    342342http/tests/inspector/network/resource-sizes-memory-cache.html [ Failure ]
     343http/tests/inspector/network/har/har-page.html [ Failure ]
    343344
    344345webkit.org/b/164491 [ Yosemite ElCapitan ] fast/visual-viewport/rtl-zoomed-rects.html [ Failure ]
  • trunk/LayoutTests/platform/mac/TestExpectations

    r223632 r223856  
    14301430# Request Header networking data not available without Network Session.
    14311431[ ElCapitan ] http/tests/inspector/network/resource-request-headers.html [ Failure ]
     1432[ ElCapitan ] http/tests/inspector/network/har/har-page.html [ Failure ]
    14321433
    14331434[ ElCapitan ] http/tests/inspector/network/ping-type.html [ Skip ]
  • trunk/LayoutTests/platform/win/TestExpectations

    r223762 r223856  
    36003600http/tests/cache/cache-control-immutable-https.html [ Skip ]
    36013601http/tests/inspector/network/resource-request-headers.html [ Skip ]
     3602http/tests/inspector/network/har/har-page.html [ Skip ]
    36023603http/tests/local/blob/send-hybrid-blob-using-open-panel.html [ Skip ]
    36033604http/tests/security/contentSecurityPolicy/cross-origin-plugin-document-allowed-in-child-window.html [ Skip ]
  • trunk/Source/JavaScriptCore/ChangeLog

    r223836 r223856  
     12017-10-23  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Please support HAR Export for network traffic
     4        https://bugs.webkit.org/show_bug.cgi?id=146692
     5        <rdar://problem/7463672>
     6
     7        Reviewed by Brian Burg.
     8
     9        * inspector/protocol/Network.json:
     10        Add a walltime to each send request.
     11
    1122017-10-23  Matt Lewis  <jlewis3@apple.com>
    213
  • trunk/Source/JavaScriptCore/inspector/protocol/Network.json

    r218898 r223856  
    217217                { "name": "documentURL", "type": "string", "description": "URL of the document this request is loaded for." },
    218218                { "name": "request", "$ref": "Request", "description": "Request data." },
    219                 { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp." },
     219                { "name": "timestamp", "$ref": "Timestamp" },
     220                { "name": "walltime", "$ref": "Walltime" },
    220221                { "name": "initiator", "$ref": "Initiator", "description": "Request initiator." },
    221222                { "name": "redirectResponse", "optional": true, "$ref": "Response", "description": "Redirect response data." },
  • trunk/Source/WebCore/ChangeLog

    r223855 r223856  
     12017-10-23  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Please support HAR Export for network traffic
     4        https://bugs.webkit.org/show_bug.cgi?id=146692
     5        <rdar://problem/7463672>
     6
     7        Reviewed by Brian Burg.
     8
     9        Tests: http/tests/inspector/network/har/har-basic.html
     10               http/tests/inspector/network/har/har-page.html
     11
     12        * inspector/InspectorNetworkAgent.cpp:
     13        (WebCore::InspectorNetworkAgent::willSendRequest):
     14        Include the wall time when sending a request. This is needed for HAR to
     15        include a wall time, and can be used for Cookie expiration time calculation
     16        as well.
     17
    1182017-10-23  Andy Estes  <aestes@apple.com>
    219
  • trunk/Source/WebCore/inspector/InspectorNetworkAgent.cpp

    r223785 r223856  
    346346    }
    347347
     348    double sendTimestamp = timestamp();
     349    double walltime = currentTime();
     350
    348351    String requestId = IdentifiersFactory::requestId(identifier);
    349352    m_resourcesData->resourceCreated(requestId, m_pageAgent->loaderId(&loader));
     
    374377    String targetId = request.initiatorIdentifier();
    375378
    376     m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader.frame()), m_pageAgent->loaderId(&loader), loader.url().string(), buildObjectForResourceRequest(request), timestamp(), initiatorObject, buildObjectForResourceResponse(redirectResponse, nullptr), type != InspectorPageAgent::OtherResource ? &protocolResourceType : nullptr, targetId.isEmpty() ? nullptr : &targetId);
     379    m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader.frame()), m_pageAgent->loaderId(&loader), loader.url().string(), buildObjectForResourceRequest(request), sendTimestamp, walltime, initiatorObject, buildObjectForResourceResponse(redirectResponse, nullptr), type != InspectorPageAgent::OtherResource ? &protocolResourceType : nullptr, targetId.isEmpty() ? nullptr : &targetId);
    377380}
    378381
  • trunk/Source/WebInspectorUI/ChangeLog

    r223807 r223856  
     12017-10-23  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Please support HAR Export for network traffic
     4        https://bugs.webkit.org/show_bug.cgi?id=146692
     5        <rdar://problem/7463672>
     6
     7        Reviewed by Brian Burg.
     8
     9        * UserInterface/Main.html:
     10        * UserInterface/Test.html:
     11        New resources.
     12
     13        * UserInterface/Base/Platform.js:
     14        Include a build number as well.
     15       
     16        * UserInterface/Base/URLUtilities.js:
     17        (parseLocationQueryParameters): Deleted.
     18        Remove unused function.
     19
     20        * UserInterface/Controllers/FrameResourceManager.js:
     21        (WI.FrameResourceManager.prototype.frameDidNavigate):
     22        (WI.FrameResourceManager.prototype.resourceRequestWillBeSent):
     23        (WI.FrameResourceManager.prototype.resourceRequestWasServedFromMemoryCache):
     24        (WI.FrameResourceManager.prototype.resourceRequestDidReceiveResponse):
     25        (WI.FrameResourceManager.prototype._addNewResourceToFrameOrTarget):
     26        Pass along a walltime.
     27
     28        * UserInterface/Protocol/NetworkObserver.js:
     29        (WI.NetworkObserver.prototype.requestWillBeSent):
     30        Pass along a walltime. This new parameter shifts old parameters.
     31
     32        * UserInterface/Controllers/HARBuilder.js: Added.
     33        (WI.HARBuilder.async.buildArchive):
     34        (WI.HARBuilder.creator):
     35        (WI.HARBuilder.pages):
     36        (WI.HARBuilder.pageTimings):
     37        (WI.HARBuilder.entry):
     38        (WI.HARBuilder.request):
     39        (WI.HARBuilder.response):
     40        (WI.HARBuilder.cookies):
     41        (WI.HARBuilder.headers):
     42        (WI.HARBuilder.content):
     43        (WI.HARBuilder.postData):
     44        (WI.HARBuilder.cache):
     45        (WI.HARBuilder.timings):
     46        (WI.HARBuilder.ipAddress):
     47        (WI.HARBuilder.date):
     48        (WI.HARBuilder.fetchType):
     49        HAR construction and helpers.
     50
     51        * UserInterface/Models/Cookie.js:
     52        (WI.Cookie.prototype.expirationDate):
     53        * UserInterface/Models/Resource.js:
     54        (WI.Resource.prototype.get queryStringParameters):
     55        (WI.Resource.prototype.get requestFormParameters):
     56        (WI.Resource.prototype.get requestSentWalltime):
     57        (WI.Resource.prototype.get requestSentDate):
     58        (WI.Resource.prototype.hasRequestFormParameters):
     59        Helpers for HAR generation and sub-sets of data.
     60
     61        * UserInterface/Models/SourceCode.js:
     62        (WI.SourceCode.prototype._processContent):
     63        Capture the raw, unmodified, base64 encoded flag and content. This ends
     64        up getting used by HAR generation and is otherwise lost.
     65
     66        * UserInterface/Test/TestHarness.js:
     67        (TestHarness.prototype.json):
     68        Helper for just logging JSON data with a filter. This defaults to
     69        a reasonable 2 space indent for JSON logs in our test output.
     70
     71        * UserInterface/Views/DOMTreeContentView.js:
     72        (WI.DOMTreeContentView.prototype.get saveData):
     73        (WI.DOMTreeContentView.get saveData.saveHandler): Deleted.
     74        Drive-by simplify while looking at other save handlers.
     75
     76        * UserInterface/Views/NetworkTableContentView.js:
     77        (WI.NetworkTableContentView.prototype.get supportsSave):
     78        (WI.NetworkTableContentView.prototype.get saveData):
     79        (WI.NetworkTableContentView.prototype.tableCellContextMenuClicked):
     80        (WI.NetworkTableContentView.prototype._HARResources):
     81        (WI.NetworkTableContentView.prototype._exportHAR):
     82        Provide a context menu and save keyboard handler to export a HAR.
     83        This matches other browsers.
     84
     85        * UserInterface/Views/ResourceClusterContentView.js:
     86        (WI.ResourceClusterContentView.prototype._canShowRequestContentView):
     87        Use code that is now available in Resource.
     88
    1892017-10-20  Matt Baker  <mattbaker@apple.com>
    290
  • trunk/Source/WebInspectorUI/UserInterface/Base/Platform.js

    r220119 r223856  
    3030        base: 0,
    3131        release: 0,
    32         name: ""
     32        name: "",
     33        build: "",
    3334    }
    3435};
    3536
    3637(function () {
    37     // Check for a nightly build by looking for a plus in the version number and a small number of stylesheets (indicating combined resources).
    38     var versionMatch = / AppleWebKit\/([^ ]+)/.exec(navigator.userAgent);
    39     if (versionMatch && versionMatch[1].indexOf("+") !== -1 && document.styleSheets.length < 10)
    40         WI.Platform.isNightlyBuild = true;
     38    let versionMatch = / AppleWebKit\/([^ ]+)/.exec(navigator.userAgent);
     39    if (versionMatch) {
     40        WI.Platform.version.build = versionMatch[1];
    4141
    42     var osVersionMatch = / Mac OS X (\d+)_(\d+)/.exec(navigator.appVersion);
     42        // Check for a nightly build by looking for a plus in the version number and a small number of stylesheets (indicating combined resources).
     43        if (versionMatch[1].indexOf("+") !== -1 && document.styleSheets.length < 10)
     44            WI.Platform.isNightlyBuild = true;
     45    }
     46
     47    let osVersionMatch = / Mac OS X (\d+)_(\d+)/.exec(navigator.appVersion);
    4348    if (osVersionMatch && osVersionMatch[1] === "10") {
    4449        WI.Platform.version.base = 10;
    4550        WI.Platform.version.release = parseInt(osVersionMatch[2]);
    4651        switch (osVersionMatch[2]) {
     52        case "12":
     53            WI.Platform.version.name = "high-sierra";
     54            break;
    4755        case "12":
    4856            WI.Platform.version.name = "sierra";
  • trunk/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js

    r223308 r223856  
    187187}
    188188
    189 function parseLocationQueryParameters(arrayResult)
    190 {
    191     // The first character is always the "?".
    192     return parseQueryString(window.location.search.substring(1), arrayResult);
    193 }
    194 
    195189function parseQueryString(queryString, arrayResult)
    196190{
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js

    r223065 r223856  
    8686            // Make a new resource (which will make the frame). Mark will mark it as loaded at the end too since we
    8787            // don't expect any more events about the load finishing for these frames.
    88             var frameResource = this._addNewResourceToFrameOrTarget(null, framePayload.id, framePayload.loaderId, framePayload.url, null, null, null, null, null, framePayload.name, framePayload.securityOrigin);
     88            var frameResource = this._addNewResourceToFrameOrTarget(null, framePayload.id, framePayload.loaderId, framePayload.url, null, null, null, null, null, null, framePayload.name, framePayload.securityOrigin);
    8989            frame = frameResource.parentFrame;
    9090            frameWasLoadedInstantly = true;
     
    164164    }
    165165
    166     resourceRequestWillBeSent(requestIdentifier, frameIdentifier, loaderIdentifier, request, type, redirectResponse, timestamp, initiator, targetId)
     166    resourceRequestWillBeSent(requestIdentifier, frameIdentifier, loaderIdentifier, request, type, redirectResponse, timestamp, walltime, initiator, targetId)
    167167    {
    168168        // Called from WI.NetworkObserver.
     
    192192
    193193        // This is a new request, make a new resource and add it to the right frame.
    194         resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, request.url, type, request.method, request.headers, request.postData, elapsedTime, null, null, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId);
     194        resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, request.url, type, request.method, request.headers, request.postData, elapsedTime, walltime, null, null, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId);
    195195
    196196        // Associate the resource with the requestIdentifier so it can be found in future loading events.
     
    328328        const responseSource = NetworkAgent.ResponseSource.MemoryCache;
    329329
    330         let resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload.url, cachedResourcePayload.type, "GET", null, null, elapsedTime, null, null, initiatorSourceCodeLocation);
     330        let resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload.url, cachedResourcePayload.type, "GET", null, null, elapsedTime, null, null, null, initiatorSourceCodeLocation);
    331331        resource.updateForResponse(cachedResourcePayload.url, response.mimeType, cachedResourcePayload.type, response.headers, response.status, response.statusText, elapsedTime, response.timing, responseSource);
    332332        resource.increaseSize(cachedResourcePayload.bodySize, elapsedTime);
     
    375375        // opened and we just missed the resourceRequestWillBeSent for it. So make a new resource and add it.
    376376        if (!resource) {
    377             resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, response.url, type, null, response.requestHeaders, null, elapsedTime, null, null, null);
     377            resource = this._addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, response.url, type, null, response.requestHeaders, null, elapsedTime, null, null, null, null);
    378378
    379379            // Associate the resource with the requestIdentifier so it can be found in future loading events.
     
    499499    // Private
    500500
    501     _addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, url, type, requestMethod, requestHeaders, requestData, elapsedTime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId)
     501    _addNewResourceToFrameOrTarget(requestIdentifier, frameIdentifier, loaderIdentifier, url, type, requestMethod, requestHeaders, requestData, elapsedTime, walltime, frameName, frameSecurityOrigin, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp, targetId)
    502502    {
    503503        console.assert(!this._waitingForMainFrameResourceTreePayload);
     
    513513                resource = frame.provisionalMainResource;
    514514            else {
    515                 resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
     515                resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, walltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
    516516                if (resource.target === WI.mainTarget)
    517517                    this._addResourceToFrame(frame, resource);
     
    524524            // This is a new request for a new frame, which is always the main resource.
    525525            console.assert(!targetId);
    526             resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
     526            resource = new WI.Resource(url, null, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, elapsedTime, walltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp);
    527527            frame = new WI.Frame(frameIdentifier, frameName, frameSecurityOrigin, loaderIdentifier, resource);
    528528            this._frameIdentifierMap.set(frame.id, frame);
  • trunk/Source/WebInspectorUI/UserInterface/Main.html

    r223806 r223856  
    821821    <script src="Controllers/FormatterSourceMap.js"></script>
    822822    <script src="Controllers/FrameResourceManager.js"></script>
     823    <script src="Controllers/HARBuilder.js"></script>
    823824    <script src="Controllers/HeapManager.js"></script>
    824825    <script src="Controllers/IssueManager.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Models/Cookie.js

    r223058 r223856  
    5252            this.httpOnly = httpOnly || false;
    5353        }
     54    }
     55
     56    // Public
     57
     58    expirationDate(requestSentDate)
     59    {
     60        if (this.maxAge) {
     61            let startDate = requestSentDate || new Date;
     62            return new Date(startDate.getTime() + (this.maxAge * 1000));
     63        }
     64
     65        return this.expires;
    5466    }
    5567
  • trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js

    r223308 r223856  
    2727WI.Resource = class Resource extends WI.SourceCode
    2828{
    29     constructor(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp)
     29    constructor(url, mimeType, type, loaderIdentifier, targetId, requestIdentifier, requestMethod, requestHeaders, requestData, requestSentTimestamp, requestSentWalltime, initiatorSourceCodeLocation, originalRequestWillBeSentTimestamp)
    3030    {
    3131        super();
     
    4343        this._loaderIdentifier = loaderIdentifier || null;
    4444        this._requestIdentifier = requestIdentifier || null;
     45        this._queryStringParameters = undefined;
     46        this._requestFormParameters = undefined;
    4547        this._requestMethod = requestMethod || null;
    4648        this._requestData = requestData || null;
     
    5456        this._originalRequestWillBeSentTimestamp = originalRequestWillBeSentTimestamp || null;
    5557        this._requestSentTimestamp = requestSentTimestamp || NaN;
     58        this._requestSentWalltime = requestSentWalltime || NaN;
    5659        this._responseReceivedTimestamp = NaN;
    5760        this._lastRedirectReceivedTimestamp = NaN;
     
    411414    }
    412415
     416    get queryStringParameters()
     417    {
     418        if (this._queryStringParameters === undefined)
     419            this._queryStringParameters = parseQueryString(this.urlComponents.queryString, true);
     420        return this._queryStringParameters;
     421    }
     422
     423    get requestFormParameters()
     424    {
     425        if (this._requestFormParameters === undefined)
     426            this._requestFormParameters = this.hasRequestFormParameters() ? parseQueryString(this.requestData, true) : null;
     427        return this._requestFormParameters;
     428    }
     429
    413430    get requestDataContentType()
    414431    {
     
    461478    }
    462479
     480    get requestSentWalltime()
     481    {
     482        return this._requestSentWalltime;
     483    }
     484
     485    get requestSentDate()
     486    {
     487        return isNaN(this._requestSentWalltime) ? null : new Date(this._requestSentWalltime * 1000);
     488    }
     489
    463490    get lastRedirectReceivedTimestamp()
    464491    {
     
    655682    {
    656683        return !isNaN(this._statusCode) || this._finished;
     684    }
     685
     686    hasRequestFormParameters()
     687    {
     688        let requestDataContentType = this.requestDataContentType;
     689        return requestDataContentType && requestDataContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i);
    657690    }
    658691
  • trunk/Source/WebInspectorUI/UserInterface/Models/SourceCode.js

    r222739 r223856  
    195195    {
    196196        // Different backend APIs return one of `content, `body`, `text`, or `scriptSource`.
    197         var content = parameters.content || parameters.body || parameters.text || parameters.scriptSource;
    198         var error = parameters.error;
     197        let rawContent = parameters.content || parameters.body || parameters.text || parameters.scriptSource;
     198        let content = rawContent;
     199        let error = parameters.error;
    199200        if (parameters.base64Encoded)
    200201            content = content ? decodeBase64ToBlob(content, this.mimeType) : "";
    201202
    202         var revision = this.revisionForRequestedContent;
     203        let revision = this.revisionForRequestedContent;
    203204
    204205        this._ignoreRevisionContentDidChangeEvent = true;
     
    214215            sourceCode: this,
    215216            content,
     217            rawContent,
     218            rawBase64Encoded: parameters.base64Encoded,
    216219        });
    217220    }
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/NetworkObserver.js

    r220119 r223856  
    2828    // Events defined by the "Network" domain.
    2929
    30     requestWillBeSent(requestId, frameId, loaderId, documentURL, request, timestamp, initiator, redirectResponse, type, targetId)
     30    requestWillBeSent(requestId, frameId, loaderId, documentURL, request, timestamp, walltime, initiator, redirectResponse, type, targetId)
    3131    {
    32         WI.frameResourceManager.resourceRequestWillBeSent(requestId, frameId, loaderId, request, type, redirectResponse, timestamp, initiator, targetId);
     32        // COMPATIBILITY(iOS 11.0): `walltime` did not exist in 11.0 and earlier.
     33        if (!NetworkAgent.hasEventParameter("requestWillBeSent", "walltime")) {
     34            walltime = undefined;
     35            initiator = arguments[6];
     36            redirectResponse = arguments[7];
     37            type = arguments[8];
     38            targetId = arguments[9];
     39        }
     40
     41        WI.frameResourceManager.resourceRequestWillBeSent(requestId, frameId, loaderId, request, type, redirectResponse, timestamp, walltime, initiator, targetId);
    3342    }
    3443
  • trunk/Source/WebInspectorUI/UserInterface/Test.html

    r223428 r223856  
    203203    <script src="Controllers/DebuggerManager.js"></script>
    204204    <script src="Controllers/FrameResourceManager.js"></script>
     205    <script src="Controllers/HARBuilder.js"></script>
    205206    <script src="Controllers/HeapManager.js"></script>
    206207    <script src="Controllers/IssueManager.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js

    r223308 r223856  
    8989        else
    9090            this.addResult(message);
     91    }
     92
     93    json(object, filter)
     94    {
     95        this.log(JSON.stringify(object, filter || null, 2));
    9196    }
    9297
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js

    r222486 r223856  
    215215    get saveData()
    216216    {
    217         function saveHandler(forceSaveAs)
    218         {
    219             WI.archiveMainFrame();
    220         }
    221 
    222         return {customSaveHandler: saveHandler};
     217        return {customSaveHandler: () => { WI.archiveMainFrame(); }};
    223218    }
    224219
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js

    r223735 r223856  
    185185    }
    186186
     187    get supportsSave()
     188    {
     189        return this._filteredEntries.some((entry) => entry.resource.finished);
     190    }
     191
     192    get saveData()
     193    {
     194        return {customSaveHandler: () => { this._exportHAR(); }};
     195    }
     196
    187197    shown()
    188198    {
     
    296306        let contextMenu = WI.ContextMenu.createFromEvent(event);
    297307        WI.appendContextMenuItemsForSourceCode(contextMenu, entry.resource);
     308
     309        contextMenu.appendSeparator();
     310        contextMenu.appendItem(WI.UIString("Export HAR"), this._exportHAR);
    298311    }
    299312
     
    13611374    }
    13621375
     1376    _HARResources()
     1377    {
     1378        let resources = this._filteredEntries.map((x) => x.resource);
     1379        const supportedHARSchemes = new Set(["http", "https", "ws", "wss"]);
     1380        return resources.filter((resource) => resource.finished && supportedHARSchemes.has(resource.urlComponents.scheme));
     1381    }
     1382
     1383    _exportHAR()
     1384    {
     1385        let resources = this._HARResources();
     1386        if (!resources.length) {
     1387            InspectorFrontendHost.beep();
     1388            return;
     1389        }
     1390
     1391        WI.HARBuilder.buildArchive(resources).then((har) => {
     1392            let mainFrame = WI.frameResourceManager.mainFrame;
     1393            let archiveName = mainFrame.mainResource.urlComponents.host || mainFrame.mainResource.displayName || "Archive";
     1394            let url = "web-inspector:///" + encodeURI(archiveName) + ".har";
     1395            WI.saveDataToFile({
     1396                url,
     1397                content: JSON.stringify(har, null, 2),
     1398                forceSaveAs: true,
     1399            });
     1400        }).catch(handlePromiseException);
     1401    }
     1402
    13631403    _waterfallPopoverContentForResource(resource)
    13641404    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/ResourceClusterContentView.js

    r223806 r223856  
    214214            return false;
    215215
    216         var requestDataContentType = this._resource.requestDataContentType;
    217         if (requestDataContentType && requestDataContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
     216        if (!this._resource.hasRequestFormParameters())
    218217            return false;
    219218
Note: See TracChangeset for help on using the changeset viewer.