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();
}
// If we are not supposed to mark visited links as such, be sure to flip the
// bits appropriately.
// If we are not supposed to mark visited links as such, be sure to
// 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 ||
gPrivateBrowsingObserver->InPrivateBrowsing()) &&
(mContentState & NS_EVENT_STATE_VISITED)) {
@ -1138,6 +1140,35 @@ RuleProcessorData::IsLink()
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
RuleProcessorData::GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd,
PRBool aCheckEdgeOnly)
@ -2012,7 +2043,10 @@ static PRBool SelectorMatches(RuleProcessorData &data,
if (aDependence)
*aDependence = PR_TRUE;
} else {
if (!(data.ContentState() & statesToCheck)) {
PRUint32 contentState = data.GetContentStateForVisitedHandling(
aTreeMatchContext.mVisitedHandling,
aNodeMatchContext.mIsRelevantLink);
if (!(contentState & statesToCheck)) {
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 (tag == nsGkAtoms::a) {
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)) {
ruleWalker->Forward(mLinkRule);
ruleWalker->SetHaveRelevantLink();

View file

@ -49,12 +49,12 @@
#include "nsChangeHint.h"
#include "nsIContent.h"
#include "nsCSSPseudoElements.h"
#include "nsRuleWalker.h"
class nsIStyleSheet;
class nsPresContext;
class nsIAtom;
class nsICSSPseudoComparator;
class nsRuleWalker;
class nsAttrValue;
// The implementation of the constructor and destructor are currently in
@ -111,6 +111,10 @@ public:
PRUint32 DocumentState();
PRBool IsLink();
PRUint32 GetContentStateForVisitedHandling(
nsRuleWalker::VisitedHandlingType aVisitedHandling,
PRBool aIsRelevantLink);
// 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),
// returns 0.
@ -154,6 +158,8 @@ private:
// mContentState is initialized lazily.
PRInt32 mContentState; // eventStateMgr->GetContentState() or
// mContent->IntrinsicState() if we have no ESM
// adjusted for not supporting :visited (but with
// visitedness information when we support it)
PRPackedBool mGotContentState;
};