Commit aa066fd6 authored by sunjian's avatar sunjian Committed by Commit bot

TransferSize implementation.

BUG=663187

Review-Url: https://codereview.chromium.org/2511313002
Cr-Commit-Position: refs/heads/master@{#437946}
parent bc2287b0
...@@ -103,6 +103,18 @@ bool IsCrossOrigin(const KURL& a, const KURL& b) { ...@@ -103,6 +103,18 @@ bool IsCrossOrigin(const KURL& a, const KURL& b) {
return !originB->isSameSchemeHostPort(originA.get()); return !originB->isSameSchemeHostPort(originA.get());
} }
void addRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) {
// Store redirect responses that were packed inside the final response.
const auto& responses = resource->response().redirectResponses();
for (size_t i = 0; i < responses.size(); ++i) {
const KURL& newURL = i + 1 < responses.size()
? KURL(responses[i + 1].url())
: resource->resourceRequest().url();
bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL);
info->addRedirect(responses[i], crossOrigin);
}
}
} // namespace } // namespace
static void RecordSriResourceIntegrityMismatchEvent( static void RecordSriResourceIntegrityMismatchEvent(
...@@ -597,7 +609,6 @@ Resource* ResourceFetcher::requestResource( ...@@ -597,7 +609,6 @@ Resource* ResourceFetcher::requestResource(
resource->setLinkPreload(false); resource->setLinkPreload(false);
break; break;
} }
if (!resource) if (!resource)
return nullptr; return nullptr;
if (resource->getType() != factory.type()) { if (resource->getType() != factory.type()) {
...@@ -641,7 +652,6 @@ Resource* ResourceFetcher::requestResource( ...@@ -641,7 +652,6 @@ Resource* ResourceFetcher::requestResource(
if (!startLoad(resource)) if (!startLoad(resource))
return nullptr; return nullptr;
scopedResourceLoadTracker.resourceLoadContinuesBeyondScope(); scopedResourceLoadTracker.resourceLoadContinuesBeyondScope();
DCHECK(!resource->errorOccurred() || DCHECK(!resource->errorOccurred() ||
...@@ -757,7 +767,7 @@ Resource* ResourceFetcher::createResourceForLoading( ...@@ -757,7 +767,7 @@ Resource* ResourceFetcher::createResourceForLoading(
return resource; return resource;
} }
void ResourceFetcher::storeResourceTimingInitiatorInformation( void ResourceFetcher::storePerformanceTimingInitiatorInformation(
Resource* resource) { Resource* resource) {
const AtomicString& fetchInitiator = resource->options().initiatorInfo.name; const AtomicString& fetchInitiator = resource->options().initiatorInfo.name;
if (fetchInitiator == FetchInitiatorTypeNames::internal) if (fetchInitiator == FetchInitiatorTypeNames::internal)
...@@ -771,6 +781,14 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation( ...@@ -771,6 +781,14 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation(
? resource->resourceRequest().navigationStartTime() ? resource->resourceRequest().navigationStartTime()
: monotonicallyIncreasingTime(); : monotonicallyIncreasingTime();
// This buffer is created and populated for providing transferSize
// and redirect timing opt-in information.
if (isMainResource) {
DCHECK(!m_navigationTimingInfo);
m_navigationTimingInfo =
ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
}
std::unique_ptr<ResourceTimingInfo> info = std::unique_ptr<ResourceTimingInfo> info =
ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource); ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
...@@ -782,8 +800,9 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation( ...@@ -782,8 +800,9 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation(
} }
if (!isMainResource || if (!isMainResource ||
context().updateTimingInfoForIFrameNavigation(info.get())) context().updateTimingInfoForIFrameNavigation(info.get())) {
m_resourceTimingInfoMap.add(resource, std::move(info)); m_resourceTimingInfoMap.add(resource, std::move(info));
}
} }
ResourceFetcher::RevalidationPolicy ResourceFetcher::RevalidationPolicy
...@@ -1125,6 +1144,10 @@ ArchiveResource* ResourceFetcher::createArchive(Resource* resource) { ...@@ -1125,6 +1144,10 @@ ArchiveResource* ResourceFetcher::createArchive(Resource* resource) {
return m_archive ? m_archive->mainResource() : nullptr; return m_archive ? m_archive->mainResource() : nullptr;
} }
ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() {
return m_navigationTimingInfo.get();
}
void ResourceFetcher::didFinishLoading(Resource* resource, void ResourceFetcher::didFinishLoading(Resource* resource,
double finishTime, double finishTime,
DidFinishLoadingReason finishReason) { DidFinishLoadingReason finishReason) {
...@@ -1143,18 +1166,19 @@ void ResourceFetcher::didFinishLoading(Resource* resource, ...@@ -1143,18 +1166,19 @@ void ResourceFetcher::didFinishLoading(Resource* resource,
DCHECK(finishReason == DidFinishFirstPartInMultipart || DCHECK(finishReason == DidFinishFirstPartInMultipart ||
!m_nonBlockingLoaders.contains(resource->loader())); !m_nonBlockingLoaders.contains(resource->loader()));
if (resource->getType() == Resource::MainResource) {
DCHECK(m_navigationTimingInfo);
// Store redirect responses that were packed inside the final response.
addRedirectsToTimingInfo(resource, m_navigationTimingInfo.get());
if (resource->response().isHTTP()) {
m_navigationTimingInfo->addFinalTransferSize(
encodedDataLength == -1 ? 0 : encodedDataLength);
}
}
if (std::unique_ptr<ResourceTimingInfo> info = if (std::unique_ptr<ResourceTimingInfo> info =
m_resourceTimingInfoMap.take(resource)) { m_resourceTimingInfoMap.take(resource)) {
// Store redirect responses that were packed inside the final response. // Store redirect responses that were packed inside the final response.
const Vector<ResourceResponse>& responses = addRedirectsToTimingInfo(resource, info.get());
resource->response().redirectResponses();
for (size_t i = 0; i < responses.size(); ++i) {
const KURL& newURL = i + 1 < responses.size()
? KURL(responses[i + 1].url())
: resource->resourceRequest().url();
bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL);
info->addRedirect(responses[i], crossOrigin);
}
if (resource->response().isHTTP() && if (resource->response().isHTTP() &&
resource->response().httpStatusCode() < 400) { resource->response().httpStatusCode() < 400) {
...@@ -1326,7 +1350,7 @@ bool ResourceFetcher::startLoad(Resource* resource) { ...@@ -1326,7 +1350,7 @@ bool ResourceFetcher::startLoad(Resource* resource) {
else else
m_nonBlockingLoaders.add(loader); m_nonBlockingLoaders.add(loader);
storeResourceTimingInitiatorInformation(resource); storePerformanceTimingInitiatorInformation(resource);
resource->setFetcherSecurityOrigin(sourceOrigin); resource->setFetcherSecurityOrigin(sourceOrigin);
loader->activateCacheAwareLoadingIfNeeded(request); loader->activateCacheAwareLoadingIfNeeded(request);
...@@ -1419,6 +1443,13 @@ ResourceRequestBlockedReason ResourceFetcher::willFollowRedirect( ...@@ -1419,6 +1443,13 @@ ResourceRequestBlockedReason ResourceFetcher::willFollowRedirect(
bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
it->value->addRedirect(redirectResponse, crossOrigin); it->value->addRedirect(redirectResponse, crossOrigin);
} }
if (resource->getType() == Resource::MainResource) {
DCHECK(m_navigationTimingInfo);
bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
m_navigationTimingInfo->addRedirect(redirectResponse, crossOrigin);
}
newRequest.setAllowStoredCredentials(resource->options().allowCredentials == newRequest.setAllowStoredCredentials(resource->options().allowCredentials ==
AllowStoredCredentials); AllowStoredCredentials);
willSendRequest(resource->identifier(), newRequest, redirectResponse, willSendRequest(resource->identifier(), newRequest, redirectResponse,
......
...@@ -152,6 +152,9 @@ class CORE_EXPORT ResourceFetcher ...@@ -152,6 +152,9 @@ class CORE_EXPORT ResourceFetcher
void reloadLoFiImages(); void reloadLoFiImages();
// Calling this method before main document resource is fetched is invalid.
ResourceTimingInfo* getNavigationTimingInfo();
// This is only exposed for testing purposes. // This is only exposed for testing purposes.
HeapListHashSet<Member<Resource>>* preloads() { return m_preloads.get(); } HeapListHashSet<Member<Resource>>* preloads() { return m_preloads.get(); }
...@@ -171,7 +174,7 @@ class CORE_EXPORT ResourceFetcher ...@@ -171,7 +174,7 @@ class CORE_EXPORT ResourceFetcher
Resource* createResourceForLoading(FetchRequest&, Resource* createResourceForLoading(FetchRequest&,
const String& charset, const String& charset,
const ResourceFactory&); const ResourceFactory&);
void storeResourceTimingInitiatorInformation(Resource*); void storePerformanceTimingInitiatorInformation(Resource*);
ResourceLoadPriority computeLoadPriority(Resource::Type, ResourceLoadPriority computeLoadPriority(Resource::Type,
const FetchRequest&, const FetchRequest&,
ResourcePriority::VisibilityStatus); ResourcePriority::VisibilityStatus);
...@@ -237,6 +240,8 @@ class CORE_EXPORT ResourceFetcher ...@@ -237,6 +240,8 @@ class CORE_EXPORT ResourceFetcher
HeapHashMap<Member<Resource>, std::unique_ptr<ResourceTimingInfo>>; HeapHashMap<Member<Resource>, std::unique_ptr<ResourceTimingInfo>>;
ResourceTimingInfoMap m_resourceTimingInfoMap; ResourceTimingInfoMap m_resourceTimingInfoMap;
std::unique_ptr<ResourceTimingInfo> m_navigationTimingInfo;
Vector<std::unique_ptr<ResourceTimingInfo>> m_scheduledResourceTimingReports; Vector<std::unique_ptr<ResourceTimingInfo>> m_scheduledResourceTimingReports;
HeapHashSet<Member<ResourceLoader>> m_loaders; HeapHashSet<Member<ResourceLoader>> m_loaders;
......
...@@ -144,6 +144,47 @@ TEST_F(ResourceFetcherTest, Vary) { ...@@ -144,6 +144,47 @@ TEST_F(ResourceFetcherTest, Vary) {
memoryCache()->remove(resource); memoryCache()->remove(resource);
} }
TEST_F(ResourceFetcherTest, NavigationTimingInfo) {
KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html");
ResourceResponse response;
response.setURL(url);
response.setHTTPStatusCode(200);
ResourceFetcher* fetcher = ResourceFetcher::create(
MockFetchContext::create(MockFetchContext::kShouldLoadNewResource));
ResourceRequest resourceRequest(url);
resourceRequest.setFrameType(WebURLRequest::FrameTypeNested);
resourceRequest.setRequestContext(WebURLRequest::RequestContextForm);
FetchRequest fetchRequest =
FetchRequest(resourceRequest, FetchInitiatorInfo());
Platform::current()->getURLLoaderMockFactory()->registerURL(
url, WebURLResponse(), "");
Resource* resource =
RawResource::fetchMainResource(fetchRequest, fetcher, SubstituteData());
resource->responseReceived(response, nullptr);
EXPECT_EQ(resource->getType(), Resource::MainResource);
ResourceTimingInfo* navigationTimingInfo = fetcher->getNavigationTimingInfo();
ASSERT_TRUE(navigationTimingInfo);
long long encodedDataLength = 123;
resource->loader()->didFinishLoading(0.0, encodedDataLength, 0);
EXPECT_EQ(navigationTimingInfo->transferSize(), encodedDataLength);
// When there are redirects.
KURL redirectURL(ParsedURLString, "http://127.0.0.1:8000/redirect.html");
ResourceResponse redirectResponse;
redirectResponse.setURL(redirectURL);
redirectResponse.setHTTPStatusCode(200);
long long redirectEncodedDataLength = 123;
redirectResponse.setEncodedDataLength(redirectEncodedDataLength);
ResourceRequest redirectResourceRequest(url);
fetcher->willFollowRedirect(resource, redirectResourceRequest,
redirectResponse);
EXPECT_EQ(navigationTimingInfo->transferSize(),
encodedDataLength + redirectEncodedDataLength);
Platform::current()->getURLLoaderMockFactory()->unregisterURL(url);
}
TEST_F(ResourceFetcherTest, VaryOnBack) { TEST_F(ResourceFetcherTest, VaryOnBack) {
MockFetchContext* context = MockFetchContext* context =
MockFetchContext::create(MockFetchContext::kShouldLoadNewResource); MockFetchContext::create(MockFetchContext::kShouldLoadNewResource);
......
...@@ -148,6 +148,10 @@ unsigned long DocumentLoader::mainResourceIdentifier() const { ...@@ -148,6 +148,10 @@ unsigned long DocumentLoader::mainResourceIdentifier() const {
return m_mainResource ? m_mainResource->identifier() : 0; return m_mainResource ? m_mainResource->identifier() : 0;
} }
ResourceTimingInfo* DocumentLoader::getNavigationTimingInfo() const {
return fetcher()->getNavigationTimingInfo();
}
const ResourceRequest& DocumentLoader::originalRequest() const { const ResourceRequest& DocumentLoader::originalRequest() const {
return m_originalRequest; return m_originalRequest;
} }
......
...@@ -60,6 +60,7 @@ class ResourceFetcher; ...@@ -60,6 +60,7 @@ class ResourceFetcher;
class DocumentInit; class DocumentInit;
class LocalFrame; class LocalFrame;
class FrameLoader; class FrameLoader;
class ResourceTimingInfo;
class WebDocumentSubresourceFilter; class WebDocumentSubresourceFilter;
struct ViewportDescriptionWrapper; struct ViewportDescriptionWrapper;
...@@ -79,6 +80,8 @@ class CORE_EXPORT DocumentLoader ...@@ -79,6 +80,8 @@ class CORE_EXPORT DocumentLoader
LocalFrame* frame() const { return m_frame; } LocalFrame* frame() const { return m_frame; }
ResourceTimingInfo* getNavigationTimingInfo() const;
virtual void detachFromFrame(); virtual void detachFromFrame();
unsigned long mainResourceIdentifier() const; unsigned long mainResourceIdentifier() const;
......
...@@ -336,12 +336,17 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) { ...@@ -336,12 +336,17 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
DCHECK(frame); DCHECK(frame);
const DocumentLoader* documentLoader = frame->loader().documentLoader(); const DocumentLoader* documentLoader = frame->loader().documentLoader();
DCHECK(documentLoader); DCHECK(documentLoader);
const DocumentLoadTiming& documentLoadTiming = documentLoader->timing(); const DocumentLoadTiming& documentLoadTiming = documentLoader->timing();
const DocumentTiming* documentTiming = const DocumentTiming* documentTiming =
frame->document() ? &(frame->document()->timing()) : nullptr; frame->document() ? &(frame->document()->timing()) : nullptr;
const ResourceResponse& finalResponse = documentLoader->response(); const ResourceResponse& finalResponse = documentLoader->response();
ResourceTimingInfo* navigationTimingInfo =
documentLoader->getNavigationTimingInfo();
if (!navigationTimingInfo)
return;
ResourceLoadTiming* resourceLoadTiming = finalResponse.resourceLoadTiming(); ResourceLoadTiming* resourceLoadTiming = finalResponse.resourceLoadTiming();
// Don't create a navigation timing instance when // Don't create a navigation timing instance when
...@@ -352,8 +357,7 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) { ...@@ -352,8 +357,7 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
double lastRedirectEndTime = documentLoadTiming.redirectEnd(); double lastRedirectEndTime = documentLoadTiming.redirectEnd();
double finishTime = documentLoadTiming.loadEventEnd(); double finishTime = documentLoadTiming.loadEventEnd();
// TODO(sunjian) Implement transfer size. crbug/663187 unsigned long long transferSize = navigationTimingInfo->transferSize();
unsigned long long transferSize = 0;
unsigned long long encodedBodyLength = finalResponse.encodedBodyLength(); unsigned long long encodedBodyLength = finalResponse.encodedBodyLength();
unsigned long long decodedBodyLength = finalResponse.decodedBodyLength(); unsigned long long decodedBodyLength = finalResponse.decodedBodyLength();
bool didReuseConnection = finalResponse.connectionReused(); bool didReuseConnection = finalResponse.connectionReused();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment