Exemple #1
0
void SVGUseElement::updateExternalDocument()
{
    URL externalDocumentURL;
    if (inDocument() && isExternalURIReference(href(), document())) {
        externalDocumentURL = document().completeURL(href());
        if (!externalDocumentURL.hasFragmentIdentifier())
            externalDocumentURL = URL();
    }

    if (externalDocumentURL == (m_externalDocument ? m_externalDocument->url() : URL()))
        return;

    if (m_externalDocument)
        m_externalDocument->removeClient(this);

    if (externalDocumentURL.isNull())
        m_externalDocument = nullptr;
    else {
        ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
        options.setContentSecurityPolicyImposition(isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

        CachedResourceRequest request { ResourceRequest { externalDocumentURL }, options };
        request.setInitiator(this);
        m_externalDocument = document().cachedResourceLoader().requestSVGDocument(request);
        if (m_externalDocument)
            m_externalDocument->addClient(this);
    }

    invalidateShadowTree();
}
Exemple #2
0
static RefPtr<StyleImage> loadPendingImage(Document& document, const StyleImage& image, const Element* element, LoadPolicy loadPolicy = LoadPolicy::Normal)
{
    auto& pendingImage = downcast<StylePendingImage>(image);
    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
    options.setContentSecurityPolicyImposition(element && element->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

    // FIXME: Why does shape-outside have different policy than other properties?
    if (loadPolicy == LoadPolicy::ShapeOutside) {
        options.mode = FetchOptions::Mode::Cors;
        options.setAllowCredentials(DoNotAllowStoredCredentials);
    }

    if (auto imageValue = pendingImage.cssImageValue())
        return imageValue->cachedImage(document.cachedResourceLoader(), options);

    if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) {
        imageGeneratorValue->loadSubimages(document.cachedResourceLoader(), options);
        return StyleGeneratedImage::create(*imageGeneratorValue);
    }

    if (auto cursorImageValue = pendingImage.cssCursorImageValue())
        return cursorImageValue->cachedImage(document.cachedResourceLoader(), options);

#if ENABLE(CSS_IMAGE_SET)
    if (auto imageSetValue = pendingImage.cssImageSetValue())
        return imageSetValue->cachedImageSet(document.cachedResourceLoader(), options);
#endif

    return nullptr;
}
Exemple #3
0
bool TextTrackLoader::load(const URL& url, const String& crossOriginMode, bool isInitiatingElementInUserAgentShadowTree)
{
    cancelLoad();

    ASSERT(is<Document>(m_scriptExecutionContext));
    Document* document = downcast<Document>(m_scriptExecutionContext);

    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
    options.setContentSecurityPolicyImposition(isInitiatingElementInUserAgentShadowTree ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

    CachedResourceRequest cueRequest(ResourceRequest(document->completeURL(url)), options);

    if (!crossOriginMode.isNull()) {
        m_crossOriginMode = crossOriginMode;
        StoredCredentials allowCredentials = equalLettersIgnoringASCIICase(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;
        }
    }

    m_resource = document->cachedResourceLoader().requestTextTrack(cueRequest);
    if (!m_resource)
        return false;

    m_resource->addClient(this);
    
    return true;
}
Exemple #4
0
static void loadPendingSVGFilters(const PendingResources& pendingResources, Document& document, const Element* element)
{
    if (pendingResources.pendingSVGFilters.isEmpty())
        return;

    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
    options.setContentSecurityPolicyImposition(element && element->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

    for (auto& filterOperation : pendingResources.pendingSVGFilters)
        filterOperation->getOrCreateCachedSVGDocumentReference()->load(document.cachedResourceLoader(), options);
}
void SVGFEImageElement::requestImageResource()
{
    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
    options.setContentSecurityPolicyImposition(isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

    CachedResourceRequest request(ResourceRequest(document().completeURL(href())), options);
    request.setInitiator(this);
    m_cachedImage = document().cachedResourceLoader().requestImage(request);

    if (m_cachedImage)
        m_cachedImage->addClient(this);
}
Exemple #6
0
ResourceLoader::ResourceLoader(Frame& frame, ResourceLoaderOptions options)
    : m_frame(&frame)
    , m_documentLoader(frame.loader().activeDocumentLoader())
    , m_defersLoading(options.defersLoadingPolicy() == DefersLoadingPolicy::AllowDefersLoading && frame.page()->defersLoading())
    , m_options(options)
{
}
void SVGFontFaceUriElement::loadFont()
{
    if (m_cachedFont)
        m_cachedFont->removeClient(this);

    const AtomicString& href = getAttribute(XLinkNames::hrefAttr);
    if (!href.isNull()) {
        ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
        options.setContentSecurityPolicyImposition(isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

        CachedResourceLoader& cachedResourceLoader = document().cachedResourceLoader();
        CachedResourceRequest request(ResourceRequest(document().completeURL(href)), options);
        request.setInitiator(this);
        m_cachedFont = cachedResourceLoader.requestFont(request, isSVGFontTarget(*this));
        if (m_cachedFont) {
            m_cachedFont->addClient(this);
            m_cachedFont->beginLoadIfNeeded(cachedResourceLoader);
        }
    } else
        m_cachedFont = nullptr;
}
Exemple #8
0
ResourceLoader::ResourceLoader(Frame* frame, ResourceLoaderOptions options)
    : m_frame(frame)
    , m_documentLoader(frame->loader().activeDocumentLoader())
    , m_identifier(0)
    , m_reachedTerminalState(false)
    , m_notifiedLoadComplete(false)
    , m_cancellationStatus(NotCancelled)
    , m_defersLoading(options.defersLoadingPolicy() == DefersLoadingPolicy::AllowDefersLoading && frame->page()->defersLoading())
    , m_options(options)
    , m_isQuickLookResource(false)
#if ENABLE(CONTENT_EXTENSIONS)
    , m_resourceType(ResourceType::Invalid)
#endif
{
}
Exemple #9
0
void ImageLoader::updateFromElement()
{
    // If we're not making renderers for the page, then don't load images. We don't want to slow
    // down the raw HTML parsing case by loading images we don't intend to display.
    Document& document = element().document();
    if (!document.hasLivingRenderTree())
        return;

    AtomicString attr = element().imageSourceURL();

    // Avoid loading a URL we already failed to load.
    if (!m_failedLoadURL.isEmpty() && attr == m_failedLoadURL)
        return;

    // Do not load any image if the 'src' attribute is missing or if it is
    // an empty string.
    CachedResourceHandle<CachedImage> newImage = nullptr;
    if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) {
        ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
        options.setContentSecurityPolicyImposition(element().isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);

        CachedResourceRequest request(ResourceRequest(document.completeURL(sourceURI(attr))), options);
        request.setInitiator(&element());

        String crossOriginMode = element().fastGetAttribute(HTMLNames::crossoriginAttr);
        if (!crossOriginMode.isNull()) {
            StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials;
            updateRequestForAccessControl(request.mutableResourceRequest(), document.securityOrigin(), allowCredentials);
        }

        if (m_loadManually) {
            bool autoLoadOtherImages = document.cachedResourceLoader().autoLoadImages();
            document.cachedResourceLoader().setAutoLoadImages(false);
            newImage = new CachedImage(request.resourceRequest(), m_element.document().page()->sessionID());
            newImage->setLoading(true);
            newImage->setOwningCachedResourceLoader(&document.cachedResourceLoader());
            document.cachedResourceLoader().m_documentResources.set(newImage->url(), newImage.get());
            document.cachedResourceLoader().setAutoLoadImages(autoLoadOtherImages);
        } else
            newImage = document.cachedResourceLoader().requestImage(request);

        // If we do not have an image here, it means that a cross-site
        // violation occurred, or that the image was blocked via Content
        // Security Policy, or the page is being dismissed. Trigger an
        // error event if the page is not being dismissed.
        if (!newImage && !pageIsBeingDismissed(document)) {
            m_failedLoadURL = attr;
            m_hasPendingErrorEvent = true;
            errorEventSender().dispatchEventSoon(*this);
        } else
            clearFailedLoadURL();
    } else if (!attr.isNull()) {
        // Fire an error event if the url is empty.
        m_failedLoadURL = attr;
        m_hasPendingErrorEvent = true;
        errorEventSender().dispatchEventSoon(*this);
    }
    
    CachedImage* oldImage = m_image.get();
    if (newImage != oldImage) {
        if (m_hasPendingBeforeLoadEvent) {
            beforeLoadEventSender().cancelEvent(*this);
            m_hasPendingBeforeLoadEvent = false;
        }
        if (m_hasPendingLoadEvent) {
            loadEventSender().cancelEvent(*this);
            m_hasPendingLoadEvent = false;
        }

        // Cancel error events that belong to the previous load, which is now cancelled by changing the src attribute.
        // If newImage is null and m_hasPendingErrorEvent is true, we know the error event has been just posted by
        // this load and we should not cancel the event.
        // FIXME: If both previous load and this one got blocked with an error, we can receive one error event instead of two.
        if (m_hasPendingErrorEvent && newImage) {
            errorEventSender().cancelEvent(*this);
            m_hasPendingErrorEvent = false;
        }

        m_image = newImage;
        m_hasPendingBeforeLoadEvent = !document.isImageDocument() && newImage;
        m_hasPendingLoadEvent = newImage;
        m_imageComplete = !newImage;

        if (newImage) {
            if (!document.isImageDocument()) {
                if (!document.hasListenerType(Document::BEFORELOAD_LISTENER))
                    dispatchPendingBeforeLoadEvent();
                else
                    beforeLoadEventSender().dispatchEventSoon(*this);
            } else
                updateRenderer();

            // If newImage is cached, addClient() will result in the load event
            // being queued to fire. Ensure this happens after beforeload is
            // dispatched.
            newImage->addClient(this);
        }
        if (oldImage) {
            oldImage->removeClient(this);
            updateRenderer();
        }
    }

    if (RenderImageResource* imageResource = renderImageResource())
        imageResource->resetAnimation();

    // Only consider updating the protection ref-count of the Element immediately before returning
    // from this function as doing so might result in the destruction of this ImageLoader.
    updatedHasPendingEvent();
}
Exemple #10
0
void CachedResource::load(CachedResourceLoader* cachedResourceLoader, const ResourceLoaderOptions& options)
{
    if (!cachedResourceLoader->frame()) {
        failBeforeStarting();
        return;
    }

    FrameLoader& frameLoader = cachedResourceLoader->frame()->loader();
    if (options.securityCheck() == DoSecurityCheck && (frameLoader.state() == FrameStateProvisional || !frameLoader.activeDocumentLoader() || frameLoader.activeDocumentLoader()->isStopping())) {
        failBeforeStarting();
        return;
    }

    m_options = options;
    m_loading = true;

#if USE(QUICK_LOOK)
    if (!m_resourceRequest.isNull() && m_resourceRequest.url().protocolIs(QLPreviewProtocol())) {
        // When QuickLook is invoked to convert a document, it returns a unique URL in the
        // NSURLReponse for the main document. To make safeQLURLForDocumentURLAndResourceURL()
        // work, we need to use the QL URL not the original URL.
        const URL& documentURL = cachedResourceLoader->frame() ? cachedResourceLoader->frame()->loader().documentLoader()->response().url() : cachedResourceLoader->document()->url();
        m_resourceRequest.setURL(safeQLURLForDocumentURLAndResourceURL(documentURL, url()));
    }
#endif

    if (!accept().isEmpty())
        m_resourceRequest.setHTTPAccept(accept());

    if (isCacheValidator()) {
        CachedResource* resourceToRevalidate = m_resourceToRevalidate;
        ASSERT(resourceToRevalidate->canUseCacheValidator());
        ASSERT(resourceToRevalidate->isLoaded());
        const String& lastModified = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::LastModified);
        const String& eTag = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::ETag);
        if (!lastModified.isEmpty() || !eTag.isEmpty()) {
            ASSERT(cachedResourceLoader->cachePolicy(type()) != CachePolicyReload);
            if (cachedResourceLoader->cachePolicy(type()) == CachePolicyRevalidate)
                m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
            if (!lastModified.isEmpty())
                m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified);
            if (!eTag.isEmpty())
                m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag);
        }
    }

#if ENABLE(LINK_PREFETCH)
    if (type() == CachedResource::LinkPrefetch || type() == CachedResource::LinkSubresource)
        m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::Purpose, "prefetch");
#endif
    m_resourceRequest.setPriority(loadPriority());

    if (type() != MainResource)
        addAdditionalRequestHeaders(cachedResourceLoader);

    // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers.
    // We should look into removing the expectation of that knowledge from the platform network stacks.
    ResourceRequest request(m_resourceRequest);
    if (!m_fragmentIdentifierForRequest.isNull()) {
        URL url = request.url();
        url.setFragmentIdentifier(m_fragmentIdentifierForRequest);
        request.setURL(url);
        m_fragmentIdentifierForRequest = String();
    }

    m_loader = platformStrategies()->loaderStrategy()->resourceLoadScheduler()->scheduleSubresourceLoad(cachedResourceLoader->frame(), this, request, request.priority(), options);
    if (!m_loader) {
        failBeforeStarting();
        return;
    }

    m_status = Pending;
}