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::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) { nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); // Since removing href or rel makes us no longer link to a // stylesheet, force updates for those too. if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::href || aAttribute == nsGkAtoms::rel || aAttribute == nsGkAtoms::title || aAttribute == nsGkAtoms::media || aAttribute == nsGkAtoms::type) { UpdateStyleSheetInternal(nullptr, nullptr, true); } if (aAttribute == nsGkAtoms::href || aAttribute == nsGkAtoms::rel) { UpdateImport(); } } // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState // is important here! The attribute is not unset until UnsetAttr 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 (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { Link::ResetLinkState(!!aNotify, false); } return rv; }
void HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent) { // If this link is ever reinserted into a document, it might // be under a different xml:base, so forget the cached state now. Link::ResetLinkState(false, Link::ElementHasHref()); // Once we have XPCOMGC we shouldn't need to call UnbindFromTree during Unlink // and so this messy event dispatch can go away. nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc(); // Check for a ShadowRoot because link elements are inert in a // ShadowRoot. ShadowRoot* oldShadowRoot = GetBindingParent() ? GetBindingParent()->GetShadowRoot() : nullptr; if (oldDoc && !oldShadowRoot) { oldDoc->UnregisterPendingLinkUpdate(this); } CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved")); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); UpdateStyleSheetInternal(oldDoc, oldShadowRoot); UpdateImport(); }
void HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent) { // Cancel any DNS prefetches // Note: Must come before ResetLinkState. If called after, it will recreate // mCachedURI based on data that is invalid - due to a call to GetHostname. CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED, HTML_LINK_DNS_PREFETCH_REQUESTED); // If this link is ever reinserted into a document, it might // be under a different xml:base, so forget the cached state now. Link::ResetLinkState(false, Link::ElementHasHref()); // If this is reinserted back into the document it will not be // from the parser. nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc(); // Check for a ShadowRoot because link elements are inert in a // ShadowRoot. ShadowRoot* oldShadowRoot = GetBindingParent() ? GetBindingParent()->GetShadowRoot() : nullptr; OwnerDoc()->UnregisterPendingLinkUpdate(this); CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved")); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); UpdateStyleSheetInternal(oldDoc, oldShadowRoot); UpdateImport(); }
void HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent) { // If this link is ever reinserted into a document, it might // be under a different xml:base, so forget the cached state now. Link::ResetLinkState(false, Link::ElementHasHref()); nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc(); // Check for a ShadowRoot because link elements are inert in a // ShadowRoot. ShadowRoot* oldShadowRoot = GetBindingParent() ? GetBindingParent()->GetShadowRoot() : nullptr; OwnerDoc()->UnregisterPendingLinkUpdate(this); CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved")); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); UpdateStyleSheetInternal(oldDoc, oldShadowRoot); UpdateImport(); }
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); }