Example #1
0
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);
}
Example #3
0
TEST_F(ResourceFetcherTest, Revalidate304) {
    KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.html");
    Resource* resource = RawResource::create(url, Resource::Raw);
    memoryCache()->add(resource);
    ResourceResponse response;
    response.setURL(url);
    response.setHTTPStatusCode(304);
    response.setHTTPHeaderField("etag", "1234567890");
    resource->responseReceived(response, nullptr);
    resource->finish();

    ResourceFetcher* fetcher =
        ResourceFetcher::create(ResourceFetcherTestMockFetchContext::create());
    ResourceRequest resourceRequest(url);
    resourceRequest.setRequestContext(WebURLRequest::RequestContextInternal);
    FetchRequest fetchRequest =
        FetchRequest(resourceRequest, FetchInitiatorInfo());
    Platform::current()->getURLLoaderMockFactory()->registerURL(
        url, WebURLResponse(), "");
    Resource* newResource = RawResource::fetch(fetchRequest, fetcher);
    fetcher->stopFetching();
    Platform::current()->getURLLoaderMockFactory()->unregisterURL(url);

    EXPECT_NE(resource, newResource);
}
bool TextTrackLoader::load(const KURL& url, const String& crossOriginMode)
{
    cancelLoad();

    if (!m_client->shouldLoadCues(this))
        return false;

    ASSERT(m_scriptExecutionContext->isDocument());
    Document* document = toDocument(m_scriptExecutionContext);
    FetchRequest cueRequest(ResourceRequest(document->completeURL(url)), FetchInitiatorTypeNames::texttrack);

    if (!crossOriginMode.isNull()) {
        m_crossOriginMode = crossOriginMode;
        StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials;
        updateRequestForAccessControl(cueRequest.mutableResourceRequest(), document->securityOrigin(), allowCredentials);
    } else {
        // Cross-origin resources that are not suitably CORS-enabled may not load.
        if (!document->securityOrigin()->canRequest(url)) {
            corsPolicyPreventedLoad();
            return false;
        }
    }

    ResourceFetcher* fetcher = document->fetcher();
    m_cachedCueData = fetcher->requestTextTrack(cueRequest);
    if (m_cachedCueData)
        m_cachedCueData->addClient(this);

    m_client->cueLoadingStarted(this);

    return true;
}
Example #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);
}
bool TextTrackLoader::load(const KURL& url, const AtomicString& crossOriginMode)
{
    cancelLoad();

    FetchRequest cueRequest(ResourceRequest(m_document.completeURL(url)), FetchInitiatorTypeNames::texttrack);

    if (!crossOriginMode.isNull()) {
        cueRequest.setCrossOriginAccessControl(m_document.securityOrigin(), crossOriginMode);
    } else if (!m_document.securityOrigin()->canRequest(url)) {
        // Text track elements without 'crossorigin' set on the parent are "No CORS"; report error if not same-origin.
        corsPolicyPreventedLoad(m_document.securityOrigin(), url);
        return false;
    }

    ResourceFetcher* fetcher = m_document.fetcher();
    setResource(fetcher->fetchRawResource(cueRequest));
    return resource();
}
Example #7
0
void SVGFontFaceUriElement::loadFont()
{
    if (m_resource)
        m_resource->removeClient(this);

    const AtomicString& href = getAttribute(XLinkNames::hrefAttr);
    if (!href.isNull()) {
        ResourceFetcher* fetcher = document().fetcher();
        FetchRequest request(ResourceRequest(document().completeURL(href)), localName());
        m_resource = fetcher->fetchFont(request);
        if (m_resource) {
            m_resource->addClient(this);
            m_resource->beginLoadIfNeeded(fetcher);
        }
    } else {
        m_resource = 0;
    }
}
void StyleRuleImport::requestStyleSheet()
{
    if (!m_parentStyleSheet)
        return;
    Document* document = m_parentStyleSheet->singleOwnerDocument();
    if (!document)
        return;

    ResourceFetcher* fetcher = document->fetcher();
    if (!fetcher)
        return;

    KURL absURL;
    if (!m_parentStyleSheet->baseURL().isNull())
        // use parent styleheet's URL as the base URL
        absURL = KURL(m_parentStyleSheet->baseURL(), m_strHref);
    else
        absURL = document->completeURL(m_strHref);

    // Check for a cycle in our import chain.  If we encounter a stylesheet
    // in our parent chain with the same URL, then just bail.
    StyleSheetContents* rootSheet = m_parentStyleSheet;
    for (StyleSheetContents* sheet = m_parentStyleSheet; sheet; sheet = sheet->parentStyleSheet()) {
        if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL())
            || equalIgnoringFragmentIdentifier(absURL, document->completeURL(sheet->originalURL())))
            return;
        rootSheet = sheet;
    }

    FetchRequest request(ResourceRequest(absURL), FetchInitiatorTypeNames::css, m_parentStyleSheet->charset());
    if (m_parentStyleSheet->isUserStyleSheet())
        m_resource = fetcher->requestUserCSSStyleSheet(request);
    else
        m_resource = fetcher->requestCSSStyleSheet(request);
    if (m_resource) {
        // if the import rule is issued dynamically, the sheet may be
        // removed from the pending sheet count, so let the doc know
        // the sheet being imported is pending.
        if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() && rootSheet == m_parentStyleSheet)
            m_parentStyleSheet->startLoadingDynamicSheet();
        m_loading = true;
        m_resource->addClient(&m_styleSheetClient);
    }
}
Example #9
0
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));
}
void CSSFontSelector::clearDocument()
{
    if (!m_document) {
        ASSERT(!m_beginLoadingTimer.isActive());
        ASSERT(m_fontsToBeginLoading.isEmpty());
        return;
    }

    m_beginLoadingTimer.stop();

    ResourceFetcher* fetcher = m_document->fetcher();
    for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) {
        // Balances incrementRequestCount() in beginLoadingFontSoon().
        fetcher->decrementRequestCount(m_fontsToBeginLoading[i].get());
    }

    m_fontsToBeginLoading.clear();

    m_document = 0;
}
void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*)
{
    Vector<ResourcePtr<FontResource> > fontsToBeginLoading;
    fontsToBeginLoading.swap(m_fontsToBeginLoading);

    // CSSFontSelector could get deleted via beginLoadIfNeeded() or loadDone() unless protected.
    RefPtr<CSSFontSelector> protect(this);

    ResourceFetcher* fetcher = m_document->fetcher();
    for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
        fontsToBeginLoading[i]->beginLoadIfNeeded(fetcher);
        // Balances incrementRequestCount() in beginLoadingFontSoon().
        fetcher->decrementRequestCount(fontsToBeginLoading[i].get());
    }
    // Ensure that if the request count reaches zero, the frame loader will know about it.
    fetcher->didLoadResource(0);
    // New font loads may be triggered by layout after the document load is complete but before we have dispatched
    // didFinishLoading for the frame. Make sure the delegate is always dispatched by checking explicitly.
    if (m_document && m_document->frame())
        m_document->frame()->loader()->checkLoadComplete();
}
Example #12
0
TEST_F(ResourceFetcherTest, LinkPreloadImageAndUse) {
    ResourceFetcher* fetcher =
        ResourceFetcher::create(ResourceFetcherTestMockFetchContext::create());

    KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.png");
    URLTestHelpers::registerMockedURLLoad(url, testImageFilename, "image/png");

    // Link preload preload scanner
    FetchRequest fetchRequestOriginal = FetchRequest(url, FetchInitiatorInfo());
    fetchRequestOriginal.setLinkPreload(true);
    Resource* resource = ImageResource::fetch(fetchRequestOriginal, fetcher);
    ASSERT_TRUE(resource);
    EXPECT_TRUE(resource->isLinkPreload());
    Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests();
    fetcher->preloadStarted(resource);

    // Image preload scanner
    FetchRequest fetchRequestPreloadScanner =
        FetchRequest(url, FetchInitiatorInfo());
    Resource* imgPreloadScannerResource =
        ImageResource::fetch(fetchRequestPreloadScanner, fetcher);
    EXPECT_EQ(resource, imgPreloadScannerResource);
    EXPECT_FALSE(resource->isLinkPreload());
    fetcher->preloadStarted(resource);

    // Image created by parser
    FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo());
    Resource* newResource = ImageResource::fetch(fetchRequest, fetcher);
    Persistent<MockResourceClient> client = new MockResourceClient(newResource);
    EXPECT_EQ(resource, newResource);
    EXPECT_FALSE(resource->isLinkPreload());

    // DCL reached
    fetcher->clearPreloads(ResourceFetcher::ClearSpeculativeMarkupPreloads);
    Platform::current()->getURLLoaderMockFactory()->unregisterURL(url);
    EXPECT_TRUE(memoryCache()->contains(resource));
    EXPECT_FALSE(resource->isPreloaded());
}
Example #13
0
TEST_F(ResourceFetcherTest, PreloadImageTwice) {
    ResourceFetcher* fetcher =
        ResourceFetcher::create(ResourceFetcherTestMockFetchContext::create());

    KURL url(ParsedURLString, "http://127.0.0.1:8000/foo.png");
    URLTestHelpers::registerMockedURLLoad(url, testImageFilename, "image/png");

    FetchRequest fetchRequestOriginal = FetchRequest(url, FetchInitiatorInfo());
    Resource* resource = ImageResource::fetch(fetchRequestOriginal, fetcher);
    ASSERT_TRUE(resource);
    Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests();
    fetcher->preloadStarted(resource);

    FetchRequest fetchRequest = FetchRequest(url, FetchInitiatorInfo());
    Resource* newResource = ImageResource::fetch(fetchRequest, fetcher);
    EXPECT_EQ(resource, newResource);
    fetcher->preloadStarted(resource);

    fetcher->clearPreloads(ResourceFetcher::ClearAllPreloads);
    Platform::current()->getURLLoaderMockFactory()->unregisterURL(url);
    EXPECT_FALSE(memoryCache()->contains(resource));
    EXPECT_FALSE(resource->isPreloaded());
}
Example #14
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());
}