Web Inspector: Doesn't show size of compressed content correctly
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Apr 2017 01:30:24 +0000 (01:30 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Apr 2017 01:30:24 +0000 (01:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155112
<rdar://problem/25006728>

Reviewed by Alex Christensen and Timothy Hatcher.

Source/JavaScriptCore:

* inspector/protocol/Network.json:
New, exact size metrics, available after the load completes.

Source/WebCore:

Tests: http/tests/inspector/network/resource-sizes-disk-cache.html
       http/tests/inspector/network/resource-sizes-memory-cache.html
       http/tests/inspector/network/resource-sizes-network.html

* inspector/InspectorNetworkAgent.cpp:
(WebCore::InspectorNetworkAgent::buildObjectForMetrics):
* platform/network/NetworkLoadMetrics.h:
(WebCore::NetworkLoadMetrics::isolatedCopy):
(WebCore::NetworkLoadMetrics::reset):
(WebCore::NetworkLoadMetrics::clearNonTimingData):
(WebCore::NetworkLoadMetrics::operator==):
(WebCore::NetworkLoadMetrics::encode):
(WebCore::NetworkLoadMetrics::decode):
* platform/spi/cf/CFNetworkSPI.h:

Source/WebInspectorUI:

* UserInterface/Controllers/FrameResourceManager.js:
(WebInspector.FrameResourceManager.prototype.resourceRequestWasServedFromMemoryCache):
Set an exact size.

* UserInterface/Models/Resource.js:
(WebInspector.Resource):
(WebInspector.Resource.prototype.get requestHeadersTransferSize):
(WebInspector.Resource.prototype.get requestBodyTransferSize):
(WebInspector.Resource.prototype.get responseHeadersTransferSize):
(WebInspector.Resource.prototype.get responseBodyTransferSize):
(WebInspector.Resource.prototype.get cachedResponseBodySize):
(WebInspector.Resource.prototype.get size):
(WebInspector.Resource.prototype.get networkEncodedSize):
(WebInspector.Resource.prototype.get networkDecodedSize):
(WebInspector.Resource.prototype.get networkTotalTransferSize):
(WebInspector.Resource.prototype.get estimatedNetworkEncodedSize):
(WebInspector.Resource.prototype.get estimatedTotalTransferSize):
(WebInspector.Resource.prototype.get compressed):
(WebInspector.Resource.prototype.updateForResponse):
(WebInspector.Resource.prototype.updateWithMetrics):
(WebInspector.Resource.prototype.setCachedResponseBodySize):
(WebInspector.Resource.prototype.increaseSize):
(WebInspector.Resource.prototype.increaseTransferSize):
(WebInspector.Resource.prototype.get encodedSize): Deleted.
(WebInspector.Resource.prototype.get transferSize): Deleted.
Be more explicit with size getters.

(WebInspector.Resource.prototype.updateWithMetrics):
If we receive the size metrics, update the specific metric values.

* UserInterface/Views/ResourceDetailsSidebarPanel.js:
(WebInspector.ResourceDetailsSidebarPanel.prototype._refreshCompressed):
(WebInspector.ResourceDetailsSidebarPanel.prototype._refreshDecodedSize):
(WebInspector.ResourceDetailsSidebarPanel.prototype._refreshTransferSize):
* UserInterface/Views/ResourceTimelineDataGridNode.js:
(WebInspector.ResourceTimelineDataGridNode.prototype.get data):
Show exact values if we have them, otherwise fall back to the calculated
values during loading.

Source/WebKit2:

* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::sendResultForCacheEntry):
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:task:didFinishCollectingMetrics:]):
Include size information in network load metrics.

LayoutTests:

* http/tests/inspector/network/resource-sizes-disk-cache-expected.txt: Added.
* http/tests/inspector/network/resource-sizes-disk-cache.html: Added.
* http/tests/inspector/network/resource-sizes-memory-cache-expected.txt: Added.
* http/tests/inspector/network/resource-sizes-memory-cache.html: Added.
* http/tests/inspector/network/resource-sizes-network-expected.txt: Added.
* http/tests/inspector/network/resource-sizes-network.html: Added.
Test resource sizes under different load conditions.

* platform/mac/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt: Added.
* platform/mac/http/tests/inspector/network/resource-sizes-network-expected.txt: Added.
Older versions of macOS will not have the new metrics, but test their output anyways.

* http/tests/inspector/network/resources/404.php: Added.
* http/tests/inspector/network/resources/gzipped-lorem-no-content-length.php: Added.
* http/tests/inspector/network/resources/gzipped-lorem.php: Added.
* http/tests/inspector/network/resources/lorem.txt: Added.
Different resources with fixed sizes (text, gzipped, 404 with fixed response).

