void ImageLoader::notifyFinished(CachedResource* resource) { ASSERT(m_failedLoadURL.isEmpty()); ASSERT(resource == m_image.get()); m_imageComplete = true; if (!hasPendingBeforeLoadEvent()) updateRenderer(); if (!m_hasPendingLoadEvent) return; if (m_element->fastHasAttribute(HTMLNames::crossoriginAttr) && !m_element->document().securityOrigin()->canRequest(image()->response().url()) && !resource->passesAccessControlCheck(m_element->document().securityOrigin())) { setImageWithoutConsideringPendingLoadEvent(0); m_hasPendingErrorEvent = true; errorEventSender().dispatchEventSoon(this); DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Cross-origin image load denied by Cross-Origin Resource Sharing policy."))); m_element->document().addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, consoleMessage); ASSERT(!m_hasPendingLoadEvent); // 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(); return; } if (resource->wasCanceled()) { m_hasPendingLoadEvent = false; // 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(); return; } loadEventSender().dispatchEventSoon(this); }
void ImageLoader::notifyFinished(CachedResource* resource) { ASSERT(m_failedLoadURL.isEmpty()); ASSERT(resource == m_image.get()); m_imageComplete = true; if (!hasPendingBeforeLoadEvent()) updateRenderer(); if (!m_hasPendingLoadEvent) return; if (element().fastHasAttribute(HTMLNames::crossoriginAttr) && !resource->passesSameOriginPolicyCheck(*element().document().securityOrigin())) { clearImageWithoutConsideringPendingLoadEvent(); m_hasPendingErrorEvent = true; errorEventSender().dispatchEventSoon(*this); static NeverDestroyed<String> consoleMessage(ASCIILiteral("Cross-origin image load denied by Cross-Origin Resource Sharing policy.")); element().document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, consoleMessage); ASSERT(!m_hasPendingLoadEvent); // 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(); return; } if (resource->wasCanceled()) { m_hasPendingLoadEvent = false; // 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(); return; } loadEventSender().dispatchEventSoon(*this); }
void ImageLoader::dispatchPendingBeforeLoadEvent() { if (m_firedBeforeLoad) return; if (!m_image) return; if (!m_element->document()->attached()) return; m_firedBeforeLoad = true; if (m_element->dispatchBeforeLoadEvent(m_image->url())) { updateRenderer(); return; } if (m_image) { m_image->removeClient(this); m_image = 0; } loadEventSender().cancelEvent(this); if (m_element->hasTagName(HTMLNames::objectTag)) static_cast<HTMLObjectElement*>(m_element)->renderFallbackContent(); }
void ImageLoader::setImage(CachedImage* newImage) { ASSERT(m_failedLoadURL.isEmpty()); CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { m_image = newImage; if (!m_firedBeforeLoad) { beforeLoadEventSender().cancelEvent(this); m_firedBeforeLoad = true; } if (!m_firedLoad) { loadEventSender().cancelEvent(this); m_firedLoad = true; } m_imageComplete = true; if (newImage) newImage->addClient(this); if (oldImage) oldImage->removeClient(this); } if (RenderImageResource* imageResource = renderImageResource()) imageResource->resetAnimation(); }
void ImageLoader::dispatchPendingLoadEvents() { loadEventSender().dispatchPendingEvents(); }
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(); }
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->getAttribute(m_element->imageSourceAttributeName()); if (attr == m_failedLoadURL) return; // Do not load any image if the 'src' attribute is missing or if it is // an empty string referring to a local file. The latter condition is // a quirk that preserves old behavior that Dashboard widgets // need (<rdar://problem/5994621>). CachedImage* newImage = 0; if (!(attr.isNull() || (attr.isEmpty() && document->baseURI().isLocalFile()))) { if (m_loadManually) { bool autoLoadOtherImages = document->docLoader()->autoLoadImages(); document->docLoader()->setAutoLoadImages(false); newImage = new CachedImage(sourceURI(attr)); newImage->setLoading(true); newImage->setDocLoader(document->docLoader()); document->docLoader()->m_documentResources.set(newImage->url(), newImage); document->docLoader()->setAutoLoadImages(autoLoadOtherImages); } else newImage = document->docLoader()->requestImage(sourceURI(attr)); // If we do not have an image here, it means that a cross-site // violation occurred. m_failedLoadURL = !newImage ? attr : AtomicString(); } CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { if (!m_firedBeforeLoad) beforeLoadEventSender().cancelEvent(this); if (!m_firedLoad) loadEventSender().cancelEvent(this); m_image = newImage; m_firedBeforeLoad = !newImage; m_firedLoad = !newImage; m_imageComplete = !newImage; if (newImage) { newImage->addClient(this); if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) dispatchPendingBeforeLoadEvent(); else beforeLoadEventSender().dispatchEventSoon(this); } if (oldImage) oldImage->removeClient(this); } if (RenderImageResource* imageResource = renderImageResource()) imageResource->resetAnimation(); }
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->getAttribute(m_element->imageSourceAttributeName()); if (attr == m_failedLoadURL) return; // Do not load any image if the 'src' attribute is missing or if it is // an empty string. CachedImage* newImage = 0; if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { ResourceRequest request = ResourceRequest(document->completeURL(sourceURI(attr))); String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) { StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; updateRequestForAccessControl(request, document->securityOrigin(), allowCredentials); } if (m_loadManually) { bool autoLoadOtherImages = document->cachedResourceLoader()->autoLoadImages(); document->cachedResourceLoader()->setAutoLoadImages(false); newImage = new CachedImage(request); newImage->setLoading(true); newImage->setOwningCachedResourceLoader(document->cachedResourceLoader()); document->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage); 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. m_failedLoadURL = !newImage ? attr : AtomicString(); } else if (!attr.isNull()) // Fire an error event if the url is empty. m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { if (!m_firedBeforeLoad) beforeLoadEventSender().cancelEvent(this); if (!m_firedLoad) loadEventSender().cancelEvent(this); m_image = newImage; m_firedBeforeLoad = !newImage; m_firedLoad = !newImage; m_imageComplete = !newImage; if (newImage) { if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) dispatchPendingBeforeLoadEvent(); else beforeLoadEventSender().dispatchEventSoon(this); // 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(); }
void ImageLoader::doUpdateFromElement(BypassMainWorldBehavior bypassBehavior, UpdateFromElementBehavior updateBehavior, const KURL& url, ReferrerPolicy referrerPolicy) { // FIXME: According to // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#the-img-element:the-img-element-55 // When "update image" is called due to environment changes and the load // fails, onerror should not be called. That is currently not the case. // // We don't need to call clearLoader here: Either we were called from the // task, or our caller updateFromElement cleared the task's loader (and set // m_pendingTask to null). m_pendingTask.reset(); // Make sure to only decrement the count when we exit this function std::unique_ptr<IncrementLoadEventDelayCount> loadDelayCounter; loadDelayCounter.swap(m_loadDelayCounter); Document& document = m_element->document(); if (!document.isActive()) return; AtomicString imageSourceURL = m_element->imageSourceURL(); ImageResource* newImage = nullptr; if (!url.isNull()) { // Unlike raw <img>, we block mixed content inside of <picture> or // <img srcset>. ResourceLoaderOptions resourceLoaderOptions = ResourceFetcher::defaultResourceOptions(); ResourceRequest resourceRequest(url); if (updateBehavior == UpdateForcedReload) { resourceRequest.setCachePolicy(WebCachePolicy::BypassingCache); resourceRequest.setLoFiState(WebURLRequest::LoFiOff); } if (referrerPolicy != ReferrerPolicyDefault) { resourceRequest.setHTTPReferrer(SecurityPolicy::generateReferrer( referrerPolicy, url, document.outgoingReferrer())); } if (isHTMLPictureElement(element()->parentNode()) || !element()->fastGetAttribute(HTMLNames::srcsetAttr).isNull()) resourceRequest.setRequestContext(WebURLRequest::RequestContextImageSet); FetchRequest request(resourceRequest, element()->localName(), resourceLoaderOptions); configureRequest(request, bypassBehavior, *m_element, document.clientHintsPreferences()); newImage = ImageResource::fetch(request, document.fetcher()); if (!newImage && !pageIsBeingDismissed(&document)) { crossSiteOrCSPViolationOccurred(imageSourceURL); dispatchErrorEvent(); } else { clearFailedLoadURL(); } } else { if (!imageSourceURL.isNull()) { // Fire an error event if the url string is not empty, but the KURL is. dispatchErrorEvent(); } noImageResourceToLoad(); } ImageResource* oldImage = m_image.get(); if (updateBehavior == UpdateSizeChanged && m_element->layoutObject() && m_element->layoutObject()->isImage() && newImage == oldImage) { toLayoutImage(m_element->layoutObject())->intrinsicSizeChanged(); } else { 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_hasPendingLoadEvent = newImage; m_imageComplete = !newImage; updateLayoutObject(); // If newImage exists and is cached, addObserver() will result in the load // event being queued to fire. Ensure this happens after beforeload is // dispatched. if (newImage) { newImage->addObserver(this); } if (oldImage) { oldImage->removeObserver(this); } } if (LayoutImageResource* imageResource = layoutImageResource()) 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(); }
void ImageLoader::doUpdateFromElement(BypassMainWorldBehavior bypassBehavior, UpdateFromElementBehavior updateBehavior) { // FIXME: According to // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#the-img-element:the-img-element-55 // When "update image" is called due to environment changes and the load fails, onerror should not be called. // That is currently not the case. // // We don't need to call clearLoader here: Either we were called from the // task, or our caller updateFromElement cleared the task's loader (and set // m_pendingTask to null). m_pendingTask.clear(); // Make sure to only decrement the count when we exit this function OwnPtr<IncrementLoadEventDelayCount> loadDelayCounter; loadDelayCounter.swap(m_loadDelayCounter); Document& document = m_element->document(); if (!document.isActive()) return; AtomicString imageSourceURL = m_element->imageSourceURL(); KURL url = imageSourceToKURL(imageSourceURL); ResourcePtr<ImageResource> newImage = 0; RefPtrWillBeRawPtr<Element> protectElement(m_element.get()); if (!url.isNull()) { // Unlike raw <img>, we block mixed content inside of <picture> or <img srcset>. ResourceLoaderOptions resourceLoaderOptions = ResourceFetcher::defaultResourceOptions(); ResourceRequest resourceRequest(url); resourceRequest.setFetchCredentialsMode(WebURLRequest::FetchCredentialsModeSameOrigin); if (updateBehavior == UpdateForcedReload) { resourceRequest.setCachePolicy(ResourceRequestCachePolicy::ReloadBypassingCache); // ImageLoader defers the load of images when in an ImageDocument. Don't defer this load on a forced reload. m_loadingImageDocument = false; } if (isHTMLPictureElement(element()->parentNode()) || !element()->fastGetAttribute(HTMLNames::srcsetAttr).isNull()) resourceRequest.setRequestContext(WebURLRequest::RequestContextImageSet); FetchRequest request(resourceRequest, element()->localName(), resourceLoaderOptions); configureRequest(request, bypassBehavior, *m_element, document.clientHintsPreferences()); // Prevent the immediate creation of a ResourceLoader (and therefore a network // request) for ImageDocument loads. In this case, the image contents have already // been requested as a main resource and ImageDocumentParser will take care of // funneling the main resource bytes into the ImageResource. if (m_loadingImageDocument) { request.setDefer(FetchRequest::DeferredByClient); request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); } newImage = ImageResource::fetch(request, document.fetcher()); if (m_loadingImageDocument && newImage) newImage->setLoading(true); if (!newImage && !pageIsBeingDismissed(&document)) { crossSiteOrCSPViolationOccurred(imageSourceURL); dispatchErrorEvent(); } else { clearFailedLoadURL(); } } else { if (!imageSourceURL.isNull()) { // Fire an error event if the url string is not empty, but the KURL is. dispatchErrorEvent(); } noImageResourceToLoad(); } ImageResource* oldImage = m_image.get(); if (updateBehavior == UpdateSizeChanged && m_element->layoutObject() && m_element->layoutObject()->isImage() && newImage == oldImage) { toLayoutImage(m_element->layoutObject())->intrinsicSizeChanged(); } else { if (newImage != oldImage) sourceImageChanged(); 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_hasPendingLoadEvent = newImage; m_imageComplete = !newImage; updateLayoutObject(); // If newImage exists and is cached, addClient() will result in the load event // being queued to fire. Ensure this happens after beforeload is dispatched. if (newImage) newImage->addClient(this); if (oldImage) oldImage->removeClient(this); } if (LayoutImageResource* imageResource = layoutImageResource()) 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(); }
void ImageLoader::doUpdateFromElement(UpdateFromElementBehavior updateBehavior) { // FIXME: According to // http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#the-img-element:the-img-element-55 // When "update image" is called due to environment changes and the load fails, onerror should not be called. // That is currently not the case. // // We don't need to call clearLoader here: Either we were called from the // task, or our caller updateFromElement cleared the task's loader (and set // m_pendingTask to null). m_pendingTask.clear(); // Make sure to only decrement the count when we exit this function OwnPtr<IncrementLoadEventDelayCount> loadDelayCounter; loadDelayCounter.swap(m_loadDelayCounter); Document& document = m_element->document(); if (!document.isActive()) return; AtomicString imageSourceURL = m_element->imageSourceURL(); KURL url = imageSourceToKURL(imageSourceURL); ResourcePtr<ImageResource> newImage = 0; if (!url.isNull()) { // Unlike raw <img>, we block mixed content inside of <picture> or <img srcset>. ResourceLoaderOptions resourceLoaderOptions = ResourceFetcher::defaultResourceOptions(); ResourceRequest resourceRequest(url); FetchRequest request(ResourceRequest(url), element()->localName(), resourceLoaderOptions); newImage = document.fetcher()->fetchImage(request); if (!newImage && !pageIsBeingDismissed(&document)) crossSiteOrCSPViolationOccured(imageSourceURL); else clearFailedLoadURL(); } else if (!imageSourceURL.isNull()) { // Fire an error event if the url string is not empty, but the KURL is. m_hasPendingErrorEvent = true; errorEventSender().dispatchEventSoon(this); } ImageResource* oldImage = m_image.get(); if (newImage != oldImage) { sourceImageChanged(); 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_hasPendingLoadEvent = newImage; m_imageComplete = !newImage; updateRenderer(); // If newImage exists and is cached, addClient() will result in the load event // being queued to fire. Ensure this happens after beforeload is dispatched. if (newImage) newImage->addClient(this); if (oldImage) oldImage->removeClient(this); } else if (updateBehavior == UpdateSizeChanged && m_element->renderer() && m_element->renderer()->isImage()) { toRenderImage(m_element->renderer())->intrinsicSizeChanged(); } 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(); }
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->getAttribute(m_element->imageSourceAttributeName()); if (attr == m_failedLoadURL) return; // Do not load any image if the 'src' attribute is missing or if it is // an empty string referring to a local file. The latter condition is // a quirk that preserves old behavior that Dashboard widgets // need (<rdar://problem/5994621>). CachedImage* newImage = 0; // CAPPFIX_WEB_IMG_SRC_NULL #if 1 if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { #else if (!(attr.isNull() || (attr.isEmpty() && document->baseURI().isLocalFile()))) { #endif ResourceRequest request = ResourceRequest(document->completeURL(sourceURI(attr))); String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) { bool allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials"); updateRequestForAccessControl(request, document->securityOrigin(), allowCredentials); } if (m_loadManually) { bool autoLoadOtherImages = document->cachedResourceLoader()->autoLoadImages(); document->cachedResourceLoader()->setAutoLoadImages(false); newImage = new CachedImage(request); newImage->setLoading(true); newImage->setOwningCachedResourceLoader(document->cachedResourceLoader()); document->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage); 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. m_failedLoadURL = !newImage ? attr : AtomicString(); // CAPPFIX_WEB_IMG_SRC_NULL #if 1 } else if (!attr.isNull()) // Fire an error event if the url is empty. m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); #else } #endif CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { if (!m_firedBeforeLoad) beforeLoadEventSender().cancelEvent(this); if (!m_firedLoad) loadEventSender().cancelEvent(this); m_image = newImage; m_firedBeforeLoad = !newImage; m_firedLoad = !newImage; m_imageComplete = !newImage; if (newImage) { newImage->addClient(this); if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) dispatchPendingBeforeLoadEvent(); else beforeLoadEventSender().dispatchEventSoon(this); } if (oldImage) oldImage->removeClient(this); } if (RenderImageResource* imageResource = renderImageResource()) imageResource->resetAnimation(); }