nsresult HTMLSharedElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href) { // If the href attribute of a <base> tag is changing, we may need to // update the document's base URI, which will cause all the links on the // page to be re-resolved given the new base. // If the href is being unset (aValue is null), we will need to find a new // <base>. if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) { SetBaseURIUsingFirstBaseWithHref(GetUncomposedDoc(), aValue ? this : nullptr); } } else if (aName == nsGkAtoms::target) { // The target attribute is in pretty much the same situation as the href // attribute, above. if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) { SetBaseTargetUsingFirstBaseWithTarget(GetUncomposedDoc(), aValue ? this : nullptr); } } } return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); }
bool SVGMPathElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, const nsAString& aValue, nsIPrincipal* aMaybeScriptedPrincipal, nsAttrValue& aResult) { bool returnVal = SVGMPathElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue, aMaybeScriptedPrincipal, aResult); if ((aNamespaceID == kNameSpaceID_XLink || aNamespaceID == kNameSpaceID_None ) && aAttribute == nsGkAtoms::href && IsInUncomposedDoc()) { // Note: If we fail the IsInDoc call, it's ok -- we'll update the target // on next BindToTree call. // Note: "href" takes priority over xlink:href. So if "xlink:href" is being // set here, we only let that update our target if "href" is *unset*. if (aNamespaceID != kNameSpaceID_XLink || !mStringAttributes[HREF].IsExplicitlySet()) { UpdateHrefTarget(GetParent(), aValue); } } return returnVal; }
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; }
NS_IMETHODIMP HTMLBodyElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker) { nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker); if (!mContentStyleRule && IsInUncomposedDoc()) { // XXXbz should this use OwnerDoc() or GetComposedDoc()? // sXBL/XBL2 issue! mContentStyleRule = new BodyRule(this); } if (aRuleWalker && mContentStyleRule) { aRuleWalker->Forward(mContentStyleRule); } return NS_OK; }
nsresult HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { // Handle type changes first, since some of the later conditions in this // method look at mType and want to see the new value. if (aName == nsGkAtoms::type) { if (aValue) { mType = aValue->GetEnumValue(); } else { mType = kMenuItemDefaultType->value; } } if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) && mType == CMD_TYPE_RADIO && !mParserCreating) { if (IsInUncomposedDoc() && GetParent()) { AddedToRadioGroup(); } } // Checked must be set no matter what type of menuitem it is, since // GetChecked() must reflect the new value if (aName == nsGkAtoms::checked && !mCheckedDirty) { if (mParserCreating) { mShouldInitChecked = true; } else { InitChecked(); } } } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); }
bool HTMLImageElement::IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) { int32_t tabIndex = TabIndex(); if (IsInUncomposedDoc()) { nsAutoString usemap; GetUseMap(usemap); // XXXbz which document should this be using? sXBL/XBL2 issue! I // think that OwnerDoc() is right, since we don't want to // assume stuff about the document we're bound to. if (OwnerDoc()->FindImageMap(usemap)) { if (aTabIndex) { // Use tab index on individual map areas *aTabIndex = (sTabFocusModel & eTabFocus_linksMask)? 0 : -1; } // Image map is not focusable itself, but flag as tabbable // so that image map areas get walked into. *aIsFocusable = false; return false; } } if (aTabIndex) { // Can be in tab order if tabindex >=0 and form controls are tabbable. *aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask)? tabIndex : -1; } *aIsFocusable = #ifdef XP_MACOSX (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) && #endif (tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)); return false; }
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); if (IsInUncomposedDoc()) { CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged")); } } return rv; }
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); }