* http/tests/inspector/network/resources/resource-size-test.js: Added.
(TestPage.registerInitializer.InspectorTest.gracefulExpectEquals):
(TestPage.registerInitializer.window.addResourceSizeTest):
(TestPage.registerInitializer):
Shared test code for resource sizes.

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

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215445 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/network/resource-sizes-disk-cache-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resource-sizes-disk-cache.html [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resource-sizes-memory-cache.html [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resource-sizes-network-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resource-sizes-network.html [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resources/404.php [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resources/gzipped-lorem-no-content-length.php [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resources/gzipped-lorem.php [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resources/lorem.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/network/resources/resource-size-test.js [new file with mode: 0644]
LayoutTests/platform/mac-wk1/TestExpectations
LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-network-expected.txt [new file with mode: 0644]
LayoutTests/platform/win/TestExpectations
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/Network.json
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorNetworkAgent.cpp
Source/WebCore/platform/network/NetworkLoadMetrics.h
Source/WebCore/platform/spi/cf/CFNetworkSPI.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js
Source/WebInspectorUI/UserInterface/Models/Resource.js
Source/WebInspectorUI/UserInterface/Views/ResourceDetailsSidebarPanel.js
Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp
Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm

index 661c834..36a1a7d 100644 (file)
@@ -1,3 +1,38 @@
+2017-04-17  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Doesn't show size of compressed content correctly
+        https://bugs.webkit.org/show_bug.cgi?id=155112
+        <rdar://problem/25006728>
+
+        Reviewed by Alex Christensen and Timothy Hatcher.
+
+        * http/tests/inspector/network/resource-sizes-disk-cache-expected.txt: Added.
+        * http/tests/inspector/network/resource-sizes-disk-cache.html: Added.
+        * http/tests/inspector/network/resource-sizes-memory-cache-expected.txt: Added.
+        * http/tests/inspector/network/resource-sizes-memory-cache.html: Added.
+        * http/tests/inspector/network/resource-sizes-network-expected.txt: Added.
+        * http/tests/inspector/network/resource-sizes-network.html: Added.
+        Test resource sizes under different load conditions.
+
+        * platform/mac/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt: Added.
+        * platform/mac/http/tests/inspector/network/resource-sizes-network-expected.txt: Added.
+        Older versions of macOS will not have the new metrics, but test their output anyways.
+
+        * http/tests/inspector/network/resources/404.php: Added.
+        * http/tests/inspector/network/resources/gzipped-lorem-no-content-length.php: Added.
+        * http/tests/inspector/network/resources/gzipped-lorem.php: Added.
+        * http/tests/inspector/network/resources/lorem.txt: Added.
+        Different resources with fixed sizes (text, gzipped, 404 with fixed response).
+
+        * http/tests/inspector/network/resources/resource-size-test.js: Added.
+        (TestPage.registerInitializer.InspectorTest.gracefulExpectEquals):
+        (TestPage.registerInitializer.window.addResourceSizeTest):
+        (TestPage.registerInitializer):
+        Shared test code for resource sizes.
+
+        * platform/mac-wk1/TestExpectations:
+        * platform/win/TestExpectations:
+
 2017-04-17  Youenn Fablet  <youenn@apple.com>
 
         Enable video autoplay when getUserMedia is on
diff --git a/LayoutTests/http/tests/inspector/network/resource-sizes-disk-cache-expected.txt b/LayoutTests/http/tests/inspector/network/resource-sizes-disk-cache-expected.txt
new file mode 100644 (file)
index 0000000..8ee2710
--- /dev/null
@@ -0,0 +1,20 @@
+Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served from the disk cache.
+
+
+== Running test suite: Resource.Size.DiskCache
+-- Running test setup.
+-- Running test case: PossibleNetworkLoad
+-- Running test case: Resource.Size.DiskCache.Basic
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(disk-cache).
+PASS: estimatedNetworkEncodedSize should be exactly 0 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 12940 bytes.
+PASS: networkEncodedSize should be exactly 0 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 0 bytes.
+PASS: requestHeadersTransferSize should be empty.
+PASS: responseHeadersTransferSize should be empty.
+
diff --git a/LayoutTests/http/tests/inspector/network/resource-sizes-disk-cache.html b/LayoutTests/http/tests/inspector/network/resource-sizes-disk-cache.html
new file mode 100644 (file)
index 0000000..75094cb
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="resources/cached-script.js"></script>
+<script src="../resources/inspector-test.js"></script>
+<script src="resources/resource-size-test.js"></script>
+<script>
+function loadAndTriggerInspector(url) {
+    fetch(url).then(() => {
+        TestPage.dispatchEventToFrontend("LoadComplete");
+    });
+}
+
+function triggerNetworkLoad() {
+    loadAndTriggerInspector("/resources/square100.png");
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Resource.Size.DiskCache");
+
+    suite.addTestCase({
+        name: "PossibleNetworkLoad",
+        description: "Load a resource from the network, it might be in an earlier disk cache",
+        setup(resolve) { InspectorTest.evaluateInPage(`internals.clearMemoryCache()`, resolve); },
+        test(resolve, reject) {
+            InspectorTest.evaluateInPage(`triggerNetworkLoad()`);
+            InspectorTest.awaitEvent("LoadComplete").then(resolve, reject);
+        }
+    })
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.DiskCache.Basic",
+        description: "Sizes of a disk cached image resource with no validation",
+        url: "/resources/square100.png",
+        statusCode: 200,
+        compressed: false,
+        responseSource: WebInspector.Resource.ResponseSource.DiskCache,
+        headers: false,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 0,
+        size: 12940,
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served from the disk cache.</p>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt b/LayoutTests/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt
new file mode 100644 (file)
index 0000000..1623ba6
--- /dev/null
@@ -0,0 +1,18 @@
+Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served from the memory cache.
+
+
+== Running test suite: Resource.Size.MemoryCache
+-- Running test case: Resource.Size.MemoryCache.Basic
+PASS: statusCode should be 304.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(memory-cache).
+PASS: estimatedNetworkEncodedSize should be exactly 0 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 27 bytes.
+PASS: networkEncodedSize should be exactly 0 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 0 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+
diff --git a/LayoutTests/http/tests/inspector/network/resource-sizes-memory-cache.html b/LayoutTests/http/tests/inspector/network/resource-sizes-memory-cache.html
new file mode 100644 (file)
index 0000000..5a76525
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="resources/cached-script.js"></script>
+<script src="../resources/inspector-test.js"></script>
+<script src="resources/resource-size-test.js"></script>
+<script>
+TestPage.dispatchEventToFrontend("LoadComplete");
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Resource.Size.MemoryCache");
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.MemoryCache.Basic",
+        description: "Sizes of a cached script resource with a validation request",
+        statusCode: 304,
+        compressed: false,
+        responseSource: WebInspector.Resource.ResponseSource.MemoryCache,
+        headers: true,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 0,
+        size: 27,
+        resourceLoader() {
+            const ignoreCache = false;
+            const pattern = /cached-script\.js$/;
+            InspectorTest.reloadPage(ignoreCache);
+            return InspectorTest.awaitEvent("LoadComplete").then((event) => {
+                let resource = null;
+                for (let item of WebInspector.frameResourceManager.mainFrame.resourceCollection.items) {
+                    if (pattern.test(item.url)) {
+                        resource = item;
+                        break;
+                    }
+                }
+                if (!resource) {
+                    InspectorTest.fail("Failed to find specific resource.");
+                    throw "Fail";
+                }
+                return resource;
+            });
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served from the memory cache.</p>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/inspector/network/resource-sizes-network-expected.txt b/LayoutTests/http/tests/inspector/network/resource-sizes-network-expected.txt
new file mode 100644 (file)
index 0000000..a00e044
--- /dev/null
@@ -0,0 +1,89 @@
+Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served over the network.
+
+
+== Running test suite: Resource.Size.Network
+-- Running test case: Resource.Size.Network.text
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 2955 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 2955 bytes.
+PASS: networkEncodedSize should be exactly 2955 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 2955 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+
+-- Running test case: Resource.Size.Network.text.gzipped
+PASS: statusCode should be 200.
+PASS: compressed should be true.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 1229 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 2955 bytes.
+PASS: networkEncodedSize should be exactly 1229 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 1229 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+
+-- Running test case: Resource.Size.Network.text.gzipped.no-content-length
+PASS: statusCode should be 200.
+PASS: compressed should be true.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 1229 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 2955 bytes.
+PASS: networkEncodedSize should be exactly 1229 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 1229 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+
+-- Running test case: Resource.Size.Network.image
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 12940 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 12940 bytes.
+PASS: networkEncodedSize should be exactly 12940 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 12940 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+
+-- Running test case: Resource.Size.Network.404
+PASS: statusCode should be 404.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 512 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 512 bytes.
+PASS: networkEncodedSize should be exactly 512 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 0 bytes.
+PASS: responseBodyTransferSize should be exactly 512 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+
+-- Running test case: Resource.Size.Network.requestData
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 28 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 28 bytes.
+PASS: networkEncodedSize should be exactly 28 bytes.
+PASS: networkTotalTransferSize should be >= (encoded body size + headers).
+PASS: requestBodyTransferSize should be exactly 1027 bytes.
+PASS: responseBodyTransferSize should be exactly 28 bytes.
+PASS: requestHeadersTransferSize should be non-empty.
+PASS: responseHeadersTransferSize should be non-empty.
+PASS: requestHeadersTransferSize should be > 1060 bytes.
+
diff --git a/LayoutTests/http/tests/inspector/network/resource-sizes-network.html b/LayoutTests/http/tests/inspector/network/resource-sizes-network.html
new file mode 100644 (file)
index 0000000..f579cfd
--- /dev/null
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../resources/inspector-test.js"></script>
+<script src="resources/resource-size-test.js"></script>
+<script>
+function triggerNetworkLoadWithRequestData() {
+    let url = "resources/data.json?" + Math.random();
+    let headerString512Bytes = "12345678";
+    for (i = 0; i < 6; ++i)
+        headerString512Bytes += headerString512Bytes;
+
+    fetch(url, {
+        method: "POST",
+        headers: {
+            "X-Header-1": headerString512Bytes, // 512 + 10 + ":" + "\r\n" whitespace
+            "X-Header-2": headerString512Bytes, // 512 + 10 + ":" + "\r\n" whitespace
+        },
+        body: headerString512Bytes + headerString512Bytes + "abc" // (512 + 512 + 3) = 1027.
+    }).then(() => {
+        TestPage.dispatchEventToFrontend("LoadComplete");
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Resource.Size.Network");
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.Network.text",
+        description: "Sizes of a plain text resource",
+        url: "resources/lorem.txt?" + Math.random(),
+        statusCode: 200,
+        compressed: false,
+        responseSource: WebInspector.Resource.ResponseSource.Network,
+        headers: true,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 2955,
+        size: 2955,
+    });
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.Network.text.gzipped",
+        description: "Sizes of a gzipped text resource",
+        url: "resources/gzipped-lorem.php?" + Math.random(),
+        statusCode: 200,
+        compressed: true,
+        responseSource: WebInspector.Resource.ResponseSource.Network,
+        headers: true,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 1229,
+        size: 2955,
+    });
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.Network.text.gzipped.no-content-length",
+        description: "Sizes of a gzipped text resource without a content-length attribute.",
+        url: "resources/gzipped-lorem-no-content-length.php?" + Math.random(),
+        statusCode: 200,
+        compressed: true,
+        responseSource: WebInspector.Resource.ResponseSource.Network,
+        headers: true,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 1229,
+        size: 2955,
+    });
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.Network.image",
+        description: "Sizes of an image resource",
+        url: "/resources/square100.png?" + Math.random(),
+        statusCode: 200,
+        compressed: false,
+        responseSource: WebInspector.Resource.ResponseSource.Network,
+        headers: true,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 12940,
+        size: 12940,
+    });
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.Network.404",
+        description: "Sizes of a 404 response.",
+        url: "resources/404.php?" + Math.random(),
+        statusCode: 404,
+        compressed: false,
+        responseSource: WebInspector.Resource.ResponseSource.Network,
+        headers: true,
+        requestBodyTransferSize: 0,
+        responseBodyTransferSize: 512,
+        size: 512,
+    });
+
+    addResourceSizeTest(suite, {
+        name: "Resource.Size.Network.requestData",
+        description: "Sizes of a resource with request data",
+        statusCode: 200,
+        compressed: false,
+        responseSource: WebInspector.Resource.ResponseSource.Network,
+        headers: true,
+        requestBodyTransferSize: 1027,
+        responseBodyTransferSize: 28,
+        size: 28,
+        resourceLoader() {
+            InspectorTest.evaluateInPage(`triggerNetworkLoadWithRequestData()`);
+            return Promise.all([
+                WebInspector.Frame.awaitEvent(WebInspector.Frame.Event.ResourceWasAdded),
+                InspectorTest.awaitEvent("LoadComplete"),
+            ]).then(([resourceWasAddedEvent, loadCompleteEvent]) => {
+                return resourceWasAddedEvent.data.resource;
+            });
+        },
+        extraChecks(resource) {
+            let minimumRequestHeadersSize = 512 + 10 + 512 + 10 + 16;
+            InspectorTest.expectGreaterThan(resource.requestHeadersTransferSize, minimumRequestHeadersSize, `requestHeadersTransferSize should be > ${minimumRequestHeadersSize} bytes.`);
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served over the network.</p>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/inspector/network/resources/404.php b/LayoutTests/http/tests/inspector/network/resources/404.php
new file mode 100644 (file)
index 0000000..ac612fa
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+header("HTTP/1.1 404 Not Found");
+
+# Non-empty response.
+$str = "12345678";
+for ($i = 0; $i < 6; ++$i)
+    $str .= $str;
+echo $str;
+
+?>
diff --git a/LayoutTests/http/tests/inspector/network/resources/gzipped-lorem-no-content-length.php b/LayoutTests/http/tests/inspector/network/resources/gzipped-lorem-no-content-length.php
new file mode 100644 (file)
index 0000000..1702f66
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+$text = file_get_contents("./lorem.txt");
+$gzipText = gzencode($text, 6);
+
+header("Content-Type: text/plain");
+header("Content-Encoding: gzip");
+flush(); // Send headers without Content-Length.
+
+echo $gzipText;
+?>
diff --git a/LayoutTests/http/tests/inspector/network/resources/gzipped-lorem.php b/LayoutTests/http/tests/inspector/network/resources/gzipped-lorem.php
new file mode 100644 (file)
index 0000000..e4e368d
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+$text = file_get_contents("./lorem.txt");
+$gzipText = gzencode($text, 6);
+
+header("Content-Type: text/plain");
+header("Content-Encoding: gzip");
+header("Content-Length: " . strlen($gzipText));
+
+echo $gzipText;
+?>
diff --git a/LayoutTests/http/tests/inspector/network/resources/lorem.txt b/LayoutTests/http/tests/inspector/network/resources/lorem.txt
new file mode 100644 (file)
index 0000000..3608380
--- /dev/null
@@ -0,0 +1,9 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a luctus justo, a placerat est. Vestibulum a venenatis lectus. Phasellus vehicula neque id est semper, ac congue felis commodo. Suspendisse potenti. Nam eget placerat erat. Nulla ultricies consequat eros ac vestibulum. Aliquam imperdiet massa augue, nec faucibus nisi semper ac. Ut nibh nisl, iaculis id mattis sit amet, ultricies sed eros. Vivamus vel mi ante. Praesent commodo finibus justo, sed hendrerit urna convallis eget. Maecenas condimentum mi elit, eu gravida eros consequat at. Nulla rutrum lorem neque, ut finibus metus posuere non. Quisque nulla justo, scelerisque sed ornare eu, aliquet id est. Ut at ornare dui.
+
+In ipsum nisl, luctus sed rhoncus vitae, euismod vel neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec eu faucibus turpis. Duis tempus commodo neque, eu lobortis risus faucibus a. Cras massa leo, tristique eu diam vel, hendrerit pellentesque ex. Donec dapibus quam ut sodales rhoncus. Vivamus mollis ornare est. Suspendisse et dapibus enim, in viverra eros.
+
+Integer commodo nisl ac nisl suscipit feugiat. Mauris pharetra, tellus id aliquam consectetur, quam nisi lobortis mi, id sagittis sem risus at nisi. Donec venenatis maximus finibus. Nullam laoreet arcu vitae lacus bibendum accumsan. Fusce in leo et lacus ornare venenatis. Aliquam odio nulla, convallis non ornare quis, facilisis eget ex. In sed nibh dapibus, scelerisque elit eget, egestas justo. Nulla et dolor dapibus, scelerisque risus quis, consectetur neque. Aliquam quis quam mi. Nulla lacus justo, lacinia eu tortor eget, convallis faucibus risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
+
+Sed fermentum vehicula augue, at sollicitudin quam consequat sit amet. Sed condimentum nec mauris et rhoncus. Aliquam euismod urna vestibulum, iaculis lectus non, sagittis urna. Cras vitae sodales quam. Aliquam ligula tortor, suscipit at lobortis et, venenatis vitae arcu. Phasellus tempor nulla id mauris interdum pellentesque. Maecenas dignissim leo ipsum, sed maximus lectus suscipit sit amet. Suspendisse et nulla in sem condimentum venenatis semper a neque. Cras ac imperdiet arcu. Aliquam et ex eu elit iaculis ornare at et metus. Quisque rhoncus tristique ligula ullamcorper mollis.
+
+Curabitur pretium, dolor vel feugiat sodales, quam ipsum lobortis leo, vel dapibus felis diam a tellus. Integer accumsan maximus lorem. Vestibulum finibus posuere orci a convallis. Ut eu hendrerit nibh. Suspendisse varius ut ex ac aliquam. Morbi nec tellus sed arcu viverra interdum vitae quis lacus. In sodales nisl at tortor blandit, eget gravida libero lacinia. Cras at leo libero. Aenean tempor hendrerit commodo. Cras in lacinia erat. Vestibulum vitae interdum purus, ut luctus tellus. Nulla mauris massa, auctor sed enim efficitur, varius lobortis mauris. Fusce sit amet massa a ante facilisis sagittis.
diff --git a/LayoutTests/http/tests/inspector/network/resources/resource-size-test.js b/LayoutTests/http/tests/inspector/network/resources/resource-size-test.js
new file mode 100644 (file)
index 0000000..8fcd5fa
--- /dev/null
@@ -0,0 +1,101 @@
+TestPage.registerInitializer(function() {
+
+    // For values expected to be zero, avoid logging the actual value if it non-zero
+    // as that may be different across implementations and could produce dynamic
+    // failing results. If the expected value is non-zero test it normally.
+    InspectorTest.gracefulExpectEquals = function(actual, expected, property, message)
+    {
+        if (!expected) {
+            if (actual === expected)
+                InspectorTest.pass(`${property} should be exactly 0 bytes.`);
+            else
+                InspectorTest.fail(`${property} should be exactly 0 bytes.`);
+        } else
+            InspectorTest.expectEqual(actual, expected, message);
+    }
+
+    // Request headers should at least include a UserAgent.
+    // Response headers should at least include a Content-Type.
+    const minimumHeadersSize = 20;
+
+    // Parameters:
+    //   - debug: dump metrics if set.
+    //   - url: if using the default resource loader this is the url to fetch()
+    //   - resourceLoader: provides a resource to test, must return a promise
+    //   - statusCode: expected resource status code value
+    //   - compressed: expected resource compressed value
+    //   - responseSource: expected resource response source to ensure test is testing the load type it expects
+    //   - headers: whether or not headers are expected
+    //   - requestBodyTransferSize, responseBodyTransferSize: exact body transfer sizes
+    //   - size: exact decoded body size whether or not there was anything transferred
+    //   - extraChecks: extra checks to perform
+    window.addResourceSizeTest = function(suite, {name, description, debug, url, statusCode, compressed, responseSource, headers, requestBodyTransferSize, responseBodyTransferSize, size, resourceLoader, extraChecks}) {
+        suite.addTestCase({
+            name, description,
+            test(resolve, reject) {
+                let promise;
+                if (resourceLoader)
+                    promise = resourceLoader();
+                else {
+                    InspectorTest.evaluateInPage(`fetch(${JSON.stringify(url)})`);
+                    promise = Promise.all([
+                        WebInspector.Frame.awaitEvent(WebInspector.Frame.Event.ResourceWasAdded),
+                        WebInspector.Resource.awaitEvent(WebInspector.Resource.Event.LoadingDidFinish),
+                    ]).then(([resourceWasAddedEvent, loadCompleteEvent]) => {
+                        return resourceWasAddedEvent.data.resource;
+                    });
+                }
+
+                promise.then((resource) => {
+                    InspectorTest.assert(resource instanceof WebInspector.Resource, "Resource should be created.");
+                    InspectorTest.expectEqual(resource.statusCode, statusCode, `statusCode should be ${statusCode}.`);
+                    InspectorTest.expectEqual(resource.compressed, compressed, `compressed should be ${compressed}.`);
+                    InspectorTest.expectEqual(resource.responseSource, responseSource, `responseSource should be ${String(responseSource)}.`);
+
+                    if (debug) {
+                        InspectorTest.log("----");
+                        InspectorTest.log("resource.requestHeadersTransferSize: " + resource.requestHeadersTransferSize);
+                        InspectorTest.log("resource.responseHeadersTransferSize: " + resource.responseHeadersTransferSize);
+                        InspectorTest.log("resource.requestBodyTransferSize: " + resource.requestBodyTransferSize);
+                        InspectorTest.log("resource.responseBodyTransferSize: " + resource.responseBodyTransferSize);
+                        InspectorTest.log("resource.cachedResponseBodySize: " + resource.cachedResponseBodySize);
+                        InspectorTest.log("----");
+                        InspectorTest.log("resource.size: " + resource.size);
+                        InspectorTest.log("resource.networkEncodedSize: " + resource.networkEncodedSize);
+                        InspectorTest.log("resource.networkDecodedSize: " + resource.networkDecodedSize);
+                        InspectorTest.log("resource.networkTotalTransferSize: " + resource.networkTotalTransferSize);
+                        InspectorTest.log("resource.estimatedNetworkEncodedSize: " + resource.estimatedNetworkEncodedSize);
+                        InspectorTest.log("resource.estimatedTotalTransferSize: " + resource.estimatedTotalTransferSize);
+                        InspectorTest.log("----");
+                    }
+
+                    // Calculated values. Try to be graceful, if the size is expected to be zero but is non-zero don't log the actual value.
+                    InspectorTest.gracefulExpectEquals(resource.estimatedNetworkEncodedSize, responseBodyTransferSize, "estimatedNetworkEncodedSize", `estimatedNetworkEncodedSize should be exactly ${responseBodyTransferSize} bytes.`);
+                    InspectorTest.expectGreaterThanOrEqual(resource.estimatedTotalTransferSize, responseBodyTransferSize + (headers ? minimumHeadersSize : 0), `estimatedTotalTransferSize should be >= (encoded body size + headers).`);
+
+                    // Exact decoded size should always be available.
+                    InspectorTest.gracefulExpectEquals(resource.size, size, "size", `size should be exactly ${size} bytes.`);
+
+                    // Exact transfer sizes if available.
+                    InspectorTest.expectEqual(resource.networkEncodedSize, responseBodyTransferSize, `networkEncodedSize should be exactly ${responseBodyTransferSize} bytes.`);
+                    InspectorTest.expectGreaterThanOrEqual(resource.networkTotalTransferSize, responseBodyTransferSize + (headers ? minimumHeadersSize : 0), `networkTotalTransferSize should be >= (encoded body size + headers).`);
+                    InspectorTest.expectEqual(resource.requestBodyTransferSize, requestBodyTransferSize, `requestBodyTransferSize should be exactly ${requestBodyTransferSize} bytes.`);
+                    InspectorTest.expectEqual(resource.responseBodyTransferSize, responseBodyTransferSize, `responseBodyTransferSize should be exactly ${responseBodyTransferSize} bytes.`);
+
+                    // Exact header sizes if available. May vary between implementations so we check if empty / non-empty.
+                    if (headers) {
+                        InspectorTest.expectGreaterThan(resource.requestHeadersTransferSize, minimumHeadersSize, `requestHeadersTransferSize should be non-empty.`);
+                        InspectorTest.expectGreaterThan(resource.responseHeadersTransferSize, minimumHeadersSize, `responseHeadersTransferSize should be non-empty.`);
+                    } else {
+                        InspectorTest.expectEqual(resource.requestHeadersTransferSize, 0, `requestHeadersTransferSize should be empty.`);
+                        InspectorTest.expectEqual(resource.responseHeadersTransferSize, 0, `responseHeadersTransferSize should be empty.`);
+                    }
+
+                    // Test may include extra checks.
+                    if (extraChecks)
+                        extraChecks(resource);
+                }).then(resolve, reject);
+            }
+        });
+    }
+});
index 0848bfa..59014b2 100644 (file)
@@ -152,6 +152,7 @@ compositing/iframes/overlapped-nested-iframes.html [ Pass Failure ]
 # Disk cache is WK2 only
 http/tests/cache/disk-cache
 http/tests/inspector/network/resource-response-source-disk-cache.html
+http/tests/inspector/network/resource-sizes-disk-cache.html
 
 [ Yosemite+ ] fast/ruby/ruby-expansion-cjk-2.html [ ImageOnlyFailure ]
 
@@ -306,11 +307,9 @@ webkit.org/b/163361 imported/w3c/web-platform-tests/html/webappapis/animation-fr
 webkit.org/b/163361 imported/w3c/web-platform-tests/html/webappapis/animation-frames/callback-invoked.html [ Pass Failure ]
 webkit.org/b/163361 imported/w3c/web-platform-tests/html/webappapis/animation-frames/callback-multicalls.html [ Pass Failure ]
 
-# Resource Timing networking data not yet available in WebKit1.
+# Resource Metrics data not available in WebKit1.
 imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [ Failure ]
 imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [ Failure ]
-
-# Request Header information only available in WebKit2
 http/tests/inspector/network/resource-request-headers.html [ Failure ]
 
 webkit.org/b/164491 [ Yosemite ElCapitan ] fast/visual-viewport/rtl-zoomed-rects.html [ Failure ]
diff --git a/LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt b/LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-memory-cache-expected.txt
new file mode 100644 (file)
index 0000000..4c93417
--- /dev/null
@@ -0,0 +1,30 @@
+Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served from the memory cache.
+
+
+== Running test suite: Resource.Size.MemoryCache
+-- Running test case: Resource.Size.MemoryCache.Basic
+PASS: statusCode should be 304.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(memory-cache).
+PASS: estimatedNetworkEncodedSize should be exactly 0 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 27 bytes.
+FAIL: networkEncodedSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 20
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+
diff --git a/LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-network-expected.txt b/LayoutTests/platform/mac/http/tests/inspector/network/resource-sizes-network-expected.txt
new file mode 100644 (file)
index 0000000..dcd2214
--- /dev/null
@@ -0,0 +1,165 @@
+Test for Resource size values (transfer size, decoded size, header size, request and response) for resources served over the network.
+
+
+== Running test suite: Resource.Size.Network
+-- Running test case: Resource.Size.Network.text
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 2955 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 2955 bytes.
+FAIL: networkEncodedSize should be exactly 2955 bytes.
+    Expected: 2955
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 2975
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 2955 bytes.
+    Expected: 2955
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+
+-- Running test case: Resource.Size.Network.text.gzipped
+PASS: statusCode should be 200.
+PASS: compressed should be true.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 1229 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 2955 bytes.
+FAIL: networkEncodedSize should be exactly 1229 bytes.
+    Expected: 1229
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 1249
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 1229 bytes.
+    Expected: 1229
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+
+-- Running test case: Resource.Size.Network.text.gzipped.no-content-length
+PASS: statusCode should be 200.
+PASS: compressed should be true.
+PASS: responseSource should be Symbol(network).
+FAIL: estimatedNetworkEncodedSize should be exactly 1229 bytes.
+    Expected: 1229
+    Actual: 2955
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 2955 bytes.
+FAIL: networkEncodedSize should be exactly 1229 bytes.
+    Expected: 1229
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 1249
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 1229 bytes.
+    Expected: 1229
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+
+-- Running test case: Resource.Size.Network.image
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 12940 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 12940 bytes.
+FAIL: networkEncodedSize should be exactly 12940 bytes.
+    Expected: 12940
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 12960
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 12940 bytes.
+    Expected: 12940
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+
+-- Running test case: Resource.Size.Network.404
+PASS: statusCode should be 404.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 512 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 512 bytes.
+FAIL: networkEncodedSize should be exactly 512 bytes.
+    Expected: 512
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 532
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 0 bytes.
+    Expected: 0
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 512 bytes.
+    Expected: 512
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+
+-- Running test case: Resource.Size.Network.requestData
+PASS: statusCode should be 200.
+PASS: compressed should be false.
+PASS: responseSource should be Symbol(network).
+PASS: estimatedNetworkEncodedSize should be exactly 28 bytes.
+PASS: estimatedTotalTransferSize should be >= (encoded body size + headers).
+PASS: size should be exactly 28 bytes.
+FAIL: networkEncodedSize should be exactly 28 bytes.
+    Expected: 28
+    Actual: NaN
+FAIL: networkTotalTransferSize should be >= (encoded body size + headers).
+    Expected: greater than or equal to 48
+    Actual: NaN
+FAIL: requestBodyTransferSize should be exactly 1027 bytes.
+    Expected: 1027
+    Actual: NaN
+FAIL: responseBodyTransferSize should be exactly 28 bytes.
+    Expected: 28
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: responseHeadersTransferSize should be non-empty.
+    Expected: greater than 20
+    Actual: NaN
+FAIL: requestHeadersTransferSize should be > 1060 bytes.
+    Expected: greater than 1060
+    Actual: NaN
+
index 7d22069..705fe84 100644 (file)
@@ -3791,7 +3791,7 @@ fast/layers/prevent-hit-test-during-layout.html [ Skip ]
 imported/w3c/web-platform-tests/webrtc [ Skip ]
 webrtc [ Skip ]
 
-# Resource Timing networking data not yet available.
+# Resource Timing Metrics not available.
 imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [ Failure ]
 imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [ Failure ]
 
index 569348f..8f29464 100644 (file)
@@ -1,3 +1,14 @@
+2017-04-17  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Doesn't show size of compressed content correctly
+        https://bugs.webkit.org/show_bug.cgi?id=155112
+        <rdar://problem/25006728>
+
+        Reviewed by Alex Christensen and Timothy Hatcher.
+
+        * inspector/protocol/Network.json:
+        New, exact size metrics, available after the load completes.
+
 2017-04-17  Youenn Fablet  <youenn@apple.com>
 
         Disable outdated WritableStream API
index 27db94e..cbbc605 100644 (file)
                 { "name": "priority", "type": "string", "enum": ["low", "medium", "high"], "optional": true, "description": "Network priority." },
                 { "name": "connectionIdentifier", "type": "string", "optional": true, "description": "Connection identifier." },
                 { "name": "remoteAddress", "type": "string", "optional": true, "description": "Remote IP address." },
-                { "name": "requestHeaders", "$ref": "Headers", "optional": true, "description": "Refined HTTP request headers that were actually transmitted over the network." }
+                { "name": "requestHeaders", "$ref": "Headers", "optional": true, "description": "Refined HTTP request headers that were actually transmitted over the network." },
+                { "name": "requestHeaderBytesSent", "type": "number", "optional": true, "description": "Total HTTP request header bytes sent over the network." },
+                { "name": "requestBodyBytesSent", "type": "number", "optional": true, "description": "Total HTTP request body bytes sent over the network." },
+                { "name": "responseHeaderBytesReceived", "type": "number", "optional": true, "description": "Total HTTP response header bytes received over the network." },
+                { "name": "responseBodyBytesReceived", "type": "number", "optional": true, "description": "Total HTTP response body bytes received over the network." },
+                { "name": "responseBodyDecodedSize", "type": "number", "optional": true, "description": "Total decoded response body size in bytes." }
             ]
         },
         {
index 33021d1..04cc370 100644 (file)
@@ -1,3 +1,26 @@
+2017-04-17  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Doesn't show size of compressed content correctly
+        https://bugs.webkit.org/show_bug.cgi?id=155112
+        <rdar://problem/25006728>
+
+        Reviewed by Alex Christensen and Timothy Hatcher.
+
+        Tests: http/tests/inspector/network/resource-sizes-disk-cache.html
+               http/tests/inspector/network/resource-sizes-memory-cache.html
+               http/tests/inspector/network/resource-sizes-network.html
+
+        * inspector/InspectorNetworkAgent.cpp:
+        (WebCore::InspectorNetworkAgent::buildObjectForMetrics):
+        * platform/network/NetworkLoadMetrics.h:
+        (WebCore::NetworkLoadMetrics::isolatedCopy):
+        (WebCore::NetworkLoadMetrics::reset):
+        (WebCore::NetworkLoadMetrics::clearNonTimingData):
+        (WebCore::NetworkLoadMetrics::operator==):
+        (WebCore::NetworkLoadMetrics::encode):
+        (WebCore::NetworkLoadMetrics::decode):
+        * platform/spi/cf/CFNetworkSPI.h:
+
 2017-04-17  Youenn Fablet  <youenn@apple.com>
 
         Enable video autoplay when getUserMedia is on
index fd6a940..99271ec 100644 (file)
@@ -226,6 +226,17 @@ Ref<Inspector::Protocol::Network::Metrics> InspectorNetworkAgent::buildObjectFor
     if (networkLoadMetrics.requestHeaders)
         metrics->setRequestHeaders(buildObjectForHeaders(*networkLoadMetrics.requestHeaders));
 
+    if (networkLoadMetrics.requestHeaderBytesSent)
+        metrics->setRequestHeaderBytesSent(*networkLoadMetrics.requestHeaderBytesSent);
+    if (networkLoadMetrics.requestBodyBytesSent)
+        metrics->setRequestBodyBytesSent(*networkLoadMetrics.requestBodyBytesSent);
+    if (networkLoadMetrics.responseHeaderBytesReceived)
+        metrics->setResponseHeaderBytesReceived(*networkLoadMetrics.responseHeaderBytesReceived);
+    if (networkLoadMetrics.responseBodyBytesReceived)
+        metrics->setResponseBodyBytesReceived(*networkLoadMetrics.responseBodyBytesReceived);
+    if (networkLoadMetrics.responseBodyDecodedSize)
+        metrics->setResponseBodyDecodedSize(*networkLoadMetrics.responseBodyDecodedSize);
+
     return metrics;
 }
 
index 67aa707..6a52652 100644 (file)
@@ -76,6 +76,12 @@ public:
         if (requestHeaders)
             copy.requestHeaders = requestHeaders.value().isolatedCopy();
 
+        copy.requestHeaderBytesSent = requestHeaderBytesSent;
+        copy.requestBodyBytesSent = requestBodyBytesSent;
+        copy.responseHeaderBytesReceived = responseHeaderBytesReceived;
+        copy.responseBodyBytesReceived = responseBodyBytesReceived;
+        copy.responseBodyDecodedSize = responseBodyDecodedSize;
+
         return copy;
     }
 
@@ -95,6 +101,11 @@ public:
         connectionIdentifier = std::nullopt;
         priority = std::nullopt;
         requestHeaders = std::nullopt;
+        requestHeaderBytesSent = std::nullopt;
+        requestBodyBytesSent = std::nullopt;
+        responseHeaderBytesReceived = std::nullopt;
+        responseBodyBytesReceived = std::nullopt;
+        responseBodyDecodedSize = std::nullopt;
     }
 
     void clearNonTimingData()
