blob: 9d697620a2a0c33d298aab90e93a3ab1da7ef7ff [file] [log] [blame]
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_ELEMENT_RULE_COLLECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_ELEMENT_RULE_COLLECTOR_H_
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/css/pseudo_style_request.h"
#include "third_party/blink/renderer/core/css/resolver/element_resolve_context.h"
#include "third_party/blink/renderer/core/css/resolver/match_request.h"
#include "third_party/blink/renderer/core/css/resolver/match_result.h"
#include "third_party/blink/renderer/core/css/selector_checker.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
class CSSStyleSheet;
class CSSRuleList;
class PartNames;
class RuleData;
class SelectorFilter;
class StaticCSSRuleList;
class StyleRuleUsageTracker;
// TODO(kochi): ShadowV0CascadeOrder is used only for Shadow DOM V0
// bug-compatible cascading order. Once Shadow DOM V0 implementation is gone,
// remove this completely.
using ShadowV0CascadeOrder = unsigned;
const ShadowV0CascadeOrder kIgnoreCascadeOrder = 0;
class MatchedRule {
DISALLOW_NEW();
public:
MatchedRule(const RuleData* rule_data,
unsigned specificity,
ShadowV0CascadeOrder cascade_order,
unsigned style_sheet_index,
const CSSStyleSheet* parent_style_sheet)
: rule_data_(rule_data),
specificity_(specificity),
parent_style_sheet_(parent_style_sheet) {
DCHECK(rule_data_);
static const unsigned kBitsForPositionInRuleData = 18;
static const unsigned kBitsForStyleSheetIndex = 32;
position_ = ((uint64_t)cascade_order
<< (kBitsForStyleSheetIndex + kBitsForPositionInRuleData)) +
((uint64_t)style_sheet_index << kBitsForPositionInRuleData) +
rule_data_->GetPosition();
}
const RuleData* GetRuleData() const { return rule_data_; }
uint64_t GetPosition() const { return position_; }
unsigned Specificity() const {
return GetRuleData()->Specificity() + specificity_;
}
const CSSStyleSheet* ParentStyleSheet() const { return parent_style_sheet_; }
void Trace(blink::Visitor* visitor) {
visitor->Trace(parent_style_sheet_);
visitor->Trace(rule_data_);
}
private:
Member<const RuleData> rule_data_;
unsigned specificity_;
uint64_t position_;
Member<const CSSStyleSheet> parent_style_sheet_;
};
} // namespace blink
WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::MatchedRule);
namespace blink {
using StyleRuleList = HeapVector<Member<StyleRule>>;
// Manages the process of finding what rules in a RuleSet apply to a given
// Element. These tend to be used several times in different contexts and should
// have ClearMatchedRules called before use.
//
// ElementRuleCollector is designed to be used as a stack object.
// Create one, ask what rules the ElementResolveContext matches
// and then let it go out of scope.
// FIXME: Currently it modifies the ComputedStyle but should not!
class ElementRuleCollector {
STACK_ALLOCATED();
public:
ElementRuleCollector(const ElementResolveContext&,
const SelectorFilter&,
ComputedStyle* = nullptr);
~ElementRuleCollector();
void SetMode(SelectorChecker::Mode mode) { mode_ = mode; }
void SetPseudoStyleRequest(const PseudoStyleRequest& request) {
pseudo_style_request_ = request;
}
void SetSameOriginOnly(bool f) { same_origin_only_ = f; }
void SetMatchingUARules(bool matching_ua_rules) {
matching_ua_rules_ = matching_ua_rules;
}
const MatchResult& MatchedResult() const;
StyleRuleList* MatchedStyleRuleList();
CSSRuleList* MatchedCSSRuleList();
void CollectMatchingRules(const MatchRequest&,
ShadowV0CascadeOrder = kIgnoreCascadeOrder,
bool matching_tree_boundary_rules = false);
void CollectMatchingShadowHostRules(
const MatchRequest&,
ShadowV0CascadeOrder = kIgnoreCascadeOrder);
void CollectMatchingPartPseudoRules(
const MatchRequest&,
PartNames&,
ShadowV0CascadeOrder = kIgnoreCascadeOrder);
void SortAndTransferMatchedRules();
void ClearMatchedRules();
void AddElementStyleProperties(const CSSPropertyValueSet*,
bool is_cacheable = true);
void FinishAddingUARules() { result_.FinishAddingUARules(); }
void FinishAddingUserRules() {
result_.FinishAddingUserRules();
}
void FinishAddingAuthorRulesForTreeScope() {
result_.FinishAddingAuthorRulesForTreeScope();
}
void SetIncludeEmptyRules(bool include) { include_empty_rules_ = include; }
bool IncludeEmptyRules() const { return include_empty_rules_; }
bool IsCollectingForPseudoElement() const {
return pseudo_style_request_.pseudo_id != kPseudoIdNone;
}
void AddMatchedRulesToTracker(StyleRuleUsageTracker*) const;
private:
template <typename RuleDataListType>
void CollectMatchingRulesForList(const RuleDataListType*,
ShadowV0CascadeOrder,
const MatchRequest&,
PartNames* = nullptr);
void DidMatchRule(const RuleData*,
const SelectorChecker::MatchResult&,
ShadowV0CascadeOrder,
const MatchRequest&);
template <class CSSRuleCollection>
CSSRule* FindStyleRule(CSSRuleCollection*, StyleRule*);
void AppendCSSOMWrapperForRule(CSSStyleSheet*, StyleRule*);
void SortMatchedRules();
StaticCSSRuleList* EnsureRuleList();
StyleRuleList* EnsureStyleRuleList();
private:
const ElementResolveContext& context_;
const SelectorFilter& selector_filter_;
scoped_refptr<ComputedStyle>
style_; // FIXME: This can be mutated during matching!
PseudoStyleRequest pseudo_style_request_;
SelectorChecker::Mode mode_;
bool can_use_fast_reject_;
bool same_origin_only_;
bool matching_ua_rules_;
bool include_empty_rules_;
HeapVector<MatchedRule, 32> matched_rules_;
// Output.
Member<StaticCSSRuleList> css_rule_list_;
Member<StyleRuleList> style_rule_list_;
MatchResult result_;
DISALLOW_COPY_AND_ASSIGN(ElementRuleCollector);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_ELEMENT_RULE_COLLECTOR_H_