Bug 411054, Audit IsNativeAnonymous()/GetBindingParent() uses, r+sr=sicking

This commit is contained in:
Olli.Pettay%helsinki.fi 2008-02-26 12:40:21 +00:00
Родитель 9841cfa886
Коммит c1e558bc24
13 изменённых файлов: 99 добавлений и 113 удалений

Просмотреть файл

@ -856,7 +856,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
{ {
// No access to anonymous content from the web! (bug 164086) // No access to anonymous content from the web! (bug 164086)
nsIContent *content = static_cast<nsIContent*>(aObj); nsIContent *content = static_cast<nsIContent*>(aObj);
if (content->IsNativeAnonymous()) { if (content->IsInNativeAnonymousSubtree()) {
rv = NS_ERROR_DOM_SECURITY_ERR; rv = NS_ERROR_DOM_SECURITY_ERR;
} }
} }

Просмотреть файл

@ -1128,12 +1128,6 @@ public:
nsIURI *aLinkURI, const nsString& aTargetSpec, nsIURI *aLinkURI, const nsString& aTargetSpec,
PRBool aClick, PRBool aIsUserTriggered); PRBool aClick, PRBool aIsUserTriggered);
/**
* Return true if aContent or one of its ancestors in the
* bindingParent chain is native anonymous.
*/
static PRBool IsNativeAnonymous(nsIContent* aContent);
/** /**
* Return top-level widget in the parent chain. * Return top-level widget in the parent chain.
*/ */

Просмотреть файл

@ -62,8 +62,8 @@ class nsIDocShell;
// IID for the nsIContent interface // IID for the nsIContent interface
#define NS_ICONTENT_IID \ #define NS_ICONTENT_IID \
{ 0xfba9aa39, 0x016e, 0x4d5d, \ { 0xd3434698, 0x3a16, 0x4dbe, \
{ 0xab, 0x62, 0x22, 0xa1, 0xb8, 0x4a, 0x3c, 0x7b } } { 0x9d, 0xed, 0xbe, 0x64, 0x16, 0x1a, 0xa3, 0x52 } }
/** /**
* A node of content in a document's content model. This interface * A node of content in a document's content model. This interface
@ -160,6 +160,17 @@ public:
SetFlags(NODE_IS_ANONYMOUS); SetFlags(NODE_IS_ANONYMOUS);
} }
/**
* Returns |this| if it is not native anonymous, otherwise
* first non native anonymous ancestor.
*/
virtual nsIContent* FindFirstNonNativeAnonymous() const;
/**
* Returns PR_TRUE if |this| or any of its ancestors is native anonymous.
*/
virtual PRBool IsInNativeAnonymousSubtree() const;
/** /**
* Get the namespace that this element's tag is defined in * Get the namespace that this element's tag is defined in
* @return the namespace * @return the namespace

Просмотреть файл

@ -3852,36 +3852,6 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
} }
} }
/* static */
PRBool
nsContentUtils::IsNativeAnonymous(nsIContent* aContent)
{
while (aContent) {
nsIContent* bindingParent = aContent->GetBindingParent();
if (bindingParent == aContent) {
NS_ASSERTION(bindingParent->IsNativeAnonymous() ||
bindingParent->IsNodeOfType(nsINode::eXUL),
"Bogus binding parent?");
return PR_TRUE;
}
// Nasty hack to work around spell-check resolving style on
// native-anonymous content that's already been torn down. Don't assert
// !IsNativeAnonymous() if aContent->GetCurrentDoc() is null. The caller
// will get "wrong" style data, but it's just asking for that sort of thing
// anyway.
NS_ASSERTION(!aContent->IsNativeAnonymous() ||
!aContent->GetCurrentDoc() ||
(aContent->GetParent() &&
aContent->GetParent()->NodeInfo()->
Equals(nsGkAtoms::use, kNameSpaceID_SVG)),
"Native anonymous node with wrong binding parent");
aContent = bindingParent;
}
return PR_FALSE;
}
/* static */ /* static */
nsIWidget* nsIWidget*
nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget)

Просмотреть файл

@ -5761,7 +5761,7 @@ nsDocument::MutationEventDispatched(nsINode* aTarget)
for (PRInt32 i = 0; i < count; ++i) { for (PRInt32 i = 0; i < count; ++i) {
nsINode* possibleTarget = mSubtreeModifiedTargets[i]; nsINode* possibleTarget = mSubtreeModifiedTargets[i];
nsCOMPtr<nsIContent> content = do_QueryInterface(possibleTarget); nsCOMPtr<nsIContent> content = do_QueryInterface(possibleTarget);
if (content && content->IsNativeAnonymous()) { if (content && content->IsInNativeAnonymousSubtree()) {
if (realTargets.IndexOf(possibleTarget) == -1) { if (realTargets.IndexOf(possibleTarget) == -1) {
realTargets.AppendObject(possibleTarget); realTargets.AppendObject(possibleTarget);
} }

Просмотреть файл

@ -427,6 +427,37 @@ nsIContent::UpdateEditableState()
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE)); SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
} }
nsIContent*
nsIContent::FindFirstNonNativeAnonymous() const
{
// This handles also nested native anonymous content.
nsIContent* content = GetBindingParent();
nsIContent* possibleResult =
!IsNativeAnonymous() ? const_cast<nsIContent*>(this) : nsnull;
while (content) {
if (content->IsNativeAnonymous()) {
content = possibleResult = content->GetParent();
} else {
content = content->GetBindingParent();
}
}
return possibleResult;
}
PRBool
nsIContent::IsInNativeAnonymousSubtree() const
{
nsIContent* content = GetBindingParent();
while (content) {
if (content->IsNativeAnonymous()) {
return PR_TRUE;
}
content = content->GetBindingParent();
}
return PR_FALSE;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsChildContentList::~nsChildContentList() nsChildContentList::~nsChildContentList()
@ -2073,12 +2104,12 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
NS_PRECONDITION(!aParent || !aDocument || NS_PRECONDITION(!aParent || !aDocument ||
!aParent->HasFlag(NODE_FORCE_XBL_BINDINGS), !aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
"Parent in document but flagged as forcing XBL"); "Parent in document but flagged as forcing XBL");
// XXXbz XUL's SetNativeAnonymous is all weird, so can't assert NS_PRECONDITION(aBindingParent != this || IsNativeAnonymous(),
// anything here
NS_PRECONDITION(IsNodeOfType(eXUL) ||
aBindingParent != this || IsNativeAnonymous(),
"Only native anonymous content should have itself as its " "Only native anonymous content should have itself as its "
"own binding parent"); "own binding parent");
NS_PRECONDITION(!IsNativeAnonymous() || aBindingParent == this,
"Native anonymous content must have itself as its "
"own binding parent");
if (!aBindingParent && aParent) { if (!aBindingParent && aParent) {
aBindingParent = aParent->GetBindingParent(); aBindingParent = aParent->GetBindingParent();
@ -2272,24 +2303,6 @@ nsGenericElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
return nsGenericElement::doPreHandleEvent(this, aVisitor); return nsGenericElement::doPreHandleEvent(this, aVisitor);
} }
static nsIContent*
FindFirstNonAnonContent(nsIContent* aContent)
{
while (aContent && aContent->IsNativeAnonymous()) {
aContent = aContent->GetParent();
}
return aContent;
}
static PRBool
IsInAnonContent(nsIContent* aContent)
{
while (aContent && !aContent->IsNativeAnonymous()) {
aContent = aContent->GetParent();
}
return !!aContent;
}
nsresult nsresult
nsGenericElement::doPreHandleEvent(nsIContent* aContent, nsGenericElement::doPreHandleEvent(nsIContent* aContent,
nsEventChainPreVisitor& aVisitor) nsEventChainPreVisitor& aVisitor)
@ -2315,10 +2328,12 @@ nsGenericElement::doPreHandleEvent(nsIContent* aContent,
// must be updated. // must be updated.
if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon || if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon ||
(aVisitor.mEvent->originalTarget == aContent && (aVisitor.mEvent->originalTarget == aContent &&
(aVisitor.mRelatedTargetIsInAnon = IsInAnonContent(relatedTarget)))) { (aVisitor.mRelatedTargetIsInAnon =
nsIContent* nonAnon = FindFirstNonAnonContent(aContent); relatedTarget->IsInNativeAnonymousSubtree()))) {
nsIContent* nonAnon = aContent->FindFirstNonNativeAnonymous();
if (nonAnon) { if (nonAnon) {
nsIContent* nonAnonRelated = FindFirstNonAnonContent(relatedTarget); nsIContent* nonAnonRelated =
relatedTarget->FindFirstNonNativeAnonymous();
if (nonAnonRelated) { if (nonAnonRelated) {
if (nonAnon == nonAnonRelated || if (nonAnon == nonAnonRelated ||
nsContentUtils::ContentIsDescendantOf(nonAnonRelated, nonAnon)) { nsContentUtils::ContentIsDescendantOf(nonAnonRelated, nonAnon)) {

Просмотреть файл

@ -237,8 +237,8 @@ nsStyledElement::ParseStyleAttribute(nsIContent* aContent,
if (doc && (aForceInDataDoc || !doc->IsLoadedAsData())) { if (doc && (aForceInDataDoc || !doc->IsLoadedAsData())) {
PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
if (!aContent->IsNativeAnonymous()) { // native anonymous content if (!aContent->IsInNativeAnonymousSubtree()) { // native anonymous content
// always assumes CSS // always assumes CSS
nsAutoString styleType; nsAutoString styleType;
doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType); doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
if (!styleType.IsEmpty()) { if (!styleType.IsEmpty()) {

Просмотреть файл

@ -1468,29 +1468,31 @@ nsEventListenerManager::PrepareToUseCaretPosition(nsIWidget* aEventWidget,
NS_ENSURE_SUCCESS(rv, PR_FALSE); NS_ENSURE_SUCCESS(rv, PR_FALSE);
NS_ENSURE_TRUE(node, PR_FALSE); NS_ENSURE_TRUE(node, PR_FALSE);
nsCOMPtr<nsIContent> content(do_QueryInterface(node)); nsCOMPtr<nsIContent> content(do_QueryInterface(node));
for ( ; content; content = content->GetParent()) { if (content) {
if (!content->IsNativeAnonymous()) { nsIContent* nonNative = content->FindFirstNonNativeAnonymous();
// It seems like selCon->ScrollSelectionIntoView should be enough, but it's content = nonNative;
// not. The problem is that scrolling the selection into view when it is }
// below the current viewport will align the top line of the frame exactly
// with the bottom of the window. This is fine, BUT, the popup event causes if (content) {
// the control to be re-focused which does this exact call to // It seems like selCon->ScrollSelectionIntoView should be enough, but it's
// ScrollContentIntoView, which has a one-pixel disagreement of whether the // not. The problem is that scrolling the selection into view when it is
// frame is actually in view. The result is that the frame is aligned with // below the current viewport will align the top line of the frame exactly
// the top of the window, but the menu is still at the bottom. // with the bottom of the window. This is fine, BUT, the popup event causes
// // the control to be re-focused which does this exact call to
// Doing this call first forces the frame to be in view, eliminating the // ScrollContentIntoView, which has a one-pixel disagreement of whether the
// problem. The only difference in the result is that if your cursor is in // frame is actually in view. The result is that the frame is aligned with
// an edit box below the current view, you'll get the edit box aligned with // the top of the window, but the menu is still at the bottom.
// the top of the window. This is arguably better behavior anyway. //
rv = aShell->ScrollContentIntoView(content, // Doing this call first forces the frame to be in view, eliminating the
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, // problem. The only difference in the result is that if your cursor is in
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE); // an edit box below the current view, you'll get the edit box aligned with
NS_ENSURE_SUCCESS(rv, PR_FALSE); // the top of the window. This is arguably better behavior anyway.
frame = aShell->GetPrimaryFrameFor(content); rv = aShell->ScrollContentIntoView(content,
NS_ASSERTION(frame, "No frame for focused content?"); NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
break; NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
} NS_ENSURE_SUCCESS(rv, PR_FALSE);
frame = aShell->GetPrimaryFrameFor(content);
NS_WARN_IF_FALSE(frame, "No frame for focused content?");
} }
// Actually scroll the selection (ie caret) into view. Note that this must // Actually scroll the selection (ie caret) into view. Note that this must

Просмотреть файл

@ -1280,9 +1280,7 @@ nsBindingManager::WalkRules(nsStyleSet* aStyleSet,
nsIContent* parent = content->GetBindingParent(); nsIContent* parent = content->GetBindingParent();
if (parent == content) { if (parent == content) {
NS_ASSERTION(content->IsNativeAnonymous() || NS_ASSERTION(content->IsNativeAnonymous(), "Unexpected binding parent");
content->IsNodeOfType(nsINode::eXUL),
"Unexpected binding parent");
break; // The anonymous content case is often deliberately hacked to break; // The anonymous content case is often deliberately hacked to
// return itself to cut off style inheritance here. Do that. // return itself to cut off style inheritance here. Do that.

Просмотреть файл

@ -282,24 +282,16 @@ nsFindContentIterator::Reset()
// see if the start node is an anonymous text node inside a text control // see if the start node is an anonymous text node inside a text control
nsCOMPtr<nsIContent> startContent(do_QueryInterface(mStartNode)); nsCOMPtr<nsIContent> startContent(do_QueryInterface(mStartNode));
for ( ; startContent; startContent = startContent->GetParent()) { if (startContent) {
if (!startContent->IsNativeAnonymous() && mStartOuterNode =
(!startContent->GetBindingParent() || do_QueryInterface(startContent->FindFirstNonNativeAnonymous());
!startContent->GetBindingParent()->IsNativeAnonymous())) {
mStartOuterNode = do_QueryInterface(startContent);
break;
}
} }
// see if the end node is an anonymous text node inside a text control // see if the end node is an anonymous text node inside a text control
nsCOMPtr<nsIContent> endContent(do_QueryInterface(mEndNode)); nsCOMPtr<nsIContent> endContent(do_QueryInterface(mEndNode));
for ( ; endContent; endContent = endContent->GetParent()) { if (endContent) {
if (!endContent->IsNativeAnonymous() && mEndOuterNode =
(!endContent->GetBindingParent() || do_QueryInterface(endContent->FindFirstNonNativeAnonymous());
!endContent->GetBindingParent()->IsNativeAnonymous())) {
mEndOuterNode = do_QueryInterface(endContent);
break;
}
} }
// Note: OK to just set up the outer iterator here; if our range has a native // Note: OK to just set up the outer iterator here; if our range has a native

Просмотреть файл

@ -5743,16 +5743,18 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
nsIContent* content = newAnonymousItems[i]; nsIContent* content = newAnonymousItems[i];
NS_ASSERTION(content, "null anonymous content?"); NS_ASSERTION(content, "null anonymous content?");
content->SetNativeAnonymous();
nsIContent* bindingParent = content; nsIContent* bindingParent = content;
#ifdef MOZ_SVG #ifdef MOZ_SVG
// least-surprise CSS binding until we do the SVG specified // least-surprise CSS binding until we do the SVG specified
// cascading rules for <svg:use> - bug 265894 // cascading rules for <svg:use> - bug 265894
if (aParent && if (aParent &&
aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) {
bindingParent = aParent; bindingParent = aParent;
} else
#endif #endif
{
content->SetNativeAnonymous();
}
rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE); rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

Просмотреть файл

@ -509,7 +509,8 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
nsRuleNode* lastPresHintRN = mRuleWalker->GetCurrentNode(); nsRuleNode* lastPresHintRN = mRuleWalker->GetCurrentNode();
mRuleWalker->SetLevel(eUserSheet, PR_FALSE); mRuleWalker->SetLevel(eUserSheet, PR_FALSE);
PRBool skipUserStyles = nsContentUtils::IsNativeAnonymous(aData->mContent); PRBool skipUserStyles =
aData->mContent && aData->mContent->IsInNativeAnonymousSubtree();
if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
(*aCollectorFunc)(mRuleProcessors[eUserSheet], aData); (*aCollectorFunc)(mRuleProcessors[eUserSheet], aData);
nsRuleNode* lastUserRN = mRuleWalker->GetCurrentNode(); nsRuleNode* lastUserRN = mRuleWalker->GetCurrentNode();
@ -573,7 +574,8 @@ nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
if (mRuleProcessors[ePresHintSheet]) if (mRuleProcessors[ePresHintSheet])
(*aFunc)(mRuleProcessors[ePresHintSheet], aData); (*aFunc)(mRuleProcessors[ePresHintSheet], aData);
PRBool skipUserStyles = nsContentUtils::IsNativeAnonymous(aData->mContent); PRBool skipUserStyles =
aData->mContent && aData->mContent->IsInNativeAnonymousSubtree();
if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
(*aFunc)(mRuleProcessors[eUserSheet], aData); (*aFunc)(mRuleProcessors[eUserSheet], aData);

Просмотреть файл

@ -616,7 +616,7 @@ nsBoxFrame::DidReflow(nsPresContext* aPresContext,
PRBool PRBool
nsBoxFrame::HonorPrintBackgroundSettings() nsBoxFrame::HonorPrintBackgroundSettings()
{ {
return (!mContent || !nsContentUtils::IsNativeAnonymous(mContent)) && return (!mContent || !mContent->IsInNativeAnonymousSubtree()) &&
nsContainerFrame::HonorPrintBackgroundSettings(); nsContainerFrame::HonorPrintBackgroundSettings();
} }