Add method to munge the content state appropriately for how we're matching so that matching operations in HTML and CSS style sheets follow the new rules. (Bug 147777) r=bzbarsky

This commit is contained in:
L. David Baron 2010-04-02 18:58:27 -07:00
parent 77b2baaacc
commit 3a0a941202
3 changed files with 49 additions and 5 deletions

View file

@ -1113,8 +1113,10 @@ RuleProcessorData::ContentState()
mContentState = mContent->IntrinsicState(); mContentState = mContent->IntrinsicState();
} }
// If we are not supposed to mark visited links as such, be sure to flip the // If we are not supposed to mark visited links as such, be sure to
// bits appropriately. // flip the bits appropriately. We want to do this here, rather
// than in GetContentStateForVisitedHandling, so that we don't
// expose that :visited support is disabled to the Web page.
if ((!gSupportVisitedPseudo || if ((!gSupportVisitedPseudo ||
gPrivateBrowsingObserver->InPrivateBrowsing()) && gPrivateBrowsingObserver->InPrivateBrowsing()) &&
(mContentState & NS_EVENT_STATE_VISITED)) { (mContentState & NS_EVENT_STATE_VISITED)) {
@ -1138,6 +1140,35 @@ RuleProcessorData::IsLink()
return (state & (NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) != 0; return (state & (NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) != 0;
} }
PRUint32
RuleProcessorData::GetContentStateForVisitedHandling(
nsRuleWalker::VisitedHandlingType aVisitedHandling,
PRBool aIsRelevantLink)
{
PRUint32 contentState = ContentState();
if (contentState & (NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) {
NS_ABORT_IF_FALSE(IsLink(), "IsLink() should match state");
contentState &=
~PRUint32(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED);
if (aIsRelevantLink) {
switch (aVisitedHandling) {
case nsRuleWalker::eRelevantLinkUnvisited:
contentState |= NS_EVENT_STATE_UNVISITED;
break;
case nsRuleWalker::eRelevantLinkVisited:
contentState |= NS_EVENT_STATE_VISITED;
break;
case nsRuleWalker::eLinksVisitedOrUnvisited:
contentState |= NS_EVENT_STATE_UNVISITED | NS_EVENT_STATE_VISITED;
break;
}
} else {
contentState |= NS_EVENT_STATE_UNVISITED;
}
}
return contentState;
}
PRInt32 PRInt32
RuleProcessorData::GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd, RuleProcessorData::GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd,
PRBool aCheckEdgeOnly) PRBool aCheckEdgeOnly)
@ -2012,7 +2043,10 @@ static PRBool SelectorMatches(RuleProcessorData &data,
if (aDependence) if (aDependence)
*aDependence = PR_TRUE; *aDependence = PR_TRUE;
} else { } else {
if (!(data.ContentState() & statesToCheck)) { PRUint32 contentState = data.GetContentStateForVisitedHandling(
aTreeMatchContext.mVisitedHandling,
aNodeMatchContext.mIsRelevantLink);
if (!(contentState & statesToCheck)) {
return PR_FALSE; return PR_FALSE;
} }
} }

View file

@ -238,7 +238,11 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
// if we have anchor colors, check if this is an anchor with an href // if we have anchor colors, check if this is an anchor with an href
if (tag == nsGkAtoms::a) { if (tag == nsGkAtoms::a) {
if (mLinkRule || mVisitedRule || mActiveRule) { if (mLinkRule || mVisitedRule || mActiveRule) {
PRUint32 state = aData->ContentState(); PRUint32 state = aData->GetContentStateForVisitedHandling(
ruleWalker->VisitedHandling(),
// If the node being matched is a link,
// it's the relevant link.
aData->IsLink());
if (mLinkRule && (state & NS_EVENT_STATE_UNVISITED)) { if (mLinkRule && (state & NS_EVENT_STATE_UNVISITED)) {
ruleWalker->Forward(mLinkRule); ruleWalker->Forward(mLinkRule);
ruleWalker->SetHaveRelevantLink(); ruleWalker->SetHaveRelevantLink();

View file

@ -49,12 +49,12 @@
#include "nsChangeHint.h" #include "nsChangeHint.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsCSSPseudoElements.h" #include "nsCSSPseudoElements.h"
#include "nsRuleWalker.h"
class nsIStyleSheet; class nsIStyleSheet;
class nsPresContext; class nsPresContext;
class nsIAtom; class nsIAtom;
class nsICSSPseudoComparator; class nsICSSPseudoComparator;
class nsRuleWalker;
class nsAttrValue; class nsAttrValue;
// The implementation of the constructor and destructor are currently in // The implementation of the constructor and destructor are currently in
@ -111,6 +111,10 @@ public:
PRUint32 DocumentState(); PRUint32 DocumentState();
PRBool IsLink(); PRBool IsLink();
PRUint32 GetContentStateForVisitedHandling(
nsRuleWalker::VisitedHandlingType aVisitedHandling,
PRBool aIsRelevantLink);
// Returns a 1-based index of the child in its parent. If the child // Returns a 1-based index of the child in its parent. If the child
// is not in its parent's child list (i.e., it is anonymous content), // is not in its parent's child list (i.e., it is anonymous content),
// returns 0. // returns 0.
@ -154,6 +158,8 @@ private:
// mContentState is initialized lazily. // mContentState is initialized lazily.
PRInt32 mContentState; // eventStateMgr->GetContentState() or PRInt32 mContentState; // eventStateMgr->GetContentState() or
// mContent->IntrinsicState() if we have no ESM // mContent->IntrinsicState() if we have no ESM
// adjusted for not supporting :visited (but with
// visitedness information when we support it)
PRPackedBool mGotContentState; PRPackedBool mGotContentState;
}; };