[Resource Timing] Gather timing information with reliable responseEnd time
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 25 Feb 2017 05:48:51 +0000 (05:48 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 25 Feb 2017 05:48:51 +0000 (05:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=168351

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* web-platform-tests/fetch/api/redirect/redirect-count-cross-origin-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-count-cross-origin-worker-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-count-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-count-worker-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-location-expected.txt:
* web-platform-tests/fetch/api/redirect/redirect-location-worker-expected.txt:
New behavior for too many redirects caused by <rdar://problem/30610988>.

* web-platform-tests/resource-timing/rt-nextHopProtocol-expected.txt: Added.
* web-platform-tests/resource-timing/rt-nextHopProtocol.html: Added.
* web-platform-tests/resource-timing/rt-nextHopProtocol.js: Added.
* web-platform-tests/resource-timing/rt-nextHopProtocol.worker-expected.txt: Added.
* web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html: Added.
* web-platform-tests/resource-timing/rt-nextHopProtocol.worker.js: Added.
New tests specific to just checking the nextHopProtocol property with
a non-cached resource to avoid flakeyness.

Source/WebCore:

This patch replaces the unused `double finishTime` in ResourceLoader's
didFinishLoad with a complete WebCore::NetworkLoadMetrics object. This
allows the NetworkProcess to give complete timing information, and more
final metrics about the load, to WebCore. Currently this is only used
by ResourceTiming, but it will soon be used by Web Inspector as well.
We may also end up extending this to the didFail path as well, since it
is possible that we have some metrics for load failures.

At the same time we want to start moving away from the legacy path that
populated a subset of this information in ResourceResponse's NetworkLoadMetrics.
It doesn't make sense to store this information on the ResourceResponse
for a few reasons: We don't want to store the metrics in our Network Cache and
not all of the load timing metrics have been populated yet (responseEnd).
In an effort to move off of this data we've renamed the accessor to
"deprecatedNetworkLoadMetrics". There are a few remaining clients
(ResourceHandle, PerformanceTiming, InspectorNetworkAgent) which can be
migrated separately from this patch.

Having both the legacy and new code paths adds a little bit of complexity.
One advantage of the new path is that the complete load timing data
(fetchStart -> dns -> connect -> request -> response -> responseEnd) can
be packaged together. The legacy path could not include a responseEnd, so
WebCore faked that value with its own timestamp. Having the fake responseEnd
caused issues as timestamps / clocks are different between processes. In order
for PerformanceResponseTiming to know whether or not the NetworkLoadMetrics
has the complete network timing metrics it checks isComplete(). If true
it knows it can use the responseEnd time from NetworkLoadMetrics, otherwise
it must fallback to the legacy value from LoadTiming. Once all of the
deprecatedNetworkLoadMetrics clients go away, we should always have the
complete data and this can be eliminated.

Tests: imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html
       imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html

* PlatformMac.cmake:
* WebCore.xcodeproj/project.pbxproj:
Rename NetworkLoadTiming -> NetworkLoadMetrics.

* page/PerformanceResourceTiming.cpp:
(WebCore::entryStartTime):
(WebCore::entryEndTime):
(WebCore::PerformanceResourceTiming::PerformanceResourceTiming):
(WebCore::PerformanceResourceTiming::nextHopProtocol):
(WebCore::PerformanceResourceTiming::domainLookupStart):
(WebCore::PerformanceResourceTiming::domainLookupEnd):
(WebCore::PerformanceResourceTiming::connectStart):
(WebCore::PerformanceResourceTiming::connectEnd):
(WebCore::PerformanceResourceTiming::secureConnectionStart):
(WebCore::PerformanceResourceTiming::requestStart):
(WebCore::PerformanceResourceTiming::responseStart):
(WebCore::PerformanceResourceTiming::responseEnd):
(WebCore::PerformanceResourceTiming::networkLoadTimeToDOMHighResTimeStamp):
* page/PerformanceResourceTiming.h:
Mostly just updating names and types. This does however need to get the
correct endTime based on whether the NetworkLoadMetrics are complete
(meaning includes responseEnd) or not (legacy, use LoadTiming value).

* page/PerformanceResourceTiming.idl:
Add nextHopProtocol.

* page/PerformanceTiming.cpp:
(WebCore::PerformanceTiming::domainLookupStart):
(WebCore::PerformanceTiming::domainLookupEnd):
(WebCore::PerformanceTiming::connectStart):
(WebCore::PerformanceTiming::connectEnd):
(WebCore::PerformanceTiming::secureConnectionStart):
(WebCore::PerformanceTiming::requestStart):
(WebCore::PerformanceTiming::responseStart):
(WebCore::PerformanceTiming::resourceLoadTimeRelativeToFetchStart):
* page/PerformanceTiming.h:
Navigation Timing values still uses the NetworkLoadTiming values stored on
the DocumentLoader. This should be moved off of the deprecated path separately.

* platform/network/NetworkLoadMetrics.h: Renamed from Source/WebCore/platform/network/NetworkLoadTiming.h.
(WebCore::NetworkLoadMetrics::NetworkLoadMetrics):
(WebCore::NetworkLoadMetrics::isolatedCopy):
(WebCore::NetworkLoadMetrics::reset):
(WebCore::NetworkLoadMetrics::operator==):
(WebCore::NetworkLoadMetrics::operator!=):
(WebCore::NetworkLoadMetrics::isComplete):
(WebCore::NetworkLoadMetrics::markComplete):
(WebCore::NetworkLoadMetrics::encode):
(WebCore::NetworkLoadMetrics::decode):
Re-introduce a reset() method (for NetworkLoadSoup to reset between redirects).
Add protocolName and "complete" boolean.

* platform/network/cocoa/NetworkLoadMetrics.mm: Renamed from Source/WebCore/platform/network/cocoa/NetworkLoadTiming.mm.
(WebCore::timingValue):
(WebCore::copyTimingData):
(WebCore::setCollectsTimingData):
Use this opportunity to convert NetworkLoadTiming timestamps to WTF::Seconds.
Since we already have to modify all the clients this moves us to use the more
strongly typed units that are less ambiguous then "double". The rest of the
Performance API has already moved to these units.

* inspector/InspectorNetworkAgent.cpp:
(WebCore::InspectorNetworkAgent::buildObjectForTiming):
(WebCore::InspectorNetworkAgent::buildObjectForResourceResponse):
(WebCore::InspectorNetworkAgent::didFinishLoading):
* inspector/InspectorNetworkAgent.h:
Inspector was the only client of the finishTime, and since the value was
erratically coming from clients in different ways it was almost certainly
inaccurate. Simplify this in preparation for using NetworkLoadMetrics.

* Modules/fetch/FetchLoader.cpp:
(WebCore::FetchLoader::didFinishLoading):
* Modules/fetch/FetchLoader.h:
* fileapi/FileReaderLoader.cpp:
(WebCore::FileReaderLoader::didFinishLoading):
* fileapi/FileReaderLoader.h:
* html/MediaFragmentURIParser.cpp:
(WebCore::MediaFragmentURIParser::parseNPTTime):
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::didFinishLoadingImpl):
* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::didFinishLoading):
* loader/CrossOriginPreflightChecker.cpp:
(WebCore::CrossOriginPreflightChecker::validatePreflightResponse):
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::notifyFinished):
(WebCore::DocumentLoader::finishedLoading):
(WebCore::DocumentLoader::continueAfterContentPolicy):
(WebCore::DocumentLoader::maybeLoadEmpty):
* loader/DocumentLoader.h:
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::didReceiveResponse):
(WebCore::DocumentThreadableLoader::notifyFinished):
(WebCore::DocumentThreadableLoader::didFinishLoading):
(WebCore::DocumentThreadableLoader::loadRequest):
* loader/DocumentThreadableLoader.h:
* loader/NetscapePlugInStreamLoader.cpp:
(WebCore::NetscapePlugInStreamLoader::didFinishLoading):
* loader/NetscapePlugInStreamLoader.h:
* loader/ResourceLoadNotifier.cpp:
(WebCore::ResourceLoadNotifier::didFinishLoad):
(WebCore::ResourceLoadNotifier::dispatchDidFinishLoading):
(WebCore::ResourceLoadNotifier::sendRemainingDelegateMessages):
* loader/ResourceLoadNotifier.h:
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::deliverResponseAndData):
(WebCore::ResourceLoader::loadDataURL):
(WebCore::ResourceLoader::didFinishLoading):
(WebCore::ResourceLoader::didFinishLoadingOnePart):
* loader/ResourceLoader.h:
* loader/ResourceTiming.cpp:
(WebCore::ResourceTiming::fromLoad):
(WebCore::ResourceTiming::fromSynchronousLoad):
(WebCore::ResourceTiming::ResourceTiming):
(WebCore::ResourceTiming::isolatedCopy):
* loader/ResourceTiming.h:
(WebCore::ResourceTiming::networkLoadMetrics):
(WebCore::ResourceTiming::ResourceTiming):
(WebCore::ResourceTiming::networkLoadTiming): Deleted.
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::SubresourceLoader):
(WebCore::SubresourceLoader::willSendRequestInternal):
(WebCore::SubresourceLoader::didReceiveResponse):
(WebCore::SubresourceLoader::didFinishLoading):
(WebCore::SubresourceLoader::reportResourceTiming):
* loader/SubresourceLoader.h:
* loader/ThreadableLoaderClient.h:
(WebCore::ThreadableLoaderClient::didFinishLoading):
* loader/ThreadableLoaderClientWrapper.h:
(WebCore::ThreadableLoaderClientWrapper::didFinishLoading):
* loader/WorkerThreadableLoader.cpp:
(WebCore::WorkerThreadableLoader::MainThreadBridge::didFinishLoading):
* loader/WorkerThreadableLoader.h:
* loader/appcache/ApplicationCacheGroup.cpp:
(WebCore::ApplicationCacheGroup::didFinishLoading):
* loader/appcache/ApplicationCacheGroup.h:
* loader/cache/CachedResource.h:
(WebCore::CachedResource::setLoadFinishTime):
* loader/ios/QuickLook.mm:
(-[WebPreviewLoader connectionDidFinishLoading:]):
* page/EventSource.cpp:
(WebCore::EventSource::didFinishLoading):
* page/EventSource.h:
* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
(ResourceHandleStreamingClient::didFinishLoading):
* platform/network/BlobResourceHandle.cpp:
(WebCore::doNotifyFinish):
* platform/network/PingHandle.h:
* platform/network/ResourceHandle.h:
* platform/network/ResourceHandleClient.h:
(WebCore::ResourceHandleClient::didFinishLoading):
* platform/network/ResourceResponseBase.cpp:
(WebCore::ResourceResponseBase::crossThreadData):
(WebCore::ResourceResponseBase::fromCrossThreadData):
(WebCore::ResourceResponseBase::compare):
* platform/network/ResourceResponseBase.h:
(WebCore::ResourceResponseBase::deprecatedNetworkLoadMetrics):
(WebCore::ResourceResponseBase::encode):
(WebCore::ResourceResponseBase::decode):
(WebCore::ResourceResponseBase::networkLoadTiming): Deleted.
* platform/network/SynchronousLoaderClient.cpp:
(WebCore::SynchronousLoaderClient::didFinishLoading):
* platform/network/SynchronousLoaderClient.h:
* platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp:
(WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveResponse):
(WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading):
* platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
(WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse):
(WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading):
* platform/network/curl/ResourceHandleCurl.cpp:
(WebCore::WebCoreSynchronousLoader::didFinishLoading):
* platform/network/curl/ResourceHandleManager.cpp:
(WebCore::calculateWebTimingInformations):
(WebCore::ResourceHandleManager::downloadTimerCallback):
(WebCore::handleDataURL):
(WebCore::milisecondsSinceRequest): Deleted.
* platform/network/mac/ResourceHandleMac.mm:
(WebCore::ResourceHandle::getConnectionTimingData):
* platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
(-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]):
(-[WebCoreResourceHandleAsDelegate connectionDidFinishLoading:]):
* platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm:
(-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveResponse:]):
(-[WebCoreResourceHandleAsOperationQueueDelegate connectionDidFinishLoading:]):
* platform/network/soup/ResourceHandleSoup.cpp:
(WebCore::restartedCallback):
(WebCore::nextMultipartResponsePartCallback):
(WebCore::sendRequestCallback):
(WebCore::ResourceHandle::didStartRequest):
(WebCore::networkEventCallback):
(WebCore::ResourceHandle::sendPendingRequest):
(WebCore::readCallback):
(WebCore::milisecondsSinceRequest): Deleted.
* workers/WorkerScriptLoader.cpp:
(WebCore::WorkerScriptLoader::didFinishLoading):
* workers/WorkerScriptLoader.h:
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::didFinishLoading):
* xml/XMLHttpRequest.h:
Eliminate the unused finishTime double.

Source/WebKit2:

Change from an unused `double finishTime` to a complete WebCore::NetworkLoadMetrics
object in the didFinishLoad ResourceLoader path. We may also extend this in the
didFail path later on. This allows the NetworkProcess to give complete timing
information, and more final metrics about the load, to WebCore.

* NetworkProcess/NetworkDataTask.h:
(WebKit::NetworkDataTaskClient::didCompleteWithError):
Give the NetworkDataTaskClient a basic didCompleteWithError for a completion
without metrics. For loads that complete with an error, or haven't populated
any metrics, this will pass empty metrics onward.

* NetworkProcess/Downloads/BlobDownloadClient.cpp:
(WebKit::BlobDownloadClient::didFinishLoading):
* NetworkProcess/Downloads/BlobDownloadClient.h:
* NetworkProcess/Downloads/PendingDownload.h:
* NetworkProcess/PingLoad.h:
* NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp:
(WebKit::NetworkCache::SpeculativeLoad::didFinishLoading):
* NetworkProcess/cache/NetworkCacheSpeculativeLoad.h:
* NetworkProcess/NetworkDataTaskBlob.cpp:
(WebKit::NetworkDataTaskBlob::didFail):
* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::continueWillSendRequest):
(WebKit::NetworkLoad::didCompleteWithError):
(WebKit::NetworkLoad::didFinishLoading):
* NetworkProcess/NetworkLoad.h:
* NetworkProcess/NetworkLoadClient.h:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::didFinishLoading):
(WebKit::NetworkResourceLoader::sendResultForCacheEntry):
* NetworkProcess/NetworkResourceLoader.h:
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::didFinishResourceLoad):
(WebKit::WebResourceLoader::didReceiveResource):
* WebProcess/Network/WebResourceLoader.h:
* WebProcess/Network/WebResourceLoader.messages.in:
Change didFinishLoad paths to take a NetworkLoadMetrics object instead of finishTime.
Change didCompleteWithError pathes to include a NetworkLoadMetrics object instead of finishTime.

* NetworkProcess/cocoa/NetworkDataTaskCocoa.h:
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::didCompleteWithError):
Own a NetworkLoadTiming that will be populated with the load.