@@ -103,6 +114,11 @@ public:
         connectionIdentifier = std::nullopt;
         priority = std::nullopt;
         requestHeaders = std::nullopt;
+        requestHeaderBytesSent = std::nullopt;
+        requestBodyBytesSent = std::nullopt;
+        responseHeaderBytesReceived = std::nullopt;
+        responseBodyBytesReceived = std::nullopt;
+        responseBodyDecodedSize = std::nullopt;
     }
 
     bool operator==(const NetworkLoadMetrics& other) const
@@ -120,7 +136,12 @@ public:
             && remoteAddress == other.remoteAddress
             && connectionIdentifier == other.connectionIdentifier
             && priority == other.priority
-            && requestHeaders == other.requestHeaders;
+            && requestHeaders == other.requestHeaders
+            && requestHeaderBytesSent == other.requestHeaderBytesSent
+            && requestBodyBytesSent == other.requestBodyBytesSent
+            && responseHeaderBytesReceived == other.responseHeaderBytesReceived
+            && responseBodyBytesReceived == other.responseBodyBytesReceived
+            && responseBodyDecodedSize == other.responseBodyDecodedSize;
     }
 
     bool operator!=(const NetworkLoadMetrics& other) const
@@ -155,6 +176,12 @@ public:
     std::optional<String> connectionIdentifier;
     std::optional<NetworkLoadPriority> priority;
     std::optional<HTTPHeaderMap> requestHeaders;
+
+    std::optional<uint64_t> requestHeaderBytesSent;
+    std::optional<uint64_t> requestBodyBytesSent;
+    std::optional<uint64_t> responseHeaderBytesReceived;
+    std::optional<uint64_t> responseBodyBytesReceived;
+    std::optional<uint64_t> responseBodyDecodedSize;
 };
 
 #if PLATFORM(COCOA)
@@ -182,6 +209,11 @@ void NetworkLoadMetrics::encode(Encoder& encoder) const
     encoder << connectionIdentifier;
     encoder << priority;
     encoder << requestHeaders;
+    encoder << requestHeaderBytesSent;
+    encoder << requestBodyBytesSent;
+    encoder << responseHeaderBytesReceived;
+    encoder << responseBodyBytesReceived;
+    encoder << responseBodyDecodedSize;
 }
 
 template<class Decoder>
@@ -200,7 +232,12 @@ bool NetworkLoadMetrics::decode(Decoder& decoder, NetworkLoadMetrics& metrics)
         && decoder.decode(metrics.remoteAddress)
         && decoder.decode(metrics.connectionIdentifier)
         && decoder.decode(metrics.priority)
-        && decoder.decode(metrics.requestHeaders);
+        && decoder.decode(metrics.requestHeaders)
+        && decoder.decode(metrics.requestHeaderBytesSent)
+        && decoder.decode(metrics.requestBodyBytesSent)
+        && decoder.decode(metrics.responseHeaderBytesReceived)
+        && decoder.decode(metrics.responseBodyBytesReceived)
+        && decoder.decode(metrics.responseBodyDecodedSize);
 }
 
 } // namespace WebCore
