nsresult HTMLLinkElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, const nsAString& aValue, bool aNotify) { nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify); // The ordering of the parent class's SetAttr call and Link::ResetLinkState // is important here! The attribute is not set until SetAttr returns, and // we will need the updated attribute value because notifying the document // that content states have changed will call IntrinsicState, which will try // to get updated information about the visitedness from Link. if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { Link::ResetLinkState(!!aNotify, true); if (IsInUncomposedDoc()) { CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged")); } } if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None && (aName == nsGkAtoms::href || aName == nsGkAtoms::rel || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type)) { bool dropSheet = false; if (aName == nsGkAtoms::rel) { uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(aValue, NodePrincipal()); if (GetSheet()) { dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET); } else if (linkTypes & eHTMLIMPORT) { UpdateImport(); } else if ((linkTypes & ePRECONNECT) && IsInComposedDoc()) { UpdatePreconnect(); } } if (aName == nsGkAtoms::href) { UpdateImport(); if (IsInComposedDoc()) { UpdatePreconnect(); } } UpdateStyleSheetInternal(nullptr, nullptr, dropSheet || (aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type)); } return rv; }
nsresult HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers) { Link::ResetLinkState(false, Link::ElementHasHref()); nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, aBindingParent, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); // Link must be inert in ShadowRoot. if (aDocument && !GetContainingShadow()) { aDocument->RegisterPendingLinkUpdate(this); } if (IsInComposedDoc()) { UpdatePreconnect(); } void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal; nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, update)); void (HTMLLinkElement::*updateImport)() = &HTMLLinkElement::UpdateImport; nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, updateImport)); CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded")); return rv; }
void HTMLVideoElement::EndCloningVisually() { MOZ_ASSERT(mVisualCloneTarget); if (mDecoder) { MediaDecoderStateMachine* mdsm = mDecoder->GetStateMachine(); if (mdsm) { mdsm->SetSecondaryVideoContainer(nullptr); mDecoder->SetCloningVisually(false); } } else if (mSrcStream) { VideoFrameContainer* container = mVisualCloneTarget->GetVideoFrameContainer(); if (container && mVisualCloneTarget->mSelectedVideoStreamTrack) { mVisualCloneTarget->mSelectedVideoStreamTrack->RemoveVideoOutput( container); } } Unused << mVisualCloneTarget->SetVisualCloneSource(nullptr); Unused << SetVisualCloneTarget(nullptr); if (IsInComposedDoc() && !sCloneElementVisuallyTesting) { NotifyUAWidgetSetupOrChange(); } }
void HTMLSharedObjectElement::StartObjectLoad(bool aNotify) { // BindToTree can call us asynchronously, and we may be removed from the tree // in the interim if (!IsInComposedDoc() || !OwnerDoc()->IsActive()) { return; } LoadObject(aNotify); SetIsNetworkCreated(false); }
nsresult HTMLMarqueeElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aMaybeScriptedPrincipal, bool aNotify) { if (IsInComposedDoc() && aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::direction) { NotifyUAWidgetSetupOrChange(); } return nsGenericHTMLElement::AfterSetAttr( aNameSpaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify); }
nsresult HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) { nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); NS_ENSURE_SUCCESS(rv, rv); // See comment in SetAttr if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) { return LoadObject(aNotify, true); } return NS_OK; }
nsresult HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href) { Link::ResetLinkState(aNotify, !!aValue); if (aValue && IsInComposedDoc()) { TryDNSPrefetch(); } } } return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); }
void HTMLVideoElement::CloneElementVisually(HTMLVideoElement& aTargetVideo, ErrorResult& rv) { MOZ_ASSERT(!mUnboundFromTree, "Can't clone a video that's not bound to a DOM tree."); MOZ_ASSERT(!aTargetVideo.mUnboundFromTree, "Can't clone to a video that's not bound to a DOM tree."); if (mUnboundFromTree || aTargetVideo.mUnboundFromTree) { rv.Throw(NS_ERROR_UNEXPECTED); return; } // Do we already have a visual clone target? If so, shut it down. if (mVisualCloneTarget) { EndCloningVisually(); } // If there's a poster set on the target video, clear it, otherwise // it'll display over top of the cloned frames. aTargetVideo.UnsetHTMLAttr(nsGkAtoms::poster, rv); if (rv.Failed()) { return; } if (!SetVisualCloneTarget(&aTargetVideo)) { rv.Throw(NS_ERROR_FAILURE); return; } if (!aTargetVideo.SetVisualCloneSource(this)) { mVisualCloneTarget = nullptr; rv.Throw(NS_ERROR_FAILURE); return; } aTargetVideo.SetMediaInfo(mMediaInfo); if (IsInComposedDoc() && !sCloneElementVisuallyTesting) { NotifyUAWidgetSetupOrChange(); } MaybeBeginCloningVisually(); }
nsresult HTMLSharedObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName, nsIAtom *aPrefix, const nsAString &aValue, bool aNotify) { nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify); NS_ENSURE_SUCCESS(rv, rv); // 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 // object load from BindToTree/DoneAddingChildren. // Skip the LoadObject call in that case. // We also don't want to start loading the object when we're not yet in // a document, just in case that the caller wants to set additional // attributes before inserting the node into the document. if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && aNameSpaceID == kNameSpaceID_None && aName == URIAttrName()) { return LoadObject(aNotify, true); } return NS_OK; }
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 && IsInComposedDoc()) { 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 HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) { // It's safe to call ResetLinkState here because our new attr value has // already been set or unset. ResetLinkState needs the updated attribute // value because notifying the document that content states have changed will // call IntrinsicState, which will try to get updated information about the // visitedness from Link. if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { bool hasHref = aValue; Link::ResetLinkState(!!aNotify, hasHref); if (IsInUncomposedDoc()) { CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged")); } } if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::href) { mTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal( this, aValue ? aValue->GetStringValue() : EmptyString(), aSubjectPrincipal); } // If a link's `rel` attribute was changed from or to `localization`, // update the list of localization links. if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::rel) { Document* doc = GetComposedDoc(); if (doc) { if ((aValue && aValue->Equals(nsGkAtoms::localization, eIgnoreCase)) && (!aOldValue || !aOldValue->Equals(nsGkAtoms::localization, eIgnoreCase))) { doc->LocalizationLinkAdded(this); } else if ((aOldValue && aOldValue->Equals(nsGkAtoms::localization, eIgnoreCase)) && (!aValue || !aValue->Equals(nsGkAtoms::localization, eIgnoreCase))) { doc->LocalizationLinkRemoved(this); } } } // If the link has `rel=localization` and its `href` attribute is changed, // update the list of localization links. if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::href && AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization, eIgnoreCase)) { Document* doc = GetComposedDoc(); if (doc) { if (aOldValue) { doc->LocalizationLinkRemoved(this); } if (aValue) { doc->LocalizationLinkAdded(this); } } } if (aValue) { if (aNameSpaceID == kNameSpaceID_None && (aName == nsGkAtoms::href || aName == nsGkAtoms::rel || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type || aName == nsGkAtoms::as || aName == nsGkAtoms::crossorigin)) { bool dropSheet = false; if (aName == nsGkAtoms::rel) { nsAutoString value; aValue->ToString(value); uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(value); if (GetSheet()) { dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET); } } if ((aName == nsGkAtoms::rel || aName == nsGkAtoms::href) && IsInComposedDoc()) { TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender(); } if ((aName == nsGkAtoms::as || aName == nsGkAtoms::type || aName == nsGkAtoms::crossorigin || aName == nsGkAtoms::media) && IsInComposedDoc()) { UpdatePreload(aName, aValue, aOldValue); } const bool forceUpdate = dropSheet || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type; Unused << UpdateStyleSheetInternal( nullptr, nullptr, forceUpdate ? ForceUpdate::Yes : ForceUpdate::No); } } else { // Since removing href or rel makes us no longer link to a // stylesheet, force updates for those too. if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href || aName == nsGkAtoms::rel || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type) { Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes); } if ((aName == nsGkAtoms::as || aName == nsGkAtoms::type || aName == nsGkAtoms::crossorigin || aName == nsGkAtoms::media) && IsInComposedDoc()) { UpdatePreload(aName, aValue, aOldValue); } } } return nsGenericHTMLElement::AfterSetAttr( aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); }
nsresult CharacterData::BindToTree(Document* aDocument, nsIContent* aParent, nsIContent* aBindingParent) { MOZ_ASSERT(aParent || aDocument, "Must have document if no parent!"); MOZ_ASSERT(NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc(), "Must have the same owner document"); MOZ_ASSERT(!aParent || aDocument == aParent->GetUncomposedDoc(), "aDocument must be current doc of aParent"); MOZ_ASSERT(!GetUncomposedDoc() && !IsInUncomposedDoc(), "Already have a document. Unbind first!"); MOZ_ASSERT(!IsInComposedDoc(), "Already have a document. Unbind first!"); // Note that as we recurse into the kids, they'll have a non-null parent. So // only assert if our parent is _changing_ while we have a parent. MOZ_ASSERT(!GetParent() || aParent == GetParent(), "Already have a parent. Unbind first!"); MOZ_ASSERT(!GetBindingParent() || aBindingParent == GetBindingParent() || (!aBindingParent && aParent && aParent->GetBindingParent() == GetBindingParent()), "Already have a binding parent. Unbind first!"); MOZ_ASSERT(aBindingParent != this, "Content must not be its own binding parent"); MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() || aBindingParent == aParent, "Native anonymous content must have its parent as its " "own binding parent"); if (!aBindingParent && aParent) { aBindingParent = aParent->GetBindingParent(); } // First set the binding parent if (aBindingParent) { NS_ASSERTION(IsRootOfNativeAnonymousSubtree() || !HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) || (aParent && aParent->IsInNativeAnonymousSubtree()), "Trying to re-bind content from native anonymous subtree to " "non-native anonymous parent!"); ExtendedContentSlots()->mBindingParent = aBindingParent; // Weak, so no addref happens. if (aParent->IsInNativeAnonymousSubtree()) { SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE); } if (aParent->HasFlag(NODE_HAS_BEEN_IN_UA_WIDGET)) { SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET); } if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) { aParent->SetMayHaveAnonymousChildren(); } } if (aParent && aParent->IsInShadowTree()) { ClearSubtreeRootPointer(); SetFlags(NODE_IS_IN_SHADOW_TREE); SetIsConnected(aParent->IsInComposedDoc()); MOZ_ASSERT(aParent->GetContainingShadow()); ExtendedContentSlots()->mContainingShadow = aParent->GetContainingShadow(); } bool hadParent = !!GetParentNode(); // Set parent if (aParent) { if (!GetParent()) { NS_ADDREF(aParent); } mParent = aParent; } else { mParent = aDocument; } SetParentIsContent(aParent); // XXXbz sXBL/XBL2 issue! // Set document if (aDocument) { // We no longer need to track the subtree pointer (and in fact we'll assert // if we do this any later). ClearSubtreeRootPointer(); // XXX See the comment in Element::BindToTree SetIsInDocument(); SetIsConnected(true); if (mText.IsBidi()) { aDocument->SetBidiEnabled(); } // Clear the lazy frame construction bits. UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES); } else if (!IsInShadowTree()) { // If we're not in the doc and not in a shadow tree, // update our subtree pointer. SetSubtreeRootPointer(aParent->SubtreeRoot()); } nsNodeUtils::ParentChainChanged(this); if (!hadParent && IsRootOfNativeAnonymousSubtree()) { nsNodeUtils::NativeAnonymousChildListChange(this, false); } UpdateEditableState(false); MOZ_ASSERT(aDocument == GetUncomposedDoc(), "Bound to wrong document"); MOZ_ASSERT(aParent == GetParent(), "Bound to wrong parent"); MOZ_ASSERT(aBindingParent == GetBindingParent(), "Bound to wrong binding parent"); return NS_OK; }
nsresult HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) { // It's safe to call ResetLinkState here because our new attr value has // already been set or unset. ResetLinkState needs the updated attribute // value because notifying the document that content states have changed will // call IntrinsicState, which will try to get updated information about the // visitedness from Link. if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { bool hasHref = aValue; Link::ResetLinkState(!!aNotify, hasHref); if (IsInUncomposedDoc()) { CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged")); } } if (aValue) { if (aNameSpaceID == kNameSpaceID_None && (aName == nsGkAtoms::href || aName == nsGkAtoms::rel || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type)) { bool dropSheet = false; if (aName == nsGkAtoms::rel) { nsAutoString value; aValue->ToString(value); uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(value, NodePrincipal()); if (GetSheet()) { dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET); } else if (linkTypes & eHTMLIMPORT) { UpdateImport(); } else if ((linkTypes & ePRECONNECT) && IsInComposedDoc()) { UpdatePreconnect(); } } if (aName == nsGkAtoms::href) { UpdateImport(); if (IsInComposedDoc()) { UpdatePreconnect(); } } UpdateStyleSheetInternal(nullptr, nullptr, dropSheet || (aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type)); } } else { // Since removing href or rel makes us no longer link to a // stylesheet, force updates for those too. if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href || aName == nsGkAtoms::rel || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type) { UpdateStyleSheetInternal(nullptr, nullptr, true); } if (aName == nsGkAtoms::href || aName == nsGkAtoms::rel) { UpdateImport(); } } } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify); }