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());
}
Ejemplo n.º 2
0
void FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
    const ResourceRequest& request,
    const ResourceResponse& response) {
  if (m_webFrame->client())
    m_webFrame->client()->didLoadResourceFromMemoryCache(
        WrappedResourceRequest(request), WrappedResourceResponse(response));
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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());
}
Ejemplo n.º 8
0
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());
}
Ejemplo n.º 10
0
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());
}
Ejemplo n.º 11
0
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());
}