nsresult HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify) { nsresult rv = NS_ERROR_FAILURE; if (aForce) { // In responsive mode we generally want to re-run the full // selection algorithm whenever starting a new load, per // spec. This also causes us to re-resolve the URI as appropriate. UpdateResponsiveSource(); } if (mResponsiveSelector) { nsCOMPtr<nsIURI> url = mResponsiveSelector->GetSelectedImageURL(); rv = LoadImage(url, aForce, aNotify, eImageLoadType_Imageset); } else { nsAutoString src; if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { CancelImageRequests(aNotify); rv = NS_OK; } else { // If we have a srcset attribute or are in a <picture> element, // we always use the Imageset load type, even if we parsed no // valid responsive sources from either, per spec. rv = LoadImage(src, aForce, aNotify, HaveSrcsetOrInPicture() ? eImageLoadType_Imageset : eImageLoadType_Normal); } } if (NS_FAILED(rv)) { CancelImageRequests(aNotify); } return rv; }
nsresult HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify) { nsresult rv = NS_ERROR_FAILURE; if (mResponsiveSelector) { nsCOMPtr<nsIURI> url = mResponsiveSelector->GetSelectedImageURL(); if (url) { rv = LoadImage(url, aForce, aNotify); } else { CancelImageRequests(aNotify); rv = NS_OK; } } else { nsAutoString src; if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { CancelImageRequests(aNotify); rv = NS_OK; } else { rv = LoadImage(src, aForce, aNotify); if (NS_FAILED(rv)) { CancelImageRequests(aNotify); } } } return rv; }
void nsSVGImageElement::MaybeLoadSVGImage() { if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href) && (NS_FAILED(LoadSVGImage(PR_FALSE, PR_TRUE)) || !LoadingEnabled())) { CancelImageRequests(PR_TRUE); } }
nsresult HTMLImageElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::src) { CancelImageRequests(aNotify); } return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); }
void HTMLImageElement::MaybeLoadImage() { // Our base URI may have changed; claim that our URI changed, and the // nsImageLoadingContent will decide whether a new image load is warranted. // Note, check LoadingEnabled() after LoadImage call. nsAutoString uri; if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) && (NS_FAILED(LoadImage(uri, false, true)) || !LoadingEnabled())) { CancelImageRequests(true); } }
nsresult HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) && aValue && !aValue->IsEmptyString()) { // add the image to the hashtable as needed NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom, "Expected atom value for name/id"); mForm->AddImageElementToTable(this, nsDependentAtomString(aValue->GetAtomValue())); } // Handle src/srcset/crossorigin updates. If aNotify is false, we are coming // from the parser or some such place; we'll get bound after all the // attributes have been set, so we'll do the image load from BindToTree. if (aName == nsGkAtoms::src && aNameSpaceID == kNameSpaceID_None) { // SetAttr handles setting src in the non-responsive case, so only handle it // for responsive mode or unsetting if (!aValue) { CancelImageRequests(aNotify); } else if (mResponsiveSelector) { mResponsiveSelector->SetDefaultSource(aValue ? aValue->GetStringValue() : EmptyString()); LoadSelectedImage(false, aNotify); } } else if (aName == nsGkAtoms::srcset && aNameSpaceID == kNameSpaceID_None && aNotify && AsContent()->IsInDoc() && IsSrcsetEnabled()) { // We currently don't handle responsive mode until BindToTree UpdateSourceSet(aValue->GetStringValue()); LoadSelectedImage(false, aNotify); } else if (aName == nsGkAtoms::crossorigin && aNameSpaceID == kNameSpaceID_None && aNotify) { // We want aForce == true in this LoadImage call, because we want to force // a new load of the image with the new cross origin policy. nsCOMPtr<nsIURI> currentURI; if (NS_SUCCEEDED(GetCurrentURI(getter_AddRefs(currentURI))) && currentURI) { LoadImage(currentURI, true, aNotify); } } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify); }
void HTMLImageElement::MaybeLoadImage() { // Our base URI may have changed, or we may have had responsive parameters // change while not bound to the tree. Re-parse src/srcset and call LoadImage, // which is a no-op if it resolves to the same effective URI without aForce. // Note, check LoadingEnabled() after LoadImage call. LoadSelectedImage(false, true, false); if (!LoadingEnabled()) { CancelImageRequests(true); } }
nsresult nsSVGImageElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, const nsAString* aValue, PRBool aNotify) { if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) { // If caller is not chrome and dom.disable_image_src_set is true, // prevent setting image.src by exiting early if (nsContentUtils::GetBoolPref("dom.disable_image_src_set") && !nsContentUtils::IsCallerChrome()) { return NS_OK; } if (aValue) { LoadSVGImage(PR_TRUE, aNotify); } else { CancelImageRequests(aNotify); } } return nsSVGImageElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify); }
nsresult nsImageLoadingContent::LoadImage(const nsAString& aNewURI, PRBool aForce, PRBool aNotify) { // First, get a document (needed for security checks and the like) nsIDocument* doc = GetOurDocument(); if (!doc) { // No reason to bother, I think... return NS_OK; } nsCOMPtr<nsIURI> imageURI; nsresult rv = StringToURI(aNewURI, doc, getter_AddRefs(imageURI)); NS_ENSURE_SUCCESS(rv, rv); // XXXbiesi fire onerror if that failed? PRBool equal; if (aNewURI.IsEmpty() && doc->GetDocumentURI() && NS_SUCCEEDED(doc->GetDocumentURI()->Equals(imageURI, &equal)) && equal) { // Loading an embedded img from the same URI as the document URI will not work // as a resource cannot recursively embed itself. Attempting to do so generally // results in having to pre-emptively close down an in-flight HTTP transaction // and then incurring the significant cost of establishing a new TCP channel. // This is generally triggered from <img src=""> // In light of that, just skip loading it.. // Do make sure to drop our existing image, if any CancelImageRequests(aNotify); return NS_OK; } NS_TryToSetImmutable(imageURI); return LoadImage(imageURI, aForce, aNotify, doc); }
nsresult HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) && aValue && !aValue->IsEmptyString()) { // add the image to the hashtable as needed MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom, "Expected atom value for name/id"); mForm->AddImageElementToTable(this, nsDependentAtomString(aValue->GetAtomValue())); } // Handle src/srcset/crossorigin updates. If aNotify is false, we are coming // from the parser or some such place; we'll get bound after all the // attributes have been set, so we'll do the image load from BindToTree. nsAttrValueOrString attrVal(aValue); if (aName == nsGkAtoms::src && aNameSpaceID == kNameSpaceID_None && !aValue) { // SetAttr handles setting src since it needs to catch img.src = // img.src, so we only need to handle the unset case if (InResponsiveMode()) { if (mResponsiveSelector && mResponsiveSelector->Content() == this) { mResponsiveSelector->SetDefaultSource(NullString()); } QueueImageLoadTask(true); } else { // Bug 1076583 - We still behave synchronously in the non-responsive case CancelImageRequests(aNotify); } } else if (aName == nsGkAtoms::srcset && aNameSpaceID == kNameSpaceID_None && IsSrcsetEnabled()) { PictureSourceSrcsetChanged(this, attrVal.String(), aNotify); } else if (aName == nsGkAtoms::sizes && aNameSpaceID == kNameSpaceID_None && HTMLPictureElement::IsPictureEnabled()) { PictureSourceSizesChanged(this, attrVal.String(), aNotify); } else if (aName == nsGkAtoms::crossorigin && aNameSpaceID == kNameSpaceID_None && aNotify) { // Force a new load of the image with the new cross origin policy. if (InResponsiveMode()) { // per spec, full selection runs when this changes, even though // it doesn't directly affect the source selection QueueImageLoadTask(true); } else { // Bug 1076583 - We still use the older synchronous algorithm in // non-responsive mode. Force a new load of the image with the // new cross origin policy. ForceReload(aNotify); } } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify); }