| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |