OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/css/parser/CSSSelectorParser.h" | 5 #include "core/css/parser/CSSSelectorParser.h" |
6 | 6 |
7 #include "core/css/CSSSelectorList.h" | 7 #include "core/css/CSSSelectorList.h" |
8 #include "core/css/StyleSheetContents.h" | 8 #include "core/css/StyleSheetContents.h" |
9 #include "core/frame/UseCounter.h" | 9 #include "core/frame/UseCounter.h" |
10 #include "platform/RuntimeEnabledFeatures.h" | 10 #include "platform/RuntimeEnabledFeatures.h" |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 end->setRelationIsAffectedByPseudoContent(); | 156 end->setRelationIsAffectedByPseudoContent(); |
157 previousCompoundHasContentPseudo = compoundHasContentPseudo; | 157 previousCompoundHasContentPseudo = compoundHasContentPseudo; |
158 end->setTagHistory(selector.release()); | 158 end->setTagHistory(selector.release()); |
159 | 159 |
160 selector = nextSelector.release(); | 160 selector = nextSelector.release(); |
161 } | 161 } |
162 | 162 |
163 return selector.release(); | 163 return selector.release(); |
164 } | 164 } |
165 | 165 |
| 166 namespace { |
| 167 |
| 168 bool isScrollbarPseudoClass(CSSSelector::PseudoType pseudo) |
| 169 { |
| 170 switch (pseudo) { |
| 171 case CSSSelector::PseudoEnabled: |
| 172 case CSSSelector::PseudoDisabled: |
| 173 case CSSSelector::PseudoHover: |
| 174 case CSSSelector::PseudoActive: |
| 175 case CSSSelector::PseudoHorizontal: |
| 176 case CSSSelector::PseudoVertical: |
| 177 case CSSSelector::PseudoDecrement: |
| 178 case CSSSelector::PseudoIncrement: |
| 179 case CSSSelector::PseudoStart: |
| 180 case CSSSelector::PseudoEnd: |
| 181 case CSSSelector::PseudoDoubleButton: |
| 182 case CSSSelector::PseudoSingleButton: |
| 183 case CSSSelector::PseudoNoButton: |
| 184 case CSSSelector::PseudoCornerPresent: |
| 185 case CSSSelector::PseudoWindowInactive: |
| 186 return true; |
| 187 default: |
| 188 return false; |
| 189 } |
| 190 } |
| 191 |
| 192 bool isUserActionPseudoClass(CSSSelector::PseudoType pseudo) |
| 193 { |
| 194 switch (pseudo) { |
| 195 case CSSSelector::PseudoHover: |
| 196 case CSSSelector::PseudoFocus: |
| 197 case CSSSelector::PseudoActive: |
| 198 return true; |
| 199 default: |
| 200 return false; |
| 201 } |
| 202 } |
| 203 |
| 204 bool isPseudoClassValidAfterPseudoElement(CSSSelector::PseudoType pseudoClass, C
SSSelector::PseudoType compoundPseudoElement) |
| 205 { |
| 206 switch (compoundPseudoElement) { |
| 207 case CSSSelector::PseudoResizer: |
| 208 case CSSSelector::PseudoScrollbar: |
| 209 case CSSSelector::PseudoScrollbarCorner: |
| 210 case CSSSelector::PseudoScrollbarButton: |
| 211 case CSSSelector::PseudoScrollbarThumb: |
| 212 case CSSSelector::PseudoScrollbarTrack: |
| 213 case CSSSelector::PseudoScrollbarTrackPiece: |
| 214 return isScrollbarPseudoClass(pseudoClass); |
| 215 case CSSSelector::PseudoSelection: |
| 216 return pseudoClass == CSSSelector::PseudoWindowInactive; |
| 217 case CSSSelector::PseudoWebKitCustomElement: |
| 218 return isUserActionPseudoClass(pseudoClass); |
| 219 default: |
| 220 return false; |
| 221 } |
| 222 } |
| 223 |
| 224 bool isSimpleSelectorValidAfterPseudoElement(const CSSParserSelector& simpleSele
ctor, CSSSelector::PseudoType compoundPseudoElement) |
| 225 { |
| 226 if (compoundPseudoElement == CSSSelector::PseudoUnknown) |
| 227 return true; |
| 228 if (simpleSelector.match() != CSSSelector::PseudoClass) |
| 229 return false; |
| 230 CSSSelector::PseudoType pseudo = simpleSelector.pseudoType(); |
| 231 if (pseudo == CSSSelector::PseudoNot) { |
| 232 ASSERT(simpleSelector.selectorList()); |
| 233 ASSERT(simpleSelector.selectorList()->first()); |
| 234 ASSERT(!simpleSelector.selectorList()->first()->tagHistory()); |
| 235 pseudo = simpleSelector.selectorList()->first()->pseudoType(); |
| 236 } |
| 237 return isPseudoClassValidAfterPseudoElement(pseudo, compoundPseudoElement); |
| 238 } |
| 239 |
| 240 } // namespace |
| 241 |
166 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSPars
erTokenRange& range) | 242 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSPars
erTokenRange& range) |
167 { | 243 { |
168 OwnPtr<CSSParserSelector> compoundSelector; | 244 OwnPtr<CSSParserSelector> compoundSelector; |
169 | 245 |
170 AtomicString namespacePrefix; | 246 AtomicString namespacePrefix; |
171 AtomicString elementName; | 247 AtomicString elementName; |
| 248 CSSSelector::PseudoType compoundPseudoElement = CSSSelector::PseudoUnknown; |
172 if (!consumeName(range, elementName, namespacePrefix)) { | 249 if (!consumeName(range, elementName, namespacePrefix)) { |
173 compoundSelector = consumeSimpleSelector(range); | 250 compoundSelector = consumeSimpleSelector(range); |
174 if (!compoundSelector) | 251 if (!compoundSelector) |
175 return nullptr; | 252 return nullptr; |
| 253 if (compoundSelector->match() == CSSSelector::PseudoElement) |
| 254 compoundPseudoElement = compoundSelector->pseudoType(); |
176 } | 255 } |
177 if (m_context.isHTMLDocument()) | 256 if (m_context.isHTMLDocument()) |
178 elementName = elementName.lower(); | 257 elementName = elementName.lower(); |
179 | 258 |
180 while (OwnPtr<CSSParserSelector> simpleSelector = consumeSimpleSelector(rang
e)) { | 259 while (OwnPtr<CSSParserSelector> simpleSelector = consumeSimpleSelector(rang
e)) { |
| 260 // TODO(rune@opera.com): crbug.com/578131 |
| 261 // The UASheetMode check is a work-around to allow this selector in medi
aControls(New).css: |
| 262 // video::-webkit-media-text-track-region-container.scrolling |
| 263 if (m_context.mode() != UASheetMode && !isSimpleSelectorValidAfterPseudo
Element(*simpleSelector.get(), compoundPseudoElement)) |
| 264 return nullptr; |
| 265 if (simpleSelector->match() == CSSSelector::PseudoElement) |
| 266 compoundPseudoElement = simpleSelector->pseudoType(); |
| 267 |
181 if (compoundSelector) | 268 if (compoundSelector) |
182 compoundSelector = addSimpleSelectorToCompound(compoundSelector.rele
ase(), simpleSelector.release()); | 269 compoundSelector = addSimpleSelectorToCompound(compoundSelector.rele
ase(), simpleSelector.release()); |
183 else | 270 else |
184 compoundSelector = simpleSelector.release(); | 271 compoundSelector = simpleSelector.release(); |
185 } | 272 } |
186 | 273 |
187 if (!compoundSelector) { | 274 if (!compoundSelector) { |
188 AtomicString namespaceURI = determineNamespace(namespacePrefix); | 275 AtomicString namespaceURI = determineNamespace(namespacePrefix); |
189 if (namespaceURI.isNull()) | 276 if (namespaceURI.isNull()) |
190 return nullptr; | 277 return nullptr; |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 | 715 |
629 if (!splitAfter || !splitAfter->tagHistory()) | 716 if (!splitAfter || !splitAfter->tagHistory()) |
630 return compoundSelector; | 717 return compoundSelector; |
631 | 718 |
632 OwnPtr<CSSParserSelector> secondCompound = splitAfter->releaseTagHistory(); | 719 OwnPtr<CSSParserSelector> secondCompound = splitAfter->releaseTagHistory(); |
633 secondCompound->appendTagHistory(CSSSelector::ShadowPseudo, compoundSelector
); | 720 secondCompound->appendTagHistory(CSSSelector::ShadowPseudo, compoundSelector
); |
634 return secondCompound.release(); | 721 return secondCompound.release(); |
635 } | 722 } |
636 | 723 |
637 } // namespace blink | 724 } // namespace blink |
OLD | NEW |