Diff
Modified: trunk/LayoutTests/ChangeLog (236994 => 236995)
--- trunk/LayoutTests/ChangeLog 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/LayoutTests/ChangeLog 2018-10-10 02:49:52 UTC (rev 236995)
@@ -1,3 +1,17 @@
+2018-10-09 Devin Rousso <[email protected]>
+
+ Web Inspector: show redirect requests in Network and Timelines tabs
+ https://bugs.webkit.org/show_bug.cgi?id=150005
+ <rdar://problem/5378164>
+
+ Reviewed by Joseph Pecoraro.
+
+ * http/tests/inspector/network/resource-timing-expected.txt:
+ * http/tests/inspector/network/resource-timing.html:
+
+ * http/tests/inspector/network/resources/delay.php: Added.
+ * http/tests/inspector/network/resources/redirect.php: Added.
+
2018-10-09 Said Abou-Hallawa <[email protected]>
REGRESSION(r234620): SVGLangSpace::svgAttributeChanged() should invalidate the renderer of the SVGGeometryElement descendant only
Modified: trunk/LayoutTests/http/tests/inspector/network/resource-timing-expected.txt (236994 => 236995)
--- trunk/LayoutTests/http/tests/inspector/network/resource-timing-expected.txt 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/LayoutTests/http/tests/inspector/network/resource-timing-expected.txt 2018-10-10 02:49:52 UTC (rev 236995)
@@ -1,13 +1,14 @@
Tests that a resource has timing information.
-== Running test suite: ResourceTimingData
--- Running test case: CheckResourceTimingInformationForResource
+== Running test suite: Resource.TimingData
+-- Running test case: Resource.TimingData.Basic
PASS: Resource should be created.
PASS: Added Resource received a response.
PASS: Added Resource did finish loading.
PASS: Newly added resource should have a resource timing model.
PASS: Resource should have a start time.
+PASS: Resource should have a fetch start time.
PASS: Resource should have a request start time.
PASS: Resource should have a response start time.
PASS: domainLookupStart and domainLookupEnd should both be NaN or a number.
@@ -17,3 +18,9 @@
PASS: responseStart should come after requestStart.
PASS: responseEnd should come after responseStart.
+-- Running test case: Resource.TimingData.Redirect
+PASS: Start time should be before redirect start time.
+PASS: Redirect start time should be before redirect end time.
+PASS: Redirect duration should be at least a few milliseconds.
+PASS: Redirect end time should be before fetch start time.
+
Modified: trunk/LayoutTests/http/tests/inspector/network/resource-timing.html (236994 => 236995)
--- trunk/LayoutTests/http/tests/inspector/network/resource-timing.html 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/LayoutTests/http/tests/inspector/network/resource-timing.html 2018-10-10 02:49:52 UTC (rev 236995)
@@ -4,18 +4,24 @@
<meta charset="utf-8">
<script src=""
<script>
-function createRequest() {
+function createImageRequest() {
let img = document.createElement("img");
img.src = ""
document.body.appendChild(img);
}
+function createRedirectRequest(delay) {
+ let iframe = document.createElement("iframe");
+ iframe.src = ""
+ document.body.appendChild(iframe);
+}
+
function test()
{
- let suite = InspectorTest.createAsyncSuite("ResourceTimingData");
+ let suite = InspectorTest.createAsyncSuite("Resource.TimingData");
suite.addTestCase({
- name: "CheckResourceTimingInformationForResource",
+ name: "Resource.TimingData.Basic",
description: "Check if a resource has timing information.",
test(resolve, reject) {
Promise.all([
@@ -32,24 +38,52 @@
let timingData = resource.timingData;
InspectorTest.expectThat(timingData instanceof WI.ResourceTimingData, "Newly added resource should have a resource timing model.");
- InspectorTest.expectThat(timingData.startTime > 0, "Resource should have a start time.");
- InspectorTest.expectThat(timingData.requestStart > 0, "Resource should have a request start time.");
- InspectorTest.expectThat(timingData.responseStart > 0, "Resource should have a response start time.");
+ InspectorTest.expectGreaterThan(timingData.startTime, 0, "Resource should have a start time.");
+ InspectorTest.expectGreaterThan(timingData.fetchStart, 0, "Resource should have a fetch start time.");
+ InspectorTest.expectGreaterThan(timingData.requestStart, 0, "Resource should have a request start time.");
+ InspectorTest.expectGreaterThan(timingData.responseStart, 0, "Resource should have a response start time.");
InspectorTest.expectThat(typeof timingData.domainLookupStart === "number" && typeof timingData.domainLookupEnd === "number", "domainLookupStart and domainLookupEnd should both be NaN or a number.");
InspectorTest.expectThat(typeof timingData.connectStart === "number" && typeof timingData.connectStart === "number", "connectStart and connectEnd should both be NaN or a number.");
- InspectorTest.expectThat(timingData.startTime <= timingData.requestStart, "requestStart should come after startTime.");
+ InspectorTest.expectLessThanOrEqual(timingData.startTime, timingData.requestStart, "requestStart should come after startTime.");
InspectorTest.expectThat(isNaN(timingData.secureConnectionStart) || timingData.connectStart <= timingData.secureConnectionStart, "A secure connection should be reused or secureConnectionStart should come after connectStart.");
- InspectorTest.expectThat(timingData.requestStart <= timingData.responseStart, "responseStart should come after requestStart.");
- InspectorTest.expectThat(timingData.responseStart <= timingData.responseEnd, "responseEnd should come after responseStart.");
+ InspectorTest.expectLessThanOrEqual(timingData.requestStart, timingData.responseStart, "responseStart should come after requestStart.");
+ InspectorTest.expectLessThanOrEqual(timingData.responseStart, timingData.responseEnd, "responseEnd should come after responseStart.");
})
.then(resolve, reject);
- InspectorTest.evaluateInPage("createRequest()");
+ InspectorTest.evaluateInPage(`createImageRequest()`);
}
});
+ suite.addTestCase({
+ name: "Resource.TimingData.Redirect",
+ description: "Check if a redirected resource has timing information.",
+ test(resolve, reject) {
+ const delay = 100;
+
+ WI.Resource.awaitEvent(WI.Resource.Event.ResponseReceived)
+ .then((event) => {
+ let resource = event.target;
+
+ let timingData = resource.timingData;
+ InspectorTest.assert(timingData.startTime >= 0, "Resource should have a start time.");
+ InspectorTest.assert(timingData.redirectStart >= 0, "Resource should have a redirect start time.");
+ InspectorTest.assert(timingData.redirectEnd >= 0, "Resource should have a redirect end time.");
+ InspectorTest.assert(timingData.fetchStart >= 0, "Resource should have a fetch start time.");
+
+ InspectorTest.expectLessThanOrEqual(timingData.startTime, timingData.redirectStart, "Start time should be before redirect start time.");
+ InspectorTest.expectLessThan(timingData.redirectStart, timingData.redirectEnd, "Redirect start time should be before redirect end time.");
+ InspectorTest.expectGreaterThanOrEqual(timingData.redirectEnd - timingData.redirectStart, (delay / 2) / 1000, "Redirect duration should be at least a few milliseconds.");
+ InspectorTest.expectLessThanOrEqual(timingData.redirectEnd, timingData.fetchStart, "Redirect end time should be before fetch start time.");
+ })
+ .then(resolve, reject);
+
+ InspectorTest.evaluateInPage(`createRedirectRequest(${delay})`);
+ }
+ });
+
suite.runTestCasesAndFinish();
}
</script>
Added: trunk/LayoutTests/http/tests/inspector/network/resources/delay.php (0 => 236995)
--- trunk/LayoutTests/http/tests/inspector/network/resources/delay.php (rev 0)
+++ trunk/LayoutTests/http/tests/inspector/network/resources/delay.php 2018-10-10 02:49:52 UTC (rev 236995)
@@ -0,0 +1,11 @@
+<?php
+
+$delay = isset($_GET['delay']) ? intval($_GET['delay']) : 100;
+$redirect = isset($_GET['redirect']) ? intval($_GET['redirect']) : 'redirect.php';
+
+usleep($delay * 1000);
+
+header('Location: ' . $redirect);
+
+?>
+
Added: trunk/LayoutTests/http/tests/inspector/network/resources/redirect.php (0 => 236995)
--- trunk/LayoutTests/http/tests/inspector/network/resources/redirect.php (rev 0)
+++ trunk/LayoutTests/http/tests/inspector/network/resources/redirect.php 2018-10-10 02:49:52 UTC (rev 236995)
@@ -0,0 +1,5 @@
+<?php
+
+echo 'Redirect';
+
+?>
Modified: trunk/Source/_javascript_Core/ChangeLog (236994 => 236995)
--- trunk/Source/_javascript_Core/ChangeLog 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-10-10 02:49:52 UTC (rev 236995)
@@ -1,3 +1,14 @@
+2018-10-09 Devin Rousso <[email protected]>
+
+ Web Inspector: show redirect requests in Network and Timelines tabs
+ https://bugs.webkit.org/show_bug.cgi?id=150005
+ <rdar://problem/5378164>
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/protocol/Network.json:
+ Add missing fields to `ResourceTiming`.
+
2018-10-09 Claudio Saavedra <[email protected]>
[WPE] Explicitly link against gmodule where used
Modified: trunk/Source/_javascript_Core/inspector/protocol/Network.json (236994 => 236995)
--- trunk/Source/_javascript_Core/inspector/protocol/Network.json 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/_javascript_Core/inspector/protocol/Network.json 2018-10-10 02:49:52 UTC (rev 236995)
@@ -38,14 +38,18 @@
"type": "object",
"description": "Timing information for the request.",
"properties": [
- { "name": "startTime", "type": "number", "description": "Timing's startTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this." },
- { "name": "domainLookupStart", "type": "number", "description": "Started DNS address resolve." },
- { "name": "domainLookupEnd", "type": "number", "description": "Finished DNS address resolve." },
- { "name": "connectStart", "type": "number", "description": "Started connecting to the remote host." },
- { "name": "connectEnd", "type": "number", "description": "Connected to the remote host." },
- { "name": "secureConnectionStart", "type": "number", "description": "Started SSL handshake." },
- { "name": "requestStart", "type": "number", "description": "Started sending request." },
- { "name": "responseStart", "type": "number", "description": "Started receiving response headers." }
+ { "name": "startTime", "$ref": "Timestamp", "description": "Request is initiated" },
+ { "name": "redirectStart", "$ref": "Timestamp", "description": "Started redirect resolution." },
+ { "name": "redirectEnd", "$ref": "Timestamp", "description": "Finished redirect resolution." },
+ { "name": "fetchStart", "$ref": "Timestamp", "description": "Resource fetching started." },
+ { "name": "domainLookupStart", "type": "number", "description": "Started DNS address resolve in milliseconds relative to fetchStart." },
+ { "name": "domainLookupEnd", "type": "number", "description": "Finished DNS address resolve in milliseconds relative to fetchStart." },
+ { "name": "connectStart", "type": "number", "description": "Started connecting to the remote host in milliseconds relative to fetchStart." },
+ { "name": "connectEnd", "type": "number", "description": "Connected to the remote host in milliseconds relative to fetchStart." },
+ { "name": "secureConnectionStart", "type": "number", "description": "Started SSL handshake in milliseconds relative to fetchStart." },
+ { "name": "requestStart", "type": "number", "description": "Started sending request in milliseconds relative to fetchStart." },
+ { "name": "responseStart", "type": "number", "description": "Started receiving response headers in milliseconds relative to fetchStart." },
+ { "name": "responseEnd", "type": "number", "description": "Finished receiving response headers in milliseconds relative to fetchStart." }
]
},
{
Modified: trunk/Source/WebCore/ChangeLog (236994 => 236995)
--- trunk/Source/WebCore/ChangeLog 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebCore/ChangeLog 2018-10-10 02:49:52 UTC (rev 236995)
@@ -1,3 +1,18 @@
+2018-10-09 Devin Rousso <[email protected]>
+
+ Web Inspector: show redirect requests in Network and Timelines tabs
+ https://bugs.webkit.org/show_bug.cgi?id=150005
+ <rdar://problem/5378164>
+
+ Reviewed by Joseph Pecoraro.
+
+ Updated existing test http/tests/inspector/network/resource-timing.html.
+
+ * inspector/agents/InspectorNetworkAgent.cpp:
+ (WebCore::InspectorNetworkAgent::buildObjectForTiming):
+ (WebCore::InspectorNetworkAgent::didFinishLoading):
+ Add missing fields for `Network.types.ResourceTiming`.
+
2018-10-09 Said Abou-Hallawa <[email protected]>
REGRESSION(r234620): SVGLangSpace::svgAttributeChanged() should invalidate the renderer of the SVGGeometryElement descendant only
Modified: trunk/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp (236994 => 236995)
--- trunk/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp 2018-10-10 02:49:52 UTC (rev 236995)
@@ -197,11 +197,17 @@
Ref<Inspector::Protocol::Network::ResourceTiming> InspectorNetworkAgent::buildObjectForTiming(const NetworkLoadMetrics& timing, ResourceLoader& resourceLoader)
{
- MonotonicTime startTime = resourceLoader.loadTiming().startTime();
- Seconds startTimeInInspector = m_environment.executionStopwatch()->elapsedTimeSince(startTime);
+ auto& loadTiming = resourceLoader.loadTiming();
+ auto elapsedTimeSince = [&] (const MonotonicTime& time) {
+ return m_environment.executionStopwatch()->elapsedTimeSince(time).seconds();
+ };
+
return Inspector::Protocol::Network::ResourceTiming::create()
- .setStartTime(startTimeInInspector.seconds())
+ .setStartTime(elapsedTimeSince(loadTiming.startTime()))
+ .setRedirectStart(elapsedTimeSince(loadTiming.redirectStart()))
+ .setRedirectEnd(elapsedTimeSince(loadTiming.redirectEnd()))
+ .setFetchStart(elapsedTimeSince(loadTiming.fetchStart()))
.setDomainLookupStart(timing.domainLookupStart.milliseconds())
.setDomainLookupEnd(timing.domainLookupEnd.milliseconds())
.setConnectStart(timing.connectStart.milliseconds())
@@ -209,6 +215,7 @@
.setSecureConnectionStart(timing.secureConnectionStart.milliseconds())
.setRequestStart(timing.requestStart.milliseconds())
.setResponseStart(timing.responseStart.milliseconds())
+ .setResponseEnd(timing.responseEnd.milliseconds())
.release();
}
@@ -506,9 +513,9 @@
double elapsedFinishTime;
if (resourceLoader && networkLoadMetrics.isComplete()) {
- MonotonicTime startTime = resourceLoader->loadTiming().startTime();
- Seconds startTimeInInspector = m_environment.executionStopwatch()->elapsedTimeSince(startTime);
- elapsedFinishTime = (startTimeInInspector + networkLoadMetrics.responseEnd).seconds();
+ MonotonicTime fetchStart = resourceLoader->loadTiming().fetchStart();
+ Seconds fetchStartInInspector = m_environment.executionStopwatch()->elapsedTimeSince(fetchStart);
+ elapsedFinishTime = (fetchStartInInspector + networkLoadMetrics.responseEnd).seconds();
} else
elapsedFinishTime = timestamp();
Modified: trunk/Source/WebInspectorUI/ChangeLog (236994 => 236995)
--- trunk/Source/WebInspectorUI/ChangeLog 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/ChangeLog 2018-10-10 02:49:52 UTC (rev 236995)
@@ -1,5 +1,78 @@
2018-10-09 Devin Rousso <[email protected]>
+ Web Inspector: show redirect requests in Network and Timelines tabs
+ https://bugs.webkit.org/show_bug.cgi?id=150005
+ <rdar://problem/5378164>
+
+ Reviewed by Joseph Pecoraro.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Views/Variables.css:
+ * UserInterface/Main.html:
+ * UserInterface/Test.html:
+
+ * UserInterface/Controllers/NetworkManager.js:
+ (WI.NetworkManager.prototype.resourceRequestWillBeSent):
+
+ * UserInterface/Models/Resource.js:
+ (WI.Resource):
+ (WI.Resource.prototype.get redirects): Added.
+ (WI.Resource.prototype.get lastRedirectReceivedTimestamp):
+ (WI.Resource.prototype.updateForRedirectResponse):
+ Save each redirect in an array instead of just remembering the last timestamp.
+
+ * UserInterface/Models/ResourceTimingData.js:
+ (WI.ResourceTimingData):
+ (WI.ResourceTimingData.fromPayload.offsetToTimestamp):
+ (WI.ResourceTimingData.fromPayload):
+ (WI.ResourceTimingData.prototype.get redirectStart): Added.
+ (WI.ResourceTimingData.prototype.get redirectEnd): Added.
+ (WI.ResourceTimingData.prototype.get fetchStart): Added.
+ Add missing fields for `Network.types.ResourceTiming`.
+
+ * UserInterface/Models/Redirect.js: Added.
+ (WI.Redirect):
+ (WI.Redirect.prototype.get url):
+ (WI.Redirect.prototype.get requestMethod):
+ (WI.Redirect.prototype.get requestHeaders):
+ (WI.Redirect.prototype.get responseStatusCode):
+ (WI.Redirect.prototype.get responseStatusText):
+ (WI.Redirect.prototype.get responseHeaders):
+ (WI.Redirect.prototype.get timestamp):
+ (WI.Redirect.prototype.get urlComponents):
+
+ * UserInterface/Views/ResourceHeadersContentView.js:
+ (WI.ResourceHeadersContentView):
+ (WI.ResourceHeadersContentView.prototype.initialLayout):
+ (WI.ResourceHeadersContentView.prototype.layout):
+ (WI.ResourceHeadersContentView.prototype._refreshRedirectHeadersSections): Added.
+ (WI.ResourceHeadersContentView.prototype._resourceRequestHeadersDidChange):
+ * UserInterface/Views/ResourceHeadersContentView.css:
+ (body[dir] .resource-headers > section.summary > .details): Added.
+ (body[dir] .resource-headers > section:matches(.redirect, .headers) > .details): Added.
+ (.resource-headers .details .key):
+ (.resource-headers .summary .key):
+ (body[dir] .resource-headers > section > .details): Deleted.
+ (body[dir] .resource-headers > section.headers > .details): Deleted.
+ (.resource-headers .value): Deleted.
+ Add a request/response header section for each redirect.
+
+ * UserInterface/Views/NetworkTableContentView.js:
+ (WI.NetworkTableContentView.prototype._populateWaterfallGraph.appendBlock):
+ (WI.NetworkTableContentView.prototype._populateWaterfallGraph):
+ (WI.NetworkTableContentView.prototype._checkURLFilterAgainstResource):
+ (WI.NetworkTableContentView.prototype._waterfallPopoverContentForResource):
+ * UserInterface/Views/NetworkTableContentView.css:
+ (.waterfall .block.redirect): Added.
+ (.waterfall .block.queue):
+ * UserInterface/Views/ResourceTimelineDataGridNode.js:
+ (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar):
+ * UserInterface/Views/ResourceTimingBreakdownView.js:
+ (WI.ResourceTimingBreakdownView.prototype.initialLayout):
+ Add timeline/waterfall entries for total redirect time.
+
+2018-10-09 Devin Rousso <[email protected]>
+
Web Inspector: Canvas Tab: grayed out Record button in navigator is nearly invisible
https://bugs.webkit.org/show_bug.cgi?id=190365
<rdar://problem/45097739>
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -654,6 +654,8 @@
localizedStrings["Recording Timeline Data"] = "Recording Timeline Data";
localizedStrings["Recording error: %s"] = "Recording error: %s";
localizedStrings["Recordings"] = "Recordings";
+localizedStrings["Redirect Response"] = "Redirect Response";
+localizedStrings["Redirects"] = "Redirects";
localizedStrings["Reference Issue"] = "Reference Issue";
localizedStrings["Reflection"] = "Reflection";
localizedStrings["Refresh"] = "Refresh";
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/NetworkManager.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/NetworkManager.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/NetworkManager.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -239,9 +239,10 @@
let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
if (resource) {
// This is an existing request which is being redirected, update the resource.
- console.assert(redirectResponse);
+ console.assert(resource.parentFrame.id === frameIdentifier);
+ console.assert(resource.loaderIdentifier === loaderIdentifier);
console.assert(!targetId);
- resource.updateForRedirectResponse(request.url, request.headers, elapsedTime);
+ resource.updateForRedirectResponse(request, redirectResponse, elapsedTime, walltime);
return;
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2018-10-10 02:49:52 UTC (rev 236995)
@@ -404,6 +404,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Added: trunk/Source/WebInspectorUI/UserInterface/Models/Redirect.js (0 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Models/Redirect.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Redirect.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.Redirect = class Redirect
+{
+ constructor(url, requestMethod, requestHeaders, responseStatusCode, responseStatusText, responseHeaders, timestamp)
+ {
+ console.assert(typeof url ="" "string");
+ console.assert(typeof requestMethod === "string");
+ console.assert(typeof requestHeaders === "object");
+ console.assert(!isNaN(responseStatusCode));
+ console.assert(typeof responseStatusText === "string");
+ console.assert(typeof responseHeaders === "object");
+ console.assert(!isNaN(timestamp));
+
+ this._url = url;
+ this._urlComponents = null;
+ this._requestMethod = requestMethod;
+ this._requestHeaders = requestHeaders;
+ this._responseStatusCode = responseStatusCode;
+ this._responseStatusText = responseStatusText;
+ this._responseHeaders = responseHeaders;
+ this._timestamp = timestamp;
+ }
+
+ // Public
+
+ get url() { return this._url; }
+ get requestMethod() { return this._requestMethod; }
+ get requestHeaders() { return this._requestHeaders; }
+ get responseStatusCode() { return this._responseStatusCode; }
+ get responseStatusText() { return this._responseStatusText; }
+ get responseHeaders() { return this._responseHeaders; }
+ get timestamp() { return this._timestamp; }
+
+ get urlComponents()
+ {
+ if (!this._urlComponents)
+ this._urlComponents = parseURL(this._url);
+ return this._urlComponents;
+ }
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -58,7 +58,6 @@
this._requestSentTimestamp = requestSentTimestamp || NaN;
this._requestSentWalltime = requestSentWalltime || NaN;
this._responseReceivedTimestamp = NaN;
- this._lastRedirectReceivedTimestamp = NaN;
this._lastDataReceivedTimestamp = NaN;
this._finishedOrFailedTimestamp = NaN;
this._finishThenRequestContentPromise = null;
@@ -76,6 +75,7 @@
this._remoteAddress = null;
this._connectionIdentifier = null;
this._target = targetId ? WI.targetManager.targetForIdentifier(targetId) : WI.mainTarget;
+ this._redirects = [];
// Exact sizes if loaded over the network or cache.
this._requestHeadersTransferSize = NaN;
@@ -319,7 +319,6 @@
get responseHeaders() { return this._responseHeaders; }
get requestSentTimestamp() { return this._requestSentTimestamp; }
get requestSentWalltime() { return this._requestSentWalltime; }
- get lastRedirectReceivedTimestamp() { return this._lastRedirectReceivedTimestamp; }
get responseReceivedTimestamp() { return this._responseReceivedTimestamp; }
get lastDataReceivedTimestamp() { return this._lastDataReceivedTimestamp; }
get finishedOrFailedTimestamp() { return this._finishedOrFailedTimestamp; }
@@ -329,6 +328,7 @@
get responseHeadersTransferSize() { return this._responseHeadersTransferSize; }
get responseBodyTransferSize() { return this._responseBodyTransferSize; }
get cachedResponseBodySize() { return this._cachedResponseBodySize; }
+ get redirects() { return this._redirects; }
get urlComponents()
{
@@ -467,6 +467,11 @@
return isNaN(this._requestSentWalltime) ? null : new Date(this._requestSentWalltime * 1000);
}
+ get lastRedirectReceivedTimestamp()
+ {
+ return this._redirects.length ? this._redirects.lastValue.timestamp : NaN;
+ }
+
get firstTimestamp()
{
return this.timingData.startTime || this.lastRedirectReceivedTimestamp || this.responseReceivedTimestamp || this.lastDataReceivedTimestamp || this.finishedOrFailedTimestamp;
@@ -624,22 +629,23 @@
return null;
}
- updateForRedirectResponse(url, requestHeaders, elapsedTime)
+ updateForRedirectResponse(request, response, elapsedTime, walltime)
{
console.assert(!this._finished);
console.assert(!this._failed);
console.assert(!this._canceled);
- var oldURL = this._url;
+ let oldURL = this._url;
+ let oldHeaders = this._requestHeaders;
- if (url)
- this._url = url;
+ if (request.url)
+ this._url = request.url;
- this._requestHeaders = requestHeaders || {};
+ this._requestHeaders = request.headers || {};
this._requestCookies = null;
- this._lastRedirectReceivedTimestamp = elapsedTime || NaN;
+ this._redirects.push(new WI.Redirect(oldURL, request.method, oldHeaders, response.status, response.statusText, response.headers, elapsedTime));
- if (oldURL !== url) {
+ if (oldURL !== request.url) {
// Delete the URL components so the URL is re-parsed the next time it is requested.
this._urlComponents = null;
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ResourceTimingData.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Models/ResourceTimingData.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ResourceTimingData.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -29,6 +29,8 @@
{
data = "" || {};
+ console.assert(isNaN(data.startTime) || data.startTime <= data.fetchStart);
+ console.assert(isNaN(data.redirectStart) === isNaN(data.redirectEnd));
console.assert(isNaN(data.domainLookupStart) === isNaN(data.domainLookupEnd));
console.assert(isNaN(data.connectStart) === isNaN(data.connectEnd));
@@ -35,6 +37,9 @@
this._resource = resource;
this._startTime = data.startTime || NaN;
+ this._redirectStart = data.redirectStart || NaN;
+ this._redirectEnd = data.redirectEnd || NaN;
+ this._fetchStart = data.fetchStart || NaN;
this._domainLookupStart = data.domainLookupStart || NaN;
this._domainLookupEnd = data.domainLookupEnd || NaN;
this._connectStart = data.connectStart || NaN;
@@ -62,12 +67,30 @@
if (typeof payload.navigationStart === "number")
payload = {};
+ // COMPATIBILITY (iOS 12.0): Resource Timing data was based on startTime, not fetchStart.
+ let startTime = payload.startTime;
+ let fetchStart = payload.fetchStart;
+ let redirectStart = payload.redirectStart;
+ let redirectEnd = payload.redirectEnd;
+
+ if (isNaN(fetchStart) || fetchStart < startTime)
+ fetchStart = startTime;
+
+ if (redirectStart < startTime || redirectStart > fetchStart || redirectStart > redirectEnd)
+ redirectStart = NaN;
+
+ if (redirectEnd < startTime || redirectEnd > fetchStart || redirectEnd < redirectStart)
+ redirectEnd = NaN;
+
function offsetToTimestamp(offset) {
- return offset > 0 ? payload.startTime + (offset / 1000) : NaN;
+ return offset > 0 ? fetchStart + (offset / 1000) : NaN;
}
let data = {
- startTime: payload.startTime,
+ startTime,
+ redirectStart,
+ redirectEnd,
+ fetchStart,
domainLookupStart: offsetToTimestamp(payload.domainLookupStart),
domainLookupEnd: offsetToTimestamp(payload.domainLookupEnd),
connectStart: offsetToTimestamp(payload.connectStart),
@@ -88,6 +111,9 @@
// Public
get startTime() { return this._startTime || this._resource.requestSentTimestamp; }
+ get redirectStart() { return this._redirectStart; }
+ get redirectEnd() { return this._redirectEnd; }
+ get fetchStart() { return this._fetchStart; }
get domainLookupStart() { return this._domainLookupStart; }
get domainLookupEnd() { return this._domainLookupEnd; }
get connectStart() { return this._connectStart; }
Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Test.html 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html 2018-10-10 02:49:52 UTC (rev 236995)
@@ -173,6 +173,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css 2018-10-10 02:49:52 UTC (rev 236995)
@@ -186,9 +186,17 @@
height: 18px;
}
+.waterfall .block.filler {
+ top: 9px;
+ height: 2px;
+ background-color: lightgrey;
+}
+
+.waterfall .block.redirect {
+ background-color: var(--network-redirect-color);
+}
+
.waterfall .block.queue {
- min-width: 3px;
- -webkit-margin-start: -1px;
background-color: var(--network-queue-color);
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -651,8 +651,8 @@
return;
}
- let {startTime, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = resource.timingData;
- if (isNaN(startTime)) {
+ let {startTime, redirectStart, redirectEnd, fetchStart, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = resource.timingData;
+ if (isNaN(startTime) || isNaN(responseEnd)) {
cell.textContent = zeroWidthSpace;
return;
}
@@ -674,9 +674,12 @@
let container = cell.appendChild(document.createElement("div"));
container.className = "waterfall-container";
- function appendBlock(startTime, endTime, className) {
- let startOffset = (startTime - graphStartTime) / secondsPerPixel;
- let width = (endTime - startTime) / secondsPerPixel;
+ function appendBlock(startTimestamp, endTimestamp, className) {
+ if (isNaN(startTimestamp) || isNaN(endTimestamp) || endTimestamp - startTimestamp <= 0)
+ return null;
+
+ let startOffset = (startTimestamp - graphStartTime) / secondsPerPixel;
+ let width = (endTimestamp - startTimestamp) / secondsPerPixel;
let block = container.appendChild(document.createElement("div"));
block.classList.add("block", className);
let styleAttribute = WI.resolvedLayoutDirection() === WI.LayoutDirection.LTR ? "left" : "right";
@@ -702,16 +705,20 @@
return;
}
- // Each component.
+ appendBlock(startTime, responseEnd, "filler");
+
+ // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
+ appendBlock(redirectStart, redirectEnd, "redirect");
+
if (domainLookupStart) {
- appendBlock(startTime, domainLookupStart, "queue");
- appendBlock(domainLookupStart, connectStart || requestStart, "dns");
+ appendBlock(fetchStart, domainLookupStart, "queue");
+ appendBlock(domainLookupStart, domainLookupEnd || connectStart || requestStart, "dns");
} else if (connectStart)
- appendBlock(startTime, connectStart, "queue");
+ appendBlock(fetchStart, connectStart, "queue");
else if (requestStart)
- appendBlock(startTime, requestStart, "queue");
+ appendBlock(fetchStart, requestStart, "queue");
if (connectStart)
- appendBlock(connectStart, connectEnd, "connect");
+ appendBlock(connectStart, secureConnectionStart || connectEnd, "connect");
if (secureConnectionStart)
appendBlock(secureConnectionStart, connectEnd, "secure");
appendBlock(requestStart, responseStart, "request");
@@ -1089,8 +1096,17 @@
_checkURLFilterAgainstResource(resource)
{
- if (this._urlFilterSearchRegex.test(resource.url))
+ if (this._urlFilterSearchRegex.test(resource.url)) {
this._activeURLFilterResources.add(resource);
+ return;
+ }
+
+ for (let redirect of resource.redirects) {
+ if (this._urlFilterSearchRegex.test(redirect.url)) {
+ this._activeURLFilterResources.add(resource);
+ return;
+ }
+ }
}
_rowIndexForResource(resource)
@@ -1689,7 +1705,7 @@
let contentElement = document.createElement("div");
contentElement.className = "waterfall-popover-content";
- if (!resource.hasResponse() || !resource.timingData.startTime || !resource.timingData.responseEnd) {
+ if (!resource.hasResponse() || !resource.firstTimestamp || !resource.lastTimestamp) {
contentElement.textContent = WI.UIString("Resource has no timing data");
return contentElement;
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceHeadersContentView.css (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceHeadersContentView.css 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceHeadersContentView.css 2018-10-10 02:49:52 UTC (rev 236995)
@@ -23,11 +23,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-body[dir] .resource-headers > section > .details {
+body[dir] .resource-headers > section.summary > .details {
border-color: var(--network-system-color);
}
-body[dir] .resource-headers > section.headers > .details {
+body[dir] .resource-headers > section:matches(.redirect, .headers) > .details {
border-color: var(--network-header-color);
}
@@ -55,7 +55,6 @@
}
.resource-headers .details .key {
- color: var(--network-system-color);
font-weight: 500;
-webkit-margin-start: calc(var(--resource-headers-value-indent) * -1);
}
@@ -64,6 +63,14 @@
color: var(--text-color);
}
+.resource-headers .url + .url > .key {
+ color: transparent;
+}
+
+.resource-headers .summary .key {
+ color: var(--network-system-color);
+}
+
.resource-headers .header > .key {
color: var(--network-header-color);
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceHeadersContentView.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceHeadersContentView.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceHeadersContentView.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -46,10 +46,13 @@
this._automaticallyRevealFirstSearchResult = false;
this._bouncyHighlightElement = null;
+ this._redirectDetailsSections = [];
+
this.element.classList.add("resource-details", "resource-headers");
this.element.tabIndex = 0;
this._needsSummaryRefresh = false;
+ this._needsRedirectHeadersRefresh = false;
this._needsRequestHeadersRefresh = false;
this._needsResponseHeadersRefresh = false;
}
@@ -64,12 +67,12 @@
this.element.appendChild(this._summarySection.element);
this._refreshSummarySection();
+ this._refreshRedirectHeadersSections();
+
this._requestHeadersSection = new WI.ResourceDetailsSection(WI.UIString("Request"), "headers");
this.element.appendChild(this._requestHeadersSection.element);
this._refreshRequestHeadersSection();
- // FIXME: <https://webkit.org/b/150005> Web Inspector: Redirect requests are not shown in either Network or Timeline tabs
-
this._responseHeadersSection = new WI.ResourceDetailsSection(WI.UIString("Response"), "headers");
this.element.appendChild(this._responseHeadersSection.element);
this._refreshResponseHeadersSection();
@@ -87,6 +90,7 @@
}
this._needsSummaryRefresh = false;
+ this._needsRedirectHeadersRefresh = false;
this._needsRequestHeadersRefresh = false;
this._needsResponseHeadersRefresh = false;
}
@@ -100,6 +104,11 @@
this._needsSummaryRefresh = false;
}
+ if (this._needsRedirectHeadersRefresh) {
+ this._refreshRedirectHeadersSections();
+ this._needsRedirectHeadersRefresh = false;
+ }
+
if (this._needsRequestHeadersRefresh) {
this._refreshRequestHeadersSection();
this._needsRequestHeadersRefresh = false;
@@ -266,7 +275,9 @@
this._summarySection.toggleError(this._resource.hadLoadingError());
- this._appendKeyValuePair(detailsElement, WI.UIString("URL"), this._resource.url.insertWordBreakCharacters());
+ for (let redirect of this._resource.redirects)
+ this._appendKeyValuePair(detailsElement, WI.UIString("URL"), redirect.url.insertWordBreakCharacters(), "url");
+ this._appendKeyValuePair(detailsElement, WI.UIString("URL"), this._resource.url.insertWordBreakCharacters(), "url");
let status = emDash;
if (!isNaN(this._resource.statusCode))
@@ -282,6 +293,37 @@
this._appendKeyValuePair(detailsElement, WI.UIString("Address"), this._resource.remoteAddress);
}
+ _refreshRedirectHeadersSections()
+ {
+ let referenceElement = this._redirectDetailsSections.length ? this._redirectDetailsSections.lastValue.element : this._summarySection.element;
+
+ for (let i = this._redirectDetailsSections.length; i < this._resource.redirects.length; ++i) {
+ let redirect = this._resource.redirects[i];
+
+ let redirectRequestSection = new WI.ResourceDetailsSection(WI.UIString("Request"), "redirect");
+
+ // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
+ this._appendKeyValuePair(redirectRequestSection.detailsElement, `${redirect.requestMethod} ${redirect.urlComponents.path}`, null, "h1-status");
+
+ for (let key in redirect.requestHeaders)
+ this._appendKeyValuePair(redirectRequestSection.detailsElement, key, redirect.requestHeaders[key], "header");
+
+ referenceElement = this.element.insertBefore(redirectRequestSection.element, referenceElement.nextElementSibling);
+ this._redirectDetailsSections.push(redirectRequestSection);
+
+ let redirectResponseSection = new WI.ResourceDetailsSection(WI.UIString("Redirect Response"), "redirect");
+
+ // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
+ this._appendKeyValuePair(redirectResponseSection.detailsElement, `${redirect.responseStatusCode} ${redirect.responseStatusText}`, null, "h1-status");
+
+ for (let key in redirect.responseHeaders)
+ this._appendKeyValuePair(redirectResponseSection.detailsElement, key, redirect.responseHeaders[key], "header");
+
+ referenceElement = this.element.insertBefore(redirectResponseSection.element, referenceElement.nextElementSibling);
+ this._redirectDetailsSections.push(redirectResponseSection);
+ }
+ }
+
_refreshRequestHeadersSection()
{
let detailsElement = this._requestHeadersSection.detailsElement;
@@ -476,6 +518,8 @@
_resourceRequestHeadersDidChange(event)
{
+ this._needsSummaryRefresh = true;
+ this._needsRedirectHeadersRefresh = true;
this._needsRequestHeadersRefresh = true;
this.needsLayout();
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -396,9 +396,14 @@
}
};
+ if (resource.timingData.redirectEnd - resource.timingData.redirectStart) {
+ // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
+ popoverDataGrid.appendChild(new WI.ResourceTimingPopoverDataGridNode(WI.UIString("Redirects"), resource.timingData.redirectStart, resource.timingData.redirectEnd, graphDataSource));
+ }
+
let secondTimestamp = resource.timingData.domainLookupStart || resource.timingData.connectStart || resource.timingData.requestStart;
- if (secondTimestamp - resource.timingData.startTime)
- popoverDataGrid.appendChild(new WI.ResourceTimingPopoverDataGridNode(WI.UIString("Stalled"), resource.timingData.startTime, secondTimestamp, graphDataSource));
+ if (secondTimestamp - resource.timingData.fetchStart)
+ popoverDataGrid.appendChild(new WI.ResourceTimingPopoverDataGridNode(WI.UIString("Stalled"), resource.timingData.fetchStart, secondTimestamp, graphDataSource));
if (resource.timingData.domainLookupStart)
popoverDataGrid.appendChild(new WI.ResourceTimingPopoverDataGridNode(WI.UIString("DNS"), resource.timingData.domainLookupStart, resource.timingData.domainLookupEnd, graphDataSource));
if (resource.timingData.connectStart)
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js 2018-10-10 02:49:52 UTC (rev 236995)
@@ -101,7 +101,7 @@
{
super.initialLayout();
- let {startTime, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = this._resource.timingData;
+ let {startTime, redirectStart, redirectEnd, fetchStart, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = this._resource.timingData;
this._tableElement = this.element.appendChild(document.createElement("table"));
this._tableElement.className = "waterfall";
@@ -111,8 +111,14 @@
this._graphDuration = this._graphEndTime - this._graphStartTime;
this._appendHeaderRow(WI.UIString("Scheduling:"));
- this._appendRow(WI.UIString("Queued"), "queue", startTime, domainLookupStart || connectStart || requestStart);
+ if (redirectEnd - redirectStart) {
+ // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
+ this._appendRow(WI.UIString("Redirects"), "redirect", redirectStart, redirectEnd);
+ }
+
+ this._appendRow(WI.UIString("Queued"), "queue", fetchStart, domainLookupStart || connectStart || requestStart);
+
if (domainLookupStart || connectStart) {
this._appendEmptyRow();
this._appendHeaderRow(WI.UIString("Connection:"));
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css (236994 => 236995)
--- trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css 2018-10-10 00:31:33 UTC (rev 236994)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css 2018-10-10 02:49:52 UTC (rev 236995)
@@ -113,6 +113,7 @@
--network-pseudo-header-color: hsl(312, 35%, 51%);
--network-error-color: hsl(0, 54%, 50%);
+ --network-redirect-color: lightgrey;
--network-queue-color: hsl(0, 0%, 54%);
--network-dns-color: hsl(265, 82%, 60%);
--network-connect-color: hsl(46, 92%, 62%);