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) {
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
static void RecordSriResourceIntegrityMismatchEvent(
......@@ -597,7 +609,6 @@ Resource* ResourceFetcher::requestResource(
resource->setLinkPreload(false);
break;
}
if (!resource)
return nullptr;
if (resource->getType() != factory.type()) {
......@@ -641,7 +652,6 @@ Resource* ResourceFetcher::requestResource(
if (!startLoad(resource))
return nullptr;
scopedResourceLoadTracker.resourceLoadContinuesBeyondScope();
DCHECK(!resource->errorOccurred() ||
......@@ -757,7 +767,7 @@ Resource* ResourceFetcher::createResourceForLoading(
return resource;
}
void ResourceFetcher::storeResourceTimingInitiatorInformation(
void ResourceFetcher::storePerformanceTimingInitiatorInformation(
Resource* resource) {
const AtomicString& fetchInitiator = resource->options().initiatorInfo.name;
if (fetchInitiator == FetchInitiatorTypeNames::internal)
......@@ -771,6 +781,14 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation(
? resource->resourceRequest().navigationStartTime()
: 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 =
ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
......@@ -782,8 +800,9 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation(
}
if (!isMainResource ||
context().updateTimingInfoForIFrameNavigation(info.get()))
context().updateTimingInfoForIFrameNavigation(info.get())) {
m_resourceTimingInfoMap.add(resource, std::move(info));
}
}
ResourceFetcher::RevalidationPolicy
......@@ -1125,6 +1144,10 @@ ArchiveResource* ResourceFetcher::createArchive(Resource* resource) {
return m_archive ? m_archive->mainResource() : nullptr;
}
ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() {
return m_navigationTimingInfo.get();
}
void ResourceFetcher::didFinishLoading(Resource* resource,
double finishTime,
DidFinishLoadingReason finishReason) {
......@@ -1143,18 +1166,19 @@ void ResourceFetcher::didFinishLoading(Resource* resource,
DCHECK(finishReason == DidFinishFirstPartInMultipart ||
!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 =
m_resourceTimingInfoMap.take(resource)) {
// Store redirect responses that were packed inside the final response.
const Vector<ResourceResponse>& 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);
}
addRedirectsToTimingInfo(resource, info.get());
if (resource->response().isHTTP() &&
resource->response().httpStatusCode() < 400) {
......@@ -1326,7 +1350,7 @@ bool ResourceFetcher::startLoad(Resource* resource) {
else
m_nonBlockingLoaders.add(loader);
storeResourceTimingInitiatorInformation(resource);
storePerformanceTimingInitiatorInformation(resource);
resource->setFetcherSecurityOrigin(sourceOrigin);
loader->activateCacheAwareLoadingIfNeeded(request);
......@@ -1419,6 +1443,13 @@ ResourceRequestBlockedReason ResourceFetcher::willFollowRedirect(
bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
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 ==
AllowStoredCredentials);
willSendRequest(resource->identifier(), newRequest, redirectResponse,
......
......@@ -152,6 +152,9 @@ class CORE_EXPORT ResourceFetcher
void reloadLoFiImages();
// Calling this method before main document resource is fetched is invalid.
ResourceTimingInfo* getNavigationTimingInfo();
// This is only exposed for testing purposes.
HeapListHashSet<Member<Resource>>* preloads() { return m_preloads.get(); }
......@@ -171,7 +174,7 @@ class CORE_EXPORT ResourceFetcher
Resource* createResourceForLoading(FetchRequest&,
const String& charset,
const ResourceFactory&);
void storeResourceTimingInitiatorInformation(Resource*);
void storePerformanceTimingInitiatorInformation(Resource*);
ResourceLoadPriority computeLoadPriority(Resource::Type,
const FetchRequest&,
ResourcePriority::VisibilityStatus);
......@@ -237,6 +240,8 @@ class CORE_EXPORT ResourceFetcher
HeapHashMap<Member<Resource>, std::unique_ptr<ResourceTimingInfo>>;
ResourceTimingInfoMap m_resourceTimingInfoMap;
std::unique_ptr<ResourceTimingInfo> m_navigationTimingInfo;
Vector<std::unique_ptr<ResourceTimingInfo>> m_scheduledResourceTimingReports;
HeapHashSet<Member<ResourceLoader>> m_loaders;
......
......@@ -144,6 +144,47 @@ TEST_F(ResourceFetcherTest, Vary) {
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) {
MockFetchContext* context =
MockFetchContext::create(MockFetchContext::kShouldLoadNewResource);
......
......@@ -148,6 +148,10 @@ unsigned long DocumentLoader::mainResourceIdentifier() const {
return m_mainResource ? m_mainResource->identifier() : 0;
}
ResourceTimingInfo* DocumentLoader::getNavigationTimingInfo() const {
return fetcher()->getNavigationTimingInfo();
}
const ResourceRequest& DocumentLoader::originalRequest() const {
return m_originalRequest;
}
......
......@@ -60,6 +60,7 @@ class ResourceFetcher;
class DocumentInit;
class LocalFrame;
class FrameLoader;
class ResourceTimingInfo;
class WebDocumentSubresourceFilter;
struct ViewportDescriptionWrapper;
......@@ -79,6 +80,8 @@ class CORE_EXPORT DocumentLoader
LocalFrame* frame() const { return m_frame; }
ResourceTimingInfo* getNavigationTimingInfo() const;
virtual void detachFromFrame();
unsigned long mainResourceIdentifier() const;
......
......@@ -336,12 +336,17 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
DCHECK(frame);
const DocumentLoader* documentLoader = frame->loader().documentLoader();
DCHECK(documentLoader);
const DocumentLoadTiming& documentLoadTiming = documentLoader->timing();
const DocumentTiming* documentTiming =
frame->document() ? &(frame->document()->timing()) : nullptr;
const ResourceResponse& finalResponse = documentLoader->response();
ResourceTimingInfo* navigationTimingInfo =
documentLoader->getNavigationTimingInfo();
if (!navigationTimingInfo)
return;
ResourceLoadTiming* resourceLoadTiming = finalResponse.resourceLoadTiming();
// Don't create a navigation timing instance when
......@@ -352,8 +357,7 @@ void PerformanceBase::addNavigationTiming(LocalFrame* frame) {
double lastRedirectEndTime = documentLoadTiming.redirectEnd();
double finishTime = documentLoadTiming.loadEventEnd();
// TODO(sunjian) Implement transfer size. crbug/663187
unsigned long long transferSize = 0;
unsigned long long transferSize = navigationTimingInfo->transferSize();
unsigned long long encodedBodyLength = finalResponse.encodedBodyLength();
unsigned long long decodedBodyLength = finalResponse.decodedBodyLength();
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