static void* openFunc(const char* uri)
{
    ASSERT(XMLDocumentParserScope::currentCachedResourceLoader);
    ASSERT(currentThread() == libxmlLoaderThread);

    KURL url(KURL(), uri);

    if (!shouldAllowExternalLoad(url))
        return &globalDescriptor;

    ResourceError error;
    ResourceResponse response;
    Vector<char> data;


    {
        CachedResourceLoader* cachedResourceLoader = XMLDocumentParserScope::currentCachedResourceLoader;
        XMLDocumentParserScope scope(0);
        // FIXME: We should restore the original global error handler as well.

        if (cachedResourceLoader->frame())
            cachedResourceLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data);
    }

    // We have to check the URL again after the load to catch redirects.
    // See <https://bugs.webkit.org/show_bug.cgi?id=21963>.
    if (!shouldAllowExternalLoad(response.url()))
        return &globalDescriptor;

    return new OffsetBuffer(data);
}
Beispiel #2
0
bool TextTrackLoader::load(const KURL& url, const String& crossOriginMode)
{
    cancelLoad();

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

    ASSERT(m_scriptExecutionContext->isDocument());
    Document* document = static_cast<Document*>(m_scriptExecutionContext);
    ResourceRequest cueRequest(document->completeURL(url));

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

    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    m_cachedCueData = cachedResourceLoader->requestTextTrack(cueRequest);
    if (m_cachedCueData)
        m_cachedCueData->addClient(this);
    
    m_client->cueLoadingStarted(this);
    
    return true;
}
Beispiel #3
0
void Internals::garbageCollectDocumentResources(Document* document, ExceptionCode& ec) const
{
    if (!document) {
        ec = INVALID_ACCESS_ERR;
        return;
    }

    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    if (!cachedResourceLoader)
        return;
    cachedResourceLoader->garbageCollectDocumentResources();
}
Beispiel #4
0
std::pair<CachedImage*, float> CSSCursorImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
{
    if (is<CSSImageSetValue>(m_imageValue.get()))
        return downcast<CSSImageSetValue>(m_imageValue.get()).loadBestFitImage(loader, options);

    if (auto* cursorElement = updateCursorElement(*loader.document())) {
        if (cursorElement->href() != downcast<CSSImageValue>(m_imageValue.get()).url())
            m_imageValue = CSSImageValue::create(loader.document()->completeURL(cursorElement->href()));
    }

    return { downcast<CSSImageValue>(m_imageValue.get()).loadImage(loader, options), 1 };
}
Beispiel #5
0
void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*)
{
    Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading;
    fontsToBeginLoading.swap(m_fontsToBeginLoading);

    CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
    for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
        fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader);
        // Balances incrementRequestCount() in beginLoadingFontSoon().
        cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get());
    }
    // Ensure that if the request count reaches zero, the frame loader will know about it.
    cachedResourceLoader->loadDone();
}
Beispiel #6
0
void CachedImage::load(CachedResourceLoader& cachedResourceLoader, const ResourceLoaderOptions& options)
{
    if (cachedResourceLoader.shouldPerformImageLoad(url()))
        CachedResource::load(cachedResourceLoader, options);
    else
        setLoading(false);
}
Beispiel #7
0
void StyleRuleImport::requestStyleSheet()
{
    if (!m_parentStyleSheet)
        return;
    Document* document = m_parentStyleSheet->singleOwnerDocument();
    if (!document)
        return;

    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    if (!cachedResourceLoader)
        return;

    URL absURL;
    if (!m_parentStyleSheet->baseURL().isNull())
        // use parent styleheet's URL as the base URL
        absURL = URL(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;
    }

    CachedResourceRequest request(ResourceRequest(absURL), m_parentStyleSheet->charset());
    request.setInitiator(cachedResourceRequestInitiators().css);
    if (m_cachedSheet)
        m_cachedSheet->removeClient(&m_styleSheetClient);
    if (m_parentStyleSheet->isUserStyleSheet())
        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request);
    else
        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request);
    if (m_cachedSheet) {
        // 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_cachedSheet->addClient(&m_styleSheetClient);
    }
}
void SVGFontFaceUriElement::loadFont()
{
    if (m_cachedFont)
        m_cachedFont->removeClient(this);

    const AtomicString& href = getAttribute(XLinkNames::hrefAttr);
    if (!href.isNull()) {
        CachedResourceLoader* cachedResourceLoader = document()->cachedResourceLoader();
        ResourceRequest request(document()->completeURL(href));
        m_cachedFont = cachedResourceLoader->requestFont(request);
        if (m_cachedFont) {
            m_cachedFont->addClient(this);
            m_cachedFont->beginLoadIfNeeded(cachedResourceLoader);
        }
    } else
        m_cachedFont = 0;
}
void SVGFontFaceUriElement::loadFont()
{
    if (m_cachedFont)
        m_cachedFont->removeClient(this);

    String href = getAttribute(XLinkNames::hrefAttr);
    if (!href.isNull()) {        
        CachedResourceLoader* cachedResourceLoader = document()->cachedResourceLoader();
        m_cachedFont = cachedResourceLoader->requestFont(href);
        if (m_cachedFont) {
            m_cachedFont->setSVGFont(true);
            m_cachedFont->addClient(this);
            m_cachedFont->beginLoadIfNeeded(cachedResourceLoader);
        }
    } else
        m_cachedFont = 0;
}
Beispiel #10
0
    void preload(Document* document, const KURL& baseURL)
    {
        if (m_urlToLoad.isEmpty())
            return;

        CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
        CachedResourceRequest request(ResourceRequest(document->completeURL(m_urlToLoad, baseURL)));
        request.setInitiator(tagName());
        if (m_tagName == scriptTag) {
            request.mutableResourceRequest().setAllowCookies(crossOriginModeAllowsCookies());
            cachedResourceLoader->preload(CachedResource::Script, request, m_charset);
        }
        else if (m_tagName == imgTag || (m_tagName == inputTag && m_inputIsImage))
            cachedResourceLoader->preload(CachedResource::ImageResource, request, String());
        else if (m_tagName == linkTag && m_linkIsStyleSheet && m_linkMediaAttributeIsScreen) 
            cachedResourceLoader->preload(CachedResource::CSSStyleSheet, request, m_charset);
    }
void CachedSVGDocumentReference::load(CachedResourceLoader& loader)
{
    if (m_loadRequested)
        return;

    CachedResourceRequest request(ResourceRequest(loader.document()->completeURL(m_url)));
    request.setInitiator(cachedResourceRequestInitiators().css);
    m_document = loader.requestSVGDocument(request);
    if (m_document) {
        m_document->setCanReuse(m_canReuseResource);
        m_document->addClient(this);
        
        if (m_additionalDocumentClient)
            m_document->addClient(m_additionalDocumentClient);
    }

    m_loadRequested = true;
}
Beispiel #12
0
void XSLImportRule::loadSheet()
{
    CachedResourceLoader* cachedResourceLoader = 0;

    XSLStyleSheet* rootSheet = parentStyleSheet();

    if (rootSheet) {
        while (XSLStyleSheet* parentSheet = rootSheet->parentStyleSheet())
            rootSheet = parentSheet;
    }

    if (rootSheet)
        cachedResourceLoader = rootSheet->cachedResourceLoader();
    
    String absHref = m_strHref;
    XSLStyleSheet* parentSheet = parentStyleSheet();
    if (!parentSheet->baseURL().isNull())
        // use parent styleheet's URL as the base URL
        absHref = KURL(parentSheet->baseURL(), m_strHref).string();
    
    // Check for a cycle in our import chain.  If we encounter a stylesheet
    // in our parent chain with the same URL, then just bail.
    for (XSLStyleSheet* parentSheet = parentStyleSheet(); parentSheet; parentSheet = parentSheet->parentStyleSheet()) {
        if (absHref == parentSheet->baseURL().string())
            return;
    }
    
    CachedResourceRequest request(ResourceRequest(cachedResourceLoader->document()->completeURL(absHref)));
    if (m_cachedSheet)
        m_cachedSheet->removeClient(this);
    m_cachedSheet = cachedResourceLoader->requestXSLStyleSheet(request);
    
    if (m_cachedSheet) {
        m_cachedSheet->addClient(this);
        
        // If the imported sheet is in the cache, then setXSLStyleSheet gets called,
        // and the sheet even gets parsed (via parseString).  In this case we have
        // loaded (even if our subresources haven't), so if we have a stylesheet after
        // checking the cache, then we've clearly loaded.
        if (!m_styleSheet)
            m_loading = true;
    }
}
Beispiel #13
0
void CSSImportRule::requestStyleSheet()
{
    CSSStyleSheet* parentSheet = parentStyleSheet();
    if (!parentSheet)
        return;
    Document* document = parentSheet->findDocument();
    if (!document)
        return;

    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    if (!cachedResourceLoader)
        return;

    String absHref = m_strHref;
    if (!parentSheet->finalURL().isNull())
        // use parent styleheet's URL as the base URL
        absHref = KURL(parentSheet->finalURL(), m_strHref).string();

    // Check for a cycle in our import chain.  If we encounter a stylesheet
    // in our parent chain with the same URL, then just bail.
    CSSStyleSheet* rootSheet = parentSheet;
    for (CSSStyleSheet* sheet = parentSheet; sheet; sheet = sheet->parentStyleSheet()) {
        // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL.
        if (absHref == sheet->finalURL().string())
            return;
        rootSheet = sheet;
    }

    ResourceRequest request(document->completeURL(absHref));
    if (parentSheet->isUserStyleSheet())
        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parentSheet->charset());
    else
        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parentSheet->charset());
    if (m_cachedSheet) {
        // 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 (parentSheet && parentSheet->loadCompleted() && rootSheet == parentSheet)
            parentSheet->startLoadingDynamicSheet();
        m_loading = true;
        m_cachedSheet->addClient(&m_styleSheetClient);
    }
}
Beispiel #14
0
void CSSFontSelector::clearDocument()
{
    if (!m_document) {
        ASSERT(!m_beginLoadingTimer.isActive());
        ASSERT(m_fontsToBeginLoading.isEmpty());
        return;
    }

    m_beginLoadingTimer.stop();

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

    m_fontsToBeginLoading.clear();

    m_document = 0;
}
Beispiel #15
0
bool TextTrackLoader::load(const KURL& url)
{
    if (!m_client->shouldLoadCues(this))
        return false;
    
    cancelLoad();
    
    ASSERT(m_scriptExecutionContext->isDocument());
    Document* document = static_cast<Document*>(m_scriptExecutionContext);
    
    ResourceRequest cueRequest(document->completeURL(url));
    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    m_cachedCueData = static_cast<CachedTextTrack*>(cachedResourceLoader->requestTextTrack(cueRequest));
    if (m_cachedCueData)
        m_cachedCueData->addClient(this);
    
    m_client->cueLoadingStarted(this);
    
    return true;
}
void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*)
{
    Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading;
    fontsToBeginLoading.swap(m_fontsToBeginLoading);

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

    CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
    for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
        fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader);
        // Balances incrementRequestCount() in beginLoadingFontSoon().
        cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get());
    }
    // Ensure that if the request count reaches zero, the frame loader will know about it.
    cachedResourceLoader->loadDone();
    // 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();
}
void CSSImportRule::insertedIntoParent()
{
    CSSStyleSheet* parentSheet = parentStyleSheet();
    if (!parentSheet || !parentSheet->document())
        return;

    CachedResourceLoader* cachedResourceLoader = parentSheet->document()->cachedResourceLoader();
    if (!cachedResourceLoader)
        return;

    String absHref = m_strHref;
    if (!parentSheet->finalURL().isNull())
        // use parent styleheet's URL as the base URL
        absHref = KURL(parentSheet->finalURL(), m_strHref).string();

    // Check for a cycle in our import chain.  If we encounter a stylesheet
    // in our parent chain with the same URL, then just bail.
    StyleBase* root = this;
    for (StyleBase* curr = parent(); curr; curr = curr->parent()) {
        // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL. 
        if (curr->isCSSStyleSheet() && absHref == static_cast<CSSStyleSheet*>(curr)->finalURL().string())
            return;
        root = curr;
    }

    if (parentSheet->isUserStyleSheet())
        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(absHref, parentSheet->charset());
    else
        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(absHref, parentSheet->charset());
    if (m_cachedSheet) {
        // 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 (parentSheet && parentSheet->loadCompleted() && root == parentSheet)
            parentSheet->document()->addPendingSheet();
        m_loading = true;
        m_cachedSheet->addClient(this);
    }
}
Beispiel #18
0
void CachedImage::load(CachedResourceLoader& loader)
{
    if (loader.shouldPerformImageLoad(url()))
        CachedResource::load(loader);
    else
        setLoading(false);

    if (m_loader) {
        m_allowSubsampling = m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled();
        m_allowAsyncImageDecoding = m_loader->frameLoader()->frame().settings().asyncImageDecodingEnabled();
        m_showDebugBackground = m_loader->frameLoader()->frame().settings().showDebugBorders();
    }
}
void StyleRuleImport::requestStyleSheet(CSSStyleSheet* rootSheet, const CSSParserContext& parserContext)
{
    ASSERT(!rootSheet->parentStyleSheet());
    ASSERT(!m_cachedSheet);

    Node* ownerNode = rootSheet->ownerNode();
    if (!ownerNode)
        return;
    Document* document = ownerNode->document();

    KURL resolvedURL;
    if (!parserContext.baseURL.isNull())
        resolvedURL = KURL(parserContext.baseURL, m_strHref);
    else
        resolvedURL = document->completeURL(m_strHref);

    StyleSheetContents* rootSheetContents = rootSheet->contents();
    if (rootSheetContents->hasImportCycle(this, resolvedURL, document->baseURL()))
        return;

    ResourceRequest request(resolvedURL);
    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    if (rootSheetContents->isUserStyleSheet())
        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parserContext.charset);
    else
        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parserContext.charset);

    if (!m_cachedSheet)
        return;
    // 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 (rootSheetContents->loadCompleted())
        ownerNode->startLoadingDynamicSheet();

    m_loadContext = adoptPtr(new LoadContext(rootSheet, parserContext));
    m_cachedSheet->addClient(this);
}
Beispiel #20
0
std::pair<CachedImage*, float> CSSImageSetValue::loadBestFitImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
{
    Document* document = loader.document();
    updateDeviceScaleFactor(*document);

    if (!m_accessedBestFitImage) {
        m_accessedBestFitImage = true;

        // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here.
        // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(),
        // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
        ImageWithScale image = bestImageForScaleFactor();
        CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options);
        request.setInitiator(cachedResourceRequestInitiators().css);
        if (options.mode == FetchOptions::Mode::Cors) {
            ASSERT(document->securityOrigin());
            updateRequestForAccessControl(request.mutableResourceRequest(), *document->securityOrigin(), options.allowCredentials);
        }
        m_cachedImage = loader.requestImage(request);
        m_bestFitImageScaleFactor = image.scaleFactor;
    }
    return { m_cachedImage.get(), m_bestFitImageScaleFactor };
}
Beispiel #21
0
void CachedResource::load(CachedResourceLoader& cachedResourceLoader)
{
    if (!cachedResourceLoader.frame()) {
        RELEASE_LOG_IF_ALLOWED("load: No associated frame");
        failBeforeStarting();
        return;
    }
    Frame& frame = *cachedResourceLoader.frame();

    // Prevent new loads if we are in the PageCache or being added to the PageCache.
    // We query the top document because new frames may be created in pagehide event handlers
    // and their pageCacheState will not reflect the fact that they are about to enter page
    // cache.
    if (auto* topDocument = frame.mainFrame().document()) {
        if (topDocument->pageCacheState() != Document::NotInPageCache) {
            RELEASE_LOG_IF_ALLOWED("load: Already in page cache or being added to it (frame = %p)", &frame);
            failBeforeStarting();
            return;
        }
    }

    FrameLoader& frameLoader = frame.loader();
    if (m_options.securityCheck == DoSecurityCheck && (frameLoader.state() == FrameStateProvisional || !frameLoader.activeDocumentLoader() || frameLoader.activeDocumentLoader()->isStopping())) {
        if (frameLoader.state() == FrameStateProvisional)
            RELEASE_LOG_IF_ALLOWED("load: Failed security check -- state is provisional (frame = %p)", &frame);
        else if (!frameLoader.activeDocumentLoader())
            RELEASE_LOG_IF_ALLOWED("load: Failed security check -- not active document (frame = %p)", &frame);
        else if (frameLoader.activeDocumentLoader()->isStopping())
            RELEASE_LOG_IF_ALLOWED("load: Failed security check -- active loader is stopping (frame = %p)", &frame);
        failBeforeStarting();
        return;
    }

    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 = frameLoader.documentLoader()->response().url();
        m_resourceRequest.setURL(safeQLURLForDocumentURLAndResourceURL(documentURL, url()));
    }
#endif

    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());

    // Navigation algorithm is setting up the request before sending it to CachedResourceLoader?CachedResource.
    // So no need for extra fields for MainResource.
    if (type() != CachedResource::MainResource)
        frameLoader.addExtraFieldsToSubresourceRequest(m_resourceRequest);


    // 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()->loadResource(frame, *this, request, m_options);
    if (!m_loader) {
        RELEASE_LOG_IF_ALLOWED("load: Unable to create SubresourceLoader (frame = %p)", &frame);
        failBeforeStarting();
        return;
    }

    m_status = Pending;
}