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

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

Issue 2710113002: DO NOT SUBMIT really old prototype of sprite recognition for image replacement
Patch Set: Created 3 years, 10 months 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/ImageResourceTest.cpp
diff --git a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
index 1815328a24d6a0f9b4fd730bc7b10b6b36bcfe04..9e59568d34d6e814ad66e2ecd27042f28410de21 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
@@ -30,6 +30,7 @@
#include "core/fetch/ImageResource.h"
+#include "core/fetch/ImageResourceObserver.h"
#include "core/fetch/MemoryCache.h"
#include "core/fetch/MockResourceClients.h"
#include "core/fetch/ResourceFetcher.h"
@@ -37,16 +38,21 @@
#include "core/fetch/UniqueIdentifier.h"
#include "platform/SharedBuffer.h"
#include "platform/exported/WrappedResourceResponse.h"
+#include "platform/geometry/IntSize.h"
+#include "platform/graphics/BitmapImage.h"
#include "platform/graphics/Image.h"
+#include "platform/network/ResourceError.h"
#include "platform/scheduler/test/fake_web_task_runner.h"
#include "platform/testing/URLTestHelpers.h"
#include "platform/testing/UnitTestHelpers.h"
#include "public/platform/Platform.h"
+#include "public/platform/WebCachePolicy.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebURLLoaderMockFactory.h"
#include "public/platform/WebURLResponse.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/PtrUtil.h"
+#include "wtf/text/Base64.h"
#include <memory>
namespace blink {
@@ -87,34 +93,36 @@ static Vector<unsigned char> jpegImage()
}
// An image of size 50x50.
+const char kJpegImage2Data[] = {
+ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48,
+ 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
+ 0x00, 0x11, 0x08, 0x00, 0x32, 0x00, 0x32, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11,
+ 0x01, 0xff, 0xc4, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x10, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00,
+ 0x15, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
+ 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x00, 0x94, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0xff, 0xd9
+};
+const int kJpegImage2Width = 50;
+const int kJpegImage2Height = 50;
+
+// An image of size 50x50.
static Vector<unsigned char> jpegImage2()
{
Vector<unsigned char> jpeg;
-
- static const unsigned char data[] = {
- 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48,
- 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
- 0x00, 0x11, 0x08, 0x00, 0x32, 0x00, 0x32, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11,
- 0x01, 0xff, 0xc4, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x10, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00,
- 0x15, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
- 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x00, 0x94, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0xff, 0xd9
- };
-
- jpeg.append(data, sizeof(data));
+ jpeg.append(reinterpret_cast<const unsigned char*>(kJpegImage2Data), sizeof(kJpegImage2Data));
return jpeg;
}
@@ -637,4 +645,639 @@ TEST(ImageResourceTest, CancelOnDecodeError)
EXPECT_FALSE(cachedImage->isLoading());
}
+namespace {
+
+ // A subrange of |kJpegImage2Data| from which the image dimensions can be decoded.
+ const size_t kRangeWithDimensionsLength = arraysize(kJpegImage2Data) - 10;
+ static_assert(kRangeWithDimensionsLength < arraysize(kJpegImage2Data), "Sample image data is too short.");
+
+ TEST(ImageResourceTest, EnsureLongTestSubrangeContainsDimensions)
+ {
+ RefPtr<blink::Image> image = BitmapImage::create();
+ EXPECT_EQ(Image::SizeAvailable, image->setData(SharedBuffer::create(kJpegImage2Data, kRangeWithDimensionsLength), true));
+ EXPECT_EQ(kJpegImage2Width, image->width());
+ EXPECT_EQ(kJpegImage2Height, image->height());
+ }
+
+ // A subrange of |kJpegImage2Data| from which the image dimensions cannot be decoded.
+ const size_t kRangeWithoutDimensionsLength = 50;
+ static_assert(kRangeWithoutDimensionsLength < arraysize(kJpegImage2Data), "Sample image data is too short.");
+
+ TEST(ImageResourceTest, EnsureShortTestSubrangeDoesNotContainDimensions)
+ {
+ RefPtr<blink::Image> image = BitmapImage::create();
+ EXPECT_EQ(Image::SizeUnavailable, image->setData(SharedBuffer::create(kJpegImage2Data, kRangeWithoutDimensionsLength), true));
+ }
+
+ const char kPlaceholderForJpegImage2[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"50\" height=\"50\">\n"
+ "<rect width=\"100%\" height=\"100%\" style=\"fill:rgba(127,127,127,0.4);stroke-width:2;stroke:black\" />\n"
+ "</svg>";
+
+ // A snapshot of some of the image-related state for an ImageResource.
+ struct ImageResourceSnapshot {
+ ImageResourceSnapshot()
+ : isNull(true)
+ , hasImage(false)
+ , dataLength(0)
+ {
+ }
+
+ ImageResourceSnapshot(ImageResource* image)
+ : isNull(false)
+ , hasImage(image->hasImage())
+ , dataLength(image->hasImage() && image->getImage()->data() ? image->getImage()->data()->size() : 0)
+ , dimensions(image->hasImage() ? image->getImage()->size() : IntSize())
+ {
+ }
+
+ ImageResourceSnapshot(bool hasImage,
+ size_t dataLength,
+ const IntSize& dimensions)
+ : isNull(false)
+ , hasImage(hasImage)
+ , dataLength(dataLength)
+ , dimensions(dimensions)
+ {
+ }
+
+ bool operator==(const ImageResourceSnapshot& other) const
+ {
+ return isNull == other.isNull && hasImage == other.hasImage && dataLength == other.dataLength && dimensions == other.dimensions;
+ }
+
+ bool isNull;
+ bool hasImage;
+ size_t dataLength;
+ IntSize dimensions;
+ };
+
+ // Implement the stream output operator so that ImageResourceSnapshots can be
+ // used with EXPECT_EQ.
+ std::ostream& operator<<(std::ostream& out, const ImageResourceSnapshot& snapshot)
+ {
+ return out << "{isNull:" << snapshot.isNull << ", hasImage:" << snapshot.hasImage << ", dataLength:" << snapshot.dataLength << ", dimensions:(" << snapshot.dimensions.width() << ';' << snapshot.dimensions.height() << ")}";
+ }
+
+ // An ImageResourceObserver that keeps track of the number of times
+ // imageChanged() and imageNotifyFinished() have been called, along with the
+ // ImageResourceSnapshot from the most recent call of each.
+ class TestImageResourceObserver : public GarbageCollectedFinalized<TestImageResourceObserver>, public ImageResourceObserver {
+ USING_PRE_FINALIZER(TestImageResourceObserver, dispose);
+
+ public:
+ explicit TestImageResourceObserver(ImageResource* image)
+ : m_image(image)
+ , m_imageChangedCount(0)
+ , m_imageNotifyFinishedCount(0)
+ {
+ image->addObserver(this);
+ }
+
+ ~TestImageResourceObserver() override;
+
+ DECLARE_TRACE();
+
+ void dispose()
+ {
+ if (m_image) {
+ m_image->removeObserver(this);
+ m_image = nullptr;
+ }
+ }
+
+ size_t imageChangedCount() const { return m_imageChangedCount; }
+ const ImageResourceSnapshot& lastImageChangedSnapshot() const { return m_lastImageChangedSnapshot; }
+ size_t imageNotifyFinishedCount() const { return m_imageNotifyFinishedCount; }
+ const ImageResourceSnapshot& lastImageNotifyFinishedSnapshot() const { return m_lastImageNotifyFinishedSnapshot; }
+
+ private:
+ void imageChanged(ImageResource* image, const IntRect* = 0) override
+ {
+ EXPECT_EQ(m_image.get(), image);
+ m_imageChangedCount++;
+ m_lastImageChangedSnapshot = ImageResourceSnapshot(image);
+ }
+
+ void imageNotifyFinished(ImageResource* image) override
+ {
+ EXPECT_EQ(m_image.get(), image);
+ m_imageNotifyFinishedCount++;
+ m_lastImageNotifyFinishedSnapshot = ImageResourceSnapshot(image);
+ }
+
+ bool willRenderImage() override { return true; }
+
+ String debugName() const override { return "TestImageResourceObserver"; }
+
+ Member<ImageResource> m_image;
+
+ size_t m_imageChangedCount;
+ ImageResourceSnapshot m_lastImageChangedSnapshot;
+ size_t m_imageNotifyFinishedCount;
+ ImageResourceSnapshot m_lastImageNotifyFinishedSnapshot;
+ };
+
+ TestImageResourceObserver::~TestImageResourceObserver() {}
+
+ DEFINE_TRACE(TestImageResourceObserver)
+ {
+ visitor->trace(m_image);
+ }
+
+ // Convenience class for registering and unregistering a mock load for a test
+ // URL.
+ class ScopedRegisteredURL {
+ public:
+ ScopedRegisteredURL(const KURL& url)
+ : m_url(url)
+ {
+ URLTestHelpers::registerMockedURLLoad(url, "cancelTest.html", "text/html");
+ }
+
+ ~ScopedRegisteredURL()
+ {
+ Platform::current()->getURLLoaderMockFactory()->unregisterURL(m_url);
+ }
+
+ private:
+ KURL m_url;
+ };
+
+ // Implement the stream output operator for WebCachePolicy so that it can be
+ // used with EXPECT_EQ.
+ std::ostream& operator<<(std::ostream& out, WebCachePolicy webCachePolicy)
+ {
+ return out << static_cast<int>(webCachePolicy);
+ }
+
+ static AtomicString buildContentRangeHeader(size_t rangeLength, size_t totalLength)
+ {
+ return AtomicString(String("bytes 0-" + String::number(rangeLength - 1) + "/" + String::number(totalLength)));
+ }
+
+ // Construct an "image/jpeg" response with the following properties.
+ static ResourceResponse buildImageResponse(const KURL& url, size_t length, int statusCode, const AtomicString& contentRangeHeader, bool wasCached)
+ {
+ ResourceResponse response(url, "image/jpeg", static_cast<long long>(length), nullAtom, String());
+ response.setHTTPStatusCode(statusCode);
+ if (!contentRangeHeader.isNull())
+ response.setHTTPHeaderField("content-range", contentRangeHeader);
+ response.setWasCached(wasCached);
+ return response;
+ }
+
+ // Use the |image|'s attached ResourceLoader to simulate the image receiving a response.
+ static void simulateImageLoad(ImageResource* image, const ResourceResponse& response, const char* data, size_t length)
+ {
+ const int intLength = safeCast<int>(length);
+ ResourceLoader* loader = image->loader();
+ loader->didReceiveResponse(nullptr, WrappedResourceResponse(response));
+ if (image->loader() == loader && data && length) {
+ loader->didReceiveData(nullptr, data, intLength, intLength, intLength);
+ }
+ if (image->loader() == loader) {
+ loader->didFinishLoading(nullptr, 0.0, intLength);
+ }
+ }
+
+ // Use the |image|'s attached ResourceLoader to simulate the image encountering an error.
+ static void simulateImageFailure(ImageResource* image, const ResourceError& error)
+ {
+ ResourceLoader* loader = image->loader();
+ loader->didFail(nullptr, error);
+ if (image->loader() == loader) {
+ loader->didFinishLoading(nullptr, 0.0, 0);
+ }
+ }
+
+ static void expectOriginalRequestIsForFullImage(ImageResource* image, int testId = 0)
+ {
+ EXPECT_EQ(nullAtom, image->getOriginalResourceRequest().httpHeaderField("range")) << testId;
+ EXPECT_EQ(WebCachePolicy::UseProtocolCachePolicy, image->getOriginalResourceRequest().getCachePolicy()) << testId;
+ }
+
+ static void expectLoadingFullImage(ImageResource* image, int testId = 0)
+ {
+ EXPECT_TRUE(image->isLoading()) << testId;
+ EXPECT_FALSE(image->isPlaceholder()) << testId;
+ EXPECT_EQ(nullAtom, image->resourceRequest().httpHeaderField("range")) << testId;
+ EXPECT_EQ(WebCachePolicy::UseProtocolCachePolicy, image->resourceRequest().getCachePolicy()) << testId;
+
+ expectOriginalRequestIsForFullImage(image, testId);
+ }
+
+ static void expectLoadingPlaceholder(ImageResource* image, int testId = 0)
+ {
+ EXPECT_TRUE(image->isLoading()) << testId;
+ EXPECT_TRUE(image->isPlaceholder()) << testId;
+ EXPECT_EQ("bytes=0-2047", image->resourceRequest().httpHeaderField("range")) << testId;
+ EXPECT_EQ(WebCachePolicy::UseProtocolCachePolicy, image->resourceRequest().getCachePolicy()) << testId;
+
+ expectOriginalRequestIsForFullImage(image, testId);
+ }
+
+ static void expectLoadingFullImageFromCache(ImageResource* image, int testId = 0)
+ {
+ EXPECT_TRUE(image->isLoading()) << testId;
+ EXPECT_TRUE(image->isPlaceholder()) << testId;
+ EXPECT_EQ(nullAtom, image->resourceRequest().httpHeaderField("range")) << testId;
+ EXPECT_EQ(WebCachePolicy::ReturnCacheDataDontLoad, image->resourceRequest().getCachePolicy()) << testId;
+
+ expectOriginalRequestIsForFullImage(image, testId);
+ }
+
+ static void expectLoadingFullImageBypassingCache(ImageResource* image, int testId = 0)
+ {
+ EXPECT_TRUE(image->isLoading()) << testId;
+ EXPECT_FALSE(image->isPlaceholder()) << testId;
+ EXPECT_EQ(nullAtom, image->resourceRequest().httpHeaderField("range")) << testId;
+ EXPECT_EQ(WebCachePolicy::BypassingCache, image->resourceRequest().getCachePolicy()) << testId;
+
+ expectOriginalRequestIsForFullImage(image, testId);
+ }
+
+ // Ensure that the current state of |image| and the most recent notifications
+ // sent to |observer| all match the given |expectedSnapshot|.
+ static void expectMatchesSnapshot(ImageResource* image, const TestImageResourceObserver& observer, const ImageResourceSnapshot& expectedSnapshot, int testId = 0)
+ {
+ EXPECT_EQ(expectedSnapshot, ImageResourceSnapshot(image)) << testId;
+ EXPECT_LT(0U, observer.imageChangedCount()) << testId;
+ EXPECT_EQ(expectedSnapshot, observer.lastImageChangedSnapshot()) << testId;
+ EXPECT_EQ(1U, observer.imageNotifyFinishedCount()) << testId;
+ EXPECT_EQ(expectedSnapshot, observer.lastImageNotifyFinishedSnapshot()) << testId;
+ }
+
+} // namespace
+
+TEST(ImageResourceTest, FetchImage)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+ expectLoadingFullImage(image);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, false), kJpegImage2Data, arraysize(kJpegImage2Data));
+
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_FALSE(image->isPlaceholder());
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)));
+}
+
+TEST(ImageResourceTest, FetchPlaceholderNotCached)
+{
+ AtomicString contentRangeHeaderOptions[] = {
+ buildContentRangeHeader(kRangeWithDimensionsLength, arraysize(kJpegImage2Data)),
+ "bogus content range",
+ AtomicString(String("bytes 1-" + String::number(kRangeWithDimensionsLength) + "/" + String::number(arraysize(kJpegImage2Data)))),
+ "bytes ",
+ "",
+ };
+ for (const AtomicString& contentRange : contentRangeHeaderOptions) {
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, kRangeWithDimensionsLength, 206, contentRange, false), kJpegImage2Data, kRangeWithDimensionsLength);
+
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_TRUE(image->isPlaceholder());
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, strlen(kPlaceholderForJpegImage2), IntSize(kJpegImage2Width, kJpegImage2Height)));
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderThenFetchFullAfterLoading)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/test_placeholder_image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+ FetchRequest allowPlaceholderRequest(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(allowPlaceholderRequest, fetcher, ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, kRangeWithDimensionsLength, 206, buildContentRangeHeader(kRangeWithDimensionsLength, arraysize(kJpegImage2Data)), false), kJpegImage2Data, kRangeWithDimensionsLength);
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_TRUE(image->isPlaceholder());
+
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, strlen(kPlaceholderForJpegImage2), IntSize(kJpegImage2Width, kJpegImage2Height)));
+ const ImageResourceSnapshot placeholderSnapshot(image);
+ EXPECT_EQ(1U, observer->imageNotifyFinishedCount());
+ EXPECT_EQ(placeholderSnapshot, observer->lastImageNotifyFinishedSnapshot());
+
+ FetchRequest disallowPlaceholderRequest(testURL, FetchInitiatorInfo());
+ ImageResource* fullImage = ImageResource::fetch(disallowPlaceholderRequest, fetcher, ImageResource::PlaceholderRequestType::DisallowPlaceholder);
+ EXPECT_EQ(image, fullImage);
+ expectLoadingFullImage(image);
+
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, false), kJpegImage2Data, arraysize(kJpegImage2Data));
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+
+ const ImageResourceSnapshot expectedSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height));
+ EXPECT_EQ(expectedSnapshot, ImageResourceSnapshot(image));
+ EXPECT_LT(0U, observer->imageChangedCount());
+ EXPECT_EQ(expectedSnapshot, observer->lastImageChangedSnapshot());
+ EXPECT_EQ(1U, observer->imageNotifyFinishedCount());
+ EXPECT_EQ(placeholderSnapshot, observer->lastImageNotifyFinishedSnapshot());
+}
+
+TEST(ImageResourceTest, FetchPlaceholderThenFetchFullWhileLoading)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/test_placeholder_image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest allowPlaceholderRequest(testURL, FetchInitiatorInfo());
+ ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+ ImageResource* image = ImageResource::fetch(allowPlaceholderRequest, fetcher, ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image);
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+
+ FetchRequest disallowPlaceholderRequest(testURL, FetchInitiatorInfo());
+ ImageResource* fullImage = ImageResource::fetch(disallowPlaceholderRequest, fetcher, ImageResource::PlaceholderRequestType::DisallowPlaceholder);
+ EXPECT_EQ(image, fullImage);
+ expectLoadingFullImage(image);
+
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, false), kJpegImage2Data, arraysize(kJpegImage2Data));
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_FALSE(image->isPlaceholder());
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)));
+}
+
+TEST(ImageResourceTest, FetchPlaceholderWith204)
+{
+ const bool wasCachedOptions[] = { false, true };
+ for (const auto& wasCached : wasCachedOptions) {
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image, &wasCached - wasCachedOptions);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, 0, 204, nullAtom, wasCached), nullptr, 0);
+
+ EXPECT_EQ(Resource::DecodeError, image->getStatus()) << (&wasCached - wasCachedOptions);
+ EXPECT_FALSE(image->isPlaceholder()) << (&wasCached - wasCachedOptions);
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(false, 0, IntSize()), &wasCached - wasCachedOptions);
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderWithEntireResourceForRange)
+{
+ const bool wasCachedOptions[] = { false, true };
+ for (const auto& wasCached : wasCachedOptions) {
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ const ResourceResponse fullResponses[] = {
+ buildImageResponse(testURL, arraysize(kJpegImage2Data), 206, buildContentRangeHeader(arraysize(kJpegImage2Data), arraysize(kJpegImage2Data)), wasCached),
+ buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, wasCached),
+ buildImageResponse(testURL, arraysize(kJpegImage2Data), 404, nullAtom, wasCached),
+ };
+ for (const ResourceResponse& response : fullResponses) {
+ int testId = (&wasCached - wasCachedOptions) * arraysize(fullResponses) + (&response - fullResponses);
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image, testId);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, response, kJpegImage2Data, arraysize(kJpegImage2Data));
+
+ EXPECT_EQ(Resource::Cached, image->getStatus()) << testId;
+ EXPECT_FALSE(image->isPlaceholder()) << testId;
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)), testId);
+ }
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderPartiallyCached)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ static const char kBadResponseData[] = "bad image response";
+
+ const struct {
+ ResourceError cacheError;
+ ResourceResponse cacheResponse;
+ const char* imageData;
+ size_t imageDataLength;
+ } tests[] = {
+ { ResourceError("net", -400, testURL, "Cache miss"), ResourceResponse(), nullptr, 0 },
+ { ResourceError(), buildImageResponse(testURL, arraysize(kBadResponseData), 200, nullAtom, true), kBadResponseData, arraysize(kBadResponseData) },
+ { ResourceError(), buildImageResponse(testURL, kRangeWithDimensionsLength, 206, buildContentRangeHeader(kRangeWithDimensionsLength, arraysize(kJpegImage2Data)), true), kJpegImage2Data, kRangeWithDimensionsLength },
+ };
+ for (const auto& test : tests) {
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image, &test - tests);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, kRangeWithDimensionsLength, 206, buildContentRangeHeader(kRangeWithDimensionsLength, arraysize(kJpegImage2Data)), true), kJpegImage2Data, kRangeWithDimensionsLength);
+ expectLoadingFullImageFromCache(image, &test - tests);
+
+ if (test.cacheError.isNull()) {
+ simulateImageLoad(image, test.cacheResponse, test.imageData, test.imageDataLength);
+ } else {
+ simulateImageFailure(image, test.cacheError);
+ }
+
+ EXPECT_EQ(Resource::Cached, image->getStatus()) << (&test - tests);
+ EXPECT_TRUE(image->isPlaceholder()) << (&test - tests);
+ EXPECT_FALSE(image->willPaintBrokenImage()) << (&test - tests);
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, strlen(kPlaceholderForJpegImage2), IntSize(kJpegImage2Width, kJpegImage2Height)), &test - tests);
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderFullyCached)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ static const char kBadResponseData[] = "bad image response";
+
+ const struct {
+ ResourceResponse rangeResponse;
+ const char* imageData;
+ size_t imageDataLength;
+ } tests[] = {
+ { buildImageResponse(testURL, kRangeWithDimensionsLength, 206, buildContentRangeHeader(kRangeWithDimensionsLength, arraysize(kJpegImage2Data)), true), kJpegImage2Data, kRangeWithDimensionsLength },
+ { buildImageResponse(testURL, kRangeWithoutDimensionsLength, 206, buildContentRangeHeader(kRangeWithoutDimensionsLength, arraysize(kJpegImage2Data)), true), kJpegImage2Data, kRangeWithoutDimensionsLength },
+ { buildImageResponse(testURL, arraysize(kBadResponseData), 206, buildContentRangeHeader(arraysize(kBadResponseData), arraysize(kBadResponseData) + 10), true), kBadResponseData, arraysize(kBadResponseData) },
+ };
+ for (const auto& test : tests) {
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image, &test - tests);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, test.rangeResponse, test.imageData, test.imageDataLength);
+ expectLoadingFullImageFromCache(image, &test - tests);
+
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, true), kJpegImage2Data, arraysize(kJpegImage2Data));
+ EXPECT_EQ(Resource::Cached, image->getStatus()) << (&test - tests);
+ EXPECT_FALSE(image->isPlaceholder()) << (&test - tests);
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)), &test - tests);
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderFallbackToFullWithoutCacheCheck)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ static const char kBadResponseData[] = "bad image response";
+
+ const struct {
+ ResourceResponse rangeResponse;
+ const char* imageData;
+ size_t imageDataLength;
+ } tests[] = {
+ { buildImageResponse(testURL, kRangeWithoutDimensionsLength, 206, buildContentRangeHeader(kRangeWithoutDimensionsLength, arraysize(kJpegImage2Data)), false), kJpegImage2Data, kRangeWithoutDimensionsLength },
+ { buildImageResponse(testURL, arraysize(kBadResponseData), 206, buildContentRangeHeader(arraysize(kBadResponseData), arraysize(kBadResponseData) + 10), false), kBadResponseData, arraysize(kBadResponseData) },
+ { buildImageResponse(testURL, arraysize(kBadResponseData), 200, nullAtom, true), kBadResponseData, arraysize(kBadResponseData) },
+ };
+ for (const auto& test : tests) {
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image, &test - tests);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, test.rangeResponse, test.imageData, test.imageDataLength);
+ expectLoadingFullImageBypassingCache(image, &test - tests);
+
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, false), kJpegImage2Data, arraysize(kJpegImage2Data));
+ EXPECT_EQ(Resource::Cached, image->getStatus()) << (&test - tests);
+ EXPECT_FALSE(image->isPlaceholder()) << (&test - tests);
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)), &test - tests);
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderFallbackToFullWithCacheCheck)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ static const char kBadResponseData[] = "bad image response";
+
+ const struct {
+ ResourceResponse rangeResponse;
+ const char* imageData;
+ size_t imageDataLength;
+ } tests[] = {
+ { buildImageResponse(testURL, kRangeWithoutDimensionsLength, 206, buildContentRangeHeader(kRangeWithoutDimensionsLength, arraysize(kJpegImage2Data)), true), kJpegImage2Data, kRangeWithoutDimensionsLength },
+ { buildImageResponse(testURL, arraysize(kBadResponseData), 206, buildContentRangeHeader(arraysize(kBadResponseData), arraysize(kBadResponseData) + 10), true), kBadResponseData, arraysize(kBadResponseData) },
+ };
+ for (const auto& test : tests) {
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingPlaceholder(image, &test - tests);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, test.rangeResponse, test.imageData, test.imageDataLength);
+ expectLoadingFullImageFromCache(image, &test - tests);
+
+ simulateImageFailure(image, ResourceError("net", -400, testURL, "Cache miss"));
+ expectLoadingFullImageBypassingCache(image, &test - tests);
+
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, false), kJpegImage2Data, arraysize(kJpegImage2Data));
+ EXPECT_EQ(Resource::Cached, image->getStatus()) << (&test - tests);
+ EXPECT_FALSE(image->isPlaceholder()) << (&test - tests);
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)), &test - tests);
+ }
+}
+
+TEST(ImageResourceTest, FetchPlaceholderWithForcedCacheAndCachedRange)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ request.mutableResourceRequest().setCachePolicy(WebCachePolicy::ReturnCacheDataDontLoad);
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ EXPECT_TRUE(image->isLoading());
+ EXPECT_TRUE(image->isPlaceholder());
+ EXPECT_EQ("bytes=0-2047", image->resourceRequest().httpHeaderField("range"));
+ EXPECT_EQ(WebCachePolicy::ReturnCacheDataDontLoad, image->resourceRequest().getCachePolicy());
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 206, buildContentRangeHeader(kRangeWithDimensionsLength, arraysize(kJpegImage2Data)), true), kJpegImage2Data, kRangeWithDimensionsLength);
+ EXPECT_TRUE(image->isLoading());
+ EXPECT_TRUE(image->isPlaceholder());
+ EXPECT_EQ(WebCachePolicy::ReturnCacheDataDontLoad, image->resourceRequest().getCachePolicy());
+
+ simulateImageFailure(image, ResourceError("net", -400, testURL, "Cache miss"));
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_TRUE(image->isPlaceholder());
+
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, strlen(kPlaceholderForJpegImage2), IntSize(kJpegImage2Width, kJpegImage2Height)));
+}
+
+TEST(ImageResourceTest, FetchPlaceholderWithForcedCacheAndNoCachedRange)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ request.mutableResourceRequest().setCachePolicy(WebCachePolicy::ReturnCacheDataDontLoad);
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ EXPECT_TRUE(image->isLoading());
+ EXPECT_TRUE(image->isPlaceholder());
+ EXPECT_EQ("bytes=0-2047", image->resourceRequest().httpHeaderField("range"));
+ EXPECT_EQ(WebCachePolicy::ReturnCacheDataDontLoad, image->resourceRequest().getCachePolicy());
+
+ simulateImageFailure(image, ResourceError("net", -400, testURL, "Cache miss"));
+ EXPECT_FALSE(image->isLoading());
+ EXPECT_TRUE(image->willPaintBrokenImage());
+ EXPECT_FALSE(image->isPlaceholder());
+}
+
+TEST(ImageResourceTest, FetchDataURIAvoidsPlaceholder)
+{
+ const KURL testURL(ParsedURLString, String("data:image/jpeg;base64," + base64Encode(kJpegImage2Data, arraysize(kJpegImage2Data))));
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_FALSE(image->isPlaceholder());
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)));
+}
+
+TEST(ImageResourceTest, FetchWithPreexistingRangeHeaderAvoidsPlaceholder)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ const AtomicString testRange(String("bytes=0-" + String::number(arraysize(kJpegImage2Data) - 1)));
+ request.mutableResourceRequest().setHTTPHeaderField("range", testRange);
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ EXPECT_TRUE(image->isLoading());
+ EXPECT_FALSE(image->isPlaceholder());
+ EXPECT_EQ(testRange, image->resourceRequest().httpHeaderField("range"));
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 206, buildContentRangeHeader(arraysize(kJpegImage2Data), arraysize(kJpegImage2Data) + 10), false), kJpegImage2Data, arraysize(kJpegImage2Data));
+
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_FALSE(image->isPlaceholder());
+
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)));
+}
+
+TEST(ImageResourceTest, FetchWithPostRequestAvoidsPlaceholder)
+{
+ const KURL testURL(ParsedURLString, "http://www.test.com/image.jpg");
+ ScopedRegisteredURL scopedTestLoad(testURL);
+ FetchRequest request(testURL, FetchInitiatorInfo());
+ request.mutableResourceRequest().setHTTPMethod("POST");
+ ImageResource* image = ImageResource::fetch(request, ResourceFetcher::create(ImageResourceTestMockFetchContext::create()), ImageResource::PlaceholderRequestType::AllowPlaceholder);
+ expectLoadingFullImage(image);
+
+ TestImageResourceObserver* observer = new TestImageResourceObserver(image);
+ simulateImageLoad(image, buildImageResponse(testURL, arraysize(kJpegImage2Data), 200, nullAtom, false), kJpegImage2Data, arraysize(kJpegImage2Data));
+
+ EXPECT_EQ(Resource::Cached, image->getStatus());
+ EXPECT_FALSE(image->isPlaceholder());
+
+ expectMatchesSnapshot(image, *observer, ImageResourceSnapshot(true, arraysize(kJpegImage2Data), IntSize(kJpegImage2Width, kJpegImage2Height)));
+}
+
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/fetch/ImageResource.cpp ('k') | third_party/WebKit/Source/core/fetch/Resource.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698