index e34c4e4..51caa5f 100644 (file)
@@ -125,6 +125,10 @@ typedef void (^CFCachedURLResponseCallBackBlock)(CFCachedURLResponseRef);
 @interface NSURLSessionTaskTransactionMetrics ()
 @property (copy, readonly) NSString* _remoteAddressAndPort;
 @property (copy, readonly) NSUUID* _connectionIdentifier;
+@property (assign, readonly) NSInteger _requestHeaderBytesSent;
+@property (assign, readonly) NSInteger _responseHeaderBytesReceived;
+@property (assign, readonly) int64_t _responseBodyBytesReceived;
+@property (assign, readonly) int64_t _responseBodyBytesDecoded;
 @end
 #endif
 
index cad6a25..d98d726 100644 (file)
@@ -1,3 +1,50 @@
+2017-04-17  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Doesn't show size of compressed content correctly
+        https://bugs.webkit.org/show_bug.cgi?id=155112
+        <rdar://problem/25006728>
+
+        Reviewed by Alex Christensen and Timothy Hatcher.
+
+        * UserInterface/Controllers/FrameResourceManager.js:
+        (WebInspector.FrameResourceManager.prototype.resourceRequestWasServedFromMemoryCache):
+        Set an exact size.
+
+        * UserInterface/Models/Resource.js:
+        (WebInspector.Resource):
+        (WebInspector.Resource.prototype.get requestHeadersTransferSize):
+        (WebInspector.Resource.prototype.get requestBodyTransferSize):
+        (WebInspector.Resource.prototype.get responseHeadersTransferSize):
+        (WebInspector.Resource.prototype.get responseBodyTransferSize):
+        (WebInspector.Resource.prototype.get cachedResponseBodySize):
+        (WebInspector.Resource.prototype.get size):
+        (WebInspector.Resource.prototype.get networkEncodedSize):
+        (WebInspector.Resource.prototype.get networkDecodedSize):
+        (WebInspector.Resource.prototype.get networkTotalTransferSize):
+        (WebInspector.Resource.prototype.get estimatedNetworkEncodedSize):
+        (WebInspector.Resource.prototype.get estimatedTotalTransferSize):
+        (WebInspector.Resource.prototype.get compressed):
+        (WebInspector.Resource.prototype.updateForResponse):
+        (WebInspector.Resource.prototype.updateWithMetrics):
+        (WebInspector.Resource.prototype.setCachedResponseBodySize):
+        (WebInspector.Resource.prototype.increaseSize):
+        (WebInspector.Resource.prototype.increaseTransferSize):
+        (WebInspector.Resource.prototype.get encodedSize): Deleted.
+        (WebInspector.Resource.prototype.get transferSize): Deleted.
+        Be more explicit with size getters.
+
+        (WebInspector.Resource.prototype.updateWithMetrics):
+        If we receive the size metrics, update the specific metric values.
+
+        * UserInterface/Views/ResourceDetailsSidebarPanel.js:
+        (WebInspector.ResourceDetailsSidebarPanel.prototype._refreshCompressed):
+        (WebInspector.ResourceDetailsSidebarPanel.prototype._refreshDecodedSize):
+        (WebInspector.ResourceDetailsSidebarPanel.prototype._refreshTransferSize):
+        * UserInterface/Views/ResourceTimelineDataGridNode.js:
+        (WebInspector.ResourceTimelineDataGridNode.prototype.get data):
+        Show exact values if we have them, otherwise fall back to the calculated
+        values during loading.
+
 2017-04-17  Jon Davis  <jond@apple.com>
 
         Web Inspector: new icon for Disable Caches button in Network Tab
index 8857b9d..83a93b9 100644 (file)
@@ -334,6 +334,7 @@ WebInspector.FrameResourceManager = class FrameResourceManager extends WebInspec
         resource.updateForResponse(cachedResourcePayload.url, response.mimeType, cachedResourcePayload.type, response.headers, response.status, response.statusText, elapsedTime, response.timing, responseSource);
         resource.increaseSize(cachedResourcePayload.bodySize, elapsedTime);
         resource.increaseTransferSize(cachedResourcePayload.bodySize);
+        resource.setCachedResponseBodySize(cachedResourcePayload.bodySize);
         resource.markAsFinished(elapsedTime);
 
         console.assert(resource.cached, "This resource should be classified as cached since it was served from the MemoryCache", resource);
index 4067810..5250c3f 100644 (file)
@@ -58,9 +58,8 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
         this._finishThenRequestContentPromise = null;
         this._statusCode = NaN;
         this._statusText = null;
-        this._size = NaN;
-        this._transferSize = NaN;
         this._cached = false;
+        this._receivedNetworkLoadMetrics = false;
         this._responseSource = WebInspector.Resource.ResponseSource.Unknown;
         this._timingData = new WebInspector.ResourceTimingData(this);
         this._protocol = null;
@@ -69,6 +68,19 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
         this._connectionIdentifier = null;
         this._target = targetId ? WebInspector.targetManager.targetForIdentifier(targetId) : WebInspector.mainTarget;
 
+        // Exact sizes if loaded over the network or cache.
+        this._requestHeadersTransferSize = NaN;
+        this._requestBodyTransferSize = NaN;
+        this._responseHeadersTransferSize = NaN;
+        this._responseBodyTransferSize = NaN;
+        this._responseBodySize = NaN;
+        this._cachedResponseBodySize = NaN;
+
+        // Estimated sizes (if backend does not provide metrics).
+        this._estimatedSize = NaN;
+        this._estimatedTransferSize = NaN;
+        this._estimatedResponseHeadersSize = NaN;
+
         if (this._initiatorSourceCodeLocation && this._initiatorSourceCodeLocation.sourceCode instanceof WebInspector.Resource)
             this._initiatorSourceCodeLocation.sourceCode.addInitiatedResource(this);
     }
