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); }
TEST(ImageResourceTest, CancelOnDetach) { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); ScopedRegisteredURL scopedRegisteredURL(testURL); ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); // Emulate starting a real load. ImageResource* cachedImage = ImageResource::create(ResourceRequest(testURL)); cachedImage->setIdentifier(createUniqueIdentifier()); fetcher->startLoad(cachedImage); memoryCache()->add(cachedImage); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->getStatus()); // The load should still be alive, but a timer should be started to cancel the // load inside removeClient(). client->removeAsClient(); EXPECT_EQ(Resource::Pending, cachedImage->getStatus()); EXPECT_TRUE(memoryCache()->resourceForURL(testURL)); // Trigger the cancel timer, ensure the load was cancelled and the resource // was evicted from the cache. blink::testing::runPendingTasks(); EXPECT_EQ(Resource::LoadError, cachedImage->getStatus()); EXPECT_FALSE(memoryCache()->resourceForURL(testURL)); }
TEST(ImageResourceTest, CancelOnDetach) { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); URLTestHelpers::registerMockedURLLoad(testURL, "cancelTest.html", "text/html"); ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); // Emulate starting a real load. ImageResource* cachedImage = ImageResource::create(ResourceRequest(testURL)); cachedImage->setIdentifier(createUniqueIdentifier()); fetcher->startLoad(cachedImage); memoryCache()->add(cachedImage); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->getStatus()); // The load should still be alive, but a timer should be started to cancel the load inside removeClient(). client->removeAsClient(); EXPECT_EQ(Resource::Pending, cachedImage->getStatus()); EXPECT_NE(reinterpret_cast<Resource*>(0), memoryCache()->resourceForURL(testURL)); // Trigger the cancel timer, ensure the load was cancelled and the resource was evicted from the cache. blink::testing::runPendingTasks(); EXPECT_EQ(Resource::LoadError, cachedImage->getStatus()); EXPECT_EQ(reinterpret_cast<Resource*>(0), memoryCache()->resourceForURL(testURL)); Platform::current()->getURLLoaderMockFactory()->unregisterURL(testURL); }
TEST_F(ResourceFetcherTest, StartLoadAfterFrameDetach) { KURL secureURL(ParsedURLString, "https://secureorigin.test/image.png"); // Try to request a url. The request should fail, and a resource in an error // state should be returned, and no resource should be present in the cache. ResourceFetcher* fetcher = ResourceFetcher::create(nullptr); ResourceRequest resourceRequest(secureURL); resourceRequest.setRequestContext(WebURLRequest::RequestContextInternal); FetchRequest fetchRequest = FetchRequest(resourceRequest, FetchInitiatorInfo()); Resource* resource = RawResource::fetch(fetchRequest, fetcher); ASSERT_TRUE(resource); EXPECT_TRUE(resource->errorOccurred()); EXPECT_TRUE(resource->resourceError().isAccessCheck()); EXPECT_FALSE(memoryCache()->resourceForURL(secureURL)); // Start by calling startLoad() directly, rather than via requestResource(). // This shouldn't crash. fetcher->startLoad(RawResource::create(secureURL, Resource::Raw)); }
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()); }