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

This commit is contained in:
Olli.Pettay@helsinki.fi 2008-02-26 04:40:18 -08:00
parent bba9529cf7
commit 67622f2077
13 changed files with 99 additions and 113 deletions

View File

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

View File

@ -1128,12 +1128,6 @@ public:
nsIURI *aLinkURI, const nsString& aTargetSpec,
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.
*/

View File

@ -62,8 +62,8 @@ class nsIDocShell;
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0xfba9aa39, 0x016e, 0x4d5d, \
{ 0xab, 0x62, 0x22, 0xa1, 0xb8, 0x4a, 0x3c, 0x7b } }
{ 0xd3434698, 0x3a16, 0x4dbe, \
{ 0x9d, 0xed, 0xbe, 0x64, 0x16, 0x1a, 0xa3, 0x52 } }
/**
* A node of content in a document's content model. This interface
@ -160,6 +160,17 @@ public:
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
* @return the namespace

View File

@ -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 */
nsIWidget*
nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget)

View File

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

View File

@ -427,6 +427,37 @@ nsIContent::UpdateEditableState()
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()
@ -2073,12 +2104,12 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
NS_PRECONDITION(!aParent || !aDocument ||
!aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
"Parent in document but flagged as forcing XBL");
// XXXbz XUL's SetNativeAnonymous is all weird, so can't assert
// anything here
NS_PRECONDITION(IsNodeOfType(eXUL) ||
aBindingParent != this || IsNativeAnonymous(),
NS_PRECONDITION(aBindingParent != this || IsNativeAnonymous(),
"Only native anonymous content should have itself as its "
"own binding parent");
NS_PRECONDITION(!IsNativeAnonymous() || aBindingParent == this,
"Native anonymous content must have itself as its "
"own binding parent");
if (!aBindingParent && aParent) {
aBindingParent = aParent->GetBindingParent();
@ -2272,24 +2303,6 @@ nsGenericElement::PreHandleEvent(nsEventChainPreVisitor& 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
nsGenericElement::doPreHandleEvent(nsIContent* aContent,
nsEventChainPreVisitor& aVisitor)
@ -2315,10 +2328,12 @@ nsGenericElement::doPreHandleEvent(nsIContent* aContent,
// must be updated.
if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon ||
(aVisitor.mEvent->originalTarget == aContent &&
(aVisitor.mRelatedTargetIsInAnon = IsInAnonContent(relatedTarget)))) {
nsIContent* nonAnon = FindFirstNonAnonContent(aContent);
(aVisitor.mRelatedTargetIsInAnon =
relatedTarget->IsInNativeAnonymousSubtree()))) {
nsIContent* nonAnon = aContent->FindFirstNonNativeAnonymous();
if (nonAnon) {
nsIContent* nonAnonRelated = FindFirstNonAnonContent(relatedTarget);
nsIContent* nonAnonRelated =
relatedTarget->FindFirstNonNativeAnonymous();
if (nonAnonRelated) {
if (nonAnon == nonAnonRelated ||
nsContentUtils::ContentIsDescendantOf(nonAnonRelated, nonAnon)) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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