Commit 22822fea authored by hiroshige's avatar hiroshige Committed by Commit bot

Keep multipart responses in m_nonBlockingLoaders after first part loaded

For multipart responses, in the first ResourceLoader::didFinishLoadingOnePart(),
(1) the ResourceLoader is moved from |m_loaders| to |m_nonBlockingLoaders|
    in ResourceFetcher::subresourceLoaderFinishedLoadingOnePart(), and
(2) it is removed from |m_nonBlockingLoaders| in
    ResourceFetcher::willTerminateResourceLoader() called in didFinishLoading().
Therefore, if we call window.stop() just after multipart <img>'s onload event,
we cannot stop loading of the multipart response because it is no longer in
|m_loaders| nor |m_nonBlockingLoaders|.

However, in the second didFinishLoadingOnePart(),
(3) In subresourceLoaderFinishedLoadingOnePart(),
    the ResourceLoader is added again to |m_nonBlockingLoaders|, and
(4) We don't call didFinishLoading()/willTerminateResourceLoader().
Therefore, we can stop loading of the image after that by window.stop().

This CL makes the ResourceLoader to be kept in |m_nonBlockingLoaders| after (1)
and to be remove from |m_nonBlockingLoaders| when
ResourceLoader::didFinishLoading() is called.
This CL enables to stop loading of multipart responses at any time, and also
enables https://codereview.chromium.org/1756953002/ to stop dispatching
didFinishLoadingOnePart() for each part without affecting window.stop()
behavior on multipart responses.

BUG=570608

Review URL: https://codereview.chromium.org/1800333003

