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()); }
void FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache( const ResourceRequest& request, const ResourceResponse& response) { if (m_webFrame->client()) m_webFrame->client()->didLoadResourceFromMemoryCache( WrappedResourceRequest(request), WrappedResourceResponse(response)); }
TEST_F(ResourceFetcherTest, RevalidateWhileFinishingLoading) { KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.png"); ResourceResponse response; response.setURL(url); response.setHTTPStatusCode(200); response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600"); response.setHTTPHeaderField(HTTPNames::ETag, "1234567890"); URLTestHelpers::registerMockedURLLoadWithCustomResponse( url, testImageFilename, WebString::fromUTF8(""), WrappedResourceResponse(response)); ResourceFetcher* fetcher1 = ResourceFetcher::create(ResourceFetcherTestMockFetchContext::create()); ResourceRequest request1(url); request1.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cache"); FetchRequest fetchRequest1 = FetchRequest(request1, FetchInitiatorInfo()); Resource* resource1 = ImageResource::fetch(fetchRequest1, fetcher1); Persistent<RequestSameResourceOnComplete> client = new RequestSameResourceOnComplete(resource1); resource1->addClient(client); Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); Platform::current()->getURLLoaderMockFactory()->unregisterURL(url); EXPECT_TRUE(client->notifyFinishedCalled()); resource1->removeClient(client); memoryCache()->remove(resource1); }
TEST_F(ResourceFetcherTest, VaryImage) { ResourceFetcher* fetcher = ResourceFetcher::create(ResourceFetcherTestMockFetchContext::create()); KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html"); ResourceResponse response; response.setURL(url); response.setHTTPStatusCode(200); response.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600"); response.setHTTPHeaderField(HTTPNames::Vary, "*"); URLTestHelpers::registerMockedURLLoadWithCustomResponse( url, testImageFilename, WebString::fromUTF8(""), WrappedResourceResponse(response)); FetchRequest fetchRequestOriginal = FetchRequest(url, FetchInitiatorInfo()); Resource* resource = ImageResource::fetch(fetchRequestOriginal, fetcher); ASSERT_TRUE(resource); Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); ASSERT_TRUE(resource->hasVaryHeader()); FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo()); Resource* newResource = ImageResource::fetch(fetchRequest, fetcher); EXPECT_EQ(resource, newResource); memoryCache()->remove(newResource); Platform::current()->getURLLoaderMockFactory()->unregisterURL(url); }
TEST_F(ResourceFetcherTest, RevalidateDeferedResourceFromTwoInitiators) { KURL url(ParsedURLString, "http://127.0.0.1:8000/font.woff"); ResourceResponse response; response.setURL(url); response.setHTTPStatusCode(200); response.setHTTPHeaderField(HTTPNames::ETag, "1234567890"); Platform::current()->getURLLoaderMockFactory()->registerURL( url, WrappedResourceResponse(response), ""); ResourceFetcherTestMockFetchContext* context = ResourceFetcherTestMockFetchContext::create(); ResourceFetcher* fetcher = ResourceFetcher::create(context); // Fetch to cache a resource. ResourceRequest request1(url); FetchRequest fetchRequest1 = FetchRequest(request1, FetchInitiatorInfo()); Resource* resource1 = FontResource::fetch(fetchRequest1, fetcher); ASSERT_TRUE(resource1); fetcher->startLoad(resource1); Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); EXPECT_TRUE(resource1->isLoaded()); EXPECT_FALSE(resource1->errorOccurred()); // Set the context as it is on reloads. context->setLoadComplete(true); context->setCachePolicy(CachePolicyRevalidate); // Revalidate the resource. ResourceRequest request2(url); FetchRequest fetchRequest2 = FetchRequest(request2, FetchInitiatorInfo()); Resource* resource2 = FontResource::fetch(fetchRequest2, fetcher); ASSERT_TRUE(resource2); EXPECT_EQ(resource1, resource2); EXPECT_TRUE(resource2->isCacheValidator()); EXPECT_TRUE(resource2->stillNeedsLoad()); // Fetch the same resource again before actual load operation starts. ResourceRequest request3(url); FetchRequest fetchRequest3 = FetchRequest(request3, FetchInitiatorInfo()); Resource* resource3 = FontResource::fetch(fetchRequest3, fetcher); ASSERT_TRUE(resource3); EXPECT_EQ(resource2, resource3); EXPECT_TRUE(resource3->isCacheValidator()); EXPECT_TRUE(resource3->stillNeedsLoad()); // startLoad() can be called from any initiator. Here, call it from the // latter. fetcher->startLoad(resource3); Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); EXPECT_TRUE(resource3->isLoaded()); EXPECT_FALSE(resource3->errorOccurred()); EXPECT_TRUE(resource2->isLoaded()); EXPECT_FALSE(resource2->errorOccurred()); memoryCache()->remove(resource1); }
void WebAssociatedURLLoaderImpl::ClientAdapter::didReceiveResponse( unsigned long, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) { ALLOW_UNUSED_LOCAL(handle); DCHECK(!handle); if (!m_client) return; if (m_options.exposeAllResponseHeaders || m_options.crossOriginRequestPolicy != WebAssociatedURLLoaderOptions:: CrossOriginRequestPolicyUseAccessControl) { // Use the original ResourceResponse. m_client->didReceiveResponse(WrappedResourceResponse(response)); return; } HTTPHeaderSet exposedHeaders; extractCorsExposedHeaderNamesList(response, exposedHeaders); HTTPHeaderSet blockedHeaders; for (const auto& header : response.httpHeaderFields()) { if (FetchUtils::isForbiddenResponseHeaderName(header.key) || (!isOnAccessControlResponseHeaderWhitelist(header.key) && !exposedHeaders.contains(header.key))) blockedHeaders.add(header.key); } if (blockedHeaders.isEmpty()) { // Use the original ResourceResponse. m_client->didReceiveResponse(WrappedResourceResponse(response)); return; } // If there are blocked headers, copy the response so we can remove them. WebURLResponse validatedResponse = WrappedResourceResponse(response); for (const auto& header : blockedHeaders) validatedResponse.clearHTTPHeaderField(header); m_client->didReceiveResponse(validatedResponse); }
TEST(ImageResourceTest, CancelOnDecodeError) { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); ScopedRegisteredURL scopedRegisteredURL(testURL); ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); FetchRequest request(testURL, FetchInitiatorInfo()); ImageResource* cachedImage = ImageResource::fetch(request, fetcher); cachedImage->loader()->didReceiveResponse( nullptr, WrappedResourceResponse(ResourceResponse( testURL, "image/jpeg", 18, nullAtom, String())), nullptr); cachedImage->loader()->didReceiveData(nullptr, "notactuallyanimage", 18, 18, 18); EXPECT_EQ(Resource::DecodeError, cachedImage->getStatus()); EXPECT_FALSE(cachedImage->isLoading()); }
void AssociatedURLLoader::ClientAdapter::didReceiveResponse(unsigned long, const ResourceResponse& response) { // Try to use the original ResourceResponse if possible. WebURLResponse validatedResponse = WrappedResourceResponse(response); HTTPResponseHeaderValidator validator(m_options.crossOriginRequestPolicy == WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl); if (!m_options.exposeAllResponseHeaders) validatedResponse.visitHTTPHeaderFields(&validator); // If there are blocked headers, copy the response so we can remove them. const HTTPHeaderSet& blockedHeaders = validator.blockedHeaders(); if (!blockedHeaders.isEmpty()) { validatedResponse = WebURLResponse(validatedResponse); HTTPHeaderSet::const_iterator end = blockedHeaders.end(); for (HTTPHeaderSet::const_iterator it = blockedHeaders.begin(); it != end; ++it) validatedResponse.clearHTTPHeaderField(*it); } m_client->didReceiveResponse(m_loader, validatedResponse); }
TEST(ImageResourceTest, ReloadIfLoFi) { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); URLTestHelpers::registerMockedURLLoad(testURL, "cancelTest.html", "text/html"); ResourceRequest request = ResourceRequest(testURL); request.setLoFiState(WebURLRequest::LoFiOn); ImageResource* cachedImage = ImageResource::create(request); cachedImage->setStatus(Resource::Pending); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); // Send the image response. Vector<unsigned char> jpeg = jpegImage(); ResourceResponse resourceResponse(KURL(), "image/jpeg", jpeg.size(), nullAtom, String()); resourceResponse.addHTTPHeaderField("chrome-proxy", "q=low"); cachedImage->responseReceived(resourceResponse, nullptr); cachedImage->appendData(reinterpret_cast<const char*>(jpeg.data()), jpeg.size()); cachedImage->finish(); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->getImage()->isNull()); ASSERT_EQ(client->imageChangedCount(), 2); ASSERT_TRUE(client->notifyFinishedCalled()); ASSERT_TRUE(cachedImage->getImage()->isBitmapImage()); EXPECT_EQ(1, cachedImage->getImage()->width()); EXPECT_EQ(1, cachedImage->getImage()->height()); cachedImage->reloadIfLoFi(fetcher); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client->imageChangedCount(), 3); cachedImage->loader()->didReceiveResponse(nullptr, WrappedResourceResponse(resourceResponse), nullptr); cachedImage->loader()->didReceiveData(nullptr, reinterpret_cast<const char*>(jpeg.data()), jpeg.size(), jpeg.size()); cachedImage->loader()->didFinishLoading(nullptr, 0.0, jpeg.size()); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->getImage()->isNull()); ASSERT_TRUE(client->notifyFinishedCalled()); ASSERT_TRUE(cachedImage->getImage()->isBitmapImage()); }
TEST(ImageResourceTest, ReloadIfLoFiDuringFetch) { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); ScopedRegisteredURL scopedRegisteredURL(testURL); ResourceRequest request(testURL); request.setLoFiState(WebURLRequest::LoFiOn); FetchRequest fetchRequest(request, FetchInitiatorInfo()); ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); ImageResource* cachedImage = ImageResource::fetch(fetchRequest, fetcher); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); // Send the image response. Vector<unsigned char> jpeg = jpegImage(); ResourceResponse initialResourceResponse(testURL, "image/jpeg", jpeg.size(), nullAtom, String()); initialResourceResponse.addHTTPHeaderField("chrome-proxy", "q=low"); cachedImage->loader()->didReceiveResponse( nullptr, WrappedResourceResponse(initialResourceResponse)); cachedImage->loader()->didReceiveData( nullptr, reinterpret_cast<const char*>(jpeg.data()), jpeg.size(), jpeg.size(), jpeg.size()); EXPECT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); EXPECT_FALSE(cachedImage->getImage()->isNull()); EXPECT_EQ(1, client->imageChangedCount()); EXPECT_EQ(jpeg.size(), client->encodedSizeOnLastImageChanged()); EXPECT_FALSE(client->notifyFinishedCalled()); EXPECT_TRUE(cachedImage->getImage()->isBitmapImage()); EXPECT_EQ(1, cachedImage->getImage()->width()); EXPECT_EQ(1, cachedImage->getImage()->height()); // Call reloadIfLoFi() while the image is still loading. cachedImage->reloadIfLoFi(fetcher); EXPECT_FALSE(cachedImage->errorOccurred()); EXPECT_FALSE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(2, client->imageChangedCount()); EXPECT_EQ(0U, client->encodedSizeOnLastImageChanged()); // The client should not have been notified of completion yet, since the image // is still loading. EXPECT_FALSE(client->notifyFinishedCalled()); Vector<unsigned char> jpeg2 = jpegImage2(); cachedImage->loader()->didReceiveResponse( nullptr, WrappedResourceResponse(ResourceResponse( testURL, "image/jpeg", jpeg.size(), nullAtom, String())), nullptr); cachedImage->loader()->didReceiveData( nullptr, reinterpret_cast<const char*>(jpeg2.data()), jpeg2.size(), jpeg2.size(), jpeg2.size()); cachedImage->loader()->didFinishLoading(nullptr, 0.0, jpeg2.size()); EXPECT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); EXPECT_FALSE(cachedImage->getImage()->isNull()); EXPECT_EQ(jpeg2.size(), client->encodedSizeOnLastImageChanged()); // The client should have been notified of completion only after the reload // completed. EXPECT_TRUE(client->notifyFinishedCalled()); EXPECT_EQ(jpeg2.size(), client->encodedSizeOnNotifyFinished()); EXPECT_EQ(jpeg2.size(), client->encodedSizeOnImageNotifyFinished()); EXPECT_TRUE(cachedImage->getImage()->isBitmapImage()); EXPECT_EQ(50, cachedImage->getImage()->width()); EXPECT_EQ(50, cachedImage->getImage()->height()); }
TEST(ImageResourceTest, MultipartImage) { ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); ScopedRegisteredURL scopedRegisteredURL(testURL); // Emulate starting a real load, but don't expect any "real" // WebURLLoaderClient callbacks. ImageResource* cachedImage = ImageResource::create(ResourceRequest(testURL)); cachedImage->setIdentifier(createUniqueIdentifier()); fetcher->startLoad(cachedImage); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->getStatus()); // 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()); multipartResponse.setMultipartBoundary("boundary", strlen("boundary")); cachedImage->loader()->didReceiveResponse( nullptr, WrappedResourceResponse(multipartResponse), nullptr); EXPECT_FALSE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(0, client->imageChangedCount()); EXPECT_FALSE(client->notifyFinishedCalled()); EXPECT_EQ("multipart/x-mixed-replace", cachedImage->response().mimeType()); const char firstPart[] = "--boundary\n" "Content-Type: image/svg+xml\n\n"; cachedImage->appendData(firstPart, strlen(firstPart)); // Send the response for the first real part. No image or data buffer is // created. EXPECT_FALSE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(0, client->imageChangedCount()); EXPECT_FALSE(client->notifyFinishedCalled()); EXPECT_EQ("image/svg+xml", cachedImage->response().mimeType()); const char secondPart[] = "<svg xmlns='http://www.w3.org/2000/svg' width='1' height='1'><rect " "width='1' height='1' fill='green'/></svg>\n"; // The first bytes arrive. The data buffer is created, but no image is // created. cachedImage->appendData(secondPart, strlen(secondPart)); EXPECT_TRUE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(0, client->imageChangedCount()); EXPECT_FALSE(client->notifyFinishedCalled()); // Add a client to check an assertion error doesn't happen // (crbug.com/630983). Persistent<MockImageResourceClient> client2 = new MockImageResourceClient(cachedImage); EXPECT_EQ(0, client2->imageChangedCount()); EXPECT_FALSE(client2->notifyFinishedCalled()); const char thirdPart[] = "--boundary"; cachedImage->appendData(thirdPart, strlen(thirdPart)); ASSERT_TRUE(cachedImage->resourceBuffer()); EXPECT_EQ(strlen(secondPart) - 1, cachedImage->resourceBuffer()->size()); // This part finishes. The image is created, callbacks are sent, and the data // buffer is cleared. cachedImage->loader()->didFinishLoading(nullptr, 0.0, 0); EXPECT_TRUE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); EXPECT_FALSE(cachedImage->getImage()->isNull()); EXPECT_EQ(1, cachedImage->getImage()->width()); EXPECT_EQ(1, cachedImage->getImage()->height()); EXPECT_EQ(1, client->imageChangedCount()); EXPECT_TRUE(client->notifyFinishedCalled()); EXPECT_EQ(1, client2->imageChangedCount()); EXPECT_TRUE(client2->notifyFinishedCalled()); }