Web Inspector: Frontend should have access to Resource Timing information
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 Aug 2016 00:30:00 +0000 (00:30 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 Aug 2016 00:30:00 +0000 (00:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=160095

Patch by Johan K. Jensen <johan_jensen@apple.com> on 2016-08-26
Reviewed by Alex Christensen.

Source/JavaScriptCore:

Rename ResourceTiming property.

* inspector/protocol/Network.json:
Rename navigationStart to startTime so it's applicable
for all resources and not just the main resource.

Source/WebCore:

Show correct information with Resource Timing information
from ResourceLoader rather than DocumentLoader.

No new tests, frontend doesn't use the timing data yet.

* inspector/InspectorNetworkAgent.cpp:
(WebCore::InspectorNetworkAgent::buildObjectForTiming):
(WebCore::InspectorNetworkAgent::buildObjectForResourceResponse):
(WebCore::InspectorNetworkAgent::buildObjectForCachedResource):
(WebCore::InspectorNetworkAgent::willSendRequest):
(WebCore::InspectorNetworkAgent::didReceiveResponse):
(WebCore::InspectorNetworkAgent::didLoadResourceFromMemoryCache):
(WebCore::buildObjectForTiming): Deleted.
(WebCore::buildObjectForResourceResponse): Deleted.
(WebCore::buildObjectForCachedResource): Deleted.
Use ResourceLoader instead of DocumentLoader to get Resource Timing information.
Move functions to member functions to access the executionStopWatch.

(WebCore::InspectorNetworkAgent::didFinishLoading):
Use the load timing finishTime and convert to elapsed time for frontend.

* inspector/InspectorNetworkAgent.h:
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::didFinishLoading):
Pass the web process load timing on to the inspector.

Source/WTF:

Add method to get elapsed time for any monotonic time.
Used by InspectorNetworkAgent.

* wtf/Stopwatch.h:
(WTF::Stopwatch::elapsedTimeSinceMonotonicTime):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/Network.json
Source/WTF/ChangeLog
Source/WTF/wtf/Stopwatch.h
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorNetworkAgent.cpp
Source/WebCore/inspector/InspectorNetworkAgent.h
Source/WebCore/loader/SubresourceLoader.cpp

index ca49f6c..162cb24 100644 (file)
@@ -1,3 +1,16 @@
+2016-08-26  Johan K. Jensen  <johan_jensen@apple.com>
+
+        Web Inspector: Frontend should have access to Resource Timing information
+        https://bugs.webkit.org/show_bug.cgi?id=160095
+
+        Reviewed by Alex Christensen.
+
+        Rename ResourceTiming property.
+
+        * inspector/protocol/Network.json:
+        Rename navigationStart to startTime so it's applicable
+        for all resources and not just the main resource.
+
 2016-08-25  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Provide a way to clear an IndexedDB object store
index e317f80..230a8c0 100644 (file)
@@ -33,7 +33,7 @@
             "type": "object",
             "description": "Timing information for the request.",
             "properties": [
-                { "name": "navigationStart", "type": "number", "description": "Timing's navigationStart is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this navigationStart." },
+                { "name": "startTime", "type": "number", "description": "Timing's startTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this." },
                 { "name": "domainLookupStart", "type": "number", "description": "Started DNS address resolve." },
                 { "name": "domainLookupEnd", "type": "number", "description": "Finished DNS address resolve." },
                 { "name": "connectStart", "type": "number", "description": "Started connecting to the remote host." },
index 79b9269..299db95 100644 (file)
@@ -1,3 +1,16 @@
+2016-08-26  Johan K. Jensen  <johan_jensen@apple.com>
+
+        Web Inspector: Frontend should have access to Resource Timing information
+        https://bugs.webkit.org/show_bug.cgi?id=160095
+
+        Reviewed by Alex Christensen.
+
+        Add method to get elapsed time for any monotonic time.
+        Used by InspectorNetworkAgent.
+
+        * wtf/Stopwatch.h:
+        (WTF::Stopwatch::elapsedTimeSinceMonotonicTime):
+
 2016-08-26  Csaba Osztrogon√°c  <ossy@webkit.org>
 
         Fix the ENABLE(WEBASSEMBLY) build on Linux
index 5fb215d..0b836cc 100644 (file)
@@ -43,6 +43,7 @@ public:
     void stop();
 
     double elapsedTime();
+    double elapsedTimeSinceMonotonicTime(double);
 
     bool isActive() const { return !std::isnan(m_lastStartTime); }
 private:
@@ -81,6 +82,14 @@ inline double Stopwatch::elapsedTime()
     return m_elapsedTime + (monotonicallyIncreasingTime() - m_lastStartTime);
 }
 
+inline double Stopwatch::elapsedTimeSinceMonotonicTime(double monotonicTime)
+{
+    if (!isActive())
+        return m_elapsedTime;
+
+    return m_elapsedTime + (monotonicTime - m_lastStartTime);
+}
+
 } // namespace WTF
 
 using WTF::Stopwatch;
index 9462ad0..fd899a4 100644 (file)
@@ -1,3 +1,36 @@
+2016-08-26  Johan K. Jensen  <johan_jensen@apple.com>
+
+        Web Inspector: Frontend should have access to Resource Timing information
+        https://bugs.webkit.org/show_bug.cgi?id=160095
+
+        Reviewed by Alex Christensen.
+
+        Show correct information with Resource Timing information
+        from ResourceLoader rather than DocumentLoader.
+
+        No new tests, frontend doesn't use the timing data yet.
+
+        * inspector/InspectorNetworkAgent.cpp:
+        (WebCore::InspectorNetworkAgent::buildObjectForTiming):
+        (WebCore::InspectorNetworkAgent::buildObjectForResourceResponse):
+        (WebCore::InspectorNetworkAgent::buildObjectForCachedResource):
+        (WebCore::InspectorNetworkAgent::willSendRequest):
+        (WebCore::InspectorNetworkAgent::didReceiveResponse):
+        (WebCore::InspectorNetworkAgent::didLoadResourceFromMemoryCache):
+        (WebCore::buildObjectForTiming): Deleted.
+        (WebCore::buildObjectForResourceResponse): Deleted.
+        (WebCore::buildObjectForCachedResource): Deleted.
+        Use ResourceLoader instead of DocumentLoader to get Resource Timing information.
+        Move functions to member functions to access the executionStopWatch.
+
+        (WebCore::InspectorNetworkAgent::didFinishLoading):
+        Use the load timing finishTime and convert to elapsed time for frontend.
+
+        * inspector/InspectorNetworkAgent.h:
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::didFinishLoading):
+        Pass the web process load timing on to the inspector.
+
 2016-08-26  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, fix Windows build after r205048.
index 9e030c9..f09f49b 100644 (file)
@@ -184,10 +184,13 @@ static Ref<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
     return headersObject;
 }
 
-static Ref<Inspector::Protocol::Network::ResourceTiming> buildObjectForTiming(const NetworkLoadTiming& timing, DocumentLoader* loader)
+Ref<Inspector::Protocol::Network::ResourceTiming> InspectorNetworkAgent::buildObjectForTiming(const NetworkLoadTiming& timing, ResourceLoader& resourceLoader)
 {
+    double monotonicTime = resourceLoader.loadTiming().startTime();
+    double startTimeInInspector = m_environment.executionStopwatch()->elapsedTimeSinceMonotonicTime(monotonicTime);
+
     return Inspector::Protocol::Network::ResourceTiming::create()
-        .setNavigationStart(loader->timing().startTime())
+        .setStartTime(startTimeInInspector)
         .setDomainLookupStart(timing.domainLookupStart)
         .setDomainLookupEnd(timing.domainLookupEnd)
         .setConnectStart(timing.connectStart)
@@ -213,7 +216,7 @@ static Ref<Inspector::Protocol::Network::Request> buildObjectForResourceRequest(
     return requestObject;
 }
 
-static RefPtr<Inspector::Protocol::Network::Response> buildObjectForResourceResponse(const ResourceResponse& response, DocumentLoader* loader)
+RefPtr<Inspector::Protocol::Network::Response> InspectorNetworkAgent::buildObjectForResourceResponse(const ResourceResponse& response, ResourceLoader* resourceLoader)
 {
     if (response.isNull())
         return nullptr;
@@ -230,12 +233,13 @@ static RefPtr<Inspector::Protocol::Network::Response> buildObjectForResourceResp
         .release();
 
     responseObject->setFromDiskCache(response.source() == ResourceResponse::Source::DiskCache || response.source() == ResourceResponse::Source::DiskCacheAfterValidation);
-    responseObject->setTiming(buildObjectForTiming(response.networkLoadTiming(), loader));
+    if (resourceLoader)
+        responseObject->setTiming(buildObjectForTiming(response.networkLoadTiming(), *resourceLoader));
 
     return WTFMove(responseObject);
 }
 
-static Ref<Inspector::Protocol::Network::CachedResource> buildObjectForCachedResource(CachedResource* cachedResource, DocumentLoader* loader)
+Ref<Inspector::Protocol::Network::CachedResource> InspectorNetworkAgent::buildObjectForCachedResource(CachedResource* cachedResource)
 {
     auto resourceObject = Inspector::Protocol::Network::CachedResource::create()
         .setUrl(cachedResource->url())
@@ -243,7 +247,7 @@ static Ref<Inspector::Protocol::Network::CachedResource> buildObjectForCachedRes
         .setBodySize(cachedResource->encodedSize())
         .release();
 
-    auto resourceResponse = buildObjectForResourceResponse(cachedResource->response(), loader);
+    auto resourceResponse = buildObjectForResourceResponse(cachedResource->response(), cachedResource->loader());
     resourceObject->setResponse(WTFMove(resourceResponse));
 
     String sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(cachedResource);
@@ -305,7 +309,7 @@ void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLo
     Inspector::Protocol::Page::ResourceType resourceType = InspectorPageAgent::resourceTypeJson(type);
 
     RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader.frame() ? loader.frame()->document() : nullptr);
-    m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader.frame()), m_pageAgent->loaderId(&loader), loader.url().string(), buildObjectForResourceRequest(request), timestamp(), initiatorObject, buildObjectForResourceResponse(redirectResponse, &loader), type != InspectorPageAgent::OtherResource ? &resourceType : nullptr);
+    m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader.frame()), m_pageAgent->loaderId(&loader), loader.url().string(), buildObjectForResourceRequest(request), timestamp(), initiatorObject, buildObjectForResourceResponse(redirectResponse, nullptr), type != InspectorPageAgent::OtherResource ? &resourceType : nullptr);
 }
 
 void InspectorNetworkAgent::markResourceAsCached(unsigned long identifier)
@@ -322,7 +326,7 @@ void InspectorNetworkAgent::didReceiveResponse(unsigned long identifier, Documen
         return;
 
     String requestId = IdentifiersFactory::requestId(identifier);
-    RefPtr<Inspector::Protocol::Network::Response> resourceResponse = buildObjectForResourceResponse(response, &loader);
+    RefPtr<Inspector::Protocol::Network::Response> resourceResponse = buildObjectForResourceResponse(response, resourceLoader);
 
     bool isNotModified = response.httpStatusCode() == 304;
 
@@ -390,18 +394,14 @@ void InspectorNetworkAgent::didFinishLoading(unsigned long identifier, DocumentL
 
     m_resourcesData->maybeDecodeDataToContent(requestId);
 
-    // FIXME: The finishTime that is passed in is from the NetworkProcess and is more accurate.
-    // However, all other times passed to the Inspector are generated from the web process. Mixing
-    // times from different processes can cause the finish time to be earlier than the response
-    // received time due to inter-process communication lag.
-    finishTime = timestamp();
+    double elapsedFinishTime = finishTime ? m_environment.executionStopwatch()->elapsedTimeSinceMonotonicTime(finishTime) : timestamp();
 
     String sourceMappingURL;
     NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
     if (resourceData && resourceData->cachedResource())
         sourceMappingURL = InspectorPageAgent::sourceMapURLForResource(resourceData->cachedResource());
 
-    m_frontendDispatcher->loadingFinished(requestId, finishTime, !sourceMappingURL.isEmpty() ? &sourceMappingURL : nullptr);
+    m_frontendDispatcher->loadingFinished(requestId, elapsedFinishTime, !sourceMappingURL.isEmpty() ? &sourceMappingURL : nullptr);
 }
 
 void InspectorNetworkAgent::didFailLoading(unsigned long identifier, DocumentLoader& loader, const ResourceError& error)
@@ -435,7 +435,7 @@ void InspectorNetworkAgent::didLoadResourceFromMemoryCache(DocumentLoader& loade
 
     RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader.frame() ? loader.frame()->document() : nullptr);
 
-    m_frontendDispatcher->requestServedFromMemoryCache(requestId, frameId, loaderId, loader.url().string(), timestamp(), initiatorObject, buildObjectForCachedResource(&resource, &loader));
+    m_frontendDispatcher->requestServedFromMemoryCache(requestId, frameId, loaderId, loader.url().string(), timestamp(), initiatorObject, buildObjectForCachedResource(&resource));
 }
 
 void InspectorNetworkAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
index d3dd48d..534cef7 100644 (file)
@@ -48,6 +48,7 @@ class CachedResource;
 class Document;
 class DocumentLoader;
 class InspectorPageAgent;
+class NetworkLoadTiming;
 class NetworkResourcesData;
 class ResourceError;
 class ResourceLoader;
@@ -116,6 +117,10 @@ public:
 private:
     void enable();
 
+    Ref<Inspector::Protocol::Network::ResourceTiming> buildObjectForTiming(const NetworkLoadTiming&, ResourceLoader&);
+    RefPtr<Inspector::Protocol::Network::Response> buildObjectForResourceResponse(const ResourceResponse&, ResourceLoader*);
+    Ref<Inspector::Protocol::Network::CachedResource> buildObjectForCachedResource(CachedResource*);
+
     double timestamp();
 
     std::unique_ptr<Inspector::NetworkFrontendDispatcher> m_frontendDispatcher;
index bb01f97..c006db4 100644 (file)
@@ -460,8 +460,13 @@ void SubresourceLoader::didFinishLoading(double finishTime)
     Ref<SubresourceLoader> protectedThis(*this);
     CachedResourceHandle<CachedResource> protectResource(m_resource);
 
-    finishTime = monotonicallyIncreasingTime();
-    m_loadTiming.setResponseEnd(finishTime);
+    // FIXME: 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.
+    UNUSED_PARAM(finishTime);
+    double responseEndTime = monotonicallyIncreasingTime();
+    m_loadTiming.setResponseEnd(responseEndTime);
 
 #if ENABLE(WEB_TIMING)
     if (m_documentLoader->cachedResourceLoader().document() && RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled())
@@ -469,14 +474,14 @@ void SubresourceLoader::didFinishLoading(double finishTime)
 #endif
 
     m_state = Finishing;
-    m_resource->setLoadFinishTime(finishTime);
+    m_resource->setLoadFinishTime(responseEndTime); // FIXME: Users of the loadFinishTime should use the LoadTiming struct instead.
     m_resource->finishLoading(resourceData());
 
     if (wasCancelled())
         return;
     m_resource->finish();
     ASSERT(!reachedTerminalState());
-    didFinishLoadingOnePart(finishTime);
+    didFinishLoadingOnePart(responseEndTime);
     notifyDone();
     if (reachedTerminalState())
         return;