TEST(ImageResourceTest, DecodedDataRemainsWhileHasClients) { ResourcePtr<ImageResource> cachedImage = new ImageResource(ResourceRequest(), nullptr); cachedImage->setLoading(true); MockImageResourceClient client(cachedImage); // Send the image response. cachedImage->responseReceived(ResourceResponse(KURL(), "multipart/x-mixed-replace", 0, nullAtom, String()), nullptr); Vector<unsigned char> jpeg = jpegImage(); cachedImage->responseReceived(ResourceResponse(KURL(), "image/jpeg", jpeg.size(), nullAtom, String()), nullptr); cachedImage->appendData(reinterpret_cast<const char*>(jpeg.data()), jpeg.size()); cachedImage->finish(); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->image()->isNull()); ASSERT_TRUE(client.notifyFinishedCalled()); // The prune comes when the ImageResource still has clients. The image should not be deleted. cachedImage->prune(); ASSERT_TRUE(cachedImage->hasClients()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->image()->isNull()); // The ImageResource no longer has clients. The image should be deleted by prune. client.removeAsClient(); cachedImage->prune(); ASSERT_FALSE(cachedImage->hasClients()); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_TRUE(cachedImage->image()->isNull()); }
// Verifies that ImageBitmaps constructed from HTMLImageElements hold a reference to the original Image if the HTMLImageElement src is changed. TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) { RefPtrWillBeRawPtr<HTMLImageElement> image = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> originalImageResource = new ImageResource( StaticBitmapImage::create(m_image).get()); image->setImageResource(originalImageResource.get()); RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_image->width(), m_image->height())); ASSERT_EQ(imageBitmap->bitmapImage().get(), originalImageResource->image()); ResourcePtr<ImageResource> newImageResource = new ImageResource( StaticBitmapImage::create(m_image2).get()); image->setImageResource(newImageResource.get()); // The ImageBitmap should contain the same data as the original cached image but should no longer hold a reference. { ASSERT_NE(imageBitmap->bitmapImage().get(), originalImageResource->image()); RefPtr<SkImage> image1 = imageBitmap->bitmapImage()->imageForCurrentFrame(); ASSERT_NE(image1, nullptr); RefPtr<SkImage> image2 = originalImageResource->image()->imageForCurrentFrame(); ASSERT_NE(image2, nullptr); ASSERT_EQ(image1, image2); } { ASSERT_NE(imageBitmap->bitmapImage().get(), newImageResource->image()); RefPtr<SkImage> image1 = imageBitmap->bitmapImage()->imageForCurrentFrame(); ASSERT_NE(image1, nullptr); RefPtr<SkImage> image2 = newImageResource->image()->imageForCurrentFrame(); ASSERT_NE(image2, nullptr); ASSERT_NE(image1, image2); } }
TEST(ImageResourceTest, MultipartImage) { ResourceFetcher* fetcher = ResourceFetcher::create(nullptr); KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); URLTestHelpers::registerMockedURLLoad(testURL, "cancelTest.html", "text/html"); // Emulate starting a real load, but don't expect any "real" WebURLLoaderClient callbacks. ResourcePtr<ImageResource> cachedImage = new ImageResource(ResourceRequest(testURL), nullptr); cachedImage->setIdentifier(createUniqueIdentifier()); cachedImage->load(fetcher, ResourceLoaderOptions()); Platform::current()->unitTestSupport()->unregisterMockedURL(testURL); MockImageResourceClient client(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->status()); // Send the multipart response. No image or data buffer is created. // Note that the response must be routed through ResourceLoader to // ensure the load is flagged as multipart. ResourceResponse multipartResponse(KURL(), "multipart/x-mixed-replace", 0, nullAtom, String()); cachedImage->loader()->didReceiveResponse(nullptr, WrappedResourceResponse(multipartResponse), nullptr); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client.imageChangedCount(), 0); ASSERT_FALSE(client.notifyFinishedCalled()); // Send the response for the first real part. No image or data buffer is created. const char* svgData = "<svg xmlns='http://www.w3.org/2000/svg' width='1' height='1'><rect width='1' height='1' fill='green'/></svg>"; unsigned svgDataLength = strlen(svgData); ResourceResponse payloadResponse(KURL(), "image/svg+xml", svgDataLength, nullAtom, String()); cachedImage->loader()->didReceiveResponse(nullptr, WrappedResourceResponse(payloadResponse), nullptr); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client.imageChangedCount(), 0); ASSERT_FALSE(client.notifyFinishedCalled()); // The first bytes arrive. The data buffer is created, but no image is created. cachedImage->appendData(svgData, svgDataLength); ASSERT_TRUE(cachedImage->resourceBuffer()); ASSERT_EQ(cachedImage->resourceBuffer()->size(), svgDataLength); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client.imageChangedCount(), 0); ASSERT_FALSE(client.notifyFinishedCalled()); // This part finishes. The image is created, callbacks are sent, and the data buffer is cleared. cachedImage->finish(); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->image()->isNull()); ASSERT_EQ(cachedImage->image()->width(), 1); ASSERT_EQ(cachedImage->image()->height(), 1); ASSERT_EQ(client.imageChangedCount(), 2); ASSERT_TRUE(client.notifyFinishedCalled()); }
TEST(ImageResourceTest, UpdateBitmapImages) { ResourcePtr<ImageResource> cachedImage = new ImageResource(ResourceRequest(), nullptr); cachedImage->setLoading(true); MockImageResourceClient client(cachedImage); // Send the image response. Vector<unsigned char> jpeg = jpegImage(); cachedImage->responseReceived(ResourceResponse(KURL(), "image/jpeg", jpeg.size(), nullAtom, String()), nullptr); cachedImage->appendData(reinterpret_cast<const char*>(jpeg.data()), jpeg.size()); cachedImage->finish(); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->image()->isNull()); ASSERT_EQ(client.imageChangedCount(), 2); ASSERT_TRUE(client.notifyFinishedCalled()); ASSERT_TRUE(cachedImage->image()->isBitmapImage()); }
// Verifies that ImageBitmaps constructed from HTMLImageElements hold a reference to the original Image if the HTMLImageElement src is changed. TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) { RefPtr<HTMLImageElement> image = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> originalImageResource = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); image->setImageResource(originalImageResource.get()); RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); ASSERT_EQ(imageBitmap->bitmapImage().get(), originalImageResource->image()); ResourcePtr<ImageResource> newImageResource = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap2)).get()); image->setImageResource(newImageResource.get()); // The ImageBitmap should contain the same data as the original cached image but should no longer hold a reference. ASSERT_NE(imageBitmap->bitmapImage().get(), originalImageResource->image()); ASSERT_EQ(imageBitmap->bitmapImage()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels(), originalImageResource->image()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels()); ASSERT_NE(imageBitmap->bitmapImage().get(), newImageResource->image()); ASSERT_NE(imageBitmap->bitmapImage()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels(), newImageResource->image()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels()); }