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

Side by Side 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
7 7
8 This library is free software; you can redistribute it and/or 8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 License as published by the Free Software Foundation; either
(...skipping 28 matching lines...) Expand all
39 #include "public/platform/Platform.h" 39 #include "public/platform/Platform.h"
40 #include "public/platform/WebCachePolicy.h" 40 #include "public/platform/WebCachePolicy.h"
41 #include "wtf/CurrentTime.h" 41 #include "wtf/CurrentTime.h"
42 #include "wtf/HashCountedSet.h" 42 #include "wtf/HashCountedSet.h"
43 #include "wtf/StdLibExtras.h" 43 #include "wtf/StdLibExtras.h"
44 #include "wtf/Vector.h" 44 #include "wtf/Vector.h"
45 #include <memory> 45 #include <memory>
46 #include <v8.h> 46 #include <v8.h>
47 47
48 namespace blink { 48 namespace blink {
49 namespace {
50 // The amount of time to wait before informing the clients that the image has
51 // been updated (in seconds). This effectively throttles invalidations that
52 // result from new data arriving for this image.
53 constexpr double kFlushDelaySeconds = 1.;
54 } // namespace
49 55
50 class ImageResource::ImageResourceFactory : public ResourceFactory { 56 class ImageResource::ImageResourceFactory : public ResourceFactory {
51 STACK_ALLOCATED(); 57 STACK_ALLOCATED();
52 58
53 public: 59 public:
54 ImageResourceFactory(const FetchRequest& fetchRequest) 60 ImageResourceFactory(const FetchRequest& fetchRequest)
55 : ResourceFactory(Resource::Image), m_fetchRequest(&fetchRequest) {} 61 : ResourceFactory(Resource::Image), m_fetchRequest(&fetchRequest) {}
56 62
57 Resource* create(const ResourceRequest& request, 63 Resource* create(const ResourceRequest& request,
58 const ResourceLoaderOptions& options, 64 const ResourceLoaderOptions& options,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } 106 }
101 107
102 ImageResource::ImageResource(const ResourceRequest& resourceRequest, 108 ImageResource::ImageResource(const ResourceRequest& resourceRequest,
103 const ResourceLoaderOptions& options, 109 const ResourceLoaderOptions& options,
104 bool isPlaceholder) 110 bool isPlaceholder)
105 : Resource(resourceRequest, Image, options), 111 : Resource(resourceRequest, Image, options),
106 m_devicePixelRatioHeaderValue(1.0), 112 m_devicePixelRatioHeaderValue(1.0),
107 m_image(nullptr), 113 m_image(nullptr),
108 m_hasDevicePixelRatioHeaderValue(false), 114 m_hasDevicePixelRatioHeaderValue(false),
109 m_isSchedulingReload(false), 115 m_isSchedulingReload(false),
110 m_isPlaceholder(isPlaceholder) { 116 m_isPlaceholder(isPlaceholder),
117 m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
111 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this; 118 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(ResourceRequest) " << this;
112 } 119 }
113 120
114 ImageResource::ImageResource(blink::Image* image, 121 ImageResource::ImageResource(blink::Image* image,
115 const ResourceLoaderOptions& options) 122 const ResourceLoaderOptions& options)
116 : Resource(ResourceRequest(""), Image, options), 123 : Resource(ResourceRequest(""), Image, options),
117 m_devicePixelRatioHeaderValue(1.0), 124 m_devicePixelRatioHeaderValue(1.0),
118 m_image(image), 125 m_image(image),
119 m_hasDevicePixelRatioHeaderValue(false), 126 m_hasDevicePixelRatioHeaderValue(false),
120 m_isSchedulingReload(false), 127 m_isSchedulingReload(false),
121 m_isPlaceholder(false) { 128 m_isPlaceholder(false),
129 m_flushTimer(this, &ImageResource::flushImageIfNeeded) {
122 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(Image) " << this; 130 RESOURCE_LOADING_DVLOG(1) << "new ImageResource(Image) " << this;
123 setStatus(Cached); 131 setStatus(Cached);
124 } 132 }
125 133
126 ImageResource::~ImageResource() { 134 ImageResource::~ImageResource() {
127 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this; 135 RESOURCE_LOADING_DVLOG(1) << "~ImageResource " << this;
128 clearImage(); 136 clearImage();
129 } 137 }
130 138
131 DEFINE_TRACE(ImageResource) { 139 DEFINE_TRACE(ImageResource) {
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 return m_image->data(); 293 return m_image->data();
286 return nullptr; 294 return nullptr;
287 } 295 }
288 296
289 void ImageResource::appendData(const char* data, size_t length) { 297 void ImageResource::appendData(const char* data, size_t length) {
290 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length); 298 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length);
291 if (m_multipartParser) { 299 if (m_multipartParser) {
292 m_multipartParser->appendData(data, length); 300 m_multipartParser->appendData(data, length);
293 } else { 301 } else {
294 Resource::appendData(data, length); 302 Resource::appendData(data, length);
303
304 // If we don't have the size available yet, then update immediately since
305 // we need to know the image size as soon as possible. Likewise for
306 // animated images, update right away since we shouldn't throttle animated
307 // images.
308 if (m_sizeAvailable == Image::SizeUnavailable ||
309 (m_image && m_image->maybeAnimated())) {
310 updateImage(false);
311 return;
312 }
313
314 // For other cases, only update at |kFlushDelaySeconds| intervals. This
315 // throttles how frequently we update |m_image| and how frequently we
316 // inform the clients which causes an invalidation of this image. In other
317 // words, we only invalidate this image every |kFlushDelaySeconds| seconds
318 // while loading.
319 if (!m_flushTimer.isActive()) {
320 double now = WTF::monotonicallyIncreasingTime();
321 if (!m_lastFlushTime)
322 m_lastFlushTime = now;
323
324 DCHECK_LE(m_lastFlushTime, now);
325 double flushDelay = m_lastFlushTime - now + kFlushDelaySeconds;
326 if (flushDelay < 0.)
327 flushDelay = 0.;
328 m_flushTimer.startOneShot(flushDelay, BLINK_FROM_HERE);
329 }
330 }
331 }
332
333 void ImageResource::flushImageIfNeeded(TimerBase*) {
334 // We might have already loaded the image fully, in which case we don't need
335 // to call |updateImage()|.
336 if (isLoading()) {
337 m_lastFlushTime = WTF::monotonicallyIncreasingTime();
295 updateImage(false); 338 updateImage(false);
296 } 339 }
297 } 340 }
298 341
299 std::pair<blink::Image*, float> ImageResource::brokenImage( 342 std::pair<blink::Image*, float> ImageResource::brokenImage(
300 float deviceScaleFactor) { 343 float deviceScaleFactor) {
301 if (deviceScaleFactor >= 2) { 344 if (deviceScaleFactor >= 2) {
302 DEFINE_STATIC_REF(blink::Image, brokenImageHiRes, 345 DEFINE_STATIC_REF(blink::Image, brokenImageHiRes,
303 (blink::Image::loadPlatformResource("missingImage@2x"))); 346 (blink::Image::loadPlatformResource("missingImage@2x")));
304 return std::make_pair(brokenImageHiRes, 2); 347 return std::make_pair(brokenImageHiRes, 2);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 inline void ImageResource::clearImage() { 450 inline void ImageResource::clearImage() {
408 if (!m_image) 451 if (!m_image)
409 return; 452 return;
410 int64_t length = m_image->data() ? m_image->data()->size() : 0; 453 int64_t length = m_image->data() ? m_image->data()->size() : 0;
411 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-length); 454 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-length);
412 455
413 // If our Image has an observer, it's always us so we need to clear the back 456 // If our Image has an observer, it's always us so we need to clear the back
414 // pointer before dropping our reference. 457 // pointer before dropping our reference.
415 m_image->clearImageObserver(); 458 m_image->clearImageObserver();
416 m_image.clear(); 459 m_image.clear();
460 m_sizeAvailable = Image::SizeUnavailable;
417 } 461 }
418 462
419 void ImageResource::updateImage(bool allDataReceived) { 463 void ImageResource::updateImage(bool allDataReceived) {
420 TRACE_EVENT0("blink", "ImageResource::updateImage"); 464 TRACE_EVENT0("blink", "ImageResource::updateImage");
421 465
422 if (data()) 466 if (data())
423 createImage(); 467 createImage();
424 468
425 Image::SizeAvailability sizeAvailable = Image::SizeUnavailable;
426
427 // Have the image update its data from its internal buffer. It will not do 469 // Have the image update its data from its internal buffer. It will not do
428 // anything now, but will delay decoding until queried for info (like size or 470 // anything now, but will delay decoding until queried for info (like size or
429 // specific image frames). 471 // specific image frames).
430 if (data()) { 472 if (data()) {
431 DCHECK(m_image); 473 DCHECK(m_image);
432 sizeAvailable = m_image->setData(data(), allDataReceived); 474 m_sizeAvailable = m_image->setData(data(), allDataReceived);
433 } 475 }
434 476
435 // Go ahead and tell our observers to try to draw if we have either received 477 // Go ahead and tell our observers to try to draw if we have either received
436 // all the data or the size is known. Each chunk from the network causes 478 // all the data or the size is known. Each chunk from the network causes
437 // observers to repaint, which will force that chunk to decode. 479 // observers to repaint, which will force that chunk to decode.
438 if (sizeAvailable == Image::SizeUnavailable && !allDataReceived) 480 if (m_sizeAvailable == Image::SizeUnavailable && !allDataReceived)
439 return; 481 return;
440 482
441 if (m_isPlaceholder && allDataReceived && m_image && !m_image->isNull()) { 483 if (m_isPlaceholder && allDataReceived && m_image && !m_image->isNull()) {
442 if (sizeAvailable == Image::SizeAvailable) { 484 if (m_sizeAvailable == Image::SizeAvailable) {
443 // TODO(sclittle): Show the original image if the response consists of the 485 // TODO(sclittle): Show the original image if the response consists of the
444 // entire image, such as if the entire image response body is smaller than 486 // entire image, such as if the entire image response body is smaller than
445 // the requested range. 487 // the requested range.
446 IntSize dimensions = m_image->size(); 488 IntSize dimensions = m_image->size();
447 clearImage(); 489 clearImage();
448 m_image = PlaceholderImage::create(this, dimensions); 490 m_image = PlaceholderImage::create(this, dimensions);
449 } else { 491 } else {
450 // Clear the image so that it gets treated like a decoding error, since 492 // Clear the image so that it gets treated like a decoding error, since
451 // the attempt to build a placeholder image failed. 493 // the attempt to build a placeholder image failed.
452 clearImage(); 494 clearImage();
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 WebServiceWorkerResponseTypeOpaque; 721 WebServiceWorkerResponseTypeOpaque;
680 } 722 }
681 if (!getImage()->currentFrameHasSingleSecurityOrigin()) 723 if (!getImage()->currentFrameHasSingleSecurityOrigin())
682 return false; 724 return false;
683 if (passesAccessControlCheck(securityOrigin)) 725 if (passesAccessControlCheck(securityOrigin))
684 return true; 726 return true;
685 return !securityOrigin->taintsCanvas(response().url()); 727 return !securityOrigin->taintsCanvas(response().url());
686 } 728 }
687 729
688 } // namespace blink 730 } // namespace blink
OLDNEW
« 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