Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: sky/engine/core/css/SelectorChecker.cpp

Issue 801283006: Get rid of SelectorCheckingContext. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: missing static. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/engine/core/css/SelectorChecker.h ('k') | sky/engine/core/dom/SelectorQuery.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
(...skipping 10 matching lines...) Expand all
21 * 21 *
22 * You should have received a copy of the GNU Library General Public License 22 * You should have received a copy of the GNU Library General Public License
23 * along with this library; see the file COPYING.LIB. If not, write to 23 * along with this library; see the file COPYING.LIB. If not, write to
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA. 25 * Boston, MA 02110-1301, USA.
26 */ 26 */
27 27
28 #include "sky/engine/config.h" 28 #include "sky/engine/config.h"
29 #include "sky/engine/core/css/SelectorChecker.h" 29 #include "sky/engine/core/css/SelectorChecker.h"
30 30
31 #include "sky/engine/core/css/CSSSelector.h"
31 #include "sky/engine/core/css/CSSSelectorList.h" 32 #include "sky/engine/core/css/CSSSelectorList.h"
32 #include "sky/engine/core/dom/Document.h" 33 #include "sky/engine/core/dom/Document.h"
33 #include "sky/engine/core/dom/shadow/ShadowRoot.h" 34 #include "sky/engine/core/dom/shadow/ShadowRoot.h"
34 #include "sky/engine/core/editing/FrameSelection.h" 35 #include "sky/engine/core/editing/FrameSelection.h"
35 #include "sky/engine/core/frame/LocalFrame.h" 36 #include "sky/engine/core/frame/LocalFrame.h"
36 #include "sky/engine/core/html/parser/HTMLParserIdioms.h" 37 #include "sky/engine/core/html/parser/HTMLParserIdioms.h"
37 #include "sky/engine/core/page/FocusController.h" 38 #include "sky/engine/core/page/FocusController.h"
38 #include "sky/engine/core/rendering/style/RenderStyle.h" 39 #include "sky/engine/core/rendering/style/RenderStyle.h"
39 40
40 namespace blink { 41 namespace blink {
41 42
42 SelectorChecker::SelectorChecker() 43 static bool matchesFocusPseudoClass(const Element& element)
43 : m_matchedAttributeSelector(false) 44 {
45 if (!element.focused())
46 return false;
47 LocalFrame* frame = element.document().frame();
48 if (!frame)
49 return false;
50 if (!frame->selection().isFocusedAndActive())
51 return false;
52 return true;
53 }
54
55 SelectorChecker::SelectorChecker(const Element& element)
56 : m_element(element)
57 , m_matchedAttributeSelector(false)
44 , m_matchedFocusSelector(false) 58 , m_matchedFocusSelector(false)
45 , m_matchedHoverSelector(false) 59 , m_matchedHoverSelector(false)
46 , m_matchedActiveSelector(false) 60 , m_matchedActiveSelector(false)
47 { 61 {
48 } 62 }
49 63
50 static bool scopeContainsLastMatchedElement(const SelectorChecker::SelectorCheck ingContext& context) 64 bool SelectorChecker::match(const CSSSelector& selector, const ContainerNode* sc ope)
51 { 65 {
52 if (!context.scope) 66 bool isShadowHost = isHostInItsShadowTree(m_element, scope);
53 return true;
54 67
55 ASSERT(context.scope); 68 const CSSSelector* current = &selector;
56 if (context.scope->treeScope() == context.element->treeScope())
57 return true;
58
59 // Because Blink treats a shadow host's TreeScope as a separate one from its descendent shadow roots,
60 // if the last matched element is a shadow host, the condition above isn't m et, even though it
61 // should be.
62 return context.element == context.scope->shadowHost();
63 }
64
65 bool SelectorChecker::match(const SelectorCheckingContext& context)
66 {
67 // FIXME(sky): Get rid of SelectorCheckingContext.
68 SelectorCheckingContext matchContext(context);
69
70 bool isShadowHost = isHostInItsShadowTree(*context.element, context.scope);
71
72 while (true) { 69 while (true) {
73 const CSSSelector& selector = *matchContext.selector; 70 // Only :host should match the host:
74 // Only :host and :host-context() should match the host:
75 // http://drafts.csswg.org/css-scoping/#host-element 71 // http://drafts.csswg.org/css-scoping/#host-element
76 if (isShadowHost && !selector.isHostPseudoClass()) 72 if (isShadowHost && !current->isHostPseudoClass())
77 return false; 73 return false;
78 if (!checkOne(matchContext)) 74 if (!checkOne(*current, scope))
79 return false; 75 return false;
80 if (selector.isLastInTagHistory()) 76 if (current->isLastInTagHistory()) {
81 return scopeContainsLastMatchedElement(matchContext); 77 // Only rules in the same scope, or from :host can match.
82 matchContext.selector = selector.tagHistory(); 78 return !scope ||
79 scope->treeScope() == m_element.treeScope() ||
80 m_element == scope->shadowHost();
81 }
82 current = current->tagHistory();
83 } 83 }
84 84
85 ASSERT_NOT_REACHED(); 85 ASSERT_NOT_REACHED();
86 return false; 86 return false;
87 } 87 }
88 88
89 template<typename CharType> 89 template<typename CharType>
90 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned le ngth) 90 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned le ngth)
91 { 91 {
92 for (unsigned i = 0; i < length; ++i) 92 for (unsigned i = 0; i < length; ++i)
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 if (!attributeItem.matches(selectorAttr)) 182 if (!attributeItem.matches(selectorAttr))
183 continue; 183 continue;
184 184
185 if (attributeValueMatches(attributeItem, match, selectorValue, !caseInse nsitive)) 185 if (attributeValueMatches(attributeItem, match, selectorValue, !caseInse nsitive))
186 return true; 186 return true;
187 } 187 }
188 188
189 return false; 189 return false;
190 } 190 }
191 191
192 bool SelectorChecker::checkOne(const SelectorCheckingContext& context) 192 bool SelectorChecker::checkOne(const CSSSelector& selector, const ContainerNode* scope)
193 { 193 {
194 ASSERT(context.element);
195 const Element& element = *context.element;
196 ASSERT(context.selector);
197 const CSSSelector& selector = *context.selector;
198
199 switch (selector.match()) { 194 switch (selector.match()) {
200 case CSSSelector::Tag: 195 case CSSSelector::Tag:
201 return tagMatches(element, selector.tagQName()); 196 {
197 const AtomicString& localName = selector.tagQName().localName();
198 return localName == starAtom || localName == m_element.localName();
199 }
202 case CSSSelector::Class: 200 case CSSSelector::Class:
203 return element.hasClass() && element.classNames().contains(selector.valu e()); 201 return m_element.hasClass() && m_element.classNames().contains(selector. value());
204 case CSSSelector::Id: 202 case CSSSelector::Id:
205 return element.hasID() && element.idForStyleResolution() == selector.val ue(); 203 return m_element.hasID() && m_element.idForStyleResolution() == selector .value();
206 case CSSSelector::Exact: 204 case CSSSelector::Exact:
207 case CSSSelector::Set: 205 case CSSSelector::Set:
208 case CSSSelector::Hyphen: 206 case CSSSelector::Hyphen:
209 case CSSSelector::List: 207 case CSSSelector::List:
210 case CSSSelector::Contain: 208 case CSSSelector::Contain:
211 case CSSSelector::Begin: 209 case CSSSelector::Begin:
212 case CSSSelector::End: 210 case CSSSelector::End:
213 if (anyAttributeMatches(element, selector.match(), selector)) { 211 if (anyAttributeMatches(m_element, selector.match(), selector)) {
214 m_matchedAttributeSelector = true; 212 m_matchedAttributeSelector = true;
215 return true; 213 return true;
216 } 214 }
217 return false; 215 return false;
218 case CSSSelector::PseudoClass: 216 case CSSSelector::PseudoClass:
219 return checkPseudoClass(context); 217 return checkPseudoClass(selector, scope);
220 // FIXME(sky): Remove pseudo elements completely. 218 // FIXME(sky): Remove pseudo elements completely.
221 case CSSSelector::PseudoElement: 219 case CSSSelector::PseudoElement:
222 case CSSSelector::Unknown: 220 case CSSSelector::Unknown:
223 return false; 221 return false;
224 } 222 }
225 ASSERT_NOT_REACHED(); 223 ASSERT_NOT_REACHED();
226 return false; 224 return false;
227 } 225 }
228 226
229 bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context) 227 bool SelectorChecker::checkPseudoClass(const CSSSelector& selector, const Contai nerNode* scope)
230 { 228 {
231 ASSERT(context.element);
232 const Element& element = *context.element;
233 ASSERT(context.selector);
234 const CSSSelector& selector = *context.selector;
235 ASSERT(selector.match() == CSSSelector::PseudoClass);
236
237 // Normal element pseudo class checking.
238 switch (selector.pseudoType()) { 229 switch (selector.pseudoType()) {
239 case CSSSelector::PseudoFocus: 230 case CSSSelector::PseudoFocus:
240 m_matchedFocusSelector = true; 231 m_matchedFocusSelector = true;
241 return matchesFocusPseudoClass(element); 232 return matchesFocusPseudoClass(m_element);
242 233
243 case CSSSelector::PseudoHover: 234 case CSSSelector::PseudoHover:
244 m_matchedHoverSelector = true; 235 m_matchedHoverSelector = true;
245 return element.hovered(); 236 return m_element.hovered();
246 237
247 case CSSSelector::PseudoActive: 238 case CSSSelector::PseudoActive:
248 m_matchedActiveSelector = true; 239 m_matchedActiveSelector = true;
249 return element.active(); 240 return m_element.active();
250 241
251 case CSSSelector::PseudoLang: 242 case CSSSelector::PseudoLang:
252 { 243 {
253 AtomicString value = element.computeInheritedLanguage(); 244 AtomicString value = m_element.computeInheritedLanguage();
254 const AtomicString& argument = selector.argument(); 245 const AtomicString& argument = selector.argument();
255 if (value.isEmpty() || !value.startsWith(argument, false)) 246 if (value.isEmpty() || !value.startsWith(argument, false))
256 break; 247 break;
257 if (value.length() != argument.length() && value[argument.length()] != '-') 248 if (value.length() != argument.length() && value[argument.length()] != '-')
258 break; 249 break;
259 return true; 250 return true;
260 } 251 }
261 252
262 case CSSSelector::PseudoUnresolved: 253 case CSSSelector::PseudoUnresolved:
263 return element.isUnresolvedCustomElement(); 254 return m_element.isUnresolvedCustomElement();
264 255
265 case CSSSelector::PseudoHost: 256 case CSSSelector::PseudoHost:
266 { 257 {
267 // :host only matches a shadow host when :host is in a shadow tree o f the shadow host. 258 const ContainerNode* shadowHost = scope->shadowHost();
268 if (!context.scope) 259 if (!shadowHost || shadowHost != m_element)
269 return false; 260 return false;
270 const ContainerNode* shadowHost = context.scope->shadowHost();
271 if (!shadowHost || shadowHost != element)
272 return false;
273 ASSERT(element.shadow());
274 261
275 // For empty parameter case, i.e. just :host or :host(). 262 // For empty parameter case, i.e. just :host or :host().
276 if (!selector.selectorList()) 263 if (!selector.selectorList())
277 return true; 264 return true;
278 265
279 SelectorCheckingContext subContext(context);
280
281 // Treat the inside of :host() rules as if they were defined in the 266 // Treat the inside of :host() rules as if they were defined in the
282 // same scope as the host. 267 // same scope as the host.
283 subContext.scope = &context.element->treeScope().rootNode(); 268 const ContainerNode& scope = m_element.treeScope().rootNode();
284 269
285 for (subContext.selector = selector.selectorList()->first(); subCont ext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { 270 for (const CSSSelector* current = selector.selectorList()->first(); current; current = CSSSelectorList::next(*current)) {
286 if (match(subContext)) 271 if (match(*current, &scope))
287 return true; 272 return true;
288 } 273 }
289 return false; 274 return false;
290 } 275 }
291 276
292 case CSSSelector::PseudoUnknown: 277 case CSSSelector::PseudoUnknown:
293 case CSSSelector::PseudoNotParsed: 278 case CSSSelector::PseudoNotParsed:
294 case CSSSelector::PseudoUserAgentCustomElement: 279 case CSSSelector::PseudoUserAgentCustomElement:
295 return false; 280 return false;
296 } 281 }
297 ASSERT_NOT_REACHED(); 282 ASSERT_NOT_REACHED();
298 return false; 283 return false;
299 } 284 }
300 285
301 bool SelectorChecker::matchesFocusPseudoClass(const Element& element)
302 {
303 if (!element.focused())
304 return false;
305 LocalFrame* frame = element.document().frame();
306 if (!frame)
307 return false;
308 if (!frame->selection().isFocusedAndActive())
309 return false;
310 return true;
311 } 286 }
312
313 }
OLDNEW
« no previous file with comments | « sky/engine/core/css/SelectorChecker.h ('k') | sky/engine/core/dom/SelectorQuery.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698