@@ -432,15 +444,59 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
         return this._cached;
     }
 
+    get requestHeadersTransferSize() { return this._requestHeadersTransferSize; }
+    get requestBodyTransferSize() { return this._requestBodyTransferSize; }
+    get responseHeadersTransferSize() { return this._responseHeadersTransferSize; }
+    get responseBodyTransferSize() { return this._responseBodyTransferSize; }
+    get cachedResponseBodySize() { return this._cachedResponseBodySize; }
+
     get size()
     {
-        return this._size;
+        if (!isNaN(this._cachedResponseBodySize))
+            return this._cachedResponseBodySize;
+
+        if (!isNaN(this._responseBodySize) && this._responseBodySize !== 0)
+            return this._responseBodySize;
+
+        return this._estimatedSize;
+    }
+
+    get networkEncodedSize()
+    {
+        return this._responseBodyTransferSize;
     }
 
-    get encodedSize()
+    get networkDecodedSize()
     {
-        if (!isNaN(this._transferSize))
-            return this._transferSize;
+        return this._responseBodySize;
+    }
+
+    get networkTotalTransferSize()
+    {
+        return this._responseHeadersTransferSize + this._responseBodyTransferSize;
+    }
+
+    get estimatedNetworkEncodedSize()
+    {
+        let exact = this.networkEncodedSize; 
+        if (!isNaN(exact))
+            return exact;
+
+        if (this._cached)
+            return 0;
+
+        // FIXME: <https://webkit.org/b/158463> Network: Correctly report encoded data length (transfer size) from CFNetwork to NetworkResourceLoader
+        // macOS provides the decoded transfer size instead of the encoded size
+        // for estimatedTransferSize. So prefer the "Content-Length" property
+        // on mac if it is available.
+        if (WebInspector.Platform.name === "mac") {
+            let contentLength = Number(this._responseHeaders.valueForCaseInsensitiveKey("Content-Length"));
+            if (!isNaN(contentLength))
+                return contentLength;
+        }
+
+        if (!isNaN(this._estimatedTransferSize))
+            return this._estimatedTransferSize;
 
         // If we did not receive actual transfer size from network
         // stack, we prefer using Content-Length over resourceSize as
@@ -453,24 +509,28 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
         // work for chunks with non-trivial encodings. We need a way to
         // get actual transfer size from the network stack.
 
-        return Number(this._responseHeaders.valueForCaseInsensitiveKey("Content-Length") || this._size);
+        return Number(this._responseHeaders.valueForCaseInsensitiveKey("Content-Length") || this._estimatedSize);
     }
 
-    get transferSize()
+    get estimatedTotalTransferSize()
     {
+        let exact = this.networkTotalTransferSize;
+        if (!isNaN(exact))
+            return exact;
+
         if (this.statusCode === 304) // Not modified
-            return this._responseHeadersSize;
+            return this._estimatedResponseHeadersSize;
 
         if (this._cached)
             return 0;
 
-        return this._responseHeadersSize + this.encodedSize;
+        return this._estimatedResponseHeadersSize + this.estimatedNetworkEncodedSize;
     }
 
     get compressed()
     {
-        var contentEncoding = this._responseHeaders.valueForCaseInsensitiveKey("Content-Encoding");
-        return contentEncoding && /\b(?:gzip|deflate)\b/.test(contentEncoding);
+        let contentEncoding = this._responseHeaders.valueForCaseInsensitiveKey("Content-Encoding");
+        return !!(contentEncoding && /\b(?:gzip|deflate)\b/.test(contentEncoding));
     }
 
     get scripts()
@@ -554,9 +614,11 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
         if (source)
             this._responseSource = WebInspector.Resource.responseSourceFromPayload(source);
 
-        this._responseHeadersSize = String(this._statusCode).length + this._statusText.length + 12; // Extra length is for "HTTP/1.1 ", " ", and "\r\n".
+        const headerBaseSize = 12; // Length of "HTTP/1.1 ", " ", and "\r\n".
+        const headerPad = 4; // Length of ": " and "\r\n".
+        this._estimatedResponseHeadersSize = String(this._statusCode).length + this._statusText.length + headerBaseSize;
         for (let name in this._responseHeaders)
-            this._responseHeadersSize += name.length + this._responseHeaders[name].length + 4; // Extra length is for ": ", and "\r\n".
+            this._estimatedResponseHeadersSize += name.length + this._responseHeaders[name].length + headerPad;
 
         if (!this._cached) {
             if (statusCode === 304 || (this._responseSource === WebInspector.Resource.ResponseSource.MemoryCache || this._responseSource === WebInspector.Resource.ResponseSource.DiskCache))
@@ -580,8 +642,8 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
         if (oldType !== type)
             this.dispatchEventToListeners(WebInspector.Resource.Event.TypeDidChange, {oldType});
 
-        console.assert(isNaN(this._size));
-        console.assert(isNaN(this._transferSize));
+        console.assert(isNaN(this._estimatedSize));
+        console.assert(isNaN(this._estimatedTransferSize));
 
         // The transferSize becomes 0 when status is 304 or Content-Length is available, so
         // notify listeners of that change.
@@ -594,6 +656,8 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
 
     updateWithMetrics(metrics)
     {
+        this._receivedNetworkLoadMetrics = true;
+
         if (metrics.protocol)
             this._protocol = metrics.protocol;
         if (metrics.priority)
@@ -606,6 +670,32 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
             this._requestHeaders = metrics.requestHeaders;
             this.dispatchEventToListeners(WebInspector.Resource.Event.RequestHeadersDidChange);
         }
+
+        if ("requestHeaderBytesSent" in metrics) {
+            this._requestHeadersTransferSize = metrics.requestHeaderBytesSent;
+            this._requestBodyTransferSize = metrics.requestBodyBytesSent;
+            this._responseHeadersTransferSize = metrics.responseHeaderBytesReceived;
+            this._responseBodyTransferSize = metrics.responseBodyBytesReceived;
+            this._responseBodySize = metrics.responseBodyDecodedSize;
+
+            console.assert(this._requestHeadersTransferSize >= 0);
+            console.assert(this._requestBodyTransferSize >= 0);
+            console.assert(this._responseHeadersTransferSize >= 0);
+            console.assert(this._responseBodyTransferSize >= 0);
+            console.assert(this._responseBodySize >= 0);
+
+            this.dispatchEventToListeners(WebInspector.Resource.Event.SizeDidChange, {previousSize: this._estimatedSize});
+            this.dispatchEventToListeners(WebInspector.Resource.Event.TransferSizeDidChange);
+        }
+    }
+
+    setCachedResponseBodySize(size)
+    {
+        console.assert(!isNaN(size), "Size should be a valid number.")
+        console.assert(isNaN(this._cachedResponseBodySize), "This should only be set once.");
+        console.assert(this._estimatedSize === size, "The legacy path was updated already and matches.");
+
+        this._cachedResponseBodySize = size;
     }
 
     requestContentFromBackend()
@@ -625,30 +715,32 @@ WebInspector.Resource = class Resource extends WebInspector.SourceCode
     increaseSize(dataLength, elapsedTime)
     {
         console.assert(dataLength >= 0);
+        console.assert(!this._receivedNetworkLoadMetrics, "If we received metrics we don't need to change the estimated size.");
 
-        if (isNaN(this._size))
-            this._size = 0;
+        if (isNaN(this._estimatedSize))
+            this._estimatedSize = 0;
 
-        var previousSize = this._size;
+        let previousSize = this._estimatedSize;
 
-        this._size += dataLength;
+        this._estimatedSize += dataLength;
 
         this._lastDataReceivedTimestamp = elapsedTime || NaN;
 
         this.dispatchEventToListeners(WebInspector.Resource.Event.SizeDidChange, {previousSize});
 
-        // The transferSize is based off of size when status is not 304 or Content-Length is missing.
-        if (isNaN(this._transferSize) && this._statusCode !== 304 && !this._responseHeaders.valueForCaseInsensitiveKey("Content-Length"))
+        // The estimatedTransferSize is based off of size when status is not 304 or Content-Length is missing.
+        if (isNaN(this._estimatedTransferSize) && this._statusCode !== 304 && !this._responseHeaders.valueForCaseInsensitiveKey("Content-Length"))
             this.dispatchEventToListeners(WebInspector.Resource.Event.TransferSizeDidChange);
     }
 
     increaseTransferSize(encodedDataLength)
     {
         console.assert(encodedDataLength >= 0);
+        console.assert(!this._receivedNetworkLoadMetrics, "If we received metrics we don't need to change the estimated transfer size.");
 
-        if (isNaN(this._transferSize))
-            this._transferSize = 0;
-        this._transferSize += encodedDataLength;
+        if (isNaN(this._estimatedTransferSize))
+            this._estimatedTransferSize = 0;
+        this._estimatedTransferSize += encodedDataLength;
 
         this.dispatchEventToListeners(WebInspector.Resource.Event.TransferSizeDidChange);
     }
