CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedResource::Type type, CachedResourceRequest& request, const String& charset) { ASSERT(!memoryCache()->resourceForRequest(request.resourceRequest())); LOG(ResourceLoading, "Loading CachedResource for '%s'.", request.resourceRequest().url().elidedString().latin1().data()); CachedResourceHandle<CachedResource> resource = createResource(type, request.mutableResourceRequest(), charset); if (!memoryCache()->add(resource.get())) resource->setOwningCachedResourceLoader(this); #if ENABLE(RESOURCE_TIMING) storeResourceTimingInitiatorInformation(resource, request); #endif return resource; }
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 = m_element->document(); if (!document->renderer()) return; AtomicString attr = m_element->imageSourceURL(); if (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 = 0; if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { CachedResourceRequest request(ResourceRequest(document->completeURL(sourceURI(attr)))); request.setInitiator(element()); String crossOriginMode = m_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()); 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. // FIXME: Should we fire this event asynchronoulsy via errorEventSender()? m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); } 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 = !m_element->document()->isImageDocument() && newImage; m_hasPendingLoadEvent = newImage; m_imageComplete = !newImage; if (newImage) { if (!m_element->document()->isImageDocument()) { if (!m_element->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); } 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(); }