* NetworkProcess/cocoa/NetworkSessionCocoa.h:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
(-[WKNetworkSessionDelegate URLSession:task:didFinishCollectingMetrics:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
Populate NetworkLoadMetrics in the didFinishCollectingMetrics NSURLSessionTaskDelegate method.

* NetworkProcess/soup/NetworkDataTaskSoup.cpp:
(WebKit::NetworkDataTaskSoup::NetworkDataTaskSoup):
(WebKit::NetworkDataTaskSoup::timeoutFired):
(WebKit::NetworkDataTaskSoup::didSendRequest):
(WebKit::NetworkDataTaskSoup::dispatchDidReceiveResponse):
(WebKit::NetworkDataTaskSoup::dispatchDidCompleteWithError):
(WebKit::NetworkDataTaskSoup::tlsErrorsChanged):
(WebKit::NetworkDataTaskSoup::continueHTTPRedirection):
(WebKit::NetworkDataTaskSoup::didFinishRead):
(WebKit::NetworkDataTaskSoup::didFinishRequestNextPart):
(WebKit::NetworkDataTaskSoup::didFailDownload):
(WebKit::NetworkDataTaskSoup::didFail):
(WebKit::NetworkDataTaskSoup::networkEvent):
(WebKit::NetworkDataTaskSoup::didStartRequest):
(WebKit::NetworkDataTaskSoup::didRestart):
* NetworkProcess/soup/NetworkDataTaskSoup.h:
Instead of populating the NetworkLoadMetrics on the ResourceResponse, populate
a member variable during the entire load and dispatch didFinishCollectingMetrics
right before didCompleteLoadWithError.

Source/WTF:

* wtf/persistence/Coders.h:
(WTF::Persistence::Coder<Seconds>::encode):
(WTF::Persistence::Coder<Seconds>::decode):

LayoutTests:

* TestExpectations:
Now that nextHopProtocol is available on Mac mark the test as flakey
because the value can be set or not depending on whether or not the
resource was loaded from a cache.

* platform/ios-simulator/TestExpectations:
* platform/gtk/TestExpectations:
* platform/mac/TestExpectations:
* platform/win/TestExpectations:
Mark nextHopProtocol tests as expected to fail on ports that do not
yet support those values. Mark redirect tests as failing on ports
that encounter the CFNetwork issue causing unexpected callbacks.

* performance-api/resource-timing-apis-expected.txt:
* performance-api/resources/resource-timing-api.js:
Progressions.

* platform/mac-elcapitan/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt: Added.
* platform/mac/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt: Added.
Expected passing values on mac, except el capitan where this new resource timing data is unavailable.

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

107 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.js [new file with mode: 0644]
LayoutTests/performance-api/resource-timing-apis-expected.txt
LayoutTests/performance-api/resources/resource-timing-api.js
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/ios-simulator/TestExpectations
LayoutTests/platform/mac-elcapitan/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-wk1/TestExpectations
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/mac/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt [new file with mode: 0644]
LayoutTests/platform/win/TestExpectations
Source/WTF/ChangeLog
Source/WTF/wtf/persistence/Coders.h
Source/WebCore/ChangeLog
Source/WebCore/Modules/fetch/FetchLoader.cpp
Source/WebCore/Modules/fetch/FetchLoader.h
Source/WebCore/PlatformMac.cmake
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/fileapi/FileReaderLoader.cpp
Source/WebCore/fileapi/FileReaderLoader.h
Source/WebCore/html/MediaFragmentURIParser.cpp
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/InspectorNetworkAgent.cpp
Source/WebCore/inspector/InspectorNetworkAgent.h
Source/WebCore/loader/CrossOriginPreflightChecker.cpp
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebCore/loader/DocumentThreadableLoader.cpp
Source/WebCore/loader/DocumentThreadableLoader.h
Source/WebCore/loader/NetscapePlugInStreamLoader.cpp
Source/WebCore/loader/NetscapePlugInStreamLoader.h
Source/WebCore/loader/ResourceLoadNotifier.cpp
Source/WebCore/loader/ResourceLoadNotifier.h
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/loader/ResourceLoader.h
Source/WebCore/loader/ResourceTiming.cpp
Source/WebCore/loader/ResourceTiming.h
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/loader/SubresourceLoader.h
Source/WebCore/loader/ThreadableLoaderClient.h
Source/WebCore/loader/ThreadableLoaderClientWrapper.h
Source/WebCore/loader/WorkerThreadableLoader.cpp
Source/WebCore/loader/WorkerThreadableLoader.h
Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp
Source/WebCore/loader/appcache/ApplicationCacheGroup.h
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/ios/QuickLook.mm
Source/WebCore/page/EventSource.cpp
Source/WebCore/page/EventSource.h
Source/WebCore/page/PerformanceResourceTiming.cpp
Source/WebCore/page/PerformanceResourceTiming.h
Source/WebCore/page/PerformanceResourceTiming.idl
Source/WebCore/page/PerformanceTiming.cpp
Source/WebCore/page/PerformanceTiming.h
Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
Source/WebCore/platform/network/BlobResourceHandle.cpp
Source/WebCore/platform/network/NetworkLoadMetrics.h [moved from Source/WebCore/platform/network/NetworkLoadTiming.h with 51% similarity]
Source/WebCore/platform/network/PingHandle.h
Source/WebCore/platform/network/ResourceHandle.h
Source/WebCore/platform/network/ResourceHandleClient.h
Source/WebCore/platform/network/ResourceResponseBase.cpp
Source/WebCore/platform/network/ResourceResponseBase.h
Source/WebCore/platform/network/SynchronousLoaderClient.cpp
Source/WebCore/platform/network/SynchronousLoaderClient.h
Source/WebCore/platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp
Source/WebCore/platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp
Source/WebCore/platform/network/cocoa/NetworkLoadMetrics.mm [moved from Source/WebCore/platform/network/cocoa/NetworkLoadTiming.mm with 72% similarity]
Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp
Source/WebCore/platform/network/curl/ResourceHandleManager.cpp
Source/WebCore/platform/network/mac/ResourceHandleMac.mm
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm
Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
Source/WebCore/workers/WorkerScriptLoader.cpp
Source/WebCore/workers/WorkerScriptLoader.h
Source/WebCore/xml/XMLHttpRequest.cpp
Source/WebCore/xml/XMLHttpRequest.h
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/Downloads/BlobDownloadClient.cpp
Source/WebKit2/NetworkProcess/Downloads/BlobDownloadClient.h
Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h
Source/WebKit2/NetworkProcess/NetworkDataTask.h
Source/WebKit2/NetworkProcess/NetworkLoad.cpp
Source/WebKit2/NetworkProcess/NetworkLoad.h
Source/WebKit2/NetworkProcess/NetworkLoadClient.h
Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp
Source/WebKit2/NetworkProcess/NetworkResourceLoader.h
Source/WebKit2/NetworkProcess/PingLoad.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h
Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.h
Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm
Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.h
Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm
Source/WebKit2/NetworkProcess/soup/NetworkDataTaskSoup.cpp
Source/WebKit2/NetworkProcess/soup/NetworkDataTaskSoup.h
Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp
Source/WebKit2/WebProcess/Network/WebResourceLoader.h
Source/WebKit2/WebProcess/Network/WebResourceLoader.messages.in

index c8588b0..349c0fc 100644 (file)
@@ -1,3 +1,31 @@
+2017-02-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        [Resource Timing] Gather timing information with reliable responseEnd time
+        https://bugs.webkit.org/show_bug.cgi?id=168351
+
+        Reviewed by Alex Christensen.
+
+        * TestExpectations:
+        Now that nextHopProtocol is available on Mac mark the test as flakey
+        because the value can be set or not depending on whether or not the
+        resource was loaded from a cache.
+
+        * platform/ios-simulator/TestExpectations:
+        * platform/gtk/TestExpectations:
+        * platform/mac/TestExpectations:
+        * platform/win/TestExpectations:
+        Mark nextHopProtocol tests as expected to fail on ports that do not
+        yet support those values. Mark redirect tests as failing on ports
+        that encounter the CFNetwork issue causing unexpected callbacks.
+
+        * performance-api/resource-timing-apis-expected.txt:
+        * performance-api/resources/resource-timing-api.js:
+        Progressions.
+
+        * platform/mac-elcapitan/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt: Added.
+        * platform/mac/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt: Added.
+        Expected passing values on mac, except el capitan where this new resource timing data is unavailable.
+
 2017-02-24  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, rolling out r212944.
index 0640b16..cb518cf 100644 (file)
@@ -312,6 +312,7 @@ webkit.org/b/161088 imported/w3c/web-platform-tests/resource-timing/resource-tim
 webkit.org/b/168357 imported/w3c/web-platform-tests/resource-timing/rt-initiatorType-media.html [ Failure ]
 webkit.org/b/168448 imported/w3c/web-platform-tests/resource-timing/rt-shared-resource-in-frames.html [ Pass Failure ]
 webkit.org/b/168448 imported/w3c/web-platform-tests/resource-timing/rt-shared-resource-in-workers.html [ Pass Failure ]
+imported/w3c/web-platform-tests/resource-timing/test_resource_timing.html [ Pass Failure ]
 
 webkit.org/b/161176 [ Debug ] imported/w3c/web-platform-tests/url/url-setters.html [ Skip ]
 
index da6ae3d..04ba743 100644 (file)
@@ -1,3 +1,27 @@
+2017-02-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        [Resource Timing] Gather timing information with reliable responseEnd time
+        https://bugs.webkit.org/show_bug.cgi?id=168351
+
+        Reviewed by Alex Christensen.
+
+        * web-platform-tests/fetch/api/redirect/redirect-count-cross-origin-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-count-cross-origin-worker-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-count-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-count-worker-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-location-expected.txt:
+        * web-platform-tests/fetch/api/redirect/redirect-location-worker-expected.txt:
+        New behavior for too many redirects caused by <rdar://problem/30610988>.
+
+        * web-platform-tests/resource-timing/rt-nextHopProtocol-expected.txt: Added.
+        * web-platform-tests/resource-timing/rt-nextHopProtocol.html: Added.
+        * web-platform-tests/resource-timing/rt-nextHopProtocol.js: Added.
+        * web-platform-tests/resource-timing/rt-nextHopProtocol.worker-expected.txt: Added.
+        * web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html: Added.
+        * web-platform-tests/resource-timing/rt-nextHopProtocol.worker.js: Added.
+        New tests specific to just checking the nextHopProtocol property with
+        a non-cached resource to avoid flakeyness.
+
 2017-02-24  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, rolling out r212944.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol-expected.txt
new file mode 100644 (file)
index 0000000..82b211e
--- /dev/null
@@ -0,0 +1,5 @@
+Resource Timing: nextHopProtocol
+
+
+PASS nextHopProtocol is expected to be 'http1/1' 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html b/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html
new file mode 100644 (file)
index 0000000..3ece308
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Resource Timing - nextHopProtocol</title>
+<meta name="author" title="JosephPecoraro" href="mailto:joepeck@webkit.org">
+<meta name="assert" content="Resource Timing nextHopProtocol">
+<link rel="help" href="https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-nexthopprotocol">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/rt-utilities.js"></script>
+</head>
+<body>
+<h1>Resource Timing: nextHopProtocol</h1>
+<div id="log"></div>
+<script src="rt-nextHopProtocol.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.js b/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.js
new file mode 100644 (file)
index 0000000..ec39776
--- /dev/null
@@ -0,0 +1,5 @@
+promise_test(function(t) {
+    return loadResources(1).then(function([entry]) {
+        assert_equals(entry.nextHopProtocol, "http/1.1");
+    });
+}, "nextHopProtocol is expected to be 'http1/1'", {timeout: 3000});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker-expected.txt
new file mode 100644 (file)
index 0000000..e625e19
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS Must have PerformanceObserver and PerformanceResourceTiming in DedicatedWorkerGlobalScope 
+PASS nextHopProtocol is expected to be 'http1/1' 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html b/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.js b/LayoutTests/imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.js
new file mode 100644 (file)
index 0000000..583e45d
--- /dev/null
@@ -0,0 +1,13 @@
+importScripts("/resources/testharness.js");
+importScripts("resources/rt-utilities.js");
+
+(function() {
+    if (!testNecessaryPerformanceFeatures()) {
+        done();
+        return;
+    }
+
+    importScripts("rt-nextHopProtocol.js");
+
+    done();
+})();
index b8d846c..d970b1c 100644 (file)
@@ -6,7 +6,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 PerformanceResourceTiming
 PASS PerformanceResourceTiming is defined.
 PASS "initiatorType" in PerformanceResourceTiming.prototype is true
-FAIL "nextHopProtocol" in PerformanceResourceTiming.prototype should be true. Was false.
+PASS "nextHopProtocol" in PerformanceResourceTiming.prototype is true
 PASS "workerStart" in PerformanceResourceTiming.prototype is true
 PASS "redirectStart" in PerformanceResourceTiming.prototype is true
 PASS "redirectEnd" in PerformanceResourceTiming.prototype is true
@@ -37,7 +37,7 @@ Starting worker: resources/resource-timing-api.js
 [Worker] PerformanceResourceTiming
 PASS [Worker] PerformanceResourceTiming is defined.
 PASS [Worker] "initiatorType" in PerformanceResourceTiming.prototype is true
-FAIL [Worker] "nextHopProtocol" in PerformanceResourceTiming.prototype should be true. Was false.
+PASS [Worker] "nextHopProtocol" in PerformanceResourceTiming.prototype is true
 PASS [Worker] "workerStart" in PerformanceResourceTiming.prototype is true
 PASS [Worker] "redirectStart" in PerformanceResourceTiming.prototype is true
 PASS [Worker] "redirectEnd" in PerformanceResourceTiming.prototype is true
index 3cf5f76..b4bce6f 100644 (file)
@@ -7,7 +7,7 @@ if (self.window)
 debug("PerformanceResourceTiming");
 shouldBeDefined("PerformanceResourceTiming");
 shouldBeTrue(`"initiatorType" in PerformanceResourceTiming.prototype`);
-shouldBeTrue(`"nextHopProtocol" in PerformanceResourceTiming.prototype`); // Not yet implemented.
+shouldBeTrue(`"nextHopProtocol" in PerformanceResourceTiming.prototype`);
 shouldBeTrue(`"workerStart" in PerformanceResourceTiming.prototype`);
 shouldBeTrue(`"redirectStart" in PerformanceResourceTiming.prototype`);
 shouldBeTrue(`"redirectEnd" in PerformanceResourceTiming.prototype`);
index 81d910b..92f9905 100644 (file)
@@ -2840,6 +2840,9 @@ webkit.org/b/167999 imported/w3c/web-platform-tests/fetch/api/redirect/redirect-
 webkit.org/b/167999 imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count.html [ Failure ]
 webkit.org/b/167999 imported/w3c/web-platform-tests/fetch/api/redirect/redirect-location.html [ Failure ]
 
+webkit.org/b/168543 imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [ Failure ]
+webkit.org/b/168543 imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [ Failure ]
+
 webkit.org/b/145260 media/audio-playback-restriction-play.html [ Failure ]
 
 webkit.org/b/168188 fast/events/ime-compositionend-on-selection-change.html [ Failure ]
index bc7d1a6..eb4288b 100644 (file)
@@ -2877,6 +2877,14 @@ webkit.org/b/168054 compositing/masks/solid-color-masked.html [ ImageOnlyFailure
 webkit.org/b/168215 imported/w3c/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html [ Skip ]
 webkit.org/b/168215 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-area-element/area-download-click.html [ Skip ]
 
+# <rdar://problem/30610988>
+imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-cross-origin-worker.html [ Failure ]
+imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-cross-origin.html [ Failure ]
+imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-worker.html [ Failure ]
+imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count.html [ Failure ]
+imported/w3c/web-platform-tests/fetch/api/redirect/redirect-location-worker.html [ Failure ]
+imported/w3c/web-platform-tests/fetch/api/redirect/redirect-location.html [ Failure ]
+
 # rdar://problem/23643423
 [ Debug ] fast/frames/exponential-frames.html [ Skip ]
 
diff --git a/LayoutTests/platform/mac-elcapitan/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt b/LayoutTests/platform/mac-elcapitan/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt
new file mode 100644 (file)
index 0000000..fa5129a
--- /dev/null
@@ -0,0 +1,34 @@
+Description
+
+NOTE: Due to caching behavior in the browser, it is possible that when revisiting this page, some resources may not have to be fetched from the network. As a result, the performance timeline will not contain entries for these resources. This test will fail if any entries are missing to ensure that all resources are fetched from the network and entries for these resources exist in the Performance Timeline. If revisiting this page, please either perform a full reload of the page or clear the cache between visits.
+
+
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (iframe) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe) 
+PASS PerformanceEntry has correct order of timing attributes (iframe) 
+FAIL PerformanceEntry has correct network transfer attributes (iframe) assert_equals: encodedBodySize size expected (number) 215 but got (undefined) undefined
+FAIL PerformanceEntry has correct protocol attribute (iframe) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (img) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (img) 
+PASS PerformanceEntry has correct order of timing attributes (img) 
+FAIL PerformanceEntry has correct network transfer attributes (img) assert_equals: encodedBodySize size expected (number) 249 but got (undefined) undefined
+FAIL PerformanceEntry has correct protocol attribute (img) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (link) 
+PASS PerformanceEntry has correct order of timing attributes (link) 
+FAIL PerformanceEntry has correct network transfer attributes (link) assert_equals: encodedBodySize size expected (number) 44 but got (undefined) undefined
+FAIL PerformanceEntry has correct protocol attribute (link) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (script) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (script) 
+PASS PerformanceEntry has correct order of timing attributes (script) 
+FAIL PerformanceEntry has correct network transfer attributes (script) assert_equals: encodedBodySize size expected (number) 133 but got (undefined) undefined
+FAIL PerformanceEntry has correct protocol attribute (script) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (xmlhttprequest) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest) 
+PASS PerformanceEntry has correct order of timing attributes (xmlhttprequest) 
+FAIL PerformanceEntry has correct network transfer attributes (xmlhttprequest) assert_equals: encodedBodySize size expected (number) 112 but got (undefined) undefined
+FAIL PerformanceEntry has correct protocol attribute (xmlhttprequest) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined
+PASS window.performance Resource Timing Entries exist 
+PASS window.performance Resource Timing Entries exist 1 
+PASS window.performance Resource Timing Entries exist 2 
+
index 21fbc15..6c99c75 100644 (file)
@@ -295,6 +295,10 @@ 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.
+imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [ Failure ]
+imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [ Failure ]
+
 webkit.org/b/164491 [ Yosemite ElCapitan ] fast/visual-viewport/rtl-zoomed-rects.html [ Failure ]
 
 webkit.org/b/164933 http/tests/misc/link-rel-icon-beforeload.html [ Failure ]
index f49cab2..299d4ba 100644 (file)
@@ -1535,4 +1535,16 @@ webkit.org/b/168415 [ ElCapitan ] imported/w3c/web-platform-tests/resource-timin
 
 webkit.org/b/212466 [ ElCapitan ] js/dom/gc-slot-visitor-parallel-drain-pings-runloop-when-done.html [ Skip ]
 
+# Resource Timing networking data not yet available without Network Session.
+[ ElCapitan ] imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [ Failure ]
+[ ElCapitan ] imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [ Failure ]
+
+# <rdar://problem/30610988>
+[ Sierra+ ] imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-cross-origin-worker.html [ Failure ]
+[ Sierra+ ] imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-cross-origin.html [ Failure ]
+[ Sierra+ ] imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-worker.html [ Failure ]
+[ Sierra+ ] imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count.html [ Failure ]
+[ Sierra+ ] imported/w3c/web-platform-tests/fetch/api/redirect/redirect-location-worker.html [ Failure ]
+[ Sierra+ ] imported/w3c/web-platform-tests/fetch/api/redirect/redirect-location.html [ Failure ]
+
 webkit.org/b/168503 editing/pasteboard/drag-drop-copy-content.html [ Failure ]
diff --git a/LayoutTests/platform/mac/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt b/LayoutTests/platform/mac/imported/w3c/web-platform-tests/resource-timing/test_resource_timing-expected.txt
new file mode 100644 (file)
index 0000000..a0e5d7a
--- /dev/null
@@ -0,0 +1,34 @@
+Description
+
+NOTE: Due to caching behavior in the browser, it is possible that when revisiting this page, some resources may not have to be fetched from the network. As a result, the performance timeline will not contain entries for these resources. This test will fail if any entries are missing to ensure that all resources are fetched from the network and entries for these resources exist in the Performance Timeline. If revisiting this page, please either perform a full reload of the page or clear the cache between visits.
+
+
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (iframe) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe) 
+PASS PerformanceEntry has correct order of timing attributes (iframe) 
+FAIL PerformanceEntry has correct network transfer attributes (iframe) assert_equals: encodedBodySize size expected (number) 215 but got (undefined) undefined
+PASS PerformanceEntry has correct protocol attribute (iframe) 
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (img) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (img) 
+PASS PerformanceEntry has correct order of timing attributes (img) 
+FAIL PerformanceEntry has correct network transfer attributes (img) assert_equals: encodedBodySize size expected (number) 249 but got (undefined) undefined
+PASS PerformanceEntry has correct protocol attribute (img) 
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (link) 
+PASS PerformanceEntry has correct order of timing attributes (link) 
+FAIL PerformanceEntry has correct network transfer attributes (link) assert_equals: encodedBodySize size expected (number) 44 but got (undefined) undefined
+PASS PerformanceEntry has correct protocol attribute (link) 
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (script) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (script) 
+PASS PerformanceEntry has correct order of timing attributes (script) 
+FAIL PerformanceEntry has correct network transfer attributes (script) assert_equals: encodedBodySize size expected (number) 133 but got (undefined) undefined
+PASS PerformanceEntry has correct protocol attribute (script) 
+PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (xmlhttprequest) 
+PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest) 
+PASS PerformanceEntry has correct order of timing attributes (xmlhttprequest) 
+FAIL PerformanceEntry has correct network transfer attributes (xmlhttprequest) assert_equals: encodedBodySize size expected (number) 112 but got (undefined) undefined
+PASS PerformanceEntry has correct protocol attribute (xmlhttprequest) 
+PASS window.performance Resource Timing Entries exist 
+PASS window.performance Resource Timing Entries exist 1 
+PASS window.performance Resource Timing Entries exist 2 
+
index f358a45..3bfcd27 100644 (file)
@@ -3785,6 +3785,10 @@ fast/layers/prevent-hit-test-during-layout.html [ Skip ]
 # webrtc not supported
 imported/w3c/web-platform-tests/webrtc [ Skip ]
 
+# Resource Timing networking data not yet available.
+imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html [ Failure ]
+imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html [ Failure ]
+
 # WebCrypto tests are failing.
 webkit.org/b/165090 imported/w3c/WebCryptoAPI [ Skip ]
 webkit.org/b/165090 imported/w3c/web-platform-tests/WebCryptoAPI [ Skip ]
index a0fb129..972f40f 100644 (file)
@@ -1,3 +1,14 @@
+2017-02-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        [Resource Timing] Gather timing information with reliable responseEnd time
+        https://bugs.webkit.org/show_bug.cgi?id=168351
+
+        Reviewed by Alex Christensen.
+
+        * wtf/persistence/Coders.h:
+        (WTF::Persistence::Coder<Seconds>::encode):
+        (WTF::Persistence::Coder<Seconds>::decode):
+
 2017-02-24  Keith Miller  <keith_miller@apple.com>
 
         Rubber-stamped by Chris Dumez.
index 3cde70a..4050674 100644 (file)
@@ -30,6 +30,7 @@
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/SHA1.h>
+#include <wtf/Seconds.h>
 #include <wtf/Vector.h>
 #include <wtf/persistence/Decoder.h>
 #include <wtf/persistence/Encoder.h>
@@ -278,6 +279,23 @@ template<> struct Coder<std::chrono::system_clock::time_point> {
     }
 };
 
+template<> struct Coder<Seconds> {
+    static void encode(Encoder& encoder, const Seconds& seconds)
+    {
+        encoder << seconds.value();
+    }
+
+    static bool decode(Decoder& decoder, Seconds& result)
+    {
+        double value;
+        if (!decoder.decode(value))
+            return false;
+
+        result = Seconds(value);
+        return true;
+    }
+};
+
 template<> struct Coder<AtomicString> {
     WTF_EXPORT_PRIVATE static void encode(Encoder&, const AtomicString&);
     WTF_EXPORT_PRIVATE static bool decode(Decoder&, AtomicString&);
index 9783508..dd4c9ba 100644 (file)
@@ -1,3 +1,245 @@
+2017-02-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        [Resource Timing] Gather timing information with reliable responseEnd time
+        https://bugs.webkit.org/show_bug.cgi?id=168351
+
+        Reviewed by Alex Christensen.
+
+        This patch replaces the unused `double finishTime` in ResourceLoader's
+        didFinishLoad with a complete WebCore::NetworkLoadMetrics object. This
+        allows the NetworkProcess to give complete timing information, and more
+        final metrics about the load, to WebCore. Currently this is only used
+        by ResourceTiming, but it will soon be used by Web Inspector as well.
+        We may also end up extending this to the didFail path as well, since it
+        is possible that we have some metrics for load failures.
+
+        At the same time we want to start moving away from the legacy path that
+        populated a subset of this information in ResourceResponse's NetworkLoadMetrics.
+        It doesn't make sense to store this information on the ResourceResponse
+        for a few reasons: We don't want to store the metrics in our Network Cache and
+        not all of the load timing metrics have been populated yet (responseEnd).
+        In an effort to move off of this data we've renamed the accessor to
+        "deprecatedNetworkLoadMetrics". There are a few remaining clients
+        (ResourceHandle, PerformanceTiming, InspectorNetworkAgent) which can be
+        migrated separately from this patch.
+
+        Having both the legacy and new code paths adds a little bit of complexity.
+        One advantage of the new path is that the complete load timing data
+        (fetchStart -> dns -> connect -> request -> response -> responseEnd) can
+        be packaged together. The legacy path could not include a responseEnd, so
+        WebCore faked that value with its own timestamp. Having the fake responseEnd
+        caused issues as timestamps / clocks are different between processes. In order
+        for PerformanceResponseTiming to know whether or not the NetworkLoadMetrics
+        has the complete network timing metrics it checks isComplete(). If true
+        it knows it can use the responseEnd time from NetworkLoadMetrics, otherwise
+        it must fallback to the legacy value from LoadTiming. Once all of the
+        deprecatedNetworkLoadMetrics clients go away, we should always have the
+        complete data and this can be eliminated.
+
+        Tests: imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.html
+               imported/w3c/web-platform-tests/resource-timing/rt-nextHopProtocol.worker.html
+
+        * PlatformMac.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+        Rename NetworkLoadTiming -> NetworkLoadMetrics.
+
+        * page/PerformanceResourceTiming.cpp:
+        (WebCore::entryStartTime):
+        (WebCore::entryEndTime):
+        (WebCore::PerformanceResourceTiming::PerformanceResourceTiming):
+        (WebCore::PerformanceResourceTiming::nextHopProtocol):
+        (WebCore::PerformanceResourceTiming::domainLookupStart):
+        (WebCore::PerformanceResourceTiming::domainLookupEnd):
+        (WebCore::PerformanceResourceTiming::connectStart):
+        (WebCore::PerformanceResourceTiming::connectEnd):
+        (WebCore::PerformanceResourceTiming::secureConnectionStart):
+        (WebCore::PerformanceResourceTiming::requestStart):
+        (WebCore::PerformanceResourceTiming::responseStart):
+        (WebCore::PerformanceResourceTiming::responseEnd):
+        (WebCore::PerformanceResourceTiming::networkLoadTimeToDOMHighResTimeStamp):
+        * page/PerformanceResourceTiming.h:
+        Mostly just updating names and types. This does however need to get the
+        correct endTime based on whether the NetworkLoadMetrics are complete
+        (meaning includes responseEnd) or not (legacy, use LoadTiming value).
+
+        * page/PerformanceResourceTiming.idl:
+        Add nextHopProtocol.
+
+        * page/PerformanceTiming.cpp:
+        (WebCore::PerformanceTiming::domainLookupStart):
+        (WebCore::PerformanceTiming::domainLookupEnd):
+        (WebCore::PerformanceTiming::connectStart):
+        (WebCore::PerformanceTiming::connectEnd):
+        (WebCore::PerformanceTiming::secureConnectionStart):
+        (WebCore::PerformanceTiming::requestStart):
+        (WebCore::PerformanceTiming::responseStart):
+        (WebCore::PerformanceTiming::resourceLoadTimeRelativeToFetchStart):
+        * page/PerformanceTiming.h:
+        Navigation Timing values still uses the NetworkLoadTiming values stored on
+        the DocumentLoader. This should be moved off of the deprecated path separately.
+
+        * platform/network/NetworkLoadMetrics.h: Renamed from Source/WebCore/platform/network/NetworkLoadTiming.h.
+        (WebCore::NetworkLoadMetrics::NetworkLoadMetrics):
+        (WebCore::NetworkLoadMetrics::isolatedCopy):
+        (WebCore::NetworkLoadMetrics::reset):
+        (WebCore::NetworkLoadMetrics::operator==):
+        (WebCore::NetworkLoadMetrics::operator!=):
+        (WebCore::NetworkLoadMetrics::isComplete):
+        (WebCore::NetworkLoadMetrics::markComplete):
+        (WebCore::NetworkLoadMetrics::encode):
+        (WebCore::NetworkLoadMetrics::decode):
+        Re-introduce a reset() method (for NetworkLoadSoup to reset between redirects).
+        Add protocolName and "complete" boolean.
+
+        * platform/network/cocoa/NetworkLoadMetrics.mm: Renamed from Source/WebCore/platform/network/cocoa/NetworkLoadTiming.mm.
+        (WebCore::timingValue):
+        (WebCore::copyTimingData):
+        (WebCore::setCollectsTimingData):
+        Use this opportunity to convert NetworkLoadTiming timestamps to WTF::Seconds.
+        Since we already have to modify all the clients this moves us to use the more
+        strongly typed units that are less ambiguous then "double". The rest of the
+        Performance API has already moved to these units.
+
+        * inspector/InspectorNetworkAgent.cpp:
+        (WebCore::InspectorNetworkAgent::buildObjectForTiming):
+        (WebCore::InspectorNetworkAgent::buildObjectForResourceResponse):
+        (WebCore::InspectorNetworkAgent::didFinishLoading):
+        * inspector/InspectorNetworkAgent.h:
+        Inspector was the only client of the finishTime, and since the value was
+        erratically coming from clients in different ways it was almost certainly
+        inaccurate. Simplify this in preparation for using NetworkLoadMetrics.
+
+        * Modules/fetch/FetchLoader.cpp:
+        (WebCore::FetchLoader::didFinishLoading):
+        * Modules/fetch/FetchLoader.h:
+        * fileapi/FileReaderLoader.cpp:
+        (WebCore::FileReaderLoader::didFinishLoading):
+        * fileapi/FileReaderLoader.h:
+        * html/MediaFragmentURIParser.cpp:
+        (WebCore::MediaFragmentURIParser::parseNPTTime):
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::didFinishLoadingImpl):
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::didFinishLoading):
+        * loader/CrossOriginPreflightChecker.cpp:
+        (WebCore::CrossOriginPreflightChecker::validatePreflightResponse):
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::notifyFinished):
+        (WebCore::DocumentLoader::finishedLoading):
+        (WebCore::DocumentLoader::continueAfterContentPolicy):
+        (WebCore::DocumentLoader::maybeLoadEmpty):
+        * loader/DocumentLoader.h:
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::didReceiveResponse):
+        (WebCore::DocumentThreadableLoader::notifyFinished):
+        (WebCore::DocumentThreadableLoader::didFinishLoading):
+        (WebCore::DocumentThreadableLoader::loadRequest):
+        * loader/DocumentThreadableLoader.h:
+        * loader/NetscapePlugInStreamLoader.cpp:
+        (WebCore::NetscapePlugInStreamLoader::didFinishLoading):
+        * loader/NetscapePlugInStreamLoader.h:
+        * loader/ResourceLoadNotifier.cpp:
+        (WebCore::ResourceLoadNotifier::didFinishLoad):
+        (WebCore::ResourceLoadNotifier::dispatchDidFinishLoading):
+        (WebCore::ResourceLoadNotifier::sendRemainingDelegateMessages):
+        * loader/ResourceLoadNotifier.h:
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::deliverResponseAndData):
+        (WebCore::ResourceLoader::loadDataURL):
+        (WebCore::ResourceLoader::didFinishLoading):
+        (WebCore::ResourceLoader::didFinishLoadingOnePart):
+        * loader/ResourceLoader.h:
+        * loader/ResourceTiming.cpp:
+        (WebCore::ResourceTiming::fromLoad):
+        (WebCore::ResourceTiming::fromSynchronousLoad):
+        (WebCore::ResourceTiming::ResourceTiming):
+        (WebCore::ResourceTiming::isolatedCopy):
+        * loader/ResourceTiming.h:
+        (WebCore::ResourceTiming::networkLoadMetrics):
+        (WebCore::ResourceTiming::ResourceTiming):
+        (WebCore::ResourceTiming::networkLoadTiming): Deleted.
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::SubresourceLoader):
+        (WebCore::SubresourceLoader::willSendRequestInternal):
+        (WebCore::SubresourceLoader::didReceiveResponse):
+        (WebCore::SubresourceLoader::didFinishLoading):
+        (WebCore::SubresourceLoader::reportResourceTiming):
+        * loader/SubresourceLoader.h:
+        * loader/ThreadableLoaderClient.h:
+        (WebCore::ThreadableLoaderClient::didFinishLoading):
+        * loader/ThreadableLoaderClientWrapper.h:
+        (WebCore::ThreadableLoaderClientWrapper::didFinishLoading):
+        * loader/WorkerThreadableLoader.cpp:
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::didFinishLoading):
+        * loader/WorkerThreadableLoader.h:
+        * loader/appcache/ApplicationCacheGroup.cpp:
+        (WebCore::ApplicationCacheGroup::didFinishLoading):
+        * loader/appcache/ApplicationCacheGroup.h:
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::setLoadFinishTime):
+        * loader/ios/QuickLook.mm:
+        (-[WebPreviewLoader connectionDidFinishLoading:]):
+        * page/EventSource.cpp:
+        (WebCore::EventSource::didFinishLoading):
+        * page/EventSource.h:
+        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
+        (ResourceHandleStreamingClient::didFinishLoading):
+        * platform/network/BlobResourceHandle.cpp:
+        (WebCore::doNotifyFinish):
+        * platform/network/PingHandle.h:
+        * platform/network/ResourceHandle.h:
+        * platform/network/ResourceHandleClient.h:
+        (WebCore::ResourceHandleClient::didFinishLoading):
+        * platform/network/ResourceResponseBase.cpp:
+        (WebCore::ResourceResponseBase::crossThreadData):
+        (WebCore::ResourceResponseBase::fromCrossThreadData):
+        (WebCore::ResourceResponseBase::compare):
+        * platform/network/ResourceResponseBase.h:
+        (WebCore::ResourceResponseBase::deprecatedNetworkLoadMetrics):
+        (WebCore::ResourceResponseBase::encode):
+        (WebCore::ResourceResponseBase::decode):
+        (WebCore::ResourceResponseBase::networkLoadTiming): Deleted.
+        * platform/network/SynchronousLoaderClient.cpp:
+        (WebCore::SynchronousLoaderClient::didFinishLoading):
+        * platform/network/SynchronousLoaderClient.h:
+        * platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp:
+        (WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveResponse):
+        (WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading):
+        * platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
+        (WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse):
+        (WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading):
+        * platform/network/curl/ResourceHandleCurl.cpp:
+        (WebCore::WebCoreSynchronousLoader::didFinishLoading):
+        * platform/network/curl/ResourceHandleManager.cpp:
+        (WebCore::calculateWebTimingInformations):
+        (WebCore::ResourceHandleManager::downloadTimerCallback):
+        (WebCore::handleDataURL):
+        (WebCore::milisecondsSinceRequest): Deleted.
+        * platform/network/mac/ResourceHandleMac.mm:
+        (WebCore::ResourceHandle::getConnectionTimingData):
+        * platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
+        (-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]):
+        (-[WebCoreResourceHandleAsDelegate connectionDidFinishLoading:]):
+        * platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm:
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveResponse:]):
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connectionDidFinishLoading:]):
+        * platform/network/soup/ResourceHandleSoup.cpp:
+        (WebCore::restartedCallback):
+        (WebCore::nextMultipartResponsePartCallback):
+        (WebCore::sendRequestCallback):
+        (WebCore::ResourceHandle::didStartRequest):
+        (WebCore::networkEventCallback):
+        (WebCore::ResourceHandle::sendPendingRequest):
+        (WebCore::readCallback):
+        (WebCore::milisecondsSinceRequest): Deleted.
+        * workers/WorkerScriptLoader.cpp:
+        (WebCore::WorkerScriptLoader::didFinishLoading):
+        * workers/WorkerScriptLoader.h:
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::didFinishLoading):
+        * xml/XMLHttpRequest.h:
+        Eliminate the unused finishTime double.
+
 2017-02-24  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed GTK build fix after r212965