Cr-Commit-Position: refs/heads/master@{#381876}
parent 468ca56a
<html>
<head>
<script>
// This tests window.stop() can stop loading of multipart images after
// <img>'s onload and before the next part loaded after onload.
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
function callStop()
{
window.stop();
window.setTimeout(function() {
var broken = (testingImage.width != 2 && testingImage.width != 76);
document.getElementById("results").innerHTML = broken ? "PASS" : "FAIL";
if (window.testRunner)
testRunner.notifyDone();
}, 100);
}
function firstPartLoaded()
{
setTimeout(callStop, 0);
}
</script>
</head>
<body>
<!-- |label| is added to avoid interaction between stop-loading* tests -->
<img id=testingImage src="resources/multipart.php?interval=1&loop=1&img1=2x2-green.png&img2=abe.png&label=1" onload="firstPartLoaded()">
<p id="results"></p>
</body>
</html>
<html>
<head>
<script>
// This tests window.stop() can stop loading of multipart images after
// <img>'s onload and one more part loaded after onload.
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
function callStop()
{
window.stop();
window.setTimeout(function() {
var broken = (testingImage.width != 2 && testingImage.width != 76);
document.getElementById("results").innerHTML = broken ? "PASS" : "FAIL";
if (window.testRunner)
testRunner.notifyDone();
}, 100);
}
function firstPartLoaded()
{
setTimeout(callStop, 1500);
}
</script>
</head>
<body>
<!-- |label| is added to avoid interaction between stop-loading* tests -->
<img id=testingImage src="resources/multipart.php?interval=1&loop=1&img1=2x2-green.png&img2=abe.png&label=2" onload="firstPartLoaded()">
<p id="results"></p>
</body>
</html>
......@@ -927,7 +927,8 @@ bool ResourceFetcher::scheduleArchiveLoad(Resource* resource, const ResourceRequ
void ResourceFetcher::didFinishLoading(Resource* resource, double finishTime, int64_t encodedDataLength)
{
TRACE_EVENT_ASYNC_END0("blink.net", "Resource", resource);
willTerminateResourceLoader(resource->loader());
// The ResourceLoader might be in |m_nonBlockingLoaders| for multipart responses.
ASSERT(!(m_loaders && m_loaders->contains(resource->loader())));
if (resource && resource->response().isHTTP() && resource->response().httpStatusCode() < 400) {
ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource);
......@@ -946,7 +947,7 @@ void ResourceFetcher::didFinishLoading(Resource* resource, double finishTime, in
void ResourceFetcher::didFailLoading(const Resource* resource, const ResourceError& error)
{
TRACE_EVENT_ASYNC_END0("blink.net", "Resource", resource);
willTerminateResourceLoader(resource->loader());
removeResourceLoader(resource->loader());
bool isInternalRequest = resource->options().initiatorInfo.name == FetchInitiatorTypeNames::internal;
context().dispatchDidFail(resource->identifier(), error, isInternalRequest);
}
......@@ -983,13 +984,12 @@ void ResourceFetcher::acceptDataFromThreadedReceiver(unsigned long identifier, c
context().dispatchDidReceiveData(identifier, data, dataLength, encodedDataLength);
}
void ResourceFetcher::subresourceLoaderFinishedLoadingOnePart(ResourceLoader* loader)
void ResourceFetcher::moveResourceLoaderToNonBlocking(ResourceLoader* loader)
{
if (!m_nonBlockingLoaders)
m_nonBlockingLoaders = ResourceLoaderSet::create();
m_nonBlockingLoaders->add(loader);
m_loaders->remove(loader);
didLoadResource(loader->cachedResource());
}
void ResourceFetcher::willStartLoadingResource(Resource* resource, ResourceLoader* loader, ResourceRequest& request)
......@@ -1011,7 +1011,7 @@ void ResourceFetcher::willStartLoadingResource(Resource* resource, ResourceLoade
context().dispatchWillSendRequest(resource->identifier(), request, ResourceResponse(), resource->options().initiatorInfo);
}
void ResourceFetcher::willTerminateResourceLoader(ResourceLoader* loader)
void ResourceFetcher::removeResourceLoader(ResourceLoader* loader)
{
if (m_loaders && m_loaders->contains(loader))
m_loaders->remove(loader);
......
......@@ -113,10 +113,12 @@ public:
void didReceiveResponse(const Resource*, const ResourceResponse&);
void didReceiveData(const Resource*, const char* data, int dataLength, int encodedDataLength);
void didDownloadData(const Resource*, int dataLength, int encodedDataLength);
void subresourceLoaderFinishedLoadingOnePart(ResourceLoader*);
void willStartLoadingResource(Resource*, ResourceLoader*, ResourceRequest&);
bool defersLoading() const;
void moveResourceLoaderToNonBlocking(ResourceLoader*);
void removeResourceLoader(ResourceLoader*);
enum AccessControlLoggingDecision {
ShouldLogAccessControlErrors,
ShouldNotLogAccessControlErrors
......@@ -176,8 +178,6 @@ private:
void reloadImagesIfNotDeferred();
void willTerminateResourceLoader(ResourceLoader*);
void updateMemoryCacheStats(Resource*, RevalidationPolicy, const FetchRequest&, const ResourceFactory&, bool isStaticData) const;
Member<FetchContext> m_context;
......
......@@ -129,14 +129,17 @@ void ResourceLoader::didDownloadData(WebURLLoader*, int length, int encodedDataL
void ResourceLoader::didFinishLoadingOnePart(double finishTime, int64_t encodedDataLength)
{
ASSERT(m_state != ConnectionStateReleased);
if (!isFinishing()) {
if (isFinishing()) {
m_fetcher->removeResourceLoader(this);
} else {
// When loading a multipart resource, make the loader non-block when
// finishing loading the first part.
m_fetcher->subresourceLoaderFinishedLoadingOnePart(this);
}
m_fetcher->moveResourceLoaderToNonBlocking(this);
if (m_state == ConnectionStateReleased)
return;
m_fetcher->didLoadResource(m_resource.get());
if (m_state == ConnectionStateReleased)
return;
}
if (m_notifiedLoadComplete)
return;
......
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