Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Unified Diff: third_party/WebKit/Source/core/fetch/ImageResource.cpp

Issue 2361263003: Blink: Throttle progressively loaded images. (Closed)
Patch Set: land: rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/fetch/ImageResource.cpp
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
index 929cb375d24e5dcb1ae3a954288a0506d43996ba..dba77fe8f5ee36c3f854c9ad3502e47b888015f0 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
@@ -46,6 +46,12 @@
#include <v8.h>
namespace blink {
+namespace {
+// The amount of time to wait before informing the clients that the image has
+// been updated (in seconds). This effectively throttles invalidations that
+// result from new data arriving for this image.
+constexpr double kFlushDelaySeconds = 1.;
+} // namespace
class ImageResource::ImageResourceFactory : public ResourceFactory {
STACK_ALLOCATED();
@@ -107,7 +113,8 @@ ImageResource::ImageResource(const ResourceRequest& resourceRequest,
m_image(nullptr),
m_hasDevicePixelRatioHeaderValue(false),
m_isSchedulingReload(false),
- m_isPlaceholder(isPlaceholder) {
+ m_isPlaceholder(isPlaceholder),
+ m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this;
}
@@ -118,7 +125,8 @@ ImageResource::ImageResource(blink::Image* image,
m_image(image),
m_hasDevicePixelRatioHeaderValue(false),
m_isSchedulingReload(false),
- m_isPlaceholder(false) {
+ m_isPlaceholder(false),
+ m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
RESOURCE_LOADING_DVLOG(1) << "new ImageResource(Image) " << this;
setStatus(Cached);
}
@@ -292,6 +300,41 @@ void ImageResource::appendData(const char* data, size_t length) {
m_multipartParser->appendData(data, length);
} else {
Resource::appendData(data, length);
+
+ // If we don't have the size available yet, then update immediately since
+ // we need to know the image size as soon as possible. Likewise for
+ // animated images, update right away since we shouldn't throttle animated
+ // images.
+ if (m_sizeAvailable == Image::SizeUnavailable ||
+ (m_image && m_image->maybeAnimated())) {
+ updateImage(false);
+ return;
+ }
+
+ // For other cases, only update at |kFlushDelaySeconds| intervals. This
+ // throttles how frequently we update |m_image| and how frequently we
+ // inform the clients which causes an invalidation of this image. In other
+ // words, we only invalidate this image every |kFlushDelaySeconds| seconds
+ // while loading.
+ if (!m_flushTimer.isActive()) {
+ double now = WTF::monotonicallyIncreasingTime();
+ if (!m_lastFlushTime)
+ m_lastFlushTime = now;
+
+ DCHECK_LE(m_lastFlushTime, now);
+ double flushDelay = m_lastFlushTime - now + kFlushDelaySeconds;
+ if (flushDelay < 0.)
+ flushDelay = 0.;
+ m_flushTimer.startOneShot(flushDelay, BLINK_FROM_HERE);
+ }
+ }
+}
+
+void ImageResource::flushImageIfNeeded(TimerBase*) {
+ // We might have already loaded the image fully, in which case we don't need
+ // to call |updateImage()|.
+ if (isLoading()) {
+ m_lastFlushTime = WTF::monotonicallyIncreasingTime();
updateImage(false);
}
}
@@ -414,6 +457,7 @@ inline void ImageResource::clearImage() {
// pointer before dropping our reference.
m_image->clearImageObserver();
m_image.clear();
+ m_sizeAvailable = Image::SizeUnavailable;
}
void ImageResource::updateImage(bool allDataReceived) {
@@ -422,24 +466,22 @@ void ImageResource::updateImage(bool allDataReceived) {
if (data())
createImage();
- Image::SizeAvailability sizeAvailable = Image::SizeUnavailable;
-
// Have the image update its data from its internal buffer. It will not do
// anything now, but will delay decoding until queried for info (like size or
// specific image frames).
if (data()) {
DCHECK(m_image);
- sizeAvailable = m_image->setData(data(), allDataReceived);
+ m_sizeAvailable = m_image->setData(data(), allDataReceived);
}
// Go ahead and tell our observers to try to draw if we have either received
// all the data or the size is known. Each chunk from the network causes
// observers to repaint, which will force that chunk to decode.
- if (sizeAvailable == Image::SizeUnavailable && !allDataReceived)
+ if (m_sizeAvailable == Image::SizeUnavailable && !allDataReceived)
return;
if (m_isPlaceholder && allDataReceived && m_image && !m_image->isNull()) {
- if (sizeAvailable == Image::SizeAvailable) {
+ if (m_sizeAvailable == Image::SizeAvailable) {
// TODO(sclittle): Show the original image if the response consists of the
// entire image, such as if the entire image response body is smaller than
// the requested range.
« no previous file with comments | « third_party/WebKit/Source/core/fetch/ImageResource.h ('k') | third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698