index 6e2fd5c..d6666d7 100644 (file)
@@ -141,7 +141,7 @@ void FetchLoader::didReceiveData(const char* value, int size)
     m_consumer->append(value, size);
 }
 
-void FetchLoader::didFinishLoading(unsigned long, double)
+void FetchLoader::didFinishLoading(unsigned long)
 {
     m_client.didSucceed();
 }
index 44c1adb..92806a9 100644 (file)
@@ -57,7 +57,7 @@ private:
     // ThreadableLoaderClient API.
     void didReceiveResponse(unsigned long, const ResourceResponse&) final;
     void didReceiveData(const char*, int) final;
-    void didFinishLoading(unsigned long, double) final;
+    void didFinishLoading(unsigned long) final;
     void didFail(const ResourceError&) final;
 
 private:
index ce1a629..796dba3 100644 (file)
@@ -525,7 +525,7 @@ list(APPEND WebCore_SOURCES
     platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp
 
     platform/network/cocoa/CredentialCocoa.mm
-    platform/network/cocoa/NetworkLoadTiming.mm
+    platform/network/cocoa/NetworkLoadMetrics.mm
     platform/network/cocoa/ProtectionSpaceCocoa.mm
     platform/network/cocoa/ResourceRequestCocoa.mm
     platform/network/cocoa/ResourceResponseCocoa.mm
index 0a0a567..ad19985 100644 (file)
                5C7C88D81D0F1F4A009D2F6D /* SocketProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C7C88D71D0F1F2B009D2F6D /* SocketProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5C9A7A751AA0F6EA00958ACF /* DFABytecodeCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C39305E1AA0F6A90029C816 /* DFABytecodeCompiler.cpp */; };
                5C9A7A761AA0F6ED00958ACF /* DFABytecodeInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C3930601AA0F6A90029C816 /* DFABytecodeInterpreter.cpp */; };
-               5C9B860C1C21E3C900110F36 /* NetworkLoadTiming.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C9B860B1C21E3C600110F36 /* NetworkLoadTiming.mm */; };
+               5C9B860C1C21E3C900110F36 /* NetworkLoadMetrics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C9B860B1C21E3C600110F36 /* NetworkLoadMetrics.mm */; };
                5C9EF1711DFF71CC00A452E3 /* XPathGrammar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C9EF16F1DFF719900A452E3 /* XPathGrammar.cpp */; };
                5CB37FFE1C62D28C00F20188 /* ScrollAnimatorMock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CB37FFC1C62D27800F20188 /* ScrollAnimatorMock.cpp */; };
                5CB37FFF1C62D2A100F20188 /* ScrollAnimatorMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CB37FFD1C62D27800F20188 /* ScrollAnimatorMock.h */; };
                8A413AE11207BBA50082016E /* ScriptRunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8A413ADF1207BBA50082016E /* ScriptRunner.cpp */; };
                8A7CC96B12076D73001D4588 /* PendingScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A7CC96A12076D73001D4588 /* PendingScript.h */; settings = {ATTRIBUTES = (Private, ); }; };
                8A7CC97012076F8A001D4588 /* PendingScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8A7CC96F12076F8A001D4588 /* PendingScript.cpp */; };
-               8A81BF8511DCFD9000DA2B98 /* NetworkLoadTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A81BF8411DCFD9000DA2B98 /* NetworkLoadTiming.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               8A81BF8511DCFD9000DA2B98 /* NetworkLoadMetrics.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A81BF8411DCFD9000DA2B98 /* NetworkLoadMetrics.h */; settings = {ATTRIBUTES = (Private, ); }; };
                8A844D0511D3C18E0014065C /* Performance.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A844D0211D3C18E0014065C /* Performance.h */; };
                8A9A587011E84C36008ACFD1 /* JSPerformanceNavigation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8A9A586E11E84C35008ACFD1 /* JSPerformanceNavigation.cpp */; };
                8A9A587111E84C36008ACFD1 /* JSPerformanceNavigation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A9A586F11E84C36008ACFD1 /* JSPerformanceNavigation.h */; };
                5C6E653F1D5CEDC900F7862E /* URLParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLParser.cpp; sourceTree = "<group>"; };
                5C6E65401D5CEDC900F7862E /* URLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLParser.h; sourceTree = "<group>"; };
                5C7C88D71D0F1F2B009D2F6D /* SocketProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketProvider.h; sourceTree = "<group>"; };
-               5C9B860B1C21E3C600110F36 /* NetworkLoadTiming.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkLoadTiming.mm; sourceTree = "<group>"; };
+               5C9B860B1C21E3C600110F36 /* NetworkLoadMetrics.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkLoadMetrics.mm; sourceTree = "<group>"; };
                5C9EF16F1DFF719900A452E3 /* XPathGrammar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XPathGrammar.cpp; sourceTree = "<group>"; };
                5C9EF1701DFF719900A452E3 /* XPathGrammar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPathGrammar.h; sourceTree = "<group>"; };
                5CB37FFC1C62D27800F20188 /* ScrollAnimatorMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollAnimatorMock.cpp; sourceTree = "<group>"; };
                8A413ADF1207BBA50082016E /* ScriptRunner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptRunner.cpp; sourceTree = "<group>"; };
                8A7CC96A12076D73001D4588 /* PendingScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingScript.h; sourceTree = "<group>"; };
                8A7CC96F12076F8A001D4588 /* PendingScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingScript.cpp; sourceTree = "<group>"; };
-               8A81BF8411DCFD9000DA2B98 /* NetworkLoadTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkLoadTiming.h; sourceTree = "<group>"; };
+               8A81BF8411DCFD9000DA2B98 /* NetworkLoadMetrics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkLoadMetrics.h; sourceTree = "<group>"; };
                8A844D0211D3C18E0014065C /* Performance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Performance.h; sourceTree = "<group>"; };
                8A844D0311D3C18E0014065C /* Performance.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Performance.idl; sourceTree = "<group>"; };
                8A9A586E11E84C35008ACFD1 /* JSPerformanceNavigation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPerformanceNavigation.cpp; sourceTree = "<group>"; };
                                37DDCD9213844FD50008B793 /* MIMEHeader.cpp */,
                                37DDCD9313844FD50008B793 /* MIMEHeader.h */,
                                628D214B12131ED10055DCFC /* NetworkingContext.h */,
-                               8A81BF8411DCFD9000DA2B98 /* NetworkLoadTiming.h */,
+                               8A81BF8411DCFD9000DA2B98 /* NetworkLoadMetrics.h */,
                                1A7FA61A0DDA3BBE0028F8A5 /* NetworkStateNotifier.cpp */,
                                1A7FA6180DDA3B3A0028F8A5 /* NetworkStateNotifier.h */,
                                5C3C856C1D5A7AD30088B9EC /* NetworkStorageSession.cpp */,
                        children = (
                                3792917C1987678F00F4B661 /* CredentialCocoa.h */,
                                3792917B1987678F00F4B661 /* CredentialCocoa.mm */,
-                               5C9B860B1C21E3C600110F36 /* NetworkLoadTiming.mm */,
+                               5C9B860B1C21E3C600110F36 /* NetworkLoadMetrics.mm */,
                                372ADA37197F47B900FC501E /* ProtectionSpaceCocoa.h */,
                                372ADA39197F687600FC501E /* ProtectionSpaceCocoa.mm */,
                                7E7DE1FC195CEF260035363B /* ResourceRequestCocoa.mm */,
                                656D37430ADBA5DE00A4554D /* NetscapePlugInStreamLoader.h in Headers */,
                                A19D934B1AA11B1E00B46C24 /* NetworkExtensionContentFilter.h in Headers */,
                                628D214C12131ED10055DCFC /* NetworkingContext.h in Headers */,
-                               8A81BF8511DCFD9000DA2B98 /* NetworkLoadTiming.h in Headers */,
+                               8A81BF8511DCFD9000DA2B98 /* NetworkLoadMetrics.h in Headers */,
                                59C27F07138D28CF0079B7E2 /* NetworkResourcesData.h in Headers */,
                                1A7FA6190DDA3B3A0028F8A5 /* NetworkStateNotifier.h in Headers */,
                                E13EF3441684ECF40034C83F /* NetworkStorageSession.h in Headers */,
                                996E59DE1DF01285006612B9 /* NavigatorWebDriver.cpp in Sources */,
                                5D874F130D161D3200796C3B /* NetscapePlugInStreamLoader.cpp in Sources */,
                                A19D934A1AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm in Sources */,
-                               5C9B860C1C21E3C900110F36 /* NetworkLoadTiming.mm in Sources */,
+                               5C9B860C1C21E3C900110F36 /* NetworkLoadMetrics.mm in Sources */,
                                59C27F05138D28C10079B7E2 /* NetworkResourcesData.cpp in Sources */,
                                1A7FA61B0DDA3BBE0028F8A5 /* NetworkStateNotifier.cpp in Sources */,
                                443F04270E75C8FB007E5407 /* NetworkStateNotifierIOS.mm in Sources */,
index 7fd08fe..851ad35 100644 (file)
@@ -215,7 +215,7 @@ void FileReaderLoader::didReceiveData(const char* data, int dataLength)
         m_client->didReceiveData();
 }
 
-void FileReaderLoader::didFinishLoading(unsigned long, double)
+void FileReaderLoader::didFinishLoading(unsigned long)
 {
     if (m_variableLength && m_totalBytes > m_bytesLoaded) {
         RefPtr<ArrayBuffer> newData = m_rawData->slice(0, m_bytesLoaded);
index 5f4e73e..d15ddac 100644 (file)
@@ -70,7 +70,7 @@ public:
     // ThreadableLoaderClient
     void didReceiveResponse(unsigned long, const ResourceResponse&) override;
     void didReceiveData(const char*, int) override;
-    void didFinishLoading(unsigned long, double) override;
+    void didFinishLoading(unsigned long) override;
     void didFail(const ResourceError&) override;
 
     String stringResult();
index e64eba9..e7a516e 100644 (file)
@@ -244,7 +244,7 @@ bool MediaFragmentURIParser::parseNPTTime(const LChar* timeString, unsigned leng
 
     // http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#npttimedef
     // Normal Play Time can either be specified as seconds, with an optional
-    // fractional part to indicate miliseconds, or as colon-separated hours,
+    // fractional part to indicate milliseconds, or as colon-separated hours,
     // minutes and seconds (again with an optional fraction). Minutes and
     // seconds must be specified as exactly two digits, hours and fractional
     // seconds can be any number of digits. The hours, minutes and seconds
index 87f0d93..70f22af 100644 (file)
@@ -605,13 +605,13 @@ void InspectorInstrumentation::didReceiveDataImpl(InstrumentingAgents& instrumen
         networkAgent->didReceiveData(identifier, data, dataLength, encodedDataLength);
 }
 
-void InspectorInstrumentation::didFinishLoadingImpl(InstrumentingAgents& instrumentingAgents, unsigned long identifier, DocumentLoader* loader, double finishTime)
+void InspectorInstrumentation::didFinishLoadingImpl(InstrumentingAgents& instrumentingAgents, unsigned long identifier, DocumentLoader* loader)
 {
     if (!loader)
         return;
 
     if (InspectorNetworkAgent* networkAgent = instrumentingAgents.inspectorNetworkAgent())
-        networkAgent->didFinishLoading(identifier, *loader, finishTime);
+        networkAgent->didFinishLoading(identifier, *loader);
 }
 
 void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumentingAgents, unsigned long identifier, DocumentLoader* loader, const ResourceError& error)
index 68ceccf..80f1230 100644 (file)
@@ -157,7 +157,7 @@ public:
     static void didReceiveResourceResponse(Frame&, unsigned long identifier, DocumentLoader*, const ResourceResponse&, ResourceLoader*);
     static void didReceiveThreadableLoaderResponse(DocumentThreadableLoader&, unsigned long identifier);
     static void didReceiveData(Frame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
-    static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier, double finishTime);
+    static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier);
     static void didFailLoading(Frame*, DocumentLoader*, unsigned long identifier, const ResourceError&);
     static void continueAfterXFrameOptionsDenied(Frame&, unsigned long identifier, DocumentLoader&, const ResourceResponse&);
     static void continueWithPolicyDownload(Frame&, unsigned long identifier, DocumentLoader&, const ResourceResponse&);
@@ -327,7 +327,7 @@ private:
     static void didReceiveResourceResponseImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const ResourceResponse&, ResourceLoader*);
     static void didReceiveThreadableLoaderResponseImpl(InstrumentingAgents&, DocumentThreadableLoader&, unsigned long identifier);
     static void didReceiveDataImpl(InstrumentingAgents&, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
-    static void didFinishLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, double finishTime);
+    static void didFinishLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*);
     static void didFailLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const ResourceError&);
     static void didFinishXHRLoadingImpl(InstrumentingAgents&, unsigned long identifier, std::optional<String> decodedText, const String& url, const String& sendURL, unsigned sendLineNumber, unsigned sendColumnNumber);
     static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&);
@@ -863,10 +863,10 @@ inline void InspectorInstrumentation::didReceiveData(Frame* frame, unsigned long
         didReceiveDataImpl(*instrumentingAgents, identifier, data, dataLength, encodedDataLength);
 }
 
-inline void InspectorInstrumentation::didFinishLoading(Frame* frame, DocumentLoader* loader, unsigned long identifier, double finishTime)
+inline void InspectorInstrumentation::didFinishLoading(Frame* frame, DocumentLoader* loader, unsigned long identifier)
 {
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
-        didFinishLoadingImpl(*instrumentingAgents, identifier, loader, finishTime);
+        didFinishLoadingImpl(*instrumentingAgents, identifier, loader);
 }
 
 inline void InspectorInstrumentation::didFailLoading(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
index 569ce4a..ee34ccf 100644 (file)
@@ -114,7 +114,7 @@ public:
         m_responseText.append(m_decoder->decode(data, dataLength));
     }
 
-    void didFinishLoading(unsigned long, double) override
+    void didFinishLoading(unsigned long) override
     {
         if (m_decoder)
             m_responseText.append(m_decoder->flush());
@@ -179,20 +179,20 @@ static Ref<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
     return headersObject;
 }
 
-Ref<Inspector::Protocol::Network::ResourceTiming> InspectorNetworkAgent::buildObjectForTiming(const NetworkLoadTiming& timing, ResourceLoader& resourceLoader)
+Ref<Inspector::Protocol::Network::ResourceTiming> InspectorNetworkAgent::buildObjectForTiming(const NetworkLoadMetrics& timing, ResourceLoader& resourceLoader)
 {
     MonotonicTime startTime = resourceLoader.loadTiming().startTime();
     double startTimeInInspector = m_environment.executionStopwatch()->elapsedTimeSince(startTime);
 
     return Inspector::Protocol::Network::ResourceTiming::create()
         .setStartTime(startTimeInInspector)
-        .setDomainLookupStart(timing.domainLookupStart)
-        .setDomainLookupEnd(timing.domainLookupEnd)
-        .setConnectStart(timing.connectStart)
-        .setConnectEnd(timing.connectEnd)
-        .setSecureConnectionStart(timing.secureConnectionStart)
-        .setRequestStart(timing.requestStart)
-        .setResponseStart(timing.responseStart)
+        .setDomainLookupStart(timing.domainLookupStart.milliseconds())
+        .setDomainLookupEnd(timing.domainLookupEnd.milliseconds())
+        .setConnectStart(timing.connectStart.milliseconds())
+        .setConnectEnd(timing.connectEnd.milliseconds())
+        .setSecureConnectionStart(timing.secureConnectionStart.milliseconds())
+        .setRequestStart(timing.requestStart.milliseconds())
+        .setResponseStart(timing.responseStart.milliseconds())
         .release();
 }
 
@@ -229,7 +229,7 @@ RefPtr<Inspector::Protocol::Network::Response> InspectorNetworkAgent::buildObjec
 
     responseObject->setFromDiskCache(response.source() == ResourceResponse::Source::DiskCache || response.source() == ResourceResponse::Source::DiskCacheAfterValidation);
     if (resourceLoader)
-        responseObject->setTiming(buildObjectForTiming(response.networkLoadTiming(), *resourceLoader));
+        responseObject->setTiming(buildObjectForTiming(response.deprecatedNetworkLoadMetrics(), *resourceLoader));
 
     return WTFMove(responseObject);
 }
@@ -380,19 +380,20 @@ void InspectorNetworkAgent::didReceiveData(unsigned long identifier, const char*
     m_frontendDispatcher->dataReceived(requestId, timestamp(), dataLength, encodedDataLength);
 }
 
-void InspectorNetworkAgent::didFinishLoading(unsigned long identifier, DocumentLoader& loader, double finishTime)
+void InspectorNetworkAgent::didFinishLoading(unsigned long identifier, DocumentLoader& loader)
 {
     if (m_hiddenRequestIdentifiers.remove(identifier))
         return;
 
+    // FIXME: Inspector should make use of NetworkLoadMetrics.
+    double elapsedFinishTime = timestamp();
+
     String requestId = IdentifiersFactory::requestId(identifier);
     if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource)
         m_resourcesData->addResourceSharedBuffer(requestId, loader.frameLoader()->documentLoader()->mainResourceData(), loader.frame()->document()->encoding());
 
     m_resourcesData->maybeDecodeDataToContent(requestId);
 
-    double elapsedFinishTime = finishTime ? m_environment.executionStopwatch()->elapsedTimeSince(MonotonicTime::fromRawSeconds(finishTime)) : timestamp();
-
     String sourceMappingURL;
     NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
     if (resourceData && resourceData->cachedResource())
index a07e0dc..5c29246 100644 (file)
@@ -49,7 +49,7 @@ class Document;
 class DocumentLoader;
 class DocumentThreadableLoader;
 class InspectorPageAgent;
-class NetworkLoadTiming;
+class NetworkLoadMetrics;
 class NetworkResourcesData;
 class ResourceError;
 class ResourceLoader;
@@ -79,7 +79,7 @@ public:
     void markResourceAsCached(unsigned long identifier);
     void didReceiveResponse(unsigned long identifier, DocumentLoader&, const ResourceResponse&, ResourceLoader*);
     void didReceiveData(unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
-    void didFinishLoading(unsigned long identifier, DocumentLoader&, double finishTime);
+    void didFinishLoading(unsigned long identifier, DocumentLoader&);
     void didFailLoading(unsigned long identifier, DocumentLoader&, const ResourceError&);
     void didLoadResourceFromMemoryCache(DocumentLoader&, CachedResource&);
     void didReceiveThreadableLoaderResponse(unsigned long identifier, DocumentThreadableLoader&);
@@ -117,7 +117,7 @@ public:
 private:
     void enable();
 
-    Ref<Inspector::Protocol::Network::ResourceTiming> buildObjectForTiming(const NetworkLoadTiming&, ResourceLoader&);
+    Ref<Inspector::Protocol::Network::ResourceTiming> buildObjectForTiming(const NetworkLoadMetrics&, ResourceLoader&);
     RefPtr<Inspector::Protocol::Network::Response> buildObjectForResourceResponse(const ResourceResponse&, ResourceLoader*);
     Ref<Inspector::Protocol::Network::CachedResource> buildObjectForCachedResource(CachedResource*);
 
index 9886c51..d5285ef 100644 (file)
@@ -83,7 +83,7 @@ void CrossOriginPreflightChecker::validatePreflightResponse(DocumentThreadableLo
     // This is only showing success preflight requests and responses but we should show network events
     // for preflight failures and distinguish them better from non-preflight requests.
     InspectorInstrumentation::didReceiveResourceResponse(*frame, identifier, frame->loader().documentLoader(), response, nullptr);
-    InspectorInstrumentation::didFinishLoading(frame, frame->loader().documentLoader(), identifier, 0);
+    InspectorInstrumentation::didFinishLoading(frame, frame->loader().documentLoader(), identifier);
 
     CrossOriginPreflightResultCache::singleton().appendEntry(loader.securityOrigin().toString(), request.url(), WTFMove(result));
     loader.preflightSuccess(WTFMove(request));
index 0eb8170..ce2c5cf 100644 (file)
@@ -363,7 +363,7 @@ void DocumentLoader::notifyFinished(CachedResource& resource)
     ASSERT_UNUSED(resource, m_mainResource == &resource);
     ASSERT(m_mainResource);
     if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
-        finishedLoading(m_mainResource->loadFinishTime());
+        finishedLoading();
         return;
     }
 
@@ -375,7 +375,7 @@ void DocumentLoader::notifyFinished(CachedResource& resource)
     mainReceivedError(m_mainResource->resourceError());
 }
 
-void DocumentLoader::finishedLoading(double finishTime)
+void DocumentLoader::finishedLoading()
 {
     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
     // See <rdar://problem/6304600> for more details.
@@ -392,16 +392,12 @@ void DocumentLoader::finishedLoading(double finishTime)
         // cancel the already-finished substitute load.
         unsigned long identifier = m_identifierForLoadWithoutResourceLoader;
         m_identifierForLoadWithoutResourceLoader = 0;
-        frameLoader()->notifier().dispatchDidFinishLoading(this, identifier, finishTime);
+        frameLoader()->notifier().dispatchDidFinishLoading(this, identifier);
     }
 
     maybeFinishLoadingMultipartContent();
 
-    MonotonicTime responseEndTime = MonotonicTime::fromRawSeconds(finishTime);
-    if (!responseEndTime)
-        responseEndTime = m_timeOfLastDataReceived;
-    if (!responseEndTime)
-        responseEndTime = MonotonicTime::now();
+    MonotonicTime responseEndTime = m_timeOfLastDataReceived ? m_timeOfLastDataReceived : MonotonicTime::now();
     timing().setResponseEnd(responseEndTime);
 
     commitIfReady();
@@ -812,7 +808,7 @@ void DocumentLoader::continueAfterContentPolicy(PolicyAction policy)
         if (content && content->size())
             dataReceived(content->data(), content->size());
         if (isLoadingMainResource())
-            finishedLoading(0);
+            finishedLoading();
     }
 }
 
@@ -1425,7 +1421,7 @@ bool DocumentLoader::maybeLoadEmpty()
 
     String mimeType = shouldLoadEmpty ? "text/html" : frameLoader()->client().generatedMIMETypeForURLScheme(m_request.url().protocol().toStringWithoutCopying());
     m_response = ResourceResponse(m_request.url(), mimeType, 0, String());
-    finishedLoading(monotonicallyIncreasingTime());
+    finishedLoading();
     return true;
 }
 
index 138883f..0ad372a 100644 (file)
@@ -319,7 +319,7 @@ private:
 #endif
 
     void willSendRequest(ResourceRequest&, const ResourceResponse&);
-    void finishedLoading(double finishTime);
+    void finishedLoading();
     void mainReceivedError(const ResourceError&);
     WEBCORE_EXPORT void redirectReceived(CachedResource&, ResourceRequest&, const ResourceResponse&) override;
     WEBCORE_EXPORT void responseReceived(CachedResource&, const ResourceResponse&) override;
index d667935..34ea5af 100644 (file)
@@ -306,7 +306,7 @@ void DocumentThreadableLoader::didReceiveResponse(unsigned long identifier, cons
         if (tainting == ResourceResponse::Tainting::Opaque) {
             clearResource();
             if (m_client)
-                m_client->didFinishLoading(identifier, 0.0);
+                m_client->didFinishLoading(identifier);
         }
     } else {
         ASSERT(response.type() == ResourceResponse::Type::Opaqueredirect);
@@ -355,13 +355,13 @@ void DocumentThreadableLoader::notifyFinished(CachedResource& resource)
     if (m_resource->errorOccurred())
         didFail(m_resource->identifier(), m_resource->resourceError());
     else
-        didFinishLoading(m_resource->identifier(), m_resource->loadFinishTime());
+        didFinishLoading(m_resource->identifier());
 }
 
-void DocumentThreadableLoader::didFinishLoading(unsigned long identifier, double finishTime)
+void DocumentThreadableLoader::didFinishLoading(unsigned long identifier)
 {
     ASSERT(m_client);
-    m_client->didFinishLoading(identifier, finishTime);
+    m_client->didFinishLoading(identifier);
 }
 
 void DocumentThreadableLoader::didFail(unsigned long, const ResourceError& error)
@@ -461,7 +461,7 @@ void DocumentThreadableLoader::loadRequest(ResourceRequest&& request, SecurityCh
             // We don't want XMLHttpRequest to raise an exception for file:// resources, see <rdar://problem/4962298>.
             // FIXME: XMLHttpRequest quirks should be in XMLHttpRequest code, not in DocumentThreadableLoader.cpp.
             didReceiveResponse(identifier, response, ResourceResponse::Tainting::Basic);
-            didFinishLoading(identifier, 0.0);
+            didFinishLoading(identifier);
             return;
         }
         logErrorAndFail(error);
@@ -504,7 +504,7 @@ void DocumentThreadableLoader::loadRequest(ResourceRequest&& request, SecurityCh
 
 #if ENABLE(WEB_TIMING)
     if (RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled()) {
-        ResourceTiming resourceTiming = ResourceTiming::fromSynchronousLoad(requestURL, m_options.initiator, loadTiming, response.networkLoadTiming(), response, securityOrigin());
+        ResourceTiming resourceTiming = ResourceTiming::fromSynchronousLoad(requestURL, m_options.initiator, loadTiming, response.deprecatedNetworkLoadMetrics(), response, securityOrigin());
         if (options().initiatorContext == InitiatorContext::Worker)
             finishedTimingForWorkerLoad(resourceTiming);
         else {
@@ -514,7 +514,7 @@ void DocumentThreadableLoader::loadRequest(ResourceRequest&& request, SecurityCh
     }
 #endif
 
-    didFinishLoading(identifier, 0.0);
+    didFinishLoading(identifier);
 }
 
 bool DocumentThreadableLoader::isAllowedByContentSecurityPolicy(const URL& url, ContentSecurityPolicy::RedirectResponseReceived redirectResponseReceived)
index 37f951f..2630d57 100644 (file)
@@ -89,7 +89,7 @@ namespace WebCore {
 
         void didReceiveResponse(unsigned long identifier, const ResourceResponse&, ResourceResponse::Tainting);
         void didReceiveData(unsigned long identifier, const char* data, int dataLength);
-        void didFinishLoading(unsigned long identifier, double finishTime);
+        void didFinishLoading(unsigned long identifier);
         void didFail(unsigned long identifier, const ResourceError&);
         void makeCrossOriginAccessRequest(ResourceRequest&&);
         void makeSimpleCrossOriginAccessRequest(ResourceRequest&&);
index 6b9a344..45624c4 100644 (file)
@@ -146,14 +146,14 @@ void NetscapePlugInStreamLoader::didReceiveDataOrBuffer(const char* data, int le
     ResourceLoader::didReceiveDataOrBuffer(data, length, WTFMove(buffer), encodedDataLength, dataPayloadType);
 }
 
-void NetscapePlugInStreamLoader::didFinishLoading(double finishTime)
+void NetscapePlugInStreamLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
 {
     Ref<NetscapePlugInStreamLoader> protectedThis(*this);
 
     notifyDone();
 
     m_client->didFinishLoading(this);
-    ResourceLoader::didFinishLoading(finishTime);
+    ResourceLoader::didFinishLoading(networkLoadMetrics);
 }
 
 void NetscapePlugInStreamLoader::didFail(const ResourceError& error)
index 1fe772b..1288111 100644 (file)
@@ -62,7 +62,7 @@ private:
     void didReceiveResponse(const ResourceResponse&) override;
     void didReceiveData(const char*, unsigned, long long encodedDataLength, DataPayloadType) override;
     void didReceiveBuffer(Ref<SharedBuffer>&&, long long encodedDataLength, DataPayloadType) override;
-    void didFinishLoading(double finishTime) override;
+    void didFinishLoading(const NetworkLoadMetrics&) override;
     void didFail(const ResourceError&) override;
 
     void releaseResources() override;
index 63443d3..d0cd98b 100644 (file)
@@ -87,11 +87,14 @@ void ResourceLoadNotifier::didReceiveData(ResourceLoader* loader, const char* da
     dispatchDidReceiveData(loader->documentLoader(), loader->identifier(), data, dataLength, encodedDataLength);
 }
 
-void ResourceLoadNotifier::didFinishLoad(ResourceLoader* loader, double finishTime)
+void ResourceLoadNotifier::didFinishLoad(ResourceLoader* loader, const NetworkLoadMetrics&)
 {    
     if (Page* page = m_frame.page())
         page->progress().completeProgress(loader->identifier());
-    dispatchDidFinishLoading(loader->documentLoader(), loader->identifier(), finishTime);
+
+    // FIXME: Inspector should make use of NetworkLoadMetrics.
+
+    dispatchDidFinishLoading(loader->documentLoader(), loader->identifier());
 }
 
 void ResourceLoadNotifier::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
@@ -159,13 +162,13 @@ void ResourceLoadNotifier::dispatchDidReceiveData(DocumentLoader* loader, unsign
     InspectorInstrumentation::didReceiveData(&m_frame, identifier, data, dataLength, encodedDataLength);
 }
 
-void ResourceLoadNotifier::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier, double finishTime)
+void ResourceLoadNotifier::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
 {
     // Notifying the FrameLoaderClient may cause the frame to be destroyed.
     Ref<Frame> protect(m_frame);
     m_frame.loader().client().dispatchDidFinishLoading(loader, identifier);
 
-    InspectorInstrumentation::didFinishLoading(&m_frame, loader, identifier, finishTime);
+    InspectorInstrumentation::didFinishLoading(&m_frame, loader, identifier);
 }
 
 void ResourceLoadNotifier::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
@@ -194,7 +197,7 @@ void ResourceLoadNotifier::sendRemainingDelegateMessages(DocumentLoader* loader,
         dispatchDidReceiveData(loader, identifier, data, dataLength, encodedDataLength);
 
     if (error.isNull())
-        dispatchDidFinishLoading(loader, identifier, 0);
+        dispatchDidFinishLoading(loader, identifier);
     else
         dispatchDidFailLoading(loader, identifier, error);
 }
index f316ec2..4cc1f2b 100644 (file)
@@ -36,11 +36,11 @@ namespace WebCore {
 class AuthenticationChallenge;
 class DocumentLoader;
 class Frame;
-class Page;
+class NetworkLoadMetrics;
 class ResourceError;
 class ResourceLoader;
-class ResourceResponse;
 class ResourceRequest;
+class ResourceResponse;
 
 class ResourceLoadNotifier {
     WTF_MAKE_NONCOPYABLE(ResourceLoadNotifier);
@@ -53,14 +53,14 @@ public:
     void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
     void didReceiveResponse(ResourceLoader*, const ResourceResponse&);
     void didReceiveData(ResourceLoader*, const char*, int dataLength, int encodedDataLength);
-    void didFinishLoad(ResourceLoader*, double finishTime);
+    void didFinishLoad(ResourceLoader*, const NetworkLoadMetrics&);
     void didFailToLoad(ResourceLoader*, const ResourceError&);
 
     void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&);
     void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse);
     void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&, ResourceLoader* = nullptr);
     void dispatchDidReceiveData(DocumentLoader*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
-    void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier, double finishTime);
+    void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier);
     void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&);
 
     void sendRemainingDelegateMessages(DocumentLoader*, unsigned long identifier, const ResourceRequest&, const ResourceResponse&, const char* data, int dataLength, int encodedDataLength, const ResourceError&);
index 0fbb0c3..d65f3bf 100644 (file)
@@ -181,7 +181,8 @@ void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, Re
             return;
     }
 
-    didFinishLoading(0);
+    NetworkLoadMetrics emptyMetrics;
+    didFinishLoading(emptyMetrics);
 }
 
 void ResourceLoader::start()
@@ -271,8 +272,10 @@ void ResourceLoader::loadDataURL()
         if (!protectedThis->reachedTerminalState() && dataSize)
             protectedThis->didReceiveBuffer(result.data.releaseNonNull(), dataSize, DataPayloadWholeResource);
 
-        if (!protectedThis->reachedTerminalState())
-            protectedThis->didFinishLoading(currentTime());
+        if (!protectedThis->reachedTerminalState()) {
+            NetworkLoadMetrics emptyMetrics;
+            protectedThis->didFinishLoading(emptyMetrics);
+        }
     });
 }
 
@@ -488,9 +491,9 @@ void ResourceLoader::didReceiveDataOrBuffer(const char* data, unsigned length, R
         frameLoader()->notifier().didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length, static_cast<int>(encodedDataLength));
 }
 
-void ResourceLoader::didFinishLoading(double finishTime)
+void ResourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
 {
-    didFinishLoadingOnePart(finishTime);
+    didFinishLoadingOnePart(networkLoadMetrics);
 
     // If the load has been cancelled by a delegate in response to didFinishLoad(), do not release
     // the resources a second time, they have been released by cancel.
@@ -499,7 +502,7 @@ void ResourceLoader::didFinishLoading(double finishTime)
     releaseResources();
 }
 
-void ResourceLoader::didFinishLoadingOnePart(double finishTime)
+void ResourceLoader::didFinishLoadingOnePart(const NetworkLoadMetrics& networkLoadMetrics)
 {
     // If load has been cancelled after finishing (which could happen with a
     // JavaScript that changes the window location), do nothing.
@@ -511,7 +514,7 @@ void ResourceLoader::didFinishLoadingOnePart(double finishTime)
         return;
     m_notifiedLoadComplete = true;
     if (m_options.sendLoadCallbacks == SendCallbacks)
-        frameLoader()->notifier().didFinishLoad(this, finishTime);
+        frameLoader()->notifier().didFinishLoad(this, networkLoadMetrics);
 }
 
 void ResourceLoader::didFail(const ResourceError& error)
@@ -645,9 +648,10 @@ void ResourceLoader::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffe
     didReceiveBuffer(WTFMove(buffer), encodedDataLength, DataPayloadBytes);
 }
 
-void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
+void ResourceLoader::didFinishLoading(ResourceHandle*)
 {
-    didFinishLoading(finishTime);
+    NetworkLoadMetrics emptyMetrics;
+    didFinishLoading(emptyMetrics);
 }
 
 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
index 5bb1eda..5a5ec14 100644 (file)
@@ -50,6 +50,7 @@ class AuthenticationChallenge;
 class DocumentLoader;
 class Frame;
 class FrameLoader;
+class NetworkLoadMetrics;
 class QuickLookHandle;
 class URL;
 
@@ -102,7 +103,7 @@ public:
     virtual void didReceiveResponse(const ResourceResponse&);
     virtual void didReceiveData(const char*, unsigned, long long encodedDataLength, DataPayloadType);
     virtual void didReceiveBuffer(Ref<SharedBuffer>&&, long long encodedDataLength, DataPayloadType);
-    virtual void didFinishLoading(double finishTime);
+    virtual void didFinishLoading(const NetworkLoadMetrics&);
     virtual void didFail(const ResourceError&);
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
     virtual void didReceiveDataArray(CFArrayRef dataArray);
@@ -152,7 +153,7 @@ public:
 protected:
     ResourceLoader(Frame&, ResourceLoaderOptions);
 
-    void didFinishLoadingOnePart(double finishTime);
+    void didFinishLoadingOnePart(const NetworkLoadMetrics&);
     void cleanupForError(const ResourceError&);
 
     bool wasCancelled() const { return m_cancellationStatus >= Cancelled; }
@@ -191,7 +192,7 @@ private:
     void didReceiveResponse(ResourceHandle*, ResourceResponse&&) override;
     void didReceiveData(ResourceHandle*, const char*, unsigned, int encodedDataLength) override;
     void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int encodedDataLength) override;
-    void didFinishLoading(ResourceHandle*, double finishTime) override;
+    void didFinishLoading(ResourceHandle*) override;
     void didFail(ResourceHandle*, const ResourceError&) override;
     void wasBlocked(ResourceHandle*) override;
     void cannotShowURL(ResourceHandle*) override;
index ccdef73..0340be8 100644 (file)
@@ -60,14 +60,14 @@ ResourceTiming ResourceTiming::fromCache(const URL& url, const String& initiator
     return ResourceTiming(url, initiator, loadTiming);
 }
 
-ResourceTiming ResourceTiming::fromLoad(CachedResource& resource, const String& initiator, const LoadTiming& loadTiming, const SecurityOrigin& securityOrigin)
+ResourceTiming ResourceTiming::fromLoad(CachedResource& resource, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const SecurityOrigin& securityOrigin)
 {
-    return ResourceTiming(resource, initiator, loadTiming, securityOrigin);
+    return ResourceTiming(resource, initiator, loadTiming, networkLoadMetrics, securityOrigin);
 }
 
-ResourceTiming ResourceTiming::fromSynchronousLoad(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadTiming& networkLoadTiming, const ResourceResponse& response, const SecurityOrigin& securityOrigin)
+ResourceTiming ResourceTiming::fromSynchronousLoad(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const ResourceResponse& response, const SecurityOrigin& securityOrigin)
 {
-    return ResourceTiming(url, initiator, loadTiming, networkLoadTiming, response, securityOrigin);
+    return ResourceTiming(url, initiator, loadTiming, networkLoadMetrics, response, securityOrigin);
 }
 
 ResourceTiming::ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming)
@@ -78,27 +78,27 @@ ResourceTiming::ResourceTiming(const URL& url, const String& initiator, const Lo
 {
 }
 
-ResourceTiming::ResourceTiming(CachedResource& resource, const String& initiator, const LoadTiming& loadTiming, const SecurityOrigin& securityOrigin)
+ResourceTiming::ResourceTiming(CachedResource& resource, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const SecurityOrigin& securityOrigin)
     : m_url(resource.resourceRequest().url())
     , m_initiator(initiator)
     , m_loadTiming(loadTiming)
-    , m_networkLoadTiming(resource.response().networkLoadTiming())
+    , m_networkLoadMetrics(networkLoadMetrics)
     , m_allowTimingDetails(passesTimingAllowCheck(resource.response(), securityOrigin))
 {
 }
 
-ResourceTiming::ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadTiming& networkLoadTiming, const ResourceResponse& response, const SecurityOrigin& securityOrigin)
+ResourceTiming::ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, const ResourceResponse& response, const SecurityOrigin& securityOrigin)
     : m_url(url)
     , m_initiator(initiator)
     , m_loadTiming(loadTiming)
-    , m_networkLoadTiming(networkLoadTiming)
+    , m_networkLoadMetrics(networkLoadMetrics)
     , m_allowTimingDetails(passesTimingAllowCheck(response, securityOrigin))
 {
 }
 
 ResourceTiming ResourceTiming::isolatedCopy() const
 {
-    return ResourceTiming(m_url.isolatedCopy(), m_initiator.isolatedCopy(), m_loadTiming.isolatedCopy(), m_networkLoadTiming.isolatedCopy(), m_allowTimingDetails);
+    return ResourceTiming(m_url.isolatedCopy(), m_initiator.isolatedCopy(), m_loadTiming.isolatedCopy(), m_networkLoadMetrics.isolatedCopy(), m_allowTimingDetails);
 }
 
 } // namespace WebCore
index 222122a..646235f 100644 (file)
@@ -26,7 +26,7 @@
 #pragma once
 
 #include "LoadTiming.h"
-#include "NetworkLoadTiming.h"
+#include "NetworkLoadMetrics.h"
 #include "URL.h"
 
 namespace WebCore {
@@ -39,13 +39,13 @@ class ResourceTiming {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     static ResourceTiming fromCache(const URL&, const String& initiator, const LoadTiming&);
-    static ResourceTiming fromLoad(CachedResource&, const String& initiator, const LoadTiming&, const SecurityOrigin&);
-    static ResourceTiming fromSynchronousLoad(const URL&, const String& initiator, const LoadTiming&, const NetworkLoadTiming&, const ResourceResponse&, const SecurityOrigin&);
+    static ResourceTiming fromLoad(CachedResource&, const String& initiator, const LoadTiming&, const NetworkLoadMetrics&, const SecurityOrigin&);
+    static ResourceTiming fromSynchronousLoad(const URL&, const String& initiator, const LoadTiming&, const NetworkLoadMetrics&, const ResourceResponse&, const SecurityOrigin&);
 
     URL url() const { return m_url; }
     String initiator() const { return m_initiator; }
     LoadTiming loadTiming() const { return m_loadTiming; }
-    NetworkLoadTiming networkLoadTiming() const { return m_networkLoadTiming; }
+    NetworkLoadMetrics networkLoadMetrics() const { return m_networkLoadMetrics; }
     bool allowTimingDetails() const { return m_allowTimingDetails; }
 
     ResourceTiming isolatedCopy() const;
@@ -53,14 +53,14 @@ public:
     void overrideInitiatorName(const String& name) { m_initiator = name; }
 
 private:
-    ResourceTiming(CachedResource&, const String& initiator, const LoadTiming&, const SecurityOrigin&);
-    ResourceTiming(const URL&, const String& initiator, const LoadTiming&, const NetworkLoadTiming&, const ResourceResponse&, const SecurityOrigin&);
+    ResourceTiming(CachedResource&, const String& initiator, const LoadTiming&, const NetworkLoadMetrics&, const SecurityOrigin&);
+    ResourceTiming(const URL&, const String& initiator, const LoadTiming&, const NetworkLoadMetrics&, const ResourceResponse&, const SecurityOrigin&);
     ResourceTiming(const URL&, const String& initiator, const LoadTiming&);
-    ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadTiming& networkLoadTiming, bool allowTimingDetails)
+    ResourceTiming(const URL& url, const String& initiator, const LoadTiming& loadTiming, const NetworkLoadMetrics& networkLoadMetrics, bool allowTimingDetails)
         : m_url(url)
         , m_initiator(initiator)
         , m_loadTiming(loadTiming)
-        , m_networkLoadTiming(networkLoadTiming)
+        , m_networkLoadMetrics(networkLoadMetrics)
         , m_allowTimingDetails(allowTimingDetails)
     {
     }
@@ -68,7 +68,7 @@ private:
     URL m_url;
     String m_initiator;
     LoadTiming m_loadTiming;
-    NetworkLoadTiming m_networkLoadTiming;
+    NetworkLoadMetrics m_networkLoadMetrics;
     bool m_allowTimingDetails { false };
 };
 
index e3cadca..da8b0ae 100644 (file)
@@ -81,7 +81,6 @@ SubresourceLoader::RequestCountTracker::~RequestCountTracker()
 SubresourceLoader::SubresourceLoader(Frame& frame, CachedResource& resource, const ResourceLoaderOptions& options)
     : ResourceLoader(frame, options)
     , m_resource(&resource)
-    , m_loadingMultipartContent(false)
     , m_state(Uninitialized)
     , m_requestCountTracker(std::in_place, frame.document()->cachedResourceLoader(), resource)
 {
@@ -192,7 +191,8 @@ void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, con
             opaqueRedirectedResponse.setURL(redirectResponse.url());
             opaqueRedirectedResponse.setType(ResourceResponse::Type::Opaqueredirect);
             m_resource->responseReceived(opaqueRedirectedResponse);
-            didFinishLoading(currentTime());
+            NetworkLoadMetrics emptyMetrics;
+            didFinishLoading(emptyMetrics);
             return;
         } else if (m_redirectCount++ >= options().maxRedirectCount) {
             cancel(ResourceError(String(), 0, request().url(), ASCIILiteral("Too many redirections"), ResourceError::Type::General));
@@ -283,8 +283,12 @@ void SubresourceLoader::didReceiveResponse(const ResourceResponse& response)
     }
 #endif
 
-    // We want redirect responses to be processed through willSendRequestInternal. The only exception is redirection with no Location headers.
+    // We want redirect responses to be processed through willSendRequestInternal.
+    // The only exception is redirection with no Location headers. Or in rare circumstances,
+    // cases of too many redirects from CFNetwork (<rdar://problem/30610988>).
+#if !PLATFORM(COCOA)
     ASSERT(response.httpStatusCode() < 300 || response.httpStatusCode() >= 400 || response.httpStatusCode() == 304 || !response.httpHeaderField(HTTPHeaderName::Location));
+#endif
 
     // Reference the object in this method since the additional processing can do
     // anything including removing the last reference to this object; one example of this is 3266216.
@@ -347,8 +351,9 @@ void SubresourceLoader::didReceiveResponse(const ResourceResponse& response)
         clearResourceData();
         // Since a subresource loader does not load multipart sections progressively, data was delivered to the loader all at once.
         // After the first multipart section is complete, signal to delegates that this load is "finished"
+        NetworkLoadMetrics emptyMetrics;
         m_documentLoader->subresourceLoaderFinishedLoadingOnePart(this);
-        didFinishLoadingOnePart(0);
+        didFinishLoadingOnePart(emptyMetrics);
     }
 
     checkForHTTPStatusCodeError();
@@ -510,7 +515,7 @@ bool SubresourceLoader::checkRedirectionCrossOriginAccessControl(const ResourceR
     return true;
 }
 
-void SubresourceLoader::didFinishLoading(double finishTime)
+void SubresourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
 {
 #if USE(QUICK_LOOK)
     if (auto quickLookHandle = m_quickLookHandle.get()) {
@@ -531,30 +536,28 @@ void SubresourceLoader::didFinishLoading(double finishTime)
     Ref<SubresourceLoader> protectedThis(*this);
     CachedResourceHandle<CachedResource> protectResource(m_resource);
 
-    // FIXME: <https://webkit.org/b/168351> [Resource Timing] Gather timing information with reliable responseEnd time
-    // The finishTime that is passed in is from the NetworkProcess and is more accurate.
-    // However, all other load times are generated from the web process or offsets.
-    // Mixing times from different processes can cause the finish time to be earlier than
-    // the response received time due to inter-process communication lag. This could be solved
-    // by gathering NetworkLoadTiming information at completion time instead of at
-    // didReceiveResponse time.
-    UNUSED_PARAM(finishTime);
-    MonotonicTime responseEndTime = MonotonicTime::now();
-    m_loadTiming.setResponseEnd(responseEndTime);
+    // FIXME: Remove this with deprecatedNetworkLoadMetrics.
+    m_loadTiming.setResponseEnd(MonotonicTime::now());
 
 #if ENABLE(WEB_TIMING)
-    reportResourceTiming();
+    if (networkLoadMetrics.isComplete())
+        reportResourceTiming(networkLoadMetrics);
+    else {
+        // This is the legacy path for platforms (and ResourceHandle paths) that do not provide
+        // complete load metrics in didFinishLoad. In those cases, fall back to the possibility
+        // that they populated partial load timing information on the ResourceResponse.
+        reportResourceTiming(m_resource->response().deprecatedNetworkLoadMetrics());
+    }
 #endif
 
     m_state = Finishing;
-    m_resource->setLoadFinishTime(responseEndTime.secondsSinceEpoch().seconds()); // FIXME: Users of the loadFinishTime should use the LoadTiming struct instead.
     m_resource->finishLoading(resourceData());
 
     if (wasCancelled())
         return;
     m_resource->finish();
     ASSERT(!reachedTerminalState());
-    didFinishLoadingOnePart(responseEndTime.secondsSinceEpoch().seconds());
+    didFinishLoadingOnePart(m_resource->response().deprecatedNetworkLoadMetrics());
     notifyDone();
     if (reachedTerminalState())
         return;
@@ -662,7 +665,7 @@ void SubresourceLoader::releaseResources()
 }
 
 #if ENABLE(WEB_TIMING)
-void SubresourceLoader::reportResourceTiming()
+void SubresourceLoader::reportResourceTiming(const NetworkLoadMetrics& networkLoadMetrics)
 {
     if (!RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled())
         return;
@@ -673,9 +676,9 @@ void SubresourceLoader::reportResourceTiming()
     Document* document = m_documentLoader->cachedResourceLoader().document();
     if (!document)
         return;
-    
+
     SecurityOrigin& origin = m_origin ? *m_origin : document->securityOrigin();
-    ResourceTiming resourceTiming = ResourceTiming::fromLoad(*m_resource, m_resource->initiatorName(), m_loadTiming, origin);
+    ResourceTiming resourceTiming = ResourceTiming::fromLoad(*m_resource, m_resource->initiatorName(), m_loadTiming, networkLoadMetrics, origin);
 
     // Worker resources loaded here are all CachedRawResources loaded through WorkerThreadableLoader.
     // Pass the ResourceTiming information on so that WorkerThreadableLoader may add them to the
index 929bc56..828aa9b 100644 (file)
 
 #include "FrameLoaderTypes.h"
 #include "ResourceLoader.h"
-
 #include <wtf/text/WTFString.h>
  
 namespace WebCore {
 
 class CachedResource;
 class CachedResourceLoader;
-class Document;
+class NetworkLoadMetrics;
 class ResourceRequest;
 class SecurityOrigin;
 
@@ -71,7 +70,7 @@ private:
     void didReceiveResponse(const ResourceResponse&) override;
     void didReceiveData(const char*, unsigned, long long encodedDataLength, DataPayloadType) override;
     void didReceiveBuffer(Ref<SharedBuffer>&&, long long encodedDataLength, DataPayloadType) override;
-    void didFinishLoading(double finishTime) override;
+    void didFinishLoading(const NetworkLoadMetrics&) override;
     void didFail(const ResourceError&) override;
     void willCancel(const ResourceError&) override;
     void didCancel(const ResourceError&) override;
@@ -103,7 +102,7 @@ private:
     void notifyDone();
 
 #if ENABLE(WEB_TIMING)
-    void reportResourceTiming();
+    void reportResourceTiming(const NetworkLoadMetrics&);
 #endif
 
 #if USE(QUICK_LOOK)
@@ -135,11 +134,11 @@ private:
     ResourceRequest m_iOSOriginalRequest;
 #endif
     CachedResource* m_resource;
-    bool m_loadingMultipartContent;
     SubresourceLoaderState m_state;
     std::optional<RequestCountTracker> m_requestCountTracker;
     RefPtr<SecurityOrigin> m_origin;
     unsigned m_redirectCount { 0 };
+    bool m_loadingMultipartContent { false };
 };
 
 }
index a51c388..5d4f2c9 100644 (file)
@@ -43,7 +43,7 @@ namespace WebCore {
 
         virtual void didReceiveResponse(unsigned long /*identifier*/, const ResourceResponse&) { }
         virtual void didReceiveData(const char*, int /*dataLength*/) { }
-        virtual void didFinishLoading(unsigned long /*identifier*/, double /*finishTime*/) { }
+        virtual void didFinishLoading(unsigned long /*identifier*/) { }
         virtual void didFail(const ResourceError&) { }
 
 #if ENABLE(WEB_TIMING)
index 602b2f2..23d28da 100644 (file)
@@ -73,11 +73,11 @@ public:
             m_client->didReceiveData(data, dataLength);
     }
 
-    void didFinishLoading(unsigned long identifier, double finishTime)
+    void didFinishLoading(unsigned long identifier)
     {
         m_done = true;
         if (m_client)
-            m_client->didFinishLoading(identifier, finishTime);
+            m_client->didFinishLoading(identifier);
     }
 
     void didFail(const ResourceError& error)
index 31ea9bb..15edb45 100644 (file)
@@ -201,12 +201,12 @@ void WorkerThreadableLoader::MainThreadBridge::didReceiveData(const char* data,
     }, m_taskMode);
 }
 
-void WorkerThreadableLoader::MainThreadBridge::didFinishLoading(unsigned long identifier, double finishTime)
+void WorkerThreadableLoader::MainThreadBridge::didFinishLoading(unsigned long identifier)
 {
     m_loadingFinished = true;
-    m_loaderProxy.postTaskForModeToWorkerGlobalScope([protectedWorkerClientWrapper = makeRef(*m_workerClientWrapper), identifier, finishTime] (ScriptExecutionContext& context) mutable {
+    m_loaderProxy.postTaskForModeToWorkerGlobalScope([protectedWorkerClientWrapper = makeRef(*m_workerClientWrapper), identifier] (ScriptExecutionContext& context) mutable {
         ASSERT_UNUSED(context, context.isWorkerGlobalScope());
-        protectedWorkerClientWrapper->didFinishLoading(identifier, finishTime);
+        protectedWorkerClientWrapper->didFinishLoading(identifier);
     }, m_taskMode);
 }
 
index c0a5705..bc96c81 100644 (file)
@@ -101,7 +101,7 @@ namespace WebCore {
             void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
             void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override;
             void didReceiveData(const char*, int dataLength) override;
-            void didFinishLoading(unsigned long identifier, double finishTime) override;
+            void didFinishLoading(unsigned long identifier) override;
             void didFail(const ResourceError&) override;
 
 #if ENABLE(WEB_TIMING)
index 9f9ab00..b77beb5 100644 (file)
@@ -570,9 +570,9 @@ void ApplicationCacheGroup::didReceiveData(ResourceHandle* handle, const char* d
     m_currentResource->data().append(data, length);
 }
 
-void ApplicationCacheGroup::didFinishLoading(ResourceHandle* handle, double finishTime)
+void ApplicationCacheGroup::didFinishLoading(ResourceHandle* handle)
 {
-    InspectorInstrumentation::didFinishLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, finishTime);
+    InspectorInstrumentation::didFinishLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier);
 
     if (handle == m_manifestHandle) {
         didFinishLoadingManifest();
index ceb83df..5373845 100644 (file)
@@ -108,9 +108,10 @@ private:
     // the existing client callback cannot be used, so assume that any client that enables application cache also wants it to use credential storage.
     bool shouldUseCredentialStorage(ResourceHandle*) override { return true; }
 
+    // ResourceHandleClient
     void didReceiveResponse(ResourceHandle*, ResourceResponse&&) override;
     void didReceiveData(ResourceHandle*, const char*, unsigned length, int encodedDataLength) override;
-    void didFinishLoading(ResourceHandle*, double finishTime) override;
+    void didFinishLoading(ResourceHandle*) override;
     void didFail(ResourceHandle*, const ResourceError&) override;
 
     void didReceiveManifestResponse(const ResourceResponse&);
index 6f4e0e1..380b546 100644 (file)
@@ -260,9 +260,6 @@ public:
 
     virtual void didRetrieveDerivedDataFromCache(const String& /* type */, SharedBuffer&) { }
 
-    void setLoadFinishTime(double finishTime) { m_loadFinishTime = finishTime; }
-    double loadFinishTime() const { return m_loadFinishTime; }
-
 #if USE(FOUNDATION) || USE(SOUP)
     WEBCORE_EXPORT void tryReplaceEncodedData(SharedBuffer&);
 #endif
@@ -323,7 +320,6 @@ private:
     AtomicString m_initiatorName;
 
     double m_lastDecodedAccessTime { 0 }; // Used as a "thrash guard" in the cache
-    double m_loadFinishTime { 0 };
 
     unsigned m_encodedSize { 0 };
     unsigned m_decodedSize { 0 };
index 396b835..d935fa6 100644 (file)
@@ -40,6 +40,7 @@
 #import "ResourceLoader.h"
 #import "ResourceRequest.h"
 #import "SharedBuffer.h"
+#import <WebCore/NetworkLoadMetrics.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/Vector.h>
 #import <wtf/text/WTFString.h>
@@ -230,7 +231,9 @@ static QuickLookHandleClient& emptyClient()
 {
     ASSERT_UNUSED(connection, !connection);
     ASSERT(_hasSentDidReceiveResponse);
-    _resourceLoader->didFinishLoading(0);
+
+    NetworkLoadMetrics emptyMetrics;
+    _resourceLoader->didFinishLoading(emptyMetrics);
 }
 
 static inline bool isQuickLookPasswordError(NSError *error)
index d5555ed..2eae8cf 100644 (file)
@@ -213,7 +213,7 @@ void EventSource::didReceiveData(const char* data, int length)
     parseEventStream();
 }
 
-void EventSource::didFinishLoading(unsigned long, double)
+void EventSource::didFinishLoading(unsigned long)
 {
     ASSERT(m_state == OPEN);
     ASSERT(m_requestInFlight);
index 60501f3..3792a91 100644 (file)
@@ -81,7 +81,7 @@ private:
     // ThreadableLoaderClient
     void didReceiveResponse(unsigned long, const ResourceResponse&) final;
     void didReceiveData(const char*, int) final;
-    void didFinishLoading(unsigned long, double) final;
+    void didFinishLoading(unsigned long) final;
     void didFail(const ResourceError&) final;
 
     void stop() final;
index 270a086..c56f18e 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  * Copyright (C) 2012 Google Inc. All rights reserved.
  * Copyright (C) 2012 Intel Inc. All rights reserved.
  *
@@ -53,17 +54,32 @@ static double monotonicTimeToDOMHighResTimeStamp(MonotonicTime timeOrigin, Monot
     return Performance::reduceTimeResolution(seconds).milliseconds();
 }
 
+static double entryStartTime(MonotonicTime timeOrigin, const ResourceTiming& resourceTiming)
+{
+    return monotonicTimeToDOMHighResTimeStamp(timeOrigin, resourceTiming.loadTiming().startTime());
+}
+
+static double entryEndTime(MonotonicTime timeOrigin, const ResourceTiming& resourceTiming)
+{
+    if (resourceTiming.networkLoadMetrics().isComplete()) {
+        Seconds endTime = (resourceTiming.loadTiming().fetchStart() + resourceTiming.networkLoadMetrics().responseEnd) - timeOrigin;
+        return Performance::reduceTimeResolution(endTime).milliseconds();
+    }
+
+    return monotonicTimeToDOMHighResTimeStamp(timeOrigin, resourceTiming.loadTiming().responseEnd());
+}
+
 Ref<PerformanceResourceTiming> PerformanceResourceTiming::create(MonotonicTime timeOrigin, ResourceTiming&& resourceTiming)
 {
     return adoptRef(*new PerformanceResourceTiming(timeOrigin, WTFMove(resourceTiming)));
 }
 
 PerformanceResourceTiming::PerformanceResourceTiming(MonotonicTime timeOrigin, ResourceTiming&& resourceTiming)
-    : PerformanceEntry(PerformanceEntry::Type::Resource, resourceTiming.url().string(), ASCIILiteral("resource"), monotonicTimeToDOMHighResTimeStamp(timeOrigin, resourceTiming.loadTiming().startTime()), monotonicTimeToDOMHighResTimeStamp(timeOrigin, resourceTiming.loadTiming().responseEnd()))
+    : PerformanceEntry(PerformanceEntry::Type::Resource, resourceTiming.url().string(), ASCIILiteral("resource"), entryStartTime(timeOrigin, resourceTiming), entryEndTime(timeOrigin, resourceTiming))
     , m_initiatorType(resourceTiming.initiator())
     , m_timeOrigin(timeOrigin)
     , m_loadTiming(resourceTiming.loadTiming())
-    , m_networkLoadTiming(resourceTiming.networkLoadTiming())
+    , m_networkLoadMetrics(resourceTiming.networkLoadMetrics())
     , m_shouldReportDetails(resourceTiming.allowTimingDetails())
 {
 }
@@ -72,6 +88,11 @@ PerformanceResourceTiming::~PerformanceResourceTiming()
 {
 }
 
+String PerformanceResourceTiming::nextHopProtocol() const
+{
+    return m_networkLoadMetrics.protocol;
+}
+
 double PerformanceResourceTiming::workerStart() const
 {
     return 0.0;
@@ -106,10 +127,10 @@ double PerformanceResourceTiming::domainLookupStart() const
     if (!m_shouldReportDetails)
         return 0.0;
 
-    if (m_networkLoadTiming.domainLookupStart <= 0)
+    if (m_networkLoadMetrics.domainLookupStart <= 0_ms)
         return fetchStart();
 
-    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadTiming.domainLookupStart);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.domainLookupStart);
 }
 
 double PerformanceResourceTiming::domainLookupEnd() const
@@ -117,10 +138,10 @@ double PerformanceResourceTiming::domainLookupEnd() const
     if (!m_shouldReportDetails)
         return 0.0;
 
-    if (m_networkLoadTiming.domainLookupEnd <= 0)
+    if (m_networkLoadMetrics.domainLookupEnd <= 0_ms)
         return domainLookupStart();
 
-    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadTiming.domainLookupEnd);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.domainLookupEnd);
 }
 
 double PerformanceResourceTiming::connectStart() const
@@ -128,16 +149,10 @@ double PerformanceResourceTiming::connectStart() const
     if (!m_shouldReportDetails)
         return 0.0;
 
-    // connectStart will be -1 when a network request is not made.
-    if (m_networkLoadTiming.connectStart <= 0)
+    if (m_networkLoadMetrics.connectStart <= 0_ms)
         return domainLookupEnd();
 
-    // connectStart includes any DNS time, so we may need to trim that off.
-    double connectStart = m_networkLoadTiming.connectStart;
-    if (m_networkLoadTiming.domainLookupEnd >= 0)
-        connectStart = m_networkLoadTiming.domainLookupEnd;
-
-    return networkLoadTimeToDOMHighResTimeStamp(connectStart);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.connectStart);
 }
 
 double PerformanceResourceTiming::connectEnd() const
@@ -145,11 +160,10 @@ double PerformanceResourceTiming::connectEnd() const
     if (!m_shouldReportDetails)
         return 0.0;
 
-    // connectStart will be -1 when a network request is not made.
-    if (m_networkLoadTiming.connectEnd <= 0)
+    if (m_networkLoadMetrics.connectEnd <= 0_ms)
         return connectStart();
 
-    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadTiming.connectEnd);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.connectEnd);
 }
 
 double PerformanceResourceTiming::secureConnectionStart() const
@@ -157,10 +171,10 @@ double PerformanceResourceTiming::secureConnectionStart() const
     if (!m_shouldReportDetails)
         return 0.0;
 
-    if (m_networkLoadTiming.secureConnectionStart < 0) // Secure connection not negotiated.
+    if (m_networkLoadMetrics.secureConnectionStart <= 0_ms)
         return 0.0;
 
-    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadTiming.secureConnectionStart);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.secureConnectionStart);
 }
 
 double PerformanceResourceTiming::requestStart() const
@@ -169,10 +183,10 @@ double PerformanceResourceTiming::requestStart() const
         return 0.0;
 
     // requestStart is 0 when a network request is not made.
-    if (m_networkLoadTiming.requestStart <= 0)
+    if (m_networkLoadMetrics.requestStart <= 0_ms)
         return connectEnd();
 
-    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadTiming.requestStart);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.requestStart);
 }
 
 double PerformanceResourceTiming::responseStart() const
@@ -181,26 +195,43 @@ double PerformanceResourceTiming::responseStart() const
         return 0.0;
 
     // responseStart is 0 when a network request is not made.
-    if (m_networkLoadTiming.responseStart <= 0)
+    if (m_networkLoadMetrics.responseStart <= 0_ms)
         return requestStart();
 
-    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadTiming.responseStart);
+    return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.responseStart);
 }
 
 double PerformanceResourceTiming::responseEnd() const
 {
     // responseEnd is a required property.
-    ASSERT(m_loadTiming.responseEnd());
+    ASSERT(m_networkLoadMetrics.isComplete() || m_loadTiming.responseEnd());
+
+    if (m_networkLoadMetrics.isComplete()) {
+        // responseEnd is 0 when a network request is not made.
+        // This should mean all other properties are empty.
+        if (m_networkLoadMetrics.responseEnd <= 0_ms) {
+            ASSERT(m_networkLoadMetrics.responseStart <= 0_ms);
+            ASSERT(m_networkLoadMetrics.requestStart <= 0_ms);
+            ASSERT(m_networkLoadMetrics.requestStart <= 0_ms);
+            ASSERT(m_networkLoadMetrics.secureConnectionStart <= 0_ms);
+            ASSERT(m_networkLoadMetrics.connectEnd <= 0_ms);
+            ASSERT(m_networkLoadMetrics.connectStart <= 0_ms);
+            ASSERT(m_networkLoadMetrics.domainLookupEnd <= 0_ms);
+            ASSERT(m_networkLoadMetrics.domainLookupStart <= 0_ms);
+            return fetchStart();
+        }
+
+        return networkLoadTimeToDOMHighResTimeStamp(m_networkLoadMetrics.responseEnd);
+    }
 
     return monotonicTimeToDOMHighResTimeStamp(m_timeOrigin, m_loadTiming.responseEnd());
 }
 
-double PerformanceResourceTiming::networkLoadTimeToDOMHighResTimeStamp(double deltaMilliseconds) const
+double PerformanceResourceTiming::networkLoadTimeToDOMHighResTimeStamp(Seconds delta) const
 {
-    ASSERT(deltaMilliseconds);
-    MonotonicTime combined = m_loadTiming.fetchStart() + Seconds::fromMilliseconds(deltaMilliseconds);
-    Seconds delta = combined - m_timeOrigin;
-    return Performance::reduceTimeResolution(delta).milliseconds();
+    ASSERT(delta);
+    Seconds final = (m_loadTiming.fetchStart() + delta) - m_timeOrigin;
+    return Performance::reduceTimeResolution(final).milliseconds();
 }
 
 } // namespace WebCore
index b11a3cd..c6a7e50 100644 (file)
@@ -34,7 +34,7 @@
 #if ENABLE(WEB_TIMING)
 
 #include "LoadTiming.h"
-#include "NetworkLoadTiming.h"
+#include "NetworkLoadMetrics.h"
 #include "PerformanceEntry.h"
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
@@ -48,6 +48,7 @@ public:
     static Ref<PerformanceResourceTiming> create(MonotonicTime timeOrigin, ResourceTiming&&);
 
     AtomicString initiatorType() const { return m_initiatorType; }
+    String nextHopProtocol() const;
 
     double workerStart() const;
     double redirectStart() const;
@@ -66,12 +67,12 @@ private:
     PerformanceResourceTiming(MonotonicTime timeOrigin, ResourceTiming&&);
     ~PerformanceResourceTiming();
 
-    double networkLoadTimeToDOMHighResTimeStamp(double deltaMilliseconds) const;
+    double networkLoadTimeToDOMHighResTimeStamp(Seconds) const;
 
     AtomicString m_initiatorType;
     MonotonicTime m_timeOrigin;
     LoadTiming m_loadTiming;
-    NetworkLoadTiming m_networkLoadTiming;
+    NetworkLoadMetrics m_networkLoadMetrics;
     bool m_shouldReportDetails;
 };
 
index ebf1e20..d64312d 100644 (file)
@@ -38,6 +38,7 @@ typedef double DOMHighResTimeStamp;
     Exposed=(Window,Worker),
 ] interface PerformanceResourceTiming : PerformanceEntry {
     readonly attribute DOMString initiatorType;
+    readonly attribute DOMString nextHopProtocol;
 
     readonly attribute DOMHighResTimeStamp workerStart;
     readonly attribute DOMHighResTimeStamp redirectStart;
index 2fb5ead..69efe8b 100644 (file)
@@ -39,7 +39,7 @@
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "LoadTiming.h"
-#include "NetworkLoadTiming.h"
+#include "NetworkLoadMetrics.h"
 #include "Performance.h"
 #include "ResourceResponse.h"
 #include <wtf/CurrentTime.h>
@@ -123,11 +123,11 @@ unsigned long long PerformanceTiming::domainLookupStart() const
     if (!loader)
         return fetchStart();
     
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
     // This will be -1 when a DNS request is not performed.
     // Rather than exposing a special value that indicates no DNS, we "backfill" with fetchStart.
-    if (timing.domainLookupStart < 0)
+    if (timing.domainLookupStart < 0_ms)
         return fetchStart();
 
     return resourceLoadTimeRelativeToFetchStart(timing.domainLookupStart);
@@ -139,11 +139,11 @@ unsigned long long PerformanceTiming::domainLookupEnd() const
     if (!loader)
         return domainLookupStart();
     
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
     // This will be -1 when a DNS request is not performed.
     // Rather than exposing a special value that indicates no DNS, we "backfill" with domainLookupStart.
-    if (timing.domainLookupEnd < 0)
+    if (timing.domainLookupEnd < 0_ms)
         return domainLookupStart();
 
     return resourceLoadTimeRelativeToFetchStart(timing.domainLookupEnd);
@@ -155,17 +155,17 @@ unsigned long long PerformanceTiming::connectStart() const
     if (!loader)
         return domainLookupEnd();
 
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
     // connectStart will be -1 when a network request is not made.
     // Rather than exposing a special value that indicates no new connection, we "backfill" with domainLookupEnd.
-    double connectStart = timing.connectStart;
-    if (connectStart < 0)
+    Seconds connectStart = timing.connectStart;
+    if (connectStart < 0_ms)
         return domainLookupEnd();
 
-    // NetworkLoadTiming's connect phase includes DNS, however Navigation Timing's
+    // NetworkLoadMetrics's connect phase includes DNS, however Navigation Timing's
     // connect phase should not. So if there is DNS time, trim it from the start.
-    if (timing.domainLookupEnd >= 0 && timing.domainLookupEnd > connectStart)
+    if (timing.domainLookupEnd >= 0_ms && timing.domainLookupEnd > connectStart)
         connectStart = timing.domainLookupEnd;
 
     return resourceLoadTimeRelativeToFetchStart(connectStart);
@@ -177,11 +177,11 @@ unsigned long long PerformanceTiming::connectEnd() const
     if (!loader)
         return connectStart();
 
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
     // connectEnd will be -1 when a network request is not made.
     // Rather than exposing a special value that indicates no new connection, we "backfill" with connectStart.
-    if (timing.connectEnd < 0)
+    if (timing.connectEnd < 0_ms)
         return connectStart();
 
     return resourceLoadTimeRelativeToFetchStart(timing.connectEnd);
@@ -193,9 +193,9 @@ unsigned long long PerformanceTiming::secureConnectionStart() const
     if (!loader)
         return 0;
 
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
-    if (timing.secureConnectionStart < 0)
+    if (timing.secureConnectionStart < 0_ms)
         return 0;
 
     return resourceLoadTimeRelativeToFetchStart(timing.secureConnectionStart);
@@ -207,9 +207,9 @@ unsigned long long PerformanceTiming::requestStart() const
     if (!loader)
         return connectEnd();
     
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
-    ASSERT(timing.requestStart >= 0);
+    ASSERT(timing.requestStart >= 0_ms);
     return resourceLoadTimeRelativeToFetchStart(timing.requestStart);
 }
 
@@ -219,9 +219,9 @@ unsigned long long PerformanceTiming::responseStart() const
     if (!loader)
         return requestStart();
 
-    const NetworkLoadTiming& timing = loader->response().networkLoadTiming();
+    const NetworkLoadMetrics& timing = loader->response().deprecatedNetworkLoadMetrics();
     
-    ASSERT(timing.responseStart >= 0);
+    ASSERT(timing.responseStart >= 0_ms);
     return resourceLoadTimeRelativeToFetchStart(timing.responseStart);
 }
 
@@ -326,16 +326,16 @@ LoadTiming* PerformanceTiming::loadTiming() const
     return &loader->timing();
 }
 
-unsigned long long PerformanceTiming::resourceLoadTimeRelativeToFetchStart(double relativeMilliseconds) const
+unsigned long long PerformanceTiming::resourceLoadTimeRelativeToFetchStart(Seconds delta) const
 {
-    ASSERT(relativeMilliseconds >= 0);
+    ASSERT(delta >= 0_ms);
 
     LoadTiming* timing = loadTiming();
     if (!timing)
         return 0;
 
     WallTime fetchStart = timing->monotonicTimeToPseudoWallTime(timing->fetchStart());
-    WallTime combined = fetchStart + Seconds::fromMilliseconds(relativeMilliseconds);
+    WallTime combined = fetchStart + delta;
     Seconds reduced = Performance::reduceTimeResolution(combined.secondsSinceEpoch());
     return static_cast<unsigned long long>(reduced.milliseconds());
 }
index 0499f7d..679b35b 100644 (file)
@@ -76,7 +76,7 @@ private:
     const DocumentTiming* documentTiming() const;
     DocumentLoader* documentLoader() const;
     LoadTiming* loadTiming() const;
-    unsigned long long resourceLoadTimeRelativeToFetchStart(double) const;
+    unsigned long long resourceLoadTimeRelativeToFetchStart(Seconds) const;
     unsigned long long monotonicTimeToIntegerMilliseconds(MonotonicTime) const;
 };
 
index e29bd1f..c3bff9a 100644 (file)
@@ -103,7 +103,7 @@ class ResourceHandleStreamingClient : public ResourceHandleClient, public Stream
         void didReceiveResponse(ResourceHandle*, ResourceResponse&&) override;
         void didReceiveData(ResourceHandle*, const char*, unsigned, int) override;
         void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int encodedLength) override;
-        void didFinishLoading(ResourceHandle*, double /*finishTime*/) override;
+        void didFinishLoading(ResourceHandle*) override;
         void didFail(ResourceHandle*, const ResourceError&) override;
         void wasBlocked(ResourceHandle*) override;
         void cannotShowURL(ResourceHandle*) override;
@@ -1172,7 +1172,7 @@ void ResourceHandleStreamingClient::didReceiveBuffer(ResourceHandle*, Ref<Shared
     }
 }
 
-void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*, double)
+void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*)
 {
     handleNotifyFinished();
 }
index e06fa65..8e574c1 100644 (file)
@@ -621,7 +621,7 @@ static void doNotifyFinish(BlobResourceHandle& handle)
     if (!handle.client())
         return;
 
-    handle.client()->didFinishLoading(&handle, 0);
+    handle.client()->didFinishLoading(&handle);
 }
 
 void BlobResourceHandle::notifyFinish()
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
- * Copyright (C) 2014 Apple, Inc. All Rights Reserved.
+ * Copyright (C) 2014-2017 Apple, Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #pragma once
 
+#include <wtf/Seconds.h>
+#include <wtf/text/WTFString.h>
+
 #if PLATFORM(COCOA)
 OBJC_CLASS NSDictionary;
 #endif
 
 namespace WebCore {
-    
-class NetworkLoadTiming {
+
+class NetworkLoadMetrics {
 public:
-    NetworkLoadTiming()
-        : domainLookupStart(-1)
-        , domainLookupEnd(-1)
-        , connectStart(-1)
-        , connectEnd(-1)
-        , requestStart(0)
-        , responseStart(0)
-        , secureConnectionStart(-1)
+    NetworkLoadMetrics()
     {
+        reset();
     }
 
-    NetworkLoadTiming(const NetworkLoadTiming& other)
-        : domainLookupStart(other.domainLookupStart)
-        , domainLookupEnd(other.domainLookupEnd)
-        , connectStart(other.connectStart)
-        , connectEnd(other.connectEnd)
-        , requestStart(other.requestStart)
-        , responseStart(other.responseStart)
-        , secureConnectionStart(other.secureConnectionStart)
+    NetworkLoadMetrics isolatedCopy() const
     {
-    }
+        NetworkLoadMetrics copy;
 
-    NetworkLoadTiming& operator=(const NetworkLoadTiming& other)
-    {
-        domainLookupStart = other.domainLookupStart;
-        domainLookupEnd = other.domainLookupEnd;
-        connectStart = other.connectStart;
-        connectEnd = other.connectEnd;
-        requestStart = other.requestStart;
-        responseStart = other.responseStart;
-        secureConnectionStart = other.secureConnectionStart;
-        return *this;
+        copy.domainLookupStart = domainLookupStart;
+        copy.domainLookupEnd = domainLookupEnd;
+        copy.connectStart = connectStart;
+        copy.secureConnectionStart = secureConnectionStart;
+        copy.connectEnd = connectEnd;
+        copy.requestStart = requestStart;
+        copy.responseStart = responseStart;
+        copy.responseEnd = responseEnd;
+        copy.complete = complete;
+        copy.protocol = protocol.isolatedCopy();
+
+        return copy;
     }
 
-    NetworkLoadTiming isolatedCopy() const
+    void reset()
     {
-        // There are currently no members that need isolated copies, so we can use the copy constructor.
-        return *this;
+        domainLookupStart = Seconds(-1);
+        domainLookupEnd = Seconds(-1);
+        connectStart = Seconds(-1);
+        secureConnectionStart = Seconds(-1);
+        connectEnd = Seconds(-1);
+        requestStart = Seconds(0);
+        responseStart = Seconds(0);
+        responseEnd = Seconds(0);
+        protocol = String();
+        complete = false;
     }
-    
-    bool operator==(const NetworkLoadTiming& other) const
+
+    bool operator==(const NetworkLoadMetrics& other) const
     {
         return domainLookupStart == other.domainLookupStart
             && domainLookupEnd == other.domainLookupEnd
             && connectStart == other.connectStart
+            && secureConnectionStart == other.secureConnectionStart
             && connectEnd == other.connectEnd
             && requestStart == other.requestStart
             && responseStart == other.responseStart
-            && secureConnectionStart == other.secureConnectionStart;
+            && responseEnd == other.responseEnd
+            && complete == other.complete
+            && protocol == other.protocol;
     }
 
-    bool operator!=(const NetworkLoadTiming& other) const
+    bool operator!=(const NetworkLoadMetrics& other) const
     {
         return !(*this == other);
     }
 
+    bool isComplete() const { return complete; }
+    void markComplete() { complete = true; }
+
     template<class Encoder> void encode(Encoder&) const;
-    template<class Decoder> static bool decode(Decoder&, NetworkLoadTiming&);
-
-    // These are millisecond deltas from the start time.
-    double domainLookupStart;
-    double domainLookupEnd;
-    double connectStart;
-    double connectEnd;
-    double requestStart;
-    double responseStart;
-    double secureConnectionStart;
+    template<class Decoder> static bool decode(Decoder&, NetworkLoadMetrics&);
+
+    // These should be treated as deltas to LoadTiming's fetchStart.
+    // They should be in ascending order as listed here.
+    Seconds domainLookupStart;     // -1 if no DNS.
+    Seconds domainLookupEnd;       // -1 if no DNS.
+    Seconds connectStart;          // -1 if reused connection.
+    Seconds secureConnectionStart; // -1 if no secure connection.
+    Seconds connectEnd;            // -1 if reused connection.
+    Seconds requestStart;
+    Seconds responseStart;
+    Seconds responseEnd;
+
+    // Whether or not all of the properties (0 or otherwise) have been set.
+    bool complete { false };
+
+    // ALPN Protocol ID: https://w3c.github.io/resource-timing/#bib-RFC7301
+    String protocol;
 };
 
 #if PLATFORM(COCOA)
-WEBCORE_EXPORT void copyTimingData(NSDictionary *timingData, NetworkLoadTiming&);
+WEBCORE_EXPORT void copyTimingData(NSDictionary *timingData, NetworkLoadMetrics&);
 #endif
 
 #if PLATFORM(COCOA) && !HAVE(TIMINGDATAOPTIONS)
 WEBCORE_EXPORT void setCollectsTimingData();
 #endif
-    
+
 template<class Encoder>
-void NetworkLoadTiming::encode(Encoder& encoder) const
+void NetworkLoadMetrics::encode(Encoder& encoder) const
 {
     encoder << domainLookupStart;
     encoder << domainLookupEnd;
     encoder << connectStart;
+    encoder << secureConnectionStart;
     encoder << connectEnd;
     encoder << requestStart;
     encoder << responseStart;
-    encoder << secureConnectionStart;
+    encoder << responseEnd;
+    encoder << complete;
+    encoder << protocol;
 }
 
 template<class Decoder>
-bool NetworkLoadTiming::decode(Decoder& decoder, NetworkLoadTiming& timing)
+bool NetworkLoadMetrics::decode(Decoder& decoder, NetworkLoadMetrics& timing)
 {
     return decoder.decode(timing.domainLookupStart)
         && decoder.decode(timing.domainLookupEnd)
         && decoder.decode(timing.connectStart)
+        && decoder.decode(timing.secureConnectionStart)
         && decoder.decode(timing.connectEnd)
         && decoder.decode(timing.requestStart)
         && decoder.decode(timing.responseStart)
-        && decoder.decode(timing.secureConnectionStart);
+        && decoder.decode(timing.responseEnd)
+        && decoder.decode(timing.complete)
+        && decoder.decode(timing.protocol);
 }
 
 }
index cd9f2bf..17c54e0 100644 (file)
@@ -71,7 +71,7 @@ private:
     }
     void didReceiveResponse(ResourceHandle*, ResourceResponse&&) final { delete this; }
     void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int) final { delete this; };
-    void didFinishLoading(ResourceHandle*, double) final { delete this; }
+    void didFinishLoading(ResourceHandle*) final { delete this; }
     void didFail(ResourceHandle*, const ResourceError&) final { delete this; }
     bool shouldUseCredentialStorage(ResourceHandle*) final { return m_shouldUseCredentialStorage; }
     bool usesAsyncCallbacks() final { return m_usesAsyncCallbacks == UsesAsyncCallbacks::Yes; }
index e1c429a..86e1161 100644 (file)
@@ -83,7 +83,7 @@ class QuickLookHandle;
 class ResourceError;
 class ResourceHandleClient;
 class ResourceHandleInternal;
-class NetworkLoadTiming;
+class NetworkLoadMetrics;
 class ResourceRequest;
 class ResourceResponse;
 class SoupNetworkSession;
@@ -132,9 +132,9 @@ public:
         
 #if PLATFORM(COCOA) && ENABLE(WEB_TIMING)
 #if USE(CFURLCONNECTION)
-    static void getConnectionTimingData(CFURLConnectionRef, NetworkLoadTiming&);
+    static void getConnectionTimingData(CFURLConnectionRef, NetworkLoadMetrics&);
 #else
-    static void getConnectionTimingData(NSURLConnection *, NetworkLoadTiming&);
+    static void getConnectionTimingData(NSURLConnection *, NetworkLoadMetrics&);
 #endif
 #endif
         
@@ -178,7 +178,7 @@ public:
     void ensureReadBuffer();
     size_t currentStreamPosition() const;
     void didStartRequest();
-    double m_requestTime;
+    MonotonicTime m_requestTime;
 #endif
 
     bool hasAuthenticationChallenge() const;
index 5c371ed..362c251 100644 (file)
@@ -71,7 +71,7 @@ namespace WebCore {
         virtual void didReceiveData(ResourceHandle*, const char*, unsigned, int /*encodedDataLength*/) { }
         WEBCORE_EXPORT virtual void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int encodedDataLength);
         
-        virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/) { }
+        virtual void didFinishLoading(ResourceHandle*) { }
         virtual void didFail(ResourceHandle*, const ResourceError&) { }
         virtual void wasBlocked(ResourceHandle*) { }
         virtual void cannotShowURL(ResourceHandle*) { }
index d7e7056..92a014c 100644 (file)
@@ -71,7 +71,7 @@ ResourceResponseBase::CrossThreadData ResourceResponseBase::crossThreadData() co
     data.httpVersion = httpVersion().isolatedCopy();
 
     data.httpHeaderFields = httpHeaderFields().isolatedCopy();
-    data.networkLoadTiming = m_networkLoadTiming.isolatedCopy();
+    data.networkLoadMetrics = m_networkLoadMetrics.isolatedCopy();
     data.type = m_type;
     data.isRedirected = m_isRedirected;
 
@@ -92,7 +92,7 @@ ResourceResponse ResourceResponseBase::fromCrossThreadData(CrossThreadData&& dat
     response.setHTTPVersion(data.httpVersion);
 
     response.m_httpHeaderFields = WTFMove(data.httpHeaderFields);
-    response.m_networkLoadTiming = data.networkLoadTiming;
+    response.m_networkLoadMetrics = data.networkLoadMetrics;
     response.m_type = data.type;
     response.m_isRedirected = data.isRedirected;
 
@@ -595,7 +595,7 @@ bool ResourceResponseBase::compare(const ResourceResponse& a, const ResourceResp
         return false;
     if (a.httpHeaderFields() != b.httpHeaderFields())
         return false;
-    if (a.networkLoadTiming() != b.networkLoadTiming())
+    if (a.deprecatedNetworkLoadMetrics() != b.deprecatedNetworkLoadMetrics())
         return false;
     return ResourceResponse::platformCompare(a, b);
 }
index fbf125c..1effe1f 100644 (file)
@@ -29,7 +29,7 @@
 #include "CacheValidation.h"
 #include "CertificateInfo.h"
 #include "HTTPHeaderMap.h"
-#include "NetworkLoadTiming.h"
+#include "NetworkLoadMetrics.h"
 #include "ParsedContentRange.h"
 #include "URL.h"
 #include <wtf/SHA1.h>
@@ -58,7 +58,7 @@ public:
         String httpStatusText;
         String httpVersion;
         HTTPHeaderMap httpHeaderFields;
-        NetworkLoadTiming networkLoadTiming;
+        NetworkLoadMetrics networkLoadMetrics;
         Type type;
         bool isRedirected;
     };
@@ -140,7 +140,10 @@ public:
     const std::optional<SHA1::Digest>& cacheBodyKey() const { return m_cacheBodyKey; }
     void setCacheBodyKey(const SHA1::Digest& key) { m_cacheBodyKey = key; }
 
-    NetworkLoadTiming& networkLoadTiming() const { return m_networkLoadTiming; }
+    // FIXME: This should be eliminated from ResourceResponse.
+    // Network loading metrics should be delivered via didFinishLoad
+    // and should not be part of the ResourceResponse.
+    NetworkLoadMetrics& deprecatedNetworkLoadMetrics() const { return m_networkLoadMetrics; }
 
     // The ResourceResponse subclass may "shadow" this method to provide platform-specific memory usage information
     unsigned memoryUsage() const
@@ -192,7 +195,7 @@ protected:
     AtomicString m_httpStatusText;
     AtomicString m_httpVersion;
     HTTPHeaderMap m_httpHeaderFields;
-    mutable NetworkLoadTiming m_networkLoadTiming;
+    mutable NetworkLoadMetrics m_networkLoadMetrics;
 
     mutable std::optional<CertificateInfo> m_certificateInfo;
 
@@ -240,10 +243,10 @@ void ResourceResponseBase::encode(Encoder& encoder) const
     encoder << m_httpVersion;
     encoder << m_httpHeaderFields;
 
-    // We don't want to put the networkLoadTiming info
+    // We don't want to put the networkLoadMetrics info
     // into the disk cache, because we will never use the old info.
     if (Encoder::isIPCEncoder)
-        encoder << m_networkLoadTiming;
+        encoder << m_networkLoadMetrics;
 
     encoder << m_httpStatusCode;
     encoder << m_certificateInfo;
@@ -279,8 +282,8 @@ bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& respon
         return false;
     if (!decoder.decode(response.m_httpHeaderFields))
         return false;
-    // The networkLoadTiming info is only send over IPC and not stored in disk cache.
-    if (Decoder::isIPCDecoder && !decoder.decode(response.m_networkLoadTiming))
+    // The networkLoadMetrics info is only send over IPC and not stored in disk cache.
+    if (Decoder::isIPCDecoder && !decoder.decode(response.m_networkLoadMetrics))
         return false;
     if (!decoder.decode(response.m_httpStatusCode))
         return false;
index 87c994b..98c0b95 100644 (file)
@@ -72,7 +72,7 @@ void SynchronousLoaderClient::didReceiveData(ResourceHandle*, const char* data,
     m_data.append(data, length);
 }
 
-void SynchronousLoaderClient::didFinishLoading(ResourceHandle*, double)
+void SynchronousLoaderClient::didFinishLoading(ResourceHandle*)
 {
     m_isDone = true;
 }
index 9ca0e6a..cb9b309 100644 (file)
@@ -50,7 +50,7 @@ private:
     void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) override;
     void didReceiveResponse(ResourceHandle*, ResourceResponse&&) override;
     void didReceiveData(ResourceHandle*, const char*, unsigned, int /*encodedDataLength*/) override;
-    void didFinishLoading(ResourceHandle*, double /*finishTime*/) override;
+    void didFinishLoading(ResourceHandle*) override;
     void didFail(ResourceHandle*, const ResourceError&) override;
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
     bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace&) override;
index f7a9b2e..17fdc7f 100644 (file)
@@ -156,7 +156,7 @@ void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveResponse
         
         ResourceResponse resourceResponse(cfResponse);
 #if ENABLE(WEB_TIMING)
-        ResourceHandle::getConnectionTimingData(connection, resourceResponse.networkLoadTiming());
+        ResourceHandle::getConnectionTimingData(connection, resourceResponse.deprecatedNetworkLoadMetrics());
 #else
         UNUSED_PARAM(connection);
 #endif
@@ -195,7 +195,7 @@ void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading()
 
         LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didFinishLoading(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
 
-        m_handle->client()->didFinishLoading(m_handle, 0);
+        m_handle->client()->didFinishLoading(m_handle);
     });
 }
 
index 282d283..bec1b19 100644 (file)
@@ -171,7 +171,7 @@ void SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse(CFURLC
 
     ResourceResponse resourceResponse(cfResponse);
 #if PLATFORM(COCOA) && ENABLE(WEB_TIMING)
-    ResourceHandle::getConnectionTimingData(connection, resourceResponse.networkLoadTiming());
+    ResourceHandle::getConnectionTimingData(connection, resourceResponse.deprecatedNetworkLoadMetrics());
 #else
     UNUSED_PARAM(connection);
 #endif
@@ -192,7 +192,7 @@ void SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading()
     LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
 
     if (ResourceHandleClient* client = m_handle->client())
-        client->didFinishLoading(m_handle, 0);
+        client->didFinishLoading(m_handle);
 }
 
 void SynchronousResourceHandleCFURLConnectionDelegate::didFail(CFErrorRef error)
@@ -24,7 +24,7 @@
  */
 
 #import "config.h"
-#import "NetworkLoadTiming.h"
+#import "NetworkLoadMetrics.h"
 
 #import <WebCore/NSURLConnectionSPI.h>
 
@@ -37,7 +37,7 @@ static double timingValue(NSDictionary *timingData, NSString *key)
     return 0.0;
 }
     
-void copyTimingData(NSDictionary *timingData, NetworkLoadTiming& timing)
+void copyTimingData(NSDictionary *timingData, NetworkLoadMetrics& timing)
 {
     if (!timingData)
         return;
@@ -54,13 +54,15 @@ void copyTimingData(NSDictionary *timingData, NetworkLoadTiming& timing)
     double requestStart = timingValue(timingData, @"_kCFNTimingDataRequestStart");
     double responseStart = timingValue(timingData, @"_kCFNTimingDataResponseStart");
     
-    timing.domainLookupStart = domainLookupStart <= 0 ? -1 : (domainLookupStart - referenceStart) * 1000;
-    timing.domainLookupEnd = domainLookupEnd <= 0 ? -1 : (domainLookupEnd - referenceStart) * 1000;
-    timing.connectStart = connectStart <= 0 ? -1 : (connectStart - referenceStart) * 1000;
-    timing.secureConnectionStart = secureConnectionStart <= 0 ? -1 : (secureConnectionStart - referenceStart) * 1000;
-    timing.connectEnd = connectEnd <= 0 ? -1 : (connectEnd - referenceStart) * 1000;
-    timing.requestStart = requestStart <= 0 ? 0 : (requestStart - referenceStart) * 1000;
-    timing.responseStart = responseStart <= 0 ? 0 : (responseStart - referenceStart) * 1000;
+    timing.domainLookupStart = Seconds(domainLookupStart <= 0 ? Seconds(-1) : Seconds::fromMilliseconds(domainLookupStart - referenceStart));
+    timing.domainLookupEnd = Seconds(domainLookupEnd <= 0 ? Seconds(-1) : Seconds::fromMilliseconds(domainLookupEnd - referenceStart));
+    timing.connectStart = Seconds(connectStart <= 0 ? Seconds(-1) : Seconds::fromMilliseconds(connectStart - referenceStart));
+    timing.secureConnectionStart = Seconds(secureConnectionStart <= 0 ? Seconds(-1) : Seconds::fromMilliseconds(secureConnectionStart - referenceStart));
+    timing.connectEnd = Seconds(connectEnd <= 0 ? Seconds(-1) : Seconds::fromMilliseconds(connectEnd - referenceStart));
+    timing.requestStart = Seconds(requestStart <= 0 ? Seconds(0) : Seconds::fromMilliseconds(requestStart - referenceStart));
+    timing.responseStart = Seconds(responseStart <= 0 ? Seconds(0) : Seconds::fromMilliseconds(responseStart - referenceStart));
+
+    // NOTE: responseEnd is not populated in this code path.
 }
 
 #if !HAVE(TIMINGDATAOPTIONS)
index c254011..2adb844 100644 (file)
@@ -48,7 +48,7 @@ public:
 
     virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
     virtual void didReceiveData(ResourceHandle*, const char*, unsigned, int encodedDataLength);
-    virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/);
+    virtual void didFinishLoading(ResourceHandle*);
     virtual void didFail(ResourceHandle*, const ResourceError&);
 
     ResourceResponse resourceResponse() const { return m_response; }
@@ -75,7 +75,7 @@ void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data,
     m_data.append(data, length);
 }
 
-void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*, double)
+void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*)
 {
 }
 
index acf6027..358e02a 100644 (file)
@@ -170,14 +170,8 @@ static Lock* sharedResourceMutex(curl_lock_data data)
 }
 
 #if ENABLE(WEB_TIMING)
-static double milisecondsSinceRequest(double requestTime)
-{
-    return (monotonicallyIncreasingTime() - requestTime) * 1000.0;
-}
-
 static void calculateWebTimingInformations(ResourceHandleInternal* d)
 {
-    double startTransfertTime = 0;
     double preTransferTime = 0;
     double dnslookupTime = 0;
     double connectTime = 0;
@@ -186,20 +180,19 @@ static void calculateWebTimingInformations(ResourceHandleInternal* d)
     curl_easy_getinfo(d->m_handle, CURLINFO_NAMELOOKUP_TIME, &dnslookupTime);
     curl_easy_getinfo(d->m_handle, CURLINFO_CONNECT_TIME, &connectTime);
     curl_easy_getinfo(d->m_handle, CURLINFO_APPCONNECT_TIME, &appConnectTime);
-    curl_easy_getinfo(d->m_handle, CURLINFO_STARTTRANSFER_TIME, &startTransfertTime);
     curl_easy_getinfo(d->m_handle, CURLINFO_PRETRANSFER_TIME, &preTransferTime);
 
-    d->m_response.networkLoadTiming().domainLookupStart = 0;
-    d->m_response.networkLoadTiming().domainLookupEnd = dnslookupTime * 1000;
+    d->m_response.deprecatedNetworkLoadMetrics().domainLookupStart = Seconds(0);
+    d->m_response.deprecatedNetworkLoadMetrics().domainLookupEnd = Seconds(dnslookupTime);
 
-    d->m_response.networkLoadTiming().connectStart = dnslookupTime * 1000;
-    d->m_response.networkLoadTiming().connectEnd = connectTime * 1000;
+    d->m_response.deprecatedNetworkLoadMetrics().connectStart = Seconds(dnslookupTime);
+    d->m_response.deprecatedNetworkLoadMetrics().connectEnd = Seconds(connectTime);
 
-    d->m_response.networkLoadTiming().requestStart = connectTime * 1000;
-    d->m_response.networkLoadTiming().responseStart = preTransferTime * 1000;
+    d->m_response.deprecatedNetworkLoadMetrics().requestStart = Seconds(connectTime);
+    d->m_response.deprecatedNetworkLoadMetrics().responseStart = Seconds(preTransferTime);
 
     if (appConnectTime)
-        d->m_response.networkLoadTiming().secureConnectionStart = connectTime * 1000;
+        d->m_response.deprecatedNetworkLoadMetrics().secureConnectionStart = Seconds(connectTime);
 }
 #endif
 
@@ -677,7 +670,7 @@ void ResourceHandleManager::downloadTimerCallback()
         // find the node which has same d->m_handle as completed transfer
         CURL* handle = msg->easy_handle;
         ASSERT(handle);
-        ResourceHandle* job = 0;
+        ResourceHandle* job = nullptr;
         CURLcode err = curl_easy_getinfo(handle, CURLINFO_PRIVATE, &job);
         ASSERT_UNUSED(err, CURLE_OK == err);
         ASSERT(job);
@@ -711,7 +704,7 @@ void ResourceHandleManager::downloadTimerCallback()
                 d->m_multipartHandle->contentEnded();
 
             if (d->client()) {
-                d->client()->didFinishLoading(job, 0);
+                d->client()->didFinishLoading(job);
                 CurlCacheManager::getInstance().didFinishLoading(*job);
             }
         } else {
@@ -972,7 +965,7 @@ static void handleDataURL(ResourceHandle* handle)
     }
 
     if (handle->client())
-        handle->client()->didFinishLoading(handle, 0);
+        handle->client()->didFinishLoading(handle);
 }
 
 void ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job)
index ada8988..6a5ce43 100644 (file)
@@ -736,14 +736,14 @@ void ResourceHandle::continueWillCacheResponse(NSCachedURLResponse *response)
 
 #if USE(CFURLCONNECTION)
     
-void ResourceHandle::getConnectionTimingData(CFURLConnectionRef connection, NetworkLoadTiming& timing)
+void ResourceHandle::getConnectionTimingData(CFURLConnectionRef connection, NetworkLoadMetrics& timing)
 {
     copyTimingData((__bridge NSDictionary*)adoptCF(_CFURLConnectionCopyTimingData(connection)).get(), timing);
 }
     
 #else
     
-void ResourceHandle::getConnectionTimingData(NSURLConnection *connection, NetworkLoadTiming& timing)
+void ResourceHandle::getConnectionTimingData(NSURLConnection *connection, NetworkLoadMetrics& timing)
 {
     copyTimingData([connection _timingData], timing);
 }
index fc1f4f6..f0ec325 100644 (file)
@@ -145,7 +145,7 @@ using namespace WebCore;
     ResourceResponse resourceResponse(response);
     resourceResponse.setSource(ResourceResponse::Source::Network);
 #if ENABLE(WEB_TIMING)
-    ResourceHandle::getConnectionTimingData(connection, resourceResponse.networkLoadTiming());
+    ResourceHandle::getConnectionTimingData(connection, resourceResponse.deprecatedNetworkLoadMetrics());
 #else
     UNUSED_PARAM(connection);
 #endif
@@ -215,7 +215,7 @@ using namespace WebCore;
     if (!m_handle || !m_handle->client())
         return;
 
-    m_handle->client()->didFinishLoading(m_handle, 0);
+    m_handle->client()->didFinishLoading(m_handle);
 }
 
 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
index 002e128..2c93a4b 100644 (file)
@@ -195,7 +195,7 @@ using namespace WebCore;
         
         ResourceResponse resourceResponse(r);
 #if ENABLE(WEB_TIMING)
-        ResourceHandle::getConnectionTimingData(connection, resourceResponse.networkLoadTiming());
+        ResourceHandle::getConnectionTimingData(connection, resourceResponse.deprecatedNetworkLoadMetrics());
 #else
         UNUSED_PARAM(connection);
 #endif
@@ -274,7 +274,7 @@ using namespace WebCore;
         if (!m_handle || !m_handle->client())
             return;
 
-        m_handle->client()->didFinishLoading(m_handle, 0);
+        m_handle->client()->didFinishLoading(m_handle);
     });
 }
 
index e76fac8..e68e51c 100644 (file)
@@ -68,9 +68,6 @@ static bool createSoupRequestAndMessageForHandle(ResourceHandle*, const Resource
 static void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying = false);
 static void sendRequestCallback(GObject*, GAsyncResult*, gpointer);
 static void readCallback(GObject*, GAsyncResult*, gpointer);
-#if ENABLE(WEB_TIMING)
-static double milisecondsSinceRequest(double requestTime);
-#endif
 static void continueAfterDidReceiveResponse(ResourceHandle*);
 
 ResourceHandleInternal::~ResourceHandleInternal()
@@ -247,7 +244,7 @@ static void restartedCallback(SoupMessage*, gpointer data)
     if (!handle || handle->cancelledOrClientless())
         return;
 
-    handle->m_requestTime = monotonicallyIncreasingTime();
+    handle->m_requestTime = MonotonicTime::now();
 }
 #endif
 
@@ -468,7 +465,7 @@ static void nextMultipartResponsePartCallback(GObject* /*source*/, GAsyncResult*
     }
 
     if (!d->m_inputStream) {
-        handle->client()->didFinishLoading(handle.get(), 0);
+        handle->client()->didFinishLoading(handle.get());
         cleanupSoupRequestOperation(handle.get());
         return;
     }
@@ -530,7 +527,7 @@ static void sendRequestCallback(GObject*, GAsyncResult* result, gpointer data)
     }
 
 #if ENABLE(WEB_TIMING)
-    d->m_response.networkLoadTiming().responseStart = milisecondsSinceRequest(handle->m_requestTime);
+    d->m_response.deprecatedNetworkLoadMetrics().responseStart = MonotonicTime::now() - handle->m_requestTime;
 #endif
 
     if (soupMessage && d->m_response.isMultipart())
@@ -567,14 +564,9 @@ static void continueAfterDidReceiveResponse(ResourceHandle* handle)
 }
 
 #if ENABLE(WEB_TIMING)
-static double milisecondsSinceRequest(double requestTime)
-{
-    return (monotonicallyIncreasingTime() - requestTime) * 1000.0;
-}
-
 void ResourceHandle::didStartRequest()
 {
-    getInternal()->m_response.networkLoadTiming().requestStart = milisecondsSinceRequest(m_requestTime);
+    getInternal()->m_response.deprecatedNetworkLoadMetrics().requestStart = MonotonicTime::now() - m_requestTime;
 }
 
 #if SOUP_CHECK_VERSION(2, 49, 91)
@@ -594,24 +586,24 @@ static void networkEventCallback(SoupMessage*, GSocketClientEvent event, GIOStre
         return;
 
     ResourceHandleInternal* d = handle->getInternal();
-    double deltaTime = milisecondsSinceRequest(handle->m_requestTime);
+    Seconds deltaTime = MonotonicTime::now() - handle->m_requestTime;
     switch (event) {
     case G_SOCKET_CLIENT_RESOLVING:
-        d->m_response.networkLoadTiming().domainLookupStart = deltaTime;
+        d->m_response.deprecatedNetworkLoadMetrics().domainLookupStart = deltaTime;
         break;
     case G_SOCKET_CLIENT_RESOLVED:
-        d->m_response.networkLoadTiming().domainLookupEnd = deltaTime;
+        d->m_response.deprecatedNetworkLoadMetrics().domainLookupEnd = deltaTime;
         break;
     case G_SOCKET_CLIENT_CONNECTING:
-        d->m_response.networkLoadTiming().connectStart = deltaTime;
-        if (d->m_response.networkLoadTiming().domainLookupStart != -1) {
+        d->m_response.deprecatedNetworkLoadMetrics().connectStart = deltaTime;
+        if (d->m_response.deprecatedNetworkLoadMetrics().domainLookupStart != Seconds(-1)) {
             // WebCore/inspector/front-end/RequestTimingView.js assumes
             // that DNS time is included in connection time so must
             // substract here the DNS delta that will be added later (see
             // WebInspector.RequestTimingView.createTimingTable in the
             // file above for more details).
-            d->m_response.networkLoadTiming().connectStart -=
-                d->m_response.networkLoadTiming().domainLookupEnd - d->m_response.networkLoadTiming().domainLookupStart;
+            d->m_response.deprecatedNetworkLoadMetrics().connectStart -=
+                d->m_response.deprecatedNetworkLoadMetrics().domainLookupEnd - d->m_response.deprecatedNetworkLoadMetrics().domainLookupStart;
         }
         break;
     case G_SOCKET_CLIENT_CONNECTED:
@@ -623,12 +615,12 @@ static void networkEventCallback(SoupMessage*, GSocketClientEvent event, GIOStre
     case G_SOCKET_CLIENT_PROXY_NEGOTIATED:
         break;
     case G_SOCKET_CLIENT_TLS_HANDSHAKING:
-        d->m_response.networkLoadTiming().secureConnectionStart = deltaTime;
+        d->m_response.deprecatedNetworkLoadMetrics().secureConnectionStart = deltaTime;
         break;
     case G_SOCKET_CLIENT_TLS_HANDSHAKED:
         break;
     case G_SOCKET_CLIENT_COMPLETE:
-        d->m_response.networkLoadTiming().connectEnd = deltaTime;
+        d->m_response.deprecatedNetworkLoadMetrics().connectEnd = deltaTime;
         break;
     default:
         ASSERT_NOT_REACHED();
@@ -776,7 +768,7 @@ void ResourceHandle::timeoutFired()
 void ResourceHandle::sendPendingRequest()
 {
 #if ENABLE(WEB_TIMING)
-    m_requestTime = monotonicallyIncreasingTime();
+    m_requestTime = MonotonicTime::now();
 #endif
 
     if (d->m_firstRequest.timeoutInterval() > 0)
@@ -1020,7 +1012,7 @@ static void readCallback(GObject*, GAsyncResult* asyncResult, gpointer data)
 
         g_input_stream_close(d->m_inputStream.get(), 0, 0);
 
-        handle->client()->didFinishLoading(handle.get(), 0);
+        handle->client()->didFinishLoading(handle.get());
         cleanupSoupRequestOperation(handle.get());
         return;
     }
index b6aa267..62c9470 100644 (file)
@@ -144,7 +144,7 @@ void WorkerScriptLoader::didReceiveData(const char* data, int len)
     m_script.append(m_decoder->decode(data, len));
 }
 
-void WorkerScriptLoader::didFinishLoading(unsigned long identifier, double)
+void WorkerScriptLoader::didFinishLoading(unsigned long identifier)
 {
     if (m_failed) {
         notifyError();
index 77ce0fd..c80798a 100644 (file)
@@ -64,7 +64,7 @@ namespace WebCore {
 
         void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override;
         void didReceiveData(const char* data, int dataLength) override;
-        void didFinishLoading(unsigned long identifier, double) override;
+        void didFinishLoading(unsigned long identifier) override;
         void didFail(const ResourceError&) override;
 
     private:
index 8ab3557..8222121 100644 (file)
@@ -1029,7 +1029,7 @@ void XMLHttpRequest::didFail(const ResourceError& error)
     networkError();
 }
 
-void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
+void XMLHttpRequest::didFinishLoading(unsigned long identifier)
 {
     if (m_error)
         return;
index 0c61fdb..dad5662 100644 (file)
@@ -149,7 +149,7 @@ private:
     void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
     void didReceiveResponse(unsigned long identifier, const ResourceResponse&) override;
     void didReceiveData(const char* data, int dataLength) override;
-    void didFinishLoading(unsigned long identifier, double finishTime) override;
+    void didFinishLoading(unsigned long identifier) override;
     void didFail(const ResourceError&) override;
 
     bool responseIsXML() const;
index 7192584..30a79a6 100644 (file)
@@ -1,3 +1,81 @@
+2017-02-24  Joseph Pecoraro  <pecoraro@apple.com>
+
+        [Resource Timing] Gather timing information with reliable responseEnd time
+        https://bugs.webkit.org/show_bug.cgi?id=168351
+
+        Reviewed by Alex Christensen.
+
+        Change from an unused `double finishTime` to a complete WebCore::NetworkLoadMetrics
+        object in the didFinishLoad ResourceLoader path. We may also extend this in the
+        didFail path later on. This allows the NetworkProcess to give complete timing
+        information, and more final metrics about the load, to WebCore.
+
+        * NetworkProcess/NetworkDataTask.h:
+        (WebKit::NetworkDataTaskClient::didCompleteWithError):
+        Give the NetworkDataTaskClient a basic didCompleteWithError for a completion
+        without metrics. For loads that complete with an error, or haven't populated
+        any metrics, this will pass empty metrics onward.
+
+        * NetworkProcess/Downloads/BlobDownloadClient.cpp:
+        (WebKit::BlobDownloadClient::didFinishLoading):
+        * NetworkProcess/Downloads/BlobDownloadClient.h:
+        * NetworkProcess/Downloads/PendingDownload.h:
+        * NetworkProcess/PingLoad.h:
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp:
+        (WebKit::NetworkCache::SpeculativeLoad::didFinishLoading):
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoad.h:
+        * NetworkProcess/NetworkDataTaskBlob.cpp:
+        (WebKit::NetworkDataTaskBlob::didFail):
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::continueWillSendRequest):
+        (WebKit::NetworkLoad::didCompleteWithError):
+        (WebKit::NetworkLoad::didFinishLoading):
+        * NetworkProcess/NetworkLoad.h:
+        * NetworkProcess/NetworkLoadClient.h:
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::didFinishLoading):
+        (WebKit::NetworkResourceLoader::sendResultForCacheEntry):
+        * NetworkProcess/NetworkResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::didFinishResourceLoad):
+        (WebKit::WebResourceLoader::didReceiveResource):
+        * WebProcess/Network/WebResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.messages.in:
+        Change didFinishLoad paths to take a NetworkLoadMetrics object instead of finishTime.
+        Change didCompleteWithError pathes to include a NetworkLoadMetrics object instead of finishTime.
+
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.h:
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTaskCocoa::didCompleteWithError):
+        Own a NetworkLoadTiming that will be populated with the load.
+
+        * NetworkProcess/cocoa/NetworkSessionCocoa.h:
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
+        (-[WKNetworkSessionDelegate URLSession:task:didFinishCollectingMetrics:]):
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
+        Populate NetworkLoadMetrics in the didFinishCollectingMetrics NSURLSessionTaskDelegate method.
+
+        * NetworkProcess/soup/NetworkDataTaskSoup.cpp:
+        (WebKit::NetworkDataTaskSoup::NetworkDataTaskSoup):
+        (WebKit::NetworkDataTaskSoup::timeoutFired):
+        (WebKit::NetworkDataTaskSoup::didSendRequest):
+        (WebKit::NetworkDataTaskSoup::dispatchDidReceiveResponse):
+        (WebKit::NetworkDataTaskSoup::dispatchDidCompleteWithError):
+        (WebKit::NetworkDataTaskSoup::tlsErrorsChanged):
+        (WebKit::NetworkDataTaskSoup::continueHTTPRedirection):
+        (WebKit::NetworkDataTaskSoup::didFinishRead):
+        (WebKit::NetworkDataTaskSoup::didFinishRequestNextPart):
+        (WebKit::NetworkDataTaskSoup::didFailDownload):
+        (WebKit::NetworkDataTaskSoup::didFail):
+        (WebKit::NetworkDataTaskSoup::networkEvent):
+        (WebKit::NetworkDataTaskSoup::didStartRequest):
+        (WebKit::NetworkDataTaskSoup::didRestart):
+        * NetworkProcess/soup/NetworkDataTaskSoup.h:
+        Instead of populating the NetworkLoadMetrics on the ResourceResponse, populate
+        a member variable during the entire load and dispatch didFinishCollectingMetrics
+        right before didCompleteLoadWithError.
+
 2017-02-24  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, rolling out r212944.
index cf9acce..c6ff15a 100644 (file)
@@ -77,7 +77,7 @@ void BlobDownloadClient::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& b
     m_download.didReceiveData(buffer->size());
 }
 
-void BlobDownloadClient::didFinishLoading(ResourceHandle*, double)
+void BlobDownloadClient::didFinishLoading(ResourceHandle*)
 {
     closeFile(m_destinationFile);
     m_download.didFinish();
index 4a3e63e..4a42cc2 100644 (file)
@@ -47,7 +47,7 @@ private:
     // ResourceHandleClient
     void didReceiveResponseAsync(WebCore::ResourceHandle*, WebCore::ResourceResponse&&) final;
     void didReceiveBuffer(WebCore::ResourceHandle*, Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) final;
-    void didFinishLoading(WebCore::ResourceHandle*, double finishTime) final;
+    void didFinishLoading(WebCore::ResourceHandle*) final;
     void didFail(WebCore::ResourceHandle*, const WebCore::ResourceError&) final;
     bool usesAsyncCallbacks() final { return true; }
 
index 208d73d..38fc2e1 100644 (file)
@@ -64,7 +64,7 @@ private:
     void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) override;
     ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) override { return ShouldContinueDidReceiveResponse::No; };
     void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override { };
-    void didFinishLoading(double finishTime) override { };
+    void didFinishLoading(const WebCore::NetworkLoadMetrics&) override { };
     void didFailLoading(const WebCore::ResourceError&) override;
 
     // MessageSender.
index cc47307..6cb826d 100644 (file)
@@ -31,6 +31,7 @@
 #include "SandboxExtension.h"
 #include <WebCore/Credential.h>
 #include <WebCore/FrameLoaderTypes.h>
+#include <WebCore/NetworkLoadMetrics.h>
 #include <WebCore/ResourceHandleTypes.h>
 #include <WebCore/ResourceLoaderOptions.h>
 #include <WebCore/ResourceRequest.h>
@@ -63,11 +64,17 @@ public:
     virtual void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&) = 0;
     virtual void didReceiveResponseNetworkSession(WebCore::ResourceResponse&&, ResponseCompletionHandler&&) = 0;
     virtual void didReceiveData(Ref<WebCore::SharedBuffer>&&) = 0;
-    virtual void didCompleteWithError(const WebCore::ResourceError&) = 0;
+    virtual void didCompleteWithError(const WebCore::ResourceError&, const WebCore::NetworkLoadMetrics&) = 0;
     virtual void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) = 0;
     virtual void wasBlocked() = 0;
     virtual void cannotShowURL() = 0;
-    
+
+    void didCompleteWithError(const WebCore::ResourceError& error)
+    {
+        WebCore::NetworkLoadMetrics emptyMetrics;
+        didCompleteWithError(error, emptyMetrics);
+    }
+
     virtual ~NetworkDataTaskClient() { }
 };
 
index 1c3e281..710db79 100644 (file)
@@ -199,7 +199,8 @@ void NetworkLoad::continueWillSendRequest(WebCore::ResourceRequest&& newRequest)
     auto redirectCompletionHandler = std::exchange(m_redirectCompletionHandler, nullptr);
     ASSERT(redirectCompletionHandler);
     if (m_currentRequest.isNull()) {
-        didCompleteWithError(cancelledError(m_currentRequest));
+        NetworkLoadMetrics emptyMetrics;
+        didCompleteWithError(cancelledError(m_currentRequest), emptyMetrics);
         if (redirectCompletionHandler)
             redirectCompletionHandler({ });
         return;
@@ -408,7 +409,7 @@ void NetworkLoad::didReceiveData(Ref<SharedBuffer>&& buffer)
     m_client.get().didReceiveBuffer(WTFMove(buffer), size);
 }
 
-void NetworkLoad::didCompleteWithError(const ResourceError& error)
+void NetworkLoad::didCompleteWithError(const ResourceError& error, const WebCore::NetworkLoadMetrics& networkLoadMetrics)
 {
     ASSERT(!m_throttle);
 
@@ -418,7 +419,7 @@ void NetworkLoad::didCompleteWithError(const ResourceError& error)
 #endif
 
     if (error.isNull())
-        m_client.get().didFinishLoading(WTF::monotonicallyIncreasingTime());
+        m_client.get().didFinishLoading(networkLoadMetrics);
     else
         m_client.get().didFailLoading(error);
 }
@@ -469,10 +470,11 @@ void NetworkLoad::didReceiveBuffer(ResourceHandle* handle, Ref<SharedBuffer>&& b
     m_client.get().didReceiveBuffer(WTFMove(buffer), reportedEncodedDataLength);
 }
 
-void NetworkLoad::didFinishLoading(ResourceHandle* handle, double finishTime)
+void NetworkLoad::didFinishLoading(ResourceHandle* handle)
 {
     ASSERT_UNUSED(handle, handle == m_handle);
-    m_client.get().didFinishLoading(finishTime);
+    NetworkLoadMetrics emptyMetrics;
+    m_client.get().didFinishLoading(emptyMetrics);
 }
 
 void NetworkLoad::didFail(ResourceHandle* handle, const ResourceError& error)
index b252a0c..ef72522 100644 (file)
@@ -118,7 +118,7 @@ private:
     void didReceiveResponseAsync(WebCore::ResourceHandle*, WebCore::ResourceResponse&&) final;
     void didReceiveData(WebCore::ResourceHandle*, const char*, unsigned, int encodedDataLength) final;
     void didReceiveBuffer(WebCore::ResourceHandle*, Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) final;
-    void didFinishLoading(WebCore::ResourceHandle*, double finishTime) final;
+    void didFinishLoading(WebCore::ResourceHandle*) final;
     void didFail(WebCore::ResourceHandle*, const WebCore::ResourceError&) final;
     void wasBlocked(WebCore::ResourceHandle*) final;
     void cannotShowURL(WebCore::ResourceHandle*) final;
@@ -133,7 +133,7 @@ private:
     void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&) final;
     void didReceiveResponseNetworkSession(WebCore::ResourceResponse&&, ResponseCompletionHandler&&) final;
     void didReceiveData(Ref<WebCore::SharedBuffer>&&) final;
-    void didCompleteWithError(const WebCore::ResourceError&) final;
+    void didCompleteWithError(const WebCore::ResourceError&, const WebCore::NetworkLoadMetrics&) final;
     void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) final;
     void wasBlocked() final;
     void cannotShowURL() final;
index 87a52d2..e589e3a 100644 (file)
@@ -35,6 +35,7 @@ typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef;
 #endif
 
 namespace WebCore {
+class NetworkLoadMetrics;
 class ProtectionSpace;
 class SharedBuffer;
 }
@@ -55,7 +56,7 @@ public:
     enum class ShouldContinueDidReceiveResponse { No, Yes };
     virtual ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) = 0;
     virtual void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) = 0;
-    virtual void didFinishLoading(double finishTime) = 0;
+    virtual void didFinishLoading(const WebCore::NetworkLoadMetrics&) = 0;
     virtual void didFailLoading(const WebCore::ResourceError&) = 0;
 };
 
index bab56b3..241aac3 100644 (file)
@@ -42,6 +42,7 @@
 #include <WebCore/CertificateInfo.h>
 #include <WebCore/DiagnosticLoggingKeys.h>
 #include <WebCore/HTTPHeaderNames.h>
+#include <WebCore/NetworkLoadMetrics.h>
 #include <WebCore/ProtectionSpace.h>
 #include <WebCore/SharedBuffer.h>
 #include <WebCore/SynchronousLoaderClient.h>
@@ -390,7 +391,7 @@ void NetworkResourceLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int rep
     sendBuffer(buffer, encodedDataLength);
 }
 
-void NetworkResourceLoader::didFinishLoading(double finishTime)
+void NetworkResourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
 {
     RELEASE_LOG_IF_ALLOWED("didFinishLoading: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
 
@@ -411,7 +412,7 @@ void NetworkResourceLoader::didFinishLoading(double finishTime)
             // FIXME: Pass a real value or remove the encoded data size feature.
             sendBuffer(*m_bufferedData, -1);
         }
-        send(Messages::WebResourceLoader::DidFinishResourceLoad(finishTime));
+        send(Messages::WebResourceLoader::DidFinishResourceLoad(networkLoadMetrics));
     }
 
 #if ENABLE(NETWORK_CACHE)
