void HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode, const nsAString& aNewValue, bool aNotify) { if (!HTMLPictureElement::IsPictureEnabled()) { return; } MOZ_ASSERT(aSourceNode == this || IsPreviousSibling(aSourceNode, this), "Should not be getting notifications for non-previous-siblings"); nsIContent *currentSrc = mResponsiveSelector ? mResponsiveSelector->Content() : nullptr; if (aSourceNode == currentSrc) { // We're currently using this node as our responsive selector // source. mResponsiveSelector->SetSizesFromDescriptor(aNewValue); } // This always triggers the image update steps per the spec, even if // we are not using this source. QueueImageLoadTask(true); }
void HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent) { if (mForm) { if (aNullParent || !FindAncestorForm(mForm)) { ClearForm(true); } else { UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT); } } if (mInDocResponsiveContent) { nsIDocument* doc = GetOurOwnerDoc(); MOZ_ASSERT(doc); if (doc) { doc->RemoveResponsiveContent(this); mInDocResponsiveContent = false; } } if (GetParent() && GetParent()->IsHTMLElement(nsGkAtoms::picture) && HTMLPictureElement::IsPictureEnabled()) { // Being removed from picture re-triggers selection, even if we // weren't using a <source> peer if (aNullParent) { QueueImageLoadTask(true); } } nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); }
void HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode) { if (!HTMLPictureElement::IsPictureEnabled()) { return; } QueueImageLoadTask(true); }
nsresult HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers) { nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers); if (aParent) { UpdateFormOwner(); } if (HaveSrcsetOrInPicture()) { if (aDocument && !mInDocResponsiveContent) { aDocument->AddResponsiveContent(this); mInDocResponsiveContent = true; } bool forceLoadEvent = HTMLPictureElement::IsPictureEnabled() && aParent && aParent->IsHTMLElement(nsGkAtoms::picture); QueueImageLoadTask(forceLoadEvent); } else if (!InResponsiveMode() && HasAttr(kNameSpaceID_None, nsGkAtoms::src)) { // We skip loading when our attributes were set from parser land, // so trigger a aForce=false load now to check if things changed. // This isn't necessary for responsive mode, since creating the // image load task is asynchronous we don't need to take special // care to avoid doing so when being filled by the parser. // FIXME: Bug 660963 it would be nice if we could just have // ClearBrokenState update our state and do it fast... ClearBrokenState(); RemoveStatesSilently(NS_EVENT_STATE_BROKEN); // We still act synchronously for the non-responsive case (Bug // 1076583), but still need to delay if it is unsafe to run // script. // If loading is temporarily disabled, don't even launch MaybeLoadImage. // Otherwise MaybeLoadImage may run later when someone has reenabled // loading. if (LoadingEnabled()) { nsContentUtils::AddScriptRunner( NS_NewRunnableMethod(this, &HTMLImageElement::MaybeLoadImage)); } } return rv; }
nsresult HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, bool aNotify) { // We need to force our image to reload. This must be done here, not in // AfterSetAttr or BeforeSetAttr, because we want to do it even if the attr is // being set to its existing value, which is normally optimized away as a // no-op. // // If we are in responsive mode, we drop the forced reload behavior, // but still trigger a image load task for img.src = img.src per // spec. // // Both cases handle unsetting src in AfterSetAttr if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { // This is for dom.disable_image_src_set, which predates "srcset" // as an attribute. See Bug 773429 if (nsContentUtils::IsImageSrcSetDisabled()) { return NS_OK; } if (InResponsiveMode()) { if (mResponsiveSelector && mResponsiveSelector->Content() == this) { mResponsiveSelector->SetDefaultSource(aValue); } QueueImageLoadTask(true); } else if (aNotify) { // 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 // sync image load from BindToTree. Skip the LoadImage call in that case. // Note that this sync behavior is partially removed from the spec, bug 1076583 // A hack to get animations to reset. See bug 594771. mNewRequestsWillNeedAnimationReset = true; // Force image loading here, so that we'll try to load the image from // network if it's set to be not cacheable... If we change things so that // the state gets in Element's attr-setting happen around this // LoadImage call, we could start passing false instead of aNotify // here. LoadImage(aValue, true, aNotify, eImageLoadType_Normal); mNewRequestsWillNeedAnimationReset = false; } } return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify); }
void HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode, bool aNotify) { if (!HTMLPictureElement::IsPictureEnabled()) { return; } MOZ_ASSERT(IsPreviousSibling(aSourceNode, this), "Should not be getting notifications for non-previous-siblings"); // This always triggers the image update steps per the spec, even if // we are not switching to/from this source QueueImageLoadTask(true); }
void HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent) { if (mForm) { if (aNullParent || !FindAncestorForm(mForm)) { ClearForm(true); } else { UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT); } } if (aNullParent && nsINode::GetParentNode()->Tag() == nsGkAtoms::picture && HTMLPictureElement::IsPictureEnabled()) { // Being removed from picture re-triggers selection, even if we // weren't using a <source> peer QueueImageLoadTask(); } nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); }
void HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode, const nsAString& aNewValue, bool aNotify) { bool isSelf = aSourceNode == this; if (!IsSrcsetEnabled() || (!isSelf && !HTMLPictureElement::IsPictureEnabled())) { return; } MOZ_ASSERT(isSelf || IsPreviousSibling(aSourceNode, this), "Should not be getting notifications for non-previous-siblings"); nsIContent *currentSrc = mResponsiveSelector ? mResponsiveSelector->Content() : nullptr; if (aSourceNode == currentSrc) { // We're currently using this node as our responsive selector // source. mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue); } if (!mInDocResponsiveContent) { nsIDocument* doc = GetOurOwnerDoc(); if (doc) { doc->AddResponsiveContent(this); mInDocResponsiveContent = true; } } // This always triggers the image update steps per the spec, even if // we are not using this source. QueueImageLoadTask(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 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); }
void HTMLImageElement::MediaFeatureValuesChanged() { QueueImageLoadTask(false); }