index 1b64061..66d65b5 100644 (file)
@@ -342,8 +342,18 @@ WebInspector.ResourceDetailsSidebarPanel = class ResourceDetailsSidebarPanel ext
 
     _refreshCompressed()
     {
-        this._compressedRow.value = this._resource.compressed ? WebInspector.UIString("Yes") : WebInspector.UIString("No");
-        this._compressionRow.value = this._resource.compressed ? WebInspector.UIString("%.2f\u00d7").format(this._resource.size / this._resource.encodedSize) : null;
+        if (this._resource.compressed) {
+            this._compressedRow.value = WebInspector.UIString("Yes");
+            if (!this._resource.size)
+                this._compressionRow.value = emDash;
+            else if (!isNaN(this._resource.networkEncodedSize))
+                this._compressionRow.value = this._resource.networkEncodedSize ? WebInspector.UIString("%.2f\u00d7").format(this._resource.size / this._resource.networkEncodedSize) : emDash;
+            else
+                this._compressionRow.value = this._resource.estimatedNetworkEncodedSize ? WebInspector.UIString("%.2f\u00d7").format(this._resource.size / this._resource.estimatedNetworkEncodedSize) : emDash;
+        } else {
+            this._compressedRow.value = WebInspector.UIString("No");
+            this._compressionRow.value = null;
+        }
     }
 
     _refreshDecodedSize()
@@ -351,8 +361,11 @@ WebInspector.ResourceDetailsSidebarPanel = class ResourceDetailsSidebarPanel ext
         if (!this._resource)
             return;
 
-        this._encodedSizeRow.value = this._valueForSize(this._resource.encodedSize);
-        this._decodedSizeRow.value = this._valueForSize(this._resource.size);
+        let encodedSize = !isNaN(this._resource.networkEncodedSize) ? this._resource.networkEncodedSize : this._resource.estimatedNetworkEncodedSize;
+        let decodedSize = !isNaN(this._resource.networkDecodedSize) ? this._resource.networkDecodedSize : this._resource.size;
+
+        this._encodedSizeRow.value = this._valueForSize(encodedSize);
+        this._decodedSizeRow.value = this._valueForSize(decodedSize);
 
         this._refreshCompressed();
     }
@@ -362,8 +375,11 @@ WebInspector.ResourceDetailsSidebarPanel = class ResourceDetailsSidebarPanel ext
         if (!this._resource)
             return;
 
-        this._encodedSizeRow.value = this._valueForSize(this._resource.encodedSize);
-        this._transferSizeRow.value = this._valueForSize(this._resource.transferSize);
+        let encodedSize = !isNaN(this._resource.networkEncodedSize) ? this._resource.networkEncodedSize : this._resource.estimatedNetworkEncodedSize;
+        let transferSize = !isNaN(this._resource.networkTotalTransferSize) ? this._resource.networkTotalTransferSize : this._resource.estimatedTotalTransferSize;
+
+        this._encodedSizeRow.value = this._valueForSize(encodedSize);
+        this._transferSizeRow.value = this._valueForSize(transferSize);
 
         this._refreshCompressed();
     }
index bf6eb18..d0c2457 100644 (file)
@@ -76,7 +76,7 @@ WebInspector.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode e
             data.statusCode = resource.statusCode;
             data.cached = resource.cached;
             data.size = resource.size;
-            data.transferSize = resource.transferSize;
+            data.transferSize = !isNaN(resource.networkTotalTransferSize) ? resource.networkTotalTransferSize : resource.estimatedTotalTransferSize;
             data.requestSent = resource.requestSentTimestamp - zeroTime;
             data.duration = resource.receiveDuration;
             data.latency = resource.latency;
index b34c351..7534c12 100644 (file)
@@ -1,3 +1,17 @@
+2017-04-17  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Doesn't show size of compressed content correctly
+        https://bugs.webkit.org/show_bug.cgi?id=155112
+        <rdar://problem/25006728>
+
+        Reviewed by Alex Christensen and Timothy Hatcher.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::sendResultForCacheEntry):
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:task:didFinishCollectingMetrics:]):
+        Include size information in network load metrics.
+
 2017-04-17  Youenn Fablet  <youenn@apple.com>
 
         com.apple.WebKit.Networking.Development crashed in com.apple.WebKit: WebKit::NetworkRTCProvider::resolvedName
index 8f7598d..a0df505 100644 (file)
@@ -620,6 +620,11 @@ void NetworkResourceLoader::sendResultForCacheEntry(std::unique_ptr<NetworkCache
 
     WebCore::NetworkLoadMetrics networkLoadMetrics;
     networkLoadMetrics.markComplete();
+    networkLoadMetrics.requestHeaderBytesSent = 0;
+    networkLoadMetrics.requestBodyBytesSent = 0;
+    networkLoadMetrics.responseHeaderBytesReceived = 0;
+    networkLoadMetrics.responseBodyBytesReceived = 0;
+    networkLoadMetrics.responseBodyDecodedSize = 0;
 
     sendBuffer(*entry->buffer(), entry->buffer()->size());
     send(Messages::WebResourceLoader::DidFinishResourceLoad(networkLoadMetrics));
index 53fc38a..f0c5c3c 100644 (file)
@@ -306,8 +306,7 @@ static WebCore::NetworkLoadPriority toNetworkLoadPriority(float priority)
 
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000)
             networkLoadMetrics.remoteAddress = String(m._remoteAddressAndPort);
-            if ([m respondsToSelector:@selector(_connectionIdentifier)])
-                networkLoadMetrics.connectionIdentifier = String([m._connectionIdentifier UUIDString]);
+            networkLoadMetrics.connectionIdentifier = String([m._connectionIdentifier UUIDString]);
 #endif
 
             __block WebCore::HTTPHeaderMap requestHeaders;
@@ -315,6 +314,26 @@ static WebCore::NetworkLoadPriority toNetworkLoadPriority(float priority)
                 requestHeaders.set(String(name), String(value));
             }];
             networkLoadMetrics.requestHeaders = WTFMove(requestHeaders);
+
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000)
+            uint64_t requestHeaderBytesSent = 0;
+            uint64_t responseHeaderBytesReceived = 0;
+            uint64_t responseBodyBytesReceived = 0;
+            uint64_t responseBodyDecodedSize = 0;
+
+            for (NSURLSessionTaskTransactionMetrics *transactionMetrics in metrics.transactionMetrics) {
+                requestHeaderBytesSent += transactionMetrics._requestHeaderBytesSent;
+                responseHeaderBytesReceived += transactionMetrics._responseHeaderBytesReceived;
+                responseBodyBytesReceived += transactionMetrics._responseBodyBytesReceived;
+                responseBodyDecodedSize += transactionMetrics._responseBodyBytesDecoded ? transactionMetrics._responseBodyBytesDecoded : transactionMetrics._responseBodyBytesReceived;
+            }
+
+            networkLoadMetrics.requestHeaderBytesSent = requestHeaderBytesSent;
+            networkLoadMetrics.requestBodyBytesSent = task.countOfBytesSent;
+            networkLoadMetrics.responseHeaderBytesReceived = responseHeaderBytesReceived;
+            networkLoadMetrics.responseBodyBytesReceived = responseBodyBytesReceived;
+            networkLoadMetrics.responseBodyDecodedSize = responseBodyDecodedSize;
+#endif
         }
     }
 }