Log Message
Web Inspector: Expose Server Timing Response Headers in Network Tab https://bugs.webkit.org/show_bug.cgi?id=190440
Patch by Charles Vazac <cva...@gmail.com> on 2018-10-15 Reviewed by Joseph Pecoraro. Source/WebInspectorUI: * Localizations/en.lproj/localizedStrings.js: new key "Server Timing:" * UserInterface/Main.html: add reference to Models/ServerTimingEntry.js * UserInterface/Models/Resource.js: (WI.Resource.prototype.get serverTiming): (WI.Resource.prototype.updateForResponse): * UserInterface/Models/ServerTimingEntry.js: Added. (WI.ServerTimingEntry): (WI.ServerTimingEntry.parseHeaders): parse raw response headers into an array of ServerTimingEntry objects (WI.ServerTimingEntry.parseHeaders.consumeDelimiter): (WI.ServerTimingEntry.parseHeaders.consumeToken): (WI.ServerTimingEntry.): * UserInterface/Test.html: add reference to Models/ServerTimingEntry.js * UserInterface/Views/ResourceTimingBreakdownView.js: (WI.ResourceTimingBreakdownView.prototype._appendServerTimingRow): render a table row per ServerTimingEntry object (WI.ResourceTimingBreakdownView.prototype.initialLayout): (WI.ResourceTimingBreakdownView): LayoutTests: * inspector/unit-tests/server-timing-entry-expected.txt: * inspector/unit-tests/server-timing-entry.html:
Modified Paths
- trunk/LayoutTests/ChangeLog
- trunk/Source/WebInspectorUI/ChangeLog
- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
- trunk/Source/WebInspectorUI/UserInterface/Main.html
- trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js
- trunk/Source/WebInspectorUI/UserInterface/Test.html
- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (237150 => 237151)
--- trunk/LayoutTests/ChangeLog 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/LayoutTests/ChangeLog 2018-10-15 23:10:20 UTC (rev 237151)
@@ -1,3 +1,13 @@
+2018-10-15 Charles Vazac <cva...@gmail.com>
+
+ Web Inspector: Expose Server Timing Response Headers in Network Tab
+ https://bugs.webkit.org/show_bug.cgi?id=190440
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/unit-tests/server-timing-entry-expected.txt:
+ * inspector/unit-tests/server-timing-entry.html:
+
2018-10-15 Alex Christensen <achristen...@webkit.org>
Garden WK2 tests after r237104
Added: trunk/LayoutTests/inspector/unit-tests/server-timing-entry-expected.txt (0 => 237151)
--- trunk/LayoutTests/inspector/unit-tests/server-timing-entry-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/server-timing-entry-expected.txt 2018-10-15 23:10:20 UTC (rev 237151)
@@ -0,0 +1,555 @@
+
+== Running test suite: ServerTimingEntry
+-- Running test case: ServerTimingEntry.parseHeaders
+Testing response header: --><--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->metric<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is undefined
+
+Testing response header: -->metric;dur="123.4"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is undefined
+
+Testing response header: -->metric;desc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "description"
+
+Testing response header: -->metric;desc="description"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "description"
+
+Testing response header: -->metric;dur=123.4;desc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->metric;desc=description;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->aB3!#$%&'*+-.^_`|~<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "aB3!#$%&'*+-.^_`|~"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric;desc="descr;,=iption";dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "descr;,=iption"
+
+Testing response header: -->metric ; <--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric , <--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric ; dur = 123.4 ; desc = description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->metric ; desc = description ; dur = 123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->metric;desc = "description"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "description"
+
+Testing response header: -->metric ; <--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric , <--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric ; dur = 123.4 ; desc = description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->metric ; desc = description ; dur = 123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->metric;desc = "description"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "description"
+
+Testing response header: -->metric1;dur=12.3;desc=description1,metric2;dur=45.6;desc=description2,metric3;dur=78.9;desc=description3<--
+PASS: Parsed ServerTimingEntry count has expected results count of 3.
+PASS: name is "metric1"
+PASS: duration is 12.3
+PASS: description is "description1"
+PASS: name is "metric2"
+PASS: duration is 45.6
+PASS: description is "description2"
+PASS: name is "metric3"
+PASS: duration is 78.9
+PASS: description is "description3"
+
+Testing response header: -->metric1,metric2 ,metric3, metric4 , metric5<--
+PASS: Parsed ServerTimingEntry count has expected results count of 5.
+PASS: name is "metric1"
+PASS: duration is undefined
+PASS: description is undefined
+PASS: name is "metric2"
+PASS: duration is undefined
+PASS: description is undefined
+PASS: name is "metric3"
+PASS: duration is undefined
+PASS: description is undefined
+PASS: name is "metric4"
+PASS: duration is undefined
+PASS: description is undefined
+PASS: name is "metric5"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric;desc="description"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "description"
+
+Testing response header: -->metric;desc=" description "<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "\t description \t"
+
+Testing response header: -->metric;desc="descr\"iption"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "descr\"iption"
+
+Testing response header: -->metric;desc=\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\"\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=""\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\"\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\\""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\"\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\"\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\""\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=\"""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="\\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="\\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "\\"
+
+Testing response header: -->metric;desc="\"\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="\""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "\""
+
+Testing response header: -->metric;desc=""\\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=""\"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc="""\<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;desc=""""<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is ""
+
+Testing response header: -->metric;dur=12.3;desc=description1,metric;dur=45.6;desc=description2<--
+PASS: Parsed ServerTimingEntry count has expected results count of 2.
+PASS: name is "metric"
+PASS: duration is 12.3
+PASS: description is "description1"
+PASS: name is "metric"
+PASS: duration is 45.6
+PASS: description is "description2"
+
+Testing response header: -->metric;DuR=123.4;DeSc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: -->MeTrIc;desc=DeScRiPtIoN<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "MeTrIc"
+PASS: duration is undefined
+PASS: description is "DeScRiPtIoN"
+
+Testing response header: -->metric;dur=foo<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 0
+PASS: description is undefined
+
+Testing response header: -->metric;dur="foo"<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 0
+PASS: description is undefined
+
+WARN: Unknown Server-Timing parameter: foo bar
+WARN: Unknown Server-Timing parameter: foo bar
+WARN: Unknown Server-Timing parameter: foo bar
+Testing response header: -->metric1;foo=bar;desc=description;foo=bar;dur=123.4;foo=bar,metric2<--
+PASS: Parsed ServerTimingEntry count has expected results count of 2.
+PASS: name is "metric1"
+PASS: duration is 123.4
+PASS: description is "description"
+PASS: name is "metric2"
+PASS: duration is undefined
+PASS: description is undefined
+
+WARN: Ignoring redundant duration.
+Testing response header: -->metric;dur=123.4;dur=567.8<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is undefined
+
+WARN: Ignoring redundant duration.
+Testing response header: -->metric;dur=foo;dur=567.8<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 0
+PASS: description is undefined
+
+WARN: Ignoring redundant description.
+Testing response header: -->metric;desc=description1;desc=description2<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is "description1"
+
+WARN: Ignoring redundant duration.
+Testing response header: -->metric;dur;dur=123.4;desc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 0
+PASS: description is "description"
+
+WARN: Ignoring redundant duration.
+Testing response header: -->metric;dur=;dur=123.4;desc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 0
+PASS: description is "description"
+
+WARN: Ignoring redundant description.
+Testing response header: -->metric;desc;desc=description;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is ""
+
+WARN: Ignoring redundant description.
+Testing response header: -->metric;desc=;desc=description;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is ""
+
+Testing response header: -->metric;desc=d1 d2;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "d1"
+
+Testing response header: -->metric1;desc=d1 d2,metric2<--
+PASS: Parsed ServerTimingEntry count has expected results count of 2.
+PASS: name is "metric1"
+PASS: duration is undefined
+PASS: description is "d1"
+PASS: name is "metric2"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric;desc="d1" d2;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "d1"
+
+Testing response header: -->metric1;desc="d1" d2,metric2<--
+PASS: Parsed ServerTimingEntry count has expected results count of 2.
+PASS: name is "metric1"
+PASS: duration is undefined
+PASS: description is "d1"
+PASS: name is "metric2"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric== ""foo;dur=123.4<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric1== ""foo,metric2<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric1"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: -->metric;dur foo=12<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 0
+PASS: description is undefined
+
+WARN: Unknown Server-Timing parameter: foo
+Testing response header: -->metric;foo dur=12<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is undefined
+PASS: description is undefined
+
+Testing response header: --> <--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->=<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->[<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->]<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->;<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->,<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->=;<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->;=<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->=,<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->,=<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->;,<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->,;<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->=;,<--
+PASS: Parsed ServerTimingEntry count has expected results count of 0.
+
+Testing response header: -->metric; desc= tabs-should-get-trimmed ;dur= 42 <--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 42
+PASS: description is "tabs-should-get-trimmed"
+
+Testing response header: --> metric;dur=123.4;desc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+Testing response header: --> metric;dur=123.4;desc=description<--
+PASS: Parsed ServerTimingEntry count has expected results count of 1.
+PASS: name is "metric"
+PASS: duration is 123.4
+PASS: description is "description"
+
+
Added: trunk/LayoutTests/inspector/unit-tests/server-timing-entry.html (0 => 237151)
--- trunk/LayoutTests/inspector/unit-tests/server-timing-entry.html (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/server-timing-entry.html 2018-10-15 23:10:20 UTC (rev 237151)
@@ -0,0 +1,222 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+<script>
+function test()
+{
+ let suite = InspectorTest.createSyncSuite("ServerTimingEntry");
+
+ suite.addTestCase({
+ name: "ServerTimingEntry.parseHeaders",
+ description: "Parsing of Server-Timing headers.",
+ test() {
+ function testServerTimingHeader(header, expectedResults) {
+ var results = WI.ServerTimingEntry.parseHeaders(header);
+
+ InspectorTest.log(`Testing response header: -->${header}<--`);
+ InspectorTest.expectEqual(results.length, expectedResults.length,
+ `Parsed ServerTimingEntry count has expected results count of ${expectedResults.length}.`);
+
+ results.forEach((serverTimingEntry, index) => {
+ var expectedResult = expectedResults[index];
+ if (expectedResult === undefined) {
+ // Guard against `results.length > expectedResults.length`.
+ return;
+ }
+
+ InspectorTest.expectEqual(serverTimingEntry.name, expectedResult.name, `name is ${JSON.stringify(expectedResult.name)}`);
+ InspectorTest.expectEqual(serverTimingEntry.duration, expectedResult.dur, `duration is ${JSON.stringify(expectedResult.dur)}`);
+ InspectorTest.expectEqual(serverTimingEntry.description, expectedResult.desc, `description is ${JSON.stringify(expectedResult.desc)}`);
+ });
+
+ InspectorTest.log("");
+ }
+
+ // Tests from https://github.com/cvazac/generate-server-timing-tests.
+ // empty string
+ testServerTimingHeader(``, []);
+
+ // name only
+ testServerTimingHeader(`metric`, [{"name":"metric"}]);
+
+ // name and duration
+ testServerTimingHeader(`metric;dur=123.4`, [{"name":"metric","dur":123.4}]);
+ testServerTimingHeader(`metric;dur=\"123.4\"`, [{"name":"metric","dur":123.4}]);
+
+ // name and description
+ testServerTimingHeader(`metric;desc=description`, [{"name":"metric","desc":"description"}]);
+ testServerTimingHeader(`metric;desc=\"description\"`, [{"name":"metric","desc":"description"}]);
+
+ // name, duration, and description
+ testServerTimingHeader(`metric;dur=123.4;desc=description`, [{"name":"metric","dur":123.4,"desc":"description"}]);
+ testServerTimingHeader(`metric;desc=description;dur=123.4`, [{"name":"metric","desc":"description","dur":123.4}]);
+
+ // special chars in name
+ testServerTimingHeader(`aB3!#$%&'*+-.^_\`|~`, [{"name":"aB3!#$%&'*+-.^_`|~"}]);
+
+ // delimiter chars in quoted description
+ testServerTimingHeader(`metric;desc=\"descr;,=iption\";dur=123.4`, [{"name":"metric","desc":"descr;,=iption","dur":123.4}]);
+
+ // spaces
+ testServerTimingHeader(`metric ; `, [{"name":"metric"}]);
+ testServerTimingHeader(`metric , `, [{"name":"metric"}]);
+ testServerTimingHeader(`metric ; dur = 123.4 ; desc = description`, [{"name":"metric","dur":123.4,"desc":"description"}]);
+ testServerTimingHeader(`metric ; desc = description ; dur = 123.4`, [{"name":"metric","desc":"description","dur":123.4}]);
+ testServerTimingHeader(`metric;desc = \"description\"`, [{"name":"metric","desc":"description"}]);
+
+ // tabs
+ testServerTimingHeader(`metric\t;\t`, [{"name":"metric"}]);
+ testServerTimingHeader(`metric\t,\t`, [{"name":"metric"}]);
+ testServerTimingHeader(`metric\t;\tdur\t=\t123.4\t;\tdesc\t=\tdescription`, [{"name":"metric","dur":123.4,"desc":"description"}]);
+ testServerTimingHeader(`metric\t;\tdesc\t=\tdescription\t;\tdur\t=\t123.4`, [{"name":"metric","desc":"description","dur":123.4}]);
+ testServerTimingHeader(`metric;desc\t=\t\"description\"`, [{"name":"metric","desc":"description"}]);
+
+ // multiple entries
+ testServerTimingHeader(`metric1;dur=12.3;desc=description1,metric2;dur=45.6;desc=description2,metric3;dur=78.9;desc=description3`, [{"name":"metric1","dur":12.3,"desc":"description1"},{"name":"metric2","dur":45.6,"desc":"description2"},{"name":"metric3","dur":78.9,"desc":"description3"}]);
+ testServerTimingHeader(`metric1,metric2 ,metric3, metric4 , metric5`, [{"name":"metric1"},{"name":"metric2"},{"name":"metric3"},{"name":"metric4"},{"name":"metric5"}]);
+
+ // quoted-strings - happy path
+ testServerTimingHeader(`metric;desc=\"description\"`, [{"name":"metric","desc":"description"}]);
+ testServerTimingHeader(`metric;desc=\"\t description \t\"`, [{"name":"metric","desc":"\t description \t"}]);
+ testServerTimingHeader(`metric;desc=\"descr\\\"iption\"`, [{"name":"metric","desc":"descr\"iption"}]);
+
+ // quoted-strings - others
+ // metric;desc=\ --> ''
+ testServerTimingHeader(`metric;desc=\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=" --> ''
+ testServerTimingHeader(`metric;desc=\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\ --> ''
+ testServerTimingHeader(`metric;desc=\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\" --> ''
+ testServerTimingHeader(`metric;desc=\\\"`, [{"name":"metric","desc":""}]);
+ // metric;desc="\ --> ''
+ testServerTimingHeader(`metric;desc=\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc="" --> ''
+ testServerTimingHeader(`metric;desc=\"\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\\ --> ''
+ testServerTimingHeader(`metric;desc=\\\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\" --> ''
+ testServerTimingHeader(`metric;desc=\\\\\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\"\ --> ''
+ testServerTimingHeader(`metric;desc=\\\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\"" --> ''
+ testServerTimingHeader(`metric;desc=\\\"\"`, [{"name":"metric","desc":""}]);
+ // metric;desc="\\ --> ''
+ testServerTimingHeader(`metric;desc=\"\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc="\" --> ''
+ testServerTimingHeader(`metric;desc=\"\\\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=""\ --> ''
+ testServerTimingHeader(`metric;desc=\"\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=""" --> ''
+ testServerTimingHeader(`metric;desc=\"\"\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\\\ --> ''
+ testServerTimingHeader(`metric;desc=\\\\\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\\" --> ''
+ testServerTimingHeader(`metric;desc=\\\\\\\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\"\ --> ''
+ testServerTimingHeader(`metric;desc=\\\\\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\\"" --> ''
+ testServerTimingHeader(`metric;desc=\\\\\"\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\"\\ --> ''
+ testServerTimingHeader(`metric;desc=\\\"\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\"\" --> ''
+ testServerTimingHeader(`metric;desc=\\\"\\\"`, [{"name":"metric","desc":""}]);
+ // metric;desc=\""\ --> ''
+ testServerTimingHeader(`metric;desc=\\\"\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=\""" --> ''
+ testServerTimingHeader(`metric;desc=\\\"\"\"`, [{"name":"metric","desc":""}]);
+ // metric;desc="\\\ --> ''
+ testServerTimingHeader(`metric;desc=\"\\\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc="\\" --> '\'
+ testServerTimingHeader(`metric;desc=\"\\\\\"`, [{"name":"metric","desc":"\\"}]);
+ // metric;desc="\"\ --> ''
+ testServerTimingHeader(`metric;desc=\"\\\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc="\"" --> '"'
+ testServerTimingHeader(`metric;desc=\"\\\"\"`, [{"name":"metric","desc":"\""}]);
+ // metric;desc=""\\ --> ''
+ testServerTimingHeader(`metric;desc=\"\"\\\\`, [{"name":"metric","desc":""}]);
+ // metric;desc=""\" --> ''
+ testServerTimingHeader(`metric;desc=\"\"\\\"`, [{"name":"metric","desc":""}]);
+ // metric;desc="""\ --> ''
+ testServerTimingHeader(`metric;desc=\"\"\"\\`, [{"name":"metric","desc":""}]);
+ // metric;desc="""" --> ''
+ testServerTimingHeader(`metric;desc=\"\"\"\"`, [{"name":"metric","desc":""}]);
+
+ // duplicate entry names
+ testServerTimingHeader(`metric;dur=12.3;desc=description1,metric;dur=45.6;desc=description2`, [{"name":"metric","dur":12.3,"desc":"description1"},{"name":"metric","dur":45.6,"desc":"description2"}]);
+
+ // param name case sensitivity
+ testServerTimingHeader(`metric;DuR=123.4;DeSc=description`, [{"name":"metric","dur":123.4,"desc":"description"}]);
+
+ // param value case sensitivity
+ testServerTimingHeader(`MeTrIc;desc=DeScRiPtIoN`, [{"name":"MeTrIc","desc":"DeScRiPtIoN"}]);
+
+ // non-numeric durations
+ testServerTimingHeader(`metric;dur=foo`, [{"name":"metric","dur":0}]);
+ testServerTimingHeader(`metric;dur=\"foo\"`, [{"name":"metric","dur":0}]);
+
+ // unrecognized param names
+ testServerTimingHeader(`metric1;foo=bar;desc=description;foo=bar;dur=123.4;foo=bar,metric2`, [{"name":"metric1","desc":"description","dur":123.4},{"name":"metric2"}]);
+
+ // duplicate param names
+ testServerTimingHeader(`metric;dur=123.4;dur=567.8`, [{"name":"metric","dur":123.4}]);
+ testServerTimingHeader(`metric;dur=foo;dur=567.8`, [{"name":"metric","dur":0}]);
+ testServerTimingHeader(`metric;desc=description1;desc=description2`, [{"name":"metric","desc":"description1"}]);
+
+ // incomplete params
+ testServerTimingHeader(`metric;dur;dur=123.4;desc=description`, [{"name":"metric","dur":0,"desc":"description"}]);
+ testServerTimingHeader(`metric;dur=;dur=123.4;desc=description`, [{"name":"metric","dur":0,"desc":"description"}]);
+ testServerTimingHeader(`metric;desc;desc=description;dur=123.4`, [{"name":"metric","desc":"","dur":123.4}]);
+ testServerTimingHeader(`metric;desc=;desc=description;dur=123.4`, [{"name":"metric","desc":"","dur":123.4}]);
+
+ // extraneous characters after param value as token
+ testServerTimingHeader(`metric;desc=d1 d2;dur=123.4`, [{"name":"metric","desc":"d1","dur":123.4}]);
+ testServerTimingHeader(`metric1;desc=d1 d2,metric2`, [{"name":"metric1","desc":"d1"},{"name":"metric2"}]);
+
+ // extraneous characters after param value as quoted-string
+ testServerTimingHeader(`metric;desc=\"d1\" d2;dur=123.4`, [{"name":"metric","desc":"d1","dur":123.4}]);
+ testServerTimingHeader(`metric1;desc=\"d1\" d2,metric2`, [{"name":"metric1","desc":"d1"},{"name":"metric2"}]);
+
+ // nonsense - extraneous characters after entry name token
+ testServerTimingHeader(`metric== \"\"foo;dur=123.4`, [{"name":"metric"}]);
+ testServerTimingHeader(`metric1== \"\"foo,metric2`, [{"name":"metric1"}]);
+
+ // nonsense - extraneous characters after param name token
+ testServerTimingHeader(`metric;dur foo=12`, [{"name":"metric","dur":0}]);
+ testServerTimingHeader(`metric;foo dur=12`, [{"name":"metric"}]);
+
+ // nonsense - return zero entries
+ testServerTimingHeader(` `, []);
+ testServerTimingHeader(`=`, []);
+ testServerTimingHeader(`[`, []);
+ testServerTimingHeader(`]`, []);
+ testServerTimingHeader(`;`, []);
+ testServerTimingHeader(`,`, []);
+ testServerTimingHeader(`=;`, []);
+ testServerTimingHeader(`;=`, []);
+ testServerTimingHeader(`=,`, []);
+ testServerTimingHeader(`,=`, []);
+ testServerTimingHeader(`;,`, []);
+ testServerTimingHeader(`,;`, []);
+ testServerTimingHeader(`=;,`, []);
+
+ // tabs
+ testServerTimingHeader(`metric;\tdesc=\ttabs-should-get-trimmed\t;dur=\t42\t`, [{"name":"metric","desc":"tabs-should-get-trimmed","dur":42}]);
+
+ // leading whitespace
+ testServerTimingHeader(` metric;dur=123.4;desc=description`, [{"name":"metric","dur":123.4,"desc":"description"}]);
+ testServerTimingHeader(`\tmetric;dur=123.4;desc=description`, [{"name":"metric","dur":123.4,"desc":"description"}]);
+
+ return true;
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onLoad_="runTest()">
+</body>
+</html>
Modified: trunk/Source/WebInspectorUI/ChangeLog (237150 => 237151)
--- trunk/Source/WebInspectorUI/ChangeLog 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/Source/WebInspectorUI/ChangeLog 2018-10-15 23:10:20 UTC (rev 237151)
@@ -1,3 +1,27 @@
+2018-10-15 Charles Vazac <cva...@gmail.com>
+
+ Web Inspector: Expose Server Timing Response Headers in Network Tab
+ https://bugs.webkit.org/show_bug.cgi?id=190440
+
+ Reviewed by Joseph Pecoraro.
+
+ * Localizations/en.lproj/localizedStrings.js: new key "Server Timing:"
+ * UserInterface/Main.html: add reference to Models/ServerTimingEntry.js
+ * UserInterface/Models/Resource.js:
+ (WI.Resource.prototype.get serverTiming):
+ (WI.Resource.prototype.updateForResponse):
+ * UserInterface/Models/ServerTimingEntry.js: Added.
+ (WI.ServerTimingEntry):
+ (WI.ServerTimingEntry.parseHeaders): parse raw response headers into an array of ServerTimingEntry objects
+ (WI.ServerTimingEntry.parseHeaders.consumeDelimiter):
+ (WI.ServerTimingEntry.parseHeaders.consumeToken):
+ (WI.ServerTimingEntry.):
+ * UserInterface/Test.html: add reference to Models/ServerTimingEntry.js
+ * UserInterface/Views/ResourceTimingBreakdownView.js:
+ (WI.ResourceTimingBreakdownView.prototype._appendServerTimingRow): render a table row per ServerTimingEntry object
+ (WI.ResourceTimingBreakdownView.prototype.initialLayout):
+ (WI.ResourceTimingBreakdownView):
+
2018-10-15 Nikita Vasilyev <nvasil...@apple.com>
Web Inspector: Dark Mode: pseudo elements in DOM tree are too dark
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (237150 => 237151)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2018-10-15 23:10:20 UTC (rev 237151)
@@ -748,6 +748,7 @@
localizedStrings["Self Size"] = "Self Size";
localizedStrings["Self Time"] = "Self Time";
localizedStrings["Semantic Issue"] = "Semantic Issue";
+localizedStrings["Server Timing:"] = "Server Timing:";
localizedStrings["Service Worker"] = "Service Worker";
localizedStrings["ServiceWorker"] = "ServiceWorker";
localizedStrings["Session"] = "Session";
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (237150 => 237151)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2018-10-15 23:10:20 UTC (rev 237151)
@@ -419,6 +419,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js (237150 => 237151)
--- trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js 2018-10-15 23:10:20 UTC (rev 237151)
@@ -50,6 +50,7 @@
this._responseHeaders = {};
this._requestCookies = null;
this._responseCookies = null;
+ this._serverTimingEntries = null;
this._parentFrame = null;
this._initiatorSourceCodeLocation = initiatorSourceCodeLocation || null;
this._initiatorNode = initiatorNode || null;
@@ -606,6 +607,13 @@
return this._scripts || [];
}
+ get serverTiming()
+ {
+ if (!this._serverTimingEntries)
+ this._serverTimingEntries = WI.ServerTimingEntry.parseHeaders(this._responseHeaders.valueForCaseInsensitiveKey("Server-Timing"));
+ return this._serverTimingEntries;
+ }
+
scriptForLocation(sourceCodeLocation)
{
console.assert(!(this instanceof WI.SourceMapResource));
@@ -689,6 +697,7 @@
this._statusText = statusText;
this._responseHeaders = responseHeaders || {};
this._responseCookies = null;
+ this._serverTimingEntries = null;
this._responseReceivedTimestamp = elapsedTime || NaN;
this._timingData = WI.ResourceTimingData.fromPayload(timingData, this);
Added: trunk/Source/WebInspectorUI/UserInterface/Models/ServerTimingEntry.js (0 => 237151)
--- trunk/Source/WebInspectorUI/UserInterface/Models/ServerTimingEntry.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ServerTimingEntry.js 2018-10-15 23:10:20 UTC (rev 237151)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright 2017 The Chromium Authors. 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.ServerTimingEntry = class ServerTimingEntry
+{
+ constructor(name)
+ {
+ this._name = name;
+ this._duration = undefined;
+ this._description = undefined;
+ }
+
+ // Static
+
+ static parseHeaders(valueString = "")
+ {
+ // https://w3c.github.io/server-timing/#the-server-timing-header-field
+ function trimLeadingWhiteSpace() {
+ valueString = valueString.trimStart();
+ }
+
+ function consumeDelimiter(char) {
+ console.assert(char.length === 1);
+ trimLeadingWhiteSpace();
+ if (valueString.charAt(0) !== char)
+ return false;
+
+ valueString = valueString.substring(1);
+ return true;
+ }
+
+ function consumeToken() {
+ // https://tools.ietf.org/html/rfc7230#appendix-B
+ let result = /^(?:\s*)([\w!#$%&'*+\-.^`|~]+)(?:\s*)(.*)/.exec(valueString);
+ if (!result)
+ return null;
+
+ valueString = result[2];
+ return result[1];
+ }
+
+ function consumeTokenOrQuotedString() {
+ trimLeadingWhiteSpace();
+ if (valueString.charAt(0) === "\"")
+ return consumeQuotedString();
+
+ return consumeToken();
+ }
+
+ function consumeQuotedString() {
+ // https://tools.ietf.org/html/rfc7230#section-3.2.6
+ console.assert(valueString.charAt(0) === "\"");
+
+ // Consume the leading DQUOTE.
+ valueString = valueString.substring(1);
+
+ let unescapedValueString = "";
+ for (let i = 0; i < valueString.length; ++i) {
+ let char = valueString.charAt(i);
+ switch (char) {
+ case "\\":
+ // Backslash character found, ignore it.
+ ++i;
+ if (i < valueString.length) {
+ // Take the character after the backslash.
+ unescapedValueString += valueString.charAt(i);
+ }
+ break;
+ case "\"":
+ // Trailing DQUOTE.
+ valueString = valueString.substring(i + 1);
+ return unescapedValueString;
+ default:
+ unescapedValueString += char;
+ break;
+ }
+ }
+
+ // No trailing DQUOTE found, this was not a valid quoted-string. Consume the entire string to complete parsing.
+ valueString = "";
+ return null;
+ }
+
+ function consumeExtraneous() {
+ let result = /([,;].*)/.exec(valueString);
+ if (result)
+ valueString = result[1];
+ }
+
+ function getParserForParameter(paramName) {
+ switch (paramName) {
+ case "dur":
+ return function(paramValue, entry) {
+ if (paramValue !== null) {
+ let duration = parseFloat(paramValue);
+ if (!isNaN(duration)) {
+ entry.duration = duration;
+ return;
+ }
+ }
+ entry.duration = 0;
+ };
+
+ case "desc":
+ return function(paramValue, entry) {
+ entry.description = paramValue || "";
+ };
+
+ default:
+ return null;
+ }
+ }
+
+ let entries = [];
+ let name;
+ while ((name = consumeToken()) !== null) {
+ let entry = new WI.ServerTimingEntry(name);
+
+ while (consumeDelimiter(";")) {
+ let paramName;
+ if ((paramName = consumeToken()) === null)
+ continue;
+
+ paramName = paramName.toLowerCase();
+ let parseParameter = getParserForParameter(paramName);
+ let paramValue = null;
+ if (consumeDelimiter("=")) {
+ // Always parse the value, even if we don't recognize the parameter name.
+ paramValue = consumeTokenOrQuotedString();
+ consumeExtraneous();
+ }
+
+ if (parseParameter)
+ parseParameter(paramValue, entry);
+ else
+ console.warn("Unknown Server-Timing parameter:", paramName, paramValue)
+ }
+
+ entries.push(entry);
+ if (!consumeDelimiter(","))
+ break;
+ }
+
+ return entries;
+ }
+
+ // Public
+
+ get name() { return this._name; }
+ get duration() { return this._duration; }
+ get description() { return this._description; }
+
+ set duration(duration)
+ {
+ if (this._duration !== undefined) {
+ console.warn("Ignoring redundant duration.");
+ return;
+ }
+
+ this._duration = duration;
+ }
+
+ set description(description)
+ {
+ if (this._description !== undefined) {
+ console.warn("Ignoring redundant description.");
+ return;
+ }
+
+ this._description = description;
+ }
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (237150 => 237151)
--- trunk/Source/WebInspectorUI/UserInterface/Test.html 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html 2018-10-15 23:10:20 UTC (rev 237151)
@@ -185,6 +185,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js (237150 => 237151)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js 2018-10-15 22:51:45 UTC (rev 237150)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js 2018-10-15 23:10:20 UTC (rev 237151)
@@ -97,11 +97,48 @@
return row;
}
+ _appendServerTimingRow(label, duration, maxDuration)
+ {
+ let row = this._tableElement.appendChild(document.createElement("tr"));
+
+ let labelCell = row.appendChild(document.createElement("td"));
+ labelCell.className = "label";
+ labelCell.textContent = label;
+
+ // We need to allow duration to be zero.
+ if (duration !== undefined) {
+ let graphWidth = (duration / maxDuration) * 100;
+ let graphCell = row.appendChild(document.createElement("td"));
+ graphCell.className = "graph";
+
+ let block = graphCell.appendChild(document.createElement("div"));
+ // FIXME: Provide unique colors for the different ServerTiming rows based on the label/order.
+ block.classList.add("block", "response");
+ block.style.width = graphWidth + "%";
+ block.style.right = 0;
+
+ let timeCell = row.appendChild(document.createElement("td"));
+ timeCell.className = "time";
+ // Convert duration from milliseconds to seconds.
+ timeCell.textContent = Number.secondsToMillisecondsString(duration / 1000);
+ }
+
+ return row;
+ }
+
+ _appendDividerRow()
+ {
+ let emptyCell = this._appendEmptyRow().appendChild(document.createElement("td"));
+ emptyCell.colSpan = 3;
+ emptyCell.appendChild(document.createElement("hr"));
+ }
+
initialLayout()
{
super.initialLayout();
let {startTime, redirectStart, redirectEnd, fetchStart, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = this._resource.timingData;
+ let serverTiming = this._resource.serverTiming;
this._tableElement = this.element.appendChild(document.createElement("table"));
this._tableElement.className = "waterfall";
@@ -139,5 +176,19 @@
this._appendHeaderRow(WI.UIString("Totals:"));
this._appendHeaderRow(WI.UIString("Time to First Byte"), Number.secondsToMillisecondsString(responseStart - startTime), "total-row");
this._appendHeaderRow(WI.UIString("Start to Finish"), Number.secondsToMillisecondsString(responseEnd - startTime), "total-row");
+
+ if (serverTiming.length > 0) {
+ this._appendDividerRow()
+ this._appendHeaderRow(WI.UIString("Server Timing:"));
+
+ let maxDuration = serverTiming.reduce((max, {duration = 0}) => Math.max(max, duration), 0);
+
+ for (let entry of serverTiming) {
+ let {name, duration, description} = entry;
+
+ // For the label, prefer description over name.
+ this._appendServerTimingRow(description || name, duration, maxDuration);
+ }
+ }
}
};
_______________________________________________ webkit-changes mailing list webkit-changes@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-changes