@@ -606,13 +607,16 @@ void NetworkResourceLoader::sendResultForCacheEntry(std::unique_ptr<NetworkCache
 {
 #if ENABLE(SHAREABLE_RESOURCE)
     if (!entry->shareableResourceHandle().isNull()) {
-        send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime()));
+        send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle()));
         return;
     }
 #endif
 
+    WebCore::NetworkLoadMetrics networkLoadMetrics;
+    networkLoadMetrics.markComplete();
+
     sendBuffer(*entry->buffer(), entry->buffer()->size());
-    send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime()));
+    send(Messages::WebResourceLoader::DidFinishResourceLoad(networkLoadMetrics));
 }
 
 void NetworkResourceLoader::validateCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
index fe93ee0..e46cd91 100644 (file)
@@ -94,7 +94,7 @@ public:
     void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&&) override;
     ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) override;
     void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override;
-    void didFinishLoading(double finishTime) override;
+    void didFinishLoading(const WebCore::NetworkLoadMetrics&) override;
     void didFailLoading(const WebCore::ResourceError&) override;
 
     void convertToDownload(DownloadID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&);
index 300c308..f0144d6 100644 (file)
@@ -65,7 +65,7 @@ private:
         delete this;
     }
     void didReceiveData(Ref<WebCore::SharedBuffer>&&) final { ASSERT_NOT_REACHED(); }
-    void didCompleteWithError(const WebCore::ResourceError&) final { delete this; }
+    void didCompleteWithError(const WebCore::ResourceError&, const WebCore::NetworkLoadMetrics&) final { delete this; }
     void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) final { }
     void wasBlocked() final { delete this; }
     void cannotShowURL() final { delete this; }
index c90f58f..dc060e7 100644 (file)
@@ -116,7 +116,7 @@ void SpeculativeLoad::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int reportedE
     }
 }
 
-void SpeculativeLoad::didFinishLoading(double finishTime)
+void SpeculativeLoad::didFinishLoading(const WebCore::NetworkLoadMetrics&)
 {
     if (m_didComplete)
         return;
index 3bc2d2e..a3fe906 100644 (file)
@@ -61,7 +61,7 @@ private:
     void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) override;
     ShouldContinueDidReceiveResponse didReceiveResponse(WebCore::ResourceResponse&&) override;
     void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override;
-    void didFinishLoading(double finishTime) override;
+    void didFinishLoading(const WebCore::NetworkLoadMetrics&) override;
     void didFailLoading(const WebCore::ResourceError&) override;
 
     void didComplete();
index cc63727..ceb5963 100644 (file)
@@ -28,6 +28,7 @@
 #if USE(NETWORK_SESSION)
 
 #include "NetworkDataTask.h"
+#include <WebCore/NetworkLoadMetrics.h>
 #include <wtf/RetainPtr.h>
 
 OBJC_CLASS NSURLSessionDataTask;
@@ -50,7 +51,7 @@ public:
 
     void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend);
     void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&);
-    void didCompleteWithError(const WebCore::ResourceError&);
+    void didCompleteWithError(const WebCore::ResourceError&, const WebCore::NetworkLoadMetrics&);
     void didReceiveData(Ref<WebCore::SharedBuffer>&&);
 
     void willPerformHTTPRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&, RedirectCompletionHandler&&);
@@ -67,6 +68,8 @@ public:
 
     bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&) override;
 
+    WebCore::NetworkLoadMetrics& networkLoadMetrics() { return m_networkLoadMetrics; }
+
 private:
     NetworkDataTaskCocoa(NetworkSession&, NetworkDataTaskClient&, const WebCore::ResourceRequest&, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
 
@@ -74,6 +77,7 @@ private:
 
     RefPtr<SandboxExtension> m_sandboxExtension;
     RetainPtr<NSURLSessionDataTask> m_task;
+    WebCore::NetworkLoadMetrics m_networkLoadMetrics;
 };
 
 WebCore::Credential serverTrustCredential(const WebCore::AuthenticationChallenge&);
index 2f0471b..d447ea2 100644 (file)
@@ -150,10 +150,10 @@ void NetworkDataTaskCocoa::didReceiveChallenge(const WebCore::AuthenticationChal
     }
 }
 
-void NetworkDataTaskCocoa::didCompleteWithError(const WebCore::ResourceError& error)
+void NetworkDataTaskCocoa::didCompleteWithError(const WebCore::ResourceError& error, const WebCore::NetworkLoadMetrics& networkLoadMetrics)
 {
     if (m_client)
-        m_client->didCompleteWithError(error);
+        m_client->didCompleteWithError(error, networkLoadMetrics);
 }
 
 void NetworkDataTaskCocoa::didReceiveData(Ref<WebCore::SharedBuffer>&& data)
index c6b2dd8..dfeaf03 100644 (file)
@@ -34,6 +34,7 @@ OBJC_CLASS WKNetworkSessionDelegate;
 #include "DownloadID.h"
 #include "NetworkDataTaskCocoa.h"
 #include "NetworkSession.h"
+#include <WebCore/NetworkLoadMetrics.h>
 #include <wtf/HashMap.h>
 
 namespace WebKit {
index fdf1ec0..9d7680d 100644 (file)
@@ -41,7 +41,6 @@
 #import <WebCore/CFNetworkSPI.h>
 #import <WebCore/Credential.h>
 #import <WebCore/FrameLoaderTypes.h>
-#import <WebCore/NetworkLoadTiming.h>
 #import <WebCore/NetworkStorageSession.h>
 #import <WebCore/NotImplemented.h>
 #import <WebCore/ResourceError.h>
@@ -242,7 +241,7 @@ static NSURLSessionAuthChallengeDisposition toNSURLSessionAuthChallengeDispositi
     LOG(NetworkSession, "%llu didCompleteWithError %@", task.taskIdentifier, error);
     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
     if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials))
-        networkDataTask->didCompleteWithError(error);
+        networkDataTask->didCompleteWithError(error, networkDataTask->networkLoadMetrics());
     else if (error) {
         auto downloadID = _session->takeDownloadID(task.taskIdentifier);
         if (downloadID.downloadID()) {
@@ -262,6 +261,39 @@ static NSURLSessionAuthChallengeDisposition toNSURLSessionAuthChallengeDispositi
     }
 }
 
+- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics
+{
+    if (!_session)
+        return;
+
+    LOG(NetworkSession, "%llu didFinishCollectingMetrics", task.taskIdentifier);
+    auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
+    if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials)) {
+        NSURLSessionTaskTransactionMetrics *m = metrics.transactionMetrics.lastObject;
+        NSDate *fetchStartDate = m.fetchStartDate;
+        NSTimeInterval domainLookupStartInterval = m.domainLookupStartDate ? [m.domainLookupStartDate timeIntervalSinceDate:fetchStartDate] : -1;
+        NSTimeInterval domainLookupEndInterval = m.domainLookupEndDate ? [m.domainLookupEndDate timeIntervalSinceDate:fetchStartDate] : -1;
+        NSTimeInterval connectStartInterval = m.connectStartDate ? [m.connectStartDate timeIntervalSinceDate:fetchStartDate] : -1;
+        NSTimeInterval secureConnectionStartInterval = m.secureConnectionStartDate ? [m.secureConnectionStartDate timeIntervalSinceDate:fetchStartDate] : -1;
+        NSTimeInterval connectEndInterval = m.connectEndDate ? [m.connectEndDate timeIntervalSinceDate:fetchStartDate] : -1;
+        NSTimeInterval requestStartInterval = [m.requestStartDate timeIntervalSinceDate:fetchStartDate];
+        NSTimeInterval responseStartInterval = [m.responseStartDate timeIntervalSinceDate:fetchStartDate];
+        NSTimeInterval responseEndInterval = [m.responseEndDate timeIntervalSinceDate:fetchStartDate];
+
+        auto& networkLoadMetrics = networkDataTask->networkLoadMetrics();
+        networkLoadMetrics.domainLookupStart = Seconds(domainLookupStartInterval);
+        networkLoadMetrics.domainLookupEnd = Seconds(domainLookupEndInterval);
+        networkLoadMetrics.connectStart = Seconds(connectStartInterval);
+        networkLoadMetrics.secureConnectionStart = Seconds(secureConnectionStartInterval);
+        networkLoadMetrics.connectEnd = Seconds(connectEndInterval);
+        networkLoadMetrics.requestStart = Seconds(requestStartInterval);
+        networkLoadMetrics.responseStart = Seconds(responseStartInterval);
+        networkLoadMetrics.responseEnd = Seconds(responseEndInterval);
+        networkLoadMetrics.markComplete();
+        networkLoadMetrics.protocol = String(m.networkProtocolName);
+    }
+}
+
 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
 {
     if (!_session) {
@@ -287,7 +319,10 @@ static NSURLSessionAuthChallengeDisposition toNSURLSessionAuthChallengeDispositi
         // all the fields when sending the response to the WebContent process over IPC.
         resourceResponse.disableLazyInitialization();
 
-        copyTimingData([dataTask _timingData], resourceResponse.networkLoadTiming());
+        // FIXME: This cannot be eliminated until other code no longer relies on ResourceResponse's
+        // NetworkLoadMetrics. For example, PerformanceTiming.
+        copyTimingData([dataTask _timingData], resourceResponse.deprecatedNetworkLoadMetrics());
+
         auto completionHandlerCopy = Block_copy(completionHandler);
         networkDataTask->didReceiveResponse(WTFMove(resourceResponse), [completionHandlerCopy, taskIdentifier](WebCore::PolicyAction policyAction) {
             LOG(NetworkSession, "%llu didReceiveResponse completionHandler (%d)", taskIdentifier, policyAction);
index 9d61be2..41d926e 100644 (file)
@@ -60,7 +60,7 @@ NetworkDataTaskSoup::NetworkDataTaskSoup(NetworkSession& session, NetworkDataTas
     auto request = requestWithCredentials;
     if (request.url().protocolIsInHTTPFamily()) {
 #if ENABLE(WEB_TIMING)
-        m_startTime = monotonicallyIncreasingTimeMS();
+        m_startTime = MonotonicTime::now();
 #endif
         auto url = request.url();
         if (m_storedCredentials == AllowStoredCredentials) {
@@ -283,7 +283,7 @@ void NetworkDataTaskSoup::timeoutFired()
 
     RefPtr<NetworkDataTaskSoup> protectedThis(this);
     invalidateAndCancel();
-    m_client->didCompleteWithError(ResourceError::timeoutError(m_firstRequest.url()));
+    dispatchDidCompleteWithError(ResourceError::timeoutError(m_firstRequest.url()));
 }
 
 void NetworkDataTaskSoup::startTimeout()
@@ -341,7 +341,7 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr<GInputStream>&& inputStream)
             m_inputStream = WTFMove(inputStream);
 
 #if ENABLE(WEB_TIMING)
-        m_response.networkLoadTiming().responseStart = monotonicallyIncreasingTimeMS() - m_startTime;
+        m_networkLoadMetrics.responseStart = MonotonicTime::now() - m_startTime;
 #endif
     } else {
         m_response.setURL(m_firstRequest.url());
@@ -362,6 +362,19 @@ void NetworkDataTaskSoup::dispatchDidReceiveResponse()
 {
     ASSERT(!m_response.isNull());
 
+#if ENABLE(WEB_TIMING)
+    // FIXME: Remove this once nobody depends on deprecatedNetworkLoadMetrics.
+    NetworkLoadMetrics& deprecatedResponseMetrics = m_response.deprecatedNetworkLoadMetrics();
+    deprecatedResponseMetrics.responseStart = m_networkLoadMetrics.responseStart;
+    deprecatedResponseMetrics.domainLookupStart = m_networkLoadMetrics.domainLookupStart;
+    deprecatedResponseMetrics.domainLookupEnd = m_networkLoadMetrics.domainLookupEnd;
+    deprecatedResponseMetrics.connectStart = m_networkLoadMetrics.connectStart;
+    deprecatedResponseMetrics.secureConnectionStart = m_networkLoadMetrics.secureConnectionStart;
+    deprecatedResponseMetrics.connectEnd = m_networkLoadMetrics.connectEnd;
+    deprecatedResponseMetrics.requestStart = m_networkLoadMetrics.requestStart;
+    deprecatedResponseMetrics.responseStart = m_networkLoadMetrics.responseStart;
+#endif
+
     didReceiveResponse(ResourceResponse(m_response), [this, protectedThis = makeRef(*this)](PolicyAction policyAction) {
         if (m_state == State::Canceling || m_state == State::Completed) {
             clearRequest();
@@ -388,6 +401,16 @@ void NetworkDataTaskSoup::dispatchDidReceiveResponse()
     });
 }
 
+void NetworkDataTaskSoup::dispatchDidCompleteWithError(const ResourceError& error)
+{
+#if ENABLE(WEB_TIMING)
+    m_networkLoadMetrics.responseEnd = MonotonicTime::now() - m_startTime;
+    m_networkLoadMetrics.markComplete();
+#endif
+
+    m_client->didCompleteWithError(error, m_networkLoadMetrics);
+}
+
 void NetworkDataTaskSoup::tlsErrorsChangedCallback(SoupMessage* soupMessage, GParamSpec*, NetworkDataTaskSoup* task)
 {
     if (task->state() == State::Canceling || task->state() == State::Completed || !task->m_client) {
@@ -408,7 +431,7 @@ void NetworkDataTaskSoup::tlsErrorsChanged()
 
         RefPtr<NetworkDataTaskSoup> protectedThis(this);
         invalidateAndCancel();
-        m_client->didCompleteWithError(error);
+        dispatchDidCompleteWithError(error);
     });
 }
 
@@ -660,8 +683,10 @@ void NetworkDataTaskSoup::continueHTTPRedirection()
         auto request = newRequest;
         if (request.url().protocolIsInHTTPFamily()) {
 #if ENABLE(WEB_TIMING)
-            if (isCrossOrigin)
-                m_startTime = monotonicallyIncreasingTimeMS();
+            if (isCrossOrigin) {
+                m_startTime = MonotonicTime::now();
+                m_networkLoadMetrics.reset();
+            }
 #endif
             applyAuthenticationToRequest(request);
         }
@@ -737,7 +762,7 @@ void NetworkDataTaskSoup::didFinishRead()
 
     clearRequest();
     ASSERT(m_client);
-    m_client->didCompleteWithError({ });
+    dispatchDidCompleteWithError({ });
 }
 
 void NetworkDataTaskSoup::requestNextPartCallback(SoupMultipartInputStream* multipartInputStream, GAsyncResult* result, NetworkDataTaskSoup* task)
@@ -790,7 +815,7 @@ void NetworkDataTaskSoup::didFinishRequestNextPart()
     ASSERT(m_multipartInputStream);
     g_input_stream_close(G_INPUT_STREAM(m_multipartInputStream.get()), nullptr, nullptr);
     clearRequest();
-    m_client->didCompleteWithError({ });
+    dispatchDidCompleteWithError({ });
 }
 
 void NetworkDataTaskSoup::gotHeadersCallback(SoupMessage* soupMessage, NetworkDataTaskSoup* task)
@@ -974,7 +999,7 @@ void NetworkDataTaskSoup::didFailDownload(const ResourceError& error)
     clearRequest();
     cleanDownloadFiles();
     if (m_client)
-        m_client->didCompleteWithError(error);
+        dispatchDidCompleteWithError(error);
     else {
         auto* download = NetworkProcess::singleton().downloadManager().download(m_pendingDownloadID);
         ASSERT(download);
@@ -1003,7 +1028,7 @@ void NetworkDataTaskSoup::didFail(const ResourceError& error)
 
     clearRequest();
     ASSERT(m_client);
-    m_client->didCompleteWithError(error);
+    dispatchDidCompleteWithError(error);
 }
 
 #if ENABLE(WEB_TIMING)
@@ -1018,17 +1043,16 @@ void NetworkDataTaskSoup::networkEventCallback(SoupMessage* soupMessage, GSocket
 
 void NetworkDataTaskSoup::networkEvent(GSocketClientEvent event)
 {
-    double deltaTime = monotonicallyIncreasingTimeMS() - m_startTime;
-    auto& loadTiming = m_response.networkLoadTiming();
+    Seconds deltaTime = MonotonicTime::now() - m_startTime;
     switch (event) {
     case G_SOCKET_CLIENT_RESOLVING:
-        loadTiming.domainLookupStart = deltaTime;
+        m_networkLoadMetrics.domainLookupStart = deltaTime;
         break;
     case G_SOCKET_CLIENT_RESOLVED:
-        loadTiming.domainLookupEnd = deltaTime;
+        m_networkLoadMetrics.domainLookupEnd = deltaTime;
         break;
     case G_SOCKET_CLIENT_CONNECTING:
-        loadTiming.connectStart = deltaTime;
+        m_networkLoadMetrics.connectStart = deltaTime;
         break;
     case G_SOCKET_CLIENT_CONNECTED:
         // Web Timing considers that connection time involves dns, proxy & TLS negotiation...
@@ -1039,12 +1063,12 @@ void NetworkDataTaskSoup::networkEvent(GSocketClientEvent event)
     case G_SOCKET_CLIENT_PROXY_NEGOTIATED:
         break;
     case G_SOCKET_CLIENT_TLS_HANDSHAKING:
-        loadTiming.secureConnectionStart = deltaTime;
+        m_networkLoadMetrics.secureConnectionStart = deltaTime;
         break;
     case G_SOCKET_CLIENT_TLS_HANDSHAKED:
         break;
     case G_SOCKET_CLIENT_COMPLETE:
-        loadTiming.connectEnd = deltaTime;
+        m_networkLoadMetrics.connectEnd = deltaTime;
         break;
     default:
         ASSERT_NOT_REACHED();
@@ -1077,7 +1101,7 @@ void NetworkDataTaskSoup::requestStartedCallback(SoupSession* session, SoupMessa
 
 void NetworkDataTaskSoup::didStartRequest()
 {
-    m_response.networkLoadTiming().requestStart = monotonicallyIncreasingTimeMS() - m_startTime;
+    m_networkLoadMetrics.requestStart = MonotonicTime::now() - m_startTime;
 }
 
 void NetworkDataTaskSoup::restartedCallback(SoupMessage* soupMessage, NetworkDataTaskSoup* task)
@@ -1093,7 +1117,8 @@ void NetworkDataTaskSoup::restartedCallback(SoupMessage* soupMessage, NetworkDat
 
 void NetworkDataTaskSoup::didRestart()
 {
-    m_startTime = monotonicallyIncreasingTimeMS();
+    m_startTime = MonotonicTime::now();
+    m_networkLoadMetrics.reset();
 }
 #endif // ENABLE(WEB_TIMING)
 
index 9a15532..71bd735 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "NetworkDataTask.h"
+#include <WebCore/NetworkLoadMetrics.h>
 #include <WebCore/ProtectionSpace.h>
 #include <WebCore/ResourceResponse.h>
 #include <wtf/RunLoop.h>
@@ -63,6 +64,7 @@ private:
     static void sendRequestCallback(SoupRequest*, GAsyncResult*, NetworkDataTaskSoup*);
     void didSendRequest(GRefPtr<GInputStream>&&);
     void dispatchDidReceiveResponse();
+    void dispatchDidCompleteWithError(const WebCore::ResourceError&);
 
     static void tlsErrorsChangedCallback(SoupMessage*, GParamSpec*, NetworkDataTaskSoup*);
     void tlsErrorsChanged();
@@ -136,7 +138,8 @@ private:
     GRefPtr<GOutputStream> m_downloadOutputStream;
     bool m_allowOverwriteDownload { false };
 #if ENABLE(WEB_TIMING)
-    double m_startTime { 0 };
+    WebCore::NetworkLoadMetrics m_networkLoadMetrics;
+    MonotonicTime m_startTime;
 #endif
     RunLoop::Timer<NetworkDataTaskSoup> m_timeoutSource;
 };
index ec2e1f5..f8cd613 100644 (file)
@@ -143,12 +143,12 @@ void WebResourceLoader::didRetrieveDerivedData(const String& type, const IPC::Da
     m_coreLoader->didRetrieveDerivedDataFromCache(type, buffer.get());
 }
 
-void WebResourceLoader::didFinishResourceLoad(double finishTime)
+void WebResourceLoader::didFinishResourceLoad(const NetworkLoadMetrics& networkLoadMetrics)
 {
     LOG(Network, "(WebProcess) WebResourceLoader::didFinishResourceLoad for '%s'", m_coreLoader->url().string().latin1().data());
     RELEASE_LOG_IF_ALLOWED("didFinishResourceLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_trackingParameters.pageID, m_trackingParameters.frameID, m_trackingParameters.resourceID);
 
-    m_coreLoader->didFinishLoading(finishTime);
+    m_coreLoader->didFinishLoading(networkLoadMetrics);
 }
 
 void WebResourceLoader::didFailResourceLoad(const ResourceError& error)
@@ -162,7 +162,7 @@ void WebResourceLoader::didFailResourceLoad(const ResourceError& error)
 }
 
 #if ENABLE(SHAREABLE_RESOURCE)
-void WebResourceLoader::didReceiveResource(const ShareableResource::Handle& handle, double finishTime)
+void WebResourceLoader::didReceiveResource(const ShareableResource::Handle& handle)
 {
     LOG(Network, "(WebProcess) WebResourceLoader::didReceiveResource for '%s'", m_coreLoader->url().string().latin1().data());
     RELEASE_LOG_IF_ALLOWED("didReceiveResource: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_trackingParameters.pageID, m_trackingParameters.frameID, m_trackingParameters.resourceID);
@@ -189,7 +189,8 @@ void WebResourceLoader::didReceiveResource(const ShareableResource::Handle& hand
     if (!m_coreLoader)
         return;
 
-    m_coreLoader->didFinishLoading(finishTime);
+    NetworkLoadMetrics emptyMetrics;
+    m_coreLoader->didFinishLoading(emptyMetrics);
 }
 #endif
 
index 9e391b5..b54d2fa 100644 (file)
@@ -23,8 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef WebResourceLoader_h
-#define WebResourceLoader_h
+#pragma once
 
 #include "Connection.h"
 #include "MessageSender.h"
@@ -37,6 +36,7 @@ class DataReference;
 }
 
 namespace WebCore {
+class NetworkLoadMetrics;
 class ResourceError;
 class ResourceLoader;
 class ResourceRequest;
@@ -79,10 +79,10 @@ private:
     void didReceiveResponse(const WebCore::ResourceResponse&, bool needsContinueDidReceiveResponseMessage);
     void didReceiveData(const IPC::DataReference&, int64_t encodedDataLength);
     void didRetrieveDerivedData(const String& type, const IPC::DataReference&);
-    void didFinishResourceLoad(double finishTime);
+    void didFinishResourceLoad(const WebCore::NetworkLoadMetrics&);
     void didFailResourceLoad(const WebCore::ResourceError&);
 #if ENABLE(SHAREABLE_RESOURCE)
-    void didReceiveResource(const ShareableResource::Handle&, double finishTime);
+    void didReceiveResource(const ShareableResource::Handle&);
 #endif
 
     RefPtr<WebCore::ResourceLoader> m_coreLoader;
@@ -91,5 +91,3 @@ private:
 };
 
 } // namespace WebKit
-
-#endif // WebResourceLoader_h
index 842e0a4..335e3b2 100644 (file)
@@ -25,12 +25,12 @@ messages -> WebResourceLoader LegacyReceiver {
     DidSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent)
     DidReceiveResponse(WebCore::ResourceResponse response, bool needsContinueDidReceiveResponseMessage)
     DidReceiveData(IPC::DataReference data, int64_t encodedDataLength)
-    DidFinishResourceLoad(double finishTime)
+    DidFinishResourceLoad(WebCore::NetworkLoadMetrics networkLoadMetrics)
     DidRetrieveDerivedData(String type, IPC::DataReference data)
     DidFailResourceLoad(WebCore::ResourceError error)
 
 #if ENABLE(SHAREABLE_RESOURCE)
     // DidReceiveResource is for when we have the entire resource data available at once, such as when the resource is cached in memory
-    DidReceiveResource(WebKit::ShareableResource::Handle resource, double finishTime)
+    DidReceiveResource(WebKit::ShareableResource::Handle resource)
 #endif
 }