Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Web Inspector: Frontend should have access to Resource Timing informa…
…tion

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):

Canonical link: https://commits.webkit.org/179438@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@205062 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Johan K. Jensen authored and webkit-commit-queue committed Aug 27, 2016
1 parent 9493fec commit 08bb8a2
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 20 deletions.
13 changes: 13 additions & 0 deletions Source/JavaScriptCore/ChangeLog
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/inspector/protocol/Network.json
Expand Up @@ -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." },
Expand Down
13 changes: 13 additions & 0 deletions Source/WTF/ChangeLog
@@ -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
Expand Down
9 changes: 9 additions & 0 deletions Source/WTF/wtf/Stopwatch.h
Expand Up @@ -43,6 +43,7 @@ class Stopwatch : public RefCounted<Stopwatch> {
void stop();

double elapsedTime();
double elapsedTimeSinceMonotonicTime(double);

bool isActive() const { return !std::isnan(m_lastStartTime); }
private:
Expand Down Expand Up @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions Source/WebCore/ChangeLog
@@ -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.
Expand Down
30 changes: 15 additions & 15 deletions Source/WebCore/inspector/InspectorNetworkAgent.cpp
Expand Up @@ -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)
Expand All @@ -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;
Expand All @@ -230,20 +233,21 @@ 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())
.setType(InspectorPageAgent::cachedResourceTypeJson(*cachedResource))
.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);
Expand Down Expand Up @@ -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)
Expand All @@ -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;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/inspector/InspectorNetworkAgent.h
Expand Up @@ -48,6 +48,7 @@ class CachedResource;
class Document;
class DocumentLoader;
class InspectorPageAgent;
class NetworkLoadTiming;
class NetworkResourcesData;
class ResourceError;
class ResourceLoader;
Expand Down Expand Up @@ -116,6 +117,10 @@ class InspectorNetworkAgent final : public InspectorAgentBase, public Inspector:
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;
Expand Down
13 changes: 9 additions & 4 deletions Source/WebCore/loader/SubresourceLoader.cpp
Expand Up @@ -460,23 +460,28 @@ 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())
m_documentLoader->cachedResourceLoader().resourceTimingInformation().addResourceTiming(m_resource, *m_documentLoader->cachedResourceLoader().document(), m_resource->loader()->loadTiming());
#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;
Expand Down

0 comments on commit 08bb8a2

Please sign in to comment.