static AtomicString familyNameFromSettings(const GenericFontFamilySettings& settings, const FontDescription& fontDescription, const AtomicString& genericFamilyName) { UScriptCode script = fontDescription.script(); #if OS(ANDROID) if (fontDescription.genericFamily() == FontDescription::StandardFamily) return FontCache::getGenericFamilyNameForScript(FontFamilyNames::webkit_standard, script); if (genericFamilyName.startsWith("-webkit-")) return FontCache::getGenericFamilyNameForScript(genericFamilyName, script); #else if (fontDescription.genericFamily() == FontDescription::StandardFamily) return settings.standard(script); if (genericFamilyName == FontFamilyNames::webkit_serif) return settings.serif(script); if (genericFamilyName == FontFamilyNames::webkit_sans_serif) return settings.sansSerif(script); if (genericFamilyName == FontFamilyNames::webkit_cursive) return settings.cursive(script); if (genericFamilyName == FontFamilyNames::webkit_fantasy) return settings.fantasy(script); if (genericFamilyName == FontFamilyNames::webkit_monospace) return settings.fixed(script); if (genericFamilyName == FontFamilyNames::webkit_pictograph) return settings.pictograph(script); if (genericFamilyName == FontFamilyNames::webkit_standard) return settings.standard(script); #endif return emptyAtom; }
bool elementPatternIndicatesHexadecimal(const HTMLInputElement* inputElement) { if (!inputElement) return false; if (inputElement->fastHasAttribute(HTMLNames::patternAttr)) { AtomicString patternAttribute = inputElement->fastGetAttribute(HTMLNames::patternAttr); if (patternAttribute.startsWith("[0-9a-fA-F]")) { // The pattern is for hexadecimal, make sure nothing else is permitted. // Check if it was an exact match. if (patternAttribute.length() == 11) return true; // Is the regex specifying a character count? if (patternAttribute[11] != '{' || !patternAttribute.endsWith("}")) return false; int count = 0; // Make sure the number in the regex is actually a number. if ((sscanf(patternAttribute.string().latin1().data(), "[0-9a-fA-F]{%d}\0", &count) == 1) && count > 0) return true; } } return false; }
CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) { if (name.isNull()) return PseudoUnknown; HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseudoTypeMap(); HashMap<AtomicStringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoType->find(name.impl()); if (slot != nameToPseudoType->end()) return slot->value; if (name.startsWith("-webkit-")) return PseudoWebKitCustomElement; if (name.startsWith("x-") || name.startsWith("cue")) return PseudoUserAgentCustomElement; return PseudoUnknown; }
CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name, bool hasArguments) { PseudoType pseudoType = nameToPseudoType(name, hasArguments); if (pseudoType != PseudoUnknown) return pseudoType; if (name.startsWith("-webkit-")) return PseudoWebKitCustomElement; return PseudoUnknown; }
static inline bool shouldUpdateHeaderAfterRevalidation(const AtomicString& header) { for (size_t i = 0; i < WTF_ARRAY_LENGTH(headersToIgnoreAfterRevalidation); i++) { if (equalIgnoringCase(header, headersToIgnoreAfterRevalidation[i])) return false; } for (size_t i = 0; i < WTF_ARRAY_LENGTH(headerPrefixesToIgnoreAfterRevalidation); i++) { if (header.startsWith(headerPrefixesToIgnoreAfterRevalidation[i], TextCaseInsensitive)) return false; } return true; }
bool SelectorChecker::checkPseudoClass(const CSSSelector& selector) { switch (selector.pseudoType()) { case CSSSelector::PseudoFocus: m_matchedFocusSelector = true; return matchesFocusPseudoClass(m_element); case CSSSelector::PseudoHover: m_matchedHoverSelector = true; return m_element.hovered(); case CSSSelector::PseudoActive: m_matchedActiveSelector = true; return m_element.active(); case CSSSelector::PseudoLang: { AtomicString value = m_element.computeInheritedLanguage(); const AtomicString& argument = selector.argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') break; return true; } case CSSSelector::PseudoHost: { // We can only get here if the selector was defined in the right // scope so we don't need to check it. // For empty parameter case, i.e. just :host or :host(). if (!selector.selectorList()) return true; for (const CSSSelector* current = selector.selectorList()->first(); current; current = CSSSelectorList::next(*current)) { if (match(*current)) return true; } return false; } case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: case CSSSelector::PseudoUserAgentCustomElement: return false; } ASSERT_NOT_REACHED(); return false; }
static String getFamilyNameStringFromFamily(const AtomicString& family) { // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into // the fallback name (like "monospace") that fontconfig understands. if (family.length() && !family.startsWith("-webkit-")) return family.string(); if (family == standardFamily || family == serifFamily) return "serif"; if (family == sansSerifFamily) return "sans-serif"; if (family == monospaceFamily) return "monospace"; if (family == cursiveFamily) return "cursive"; if (family == fantasyFamily) return "fantasy"; return ""; }
// For font families where any of the fonts don't have a valid entry in the OS/2 table // for avgCharWidth, fallback to the legacy webkit behavior of getting the avgCharWidth // from the width of a '0'. This only seems to apply to a fixed number of Mac fonts, // but, in order to get similar rendering across platforms, we do this check for // all platforms. bool RenderTextControl::hasValidAvgCharWidth(AtomicString family) { if (family.isEmpty()) return false; // Internal fonts on OS X also have an invalid entry in the table for avgCharWidth. // They are hidden by having a name that begins with a period, so simply search // for that here rather than try to keep the list up to date. if (family.startsWith('.')) return false; static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0; if (!fontFamiliesWithInvalidCharWidthMap) { fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>; for (size_t i = 0; i < WTF_ARRAY_LENGTH(fontFamiliesWithInvalidCharWidth); ++i) fontFamiliesWithInvalidCharWidthMap->add(AtomicString(fontFamiliesWithInvalidCharWidth[i])); } return !fontFamiliesWithInvalidCharWidthMap->contains(family); }
PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName) { if (m_fontFaces.isEmpty()) { if (familyName.startsWith("-webkit-")) return fontDataForGenericFamily(m_document, fontDescription, familyName); if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont()) return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard"); return 0; } CSSSegmentedFontFace* face = getFontFace(fontDescription, familyName); // If no face was found, then return 0 and let the OS come up with its best match for the name. if (!face) { // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our // settings. if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont()) return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard"); return fontDataForGenericFamily(m_document, fontDescription, familyName); } // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over. return face->getFontData(fontDescription); }
void MixedContentChecker::checkMixedPrivatePublic( LocalFrame* frame, const AtomicString& resourceIPAddress) { if (!frame || !frame->document() || !frame->document()->loader()) return; // Just count these for the moment, don't block them. if (NetworkUtils::isReservedIPAddress(resourceIPAddress) && frame->document()->addressSpace() == WebAddressSpacePublic) { UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHostnameInPublicHostname); // We can simplify the IP checks here, as we've already verified that // |resourceIPAddress| is a reserved IP address, which means it's also a // valid IP address in a normalized form. if (resourceIPAddress.startsWith("127.0.0.") || resourceIPAddress == "[::1]") { UseCounter::count(frame->document(), frame->document()->isSecureContext() ? UseCounter::LoopbackEmbeddedInSecureContext : UseCounter::LoopbackEmbeddedInNonSecureContext); } } }
static String getFamilyNameStringFromFontDescriptionAndFamily(const FontDescription& fontDescription, const AtomicString& family) { // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into // the fallback name (like "monospace") that fontconfig understands. if (family.length() && !family.startsWith("-webkit-")) return family.string(); switch (fontDescription.genericFamily()) { case FontDescription::StandardFamily: case FontDescription::SerifFamily: return "serif"; case FontDescription::SansSerifFamily: return "sans-serif"; case FontDescription::MonospaceFamily: return "monospace"; case FontDescription::CursiveFamily: return "cursive"; case FontDescription::FantasyFamily: return "fantasy"; case FontDescription::NoFamily: default: return ""; } }
bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context) const { ASSERT(context.element); Element& element = *context.element; ASSERT(context.selector); const CSSSelector& selector = *context.selector; ASSERT(selector.match() == CSSSelector::PseudoClass); // Normal element pseudo class checking. switch (selector.pseudoType()) { case CSSSelector::PseudoFocus: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByFocus(); } return matchesFocusPseudoClass(element); case CSSSelector::PseudoHover: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByHover(); } return element.hovered(); case CSSSelector::PseudoActive: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByActive(); } return element.active(); case CSSSelector::PseudoLang: { AtomicString value = element.computeInheritedLanguage(); const AtomicString& argument = selector.argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') break; return true; } case CSSSelector::PseudoUnresolved: return element.isUnresolvedCustomElement(); case CSSSelector::PseudoHost: { if (m_mode == SharingRules) return true; // :host only matches a shadow host when :host is in a shadow tree of the shadow host. if (!context.scope) return false; const ContainerNode* shadowHost = context.scope->shadowHost(); if (!shadowHost || shadowHost != element) return false; ASSERT(element.shadow()); // For empty parameter case, i.e. just :host or :host(). if (!selector.selectorList()) return true; SelectorCheckingContext subContext(context); subContext.contextFlags = TreatShadowHostAsNormalScope; for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { if (match(subContext)) return true; } return false; } case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: case CSSSelector::PseudoUserAgentCustomElement: return false; } ASSERT_NOT_REACHED(); return false; }
PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName) { if (m_fontFaces.isEmpty()) { if (familyName.startsWith("-webkit-")) return fontDataForGenericFamily(m_document, fontDescription, familyName); if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont()) return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard"); return 0; } String family = familyName.string(); Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family); // If no face was found, then return 0 and let the OS come up with its best match for the name. if (!familyFontFaces || familyFontFaces->isEmpty()) { // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our // settings. if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont()) return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard"); return fontDataForGenericFamily(m_document, fontDescription, familyName); } OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFaceCache = m_fonts.add(family, nullptr).iterator->value; if (!segmentedFontFaceCache) segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >); FontTraitsMask traitsMask = fontDescription.traitsMask(); RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).iterator->value; if (!face) { face = CSSSegmentedFontFace::create(this); // Collect all matching faces and sort them in order of preference. Vector<CSSFontFace*, 32> candidateFontFaces; for (int i = familyFontFaces->size() - 1; i >= 0; --i) { CSSFontFace* candidate = familyFontFaces->at(i).get(); unsigned candidateTraitsMask = candidate->traitsMask(); if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) continue; if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) continue; #if ENABLE(SVG_FONTS) // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable // of small-caps synthesis and just ignore the font face as a candidate. if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask)) continue; #endif candidateFontFaces.append(candidate); } if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) { unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size(); for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) { CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get(); unsigned candidateTraitsMask = candidate->traitsMask(); if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) continue; if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) continue; candidateFontFaces.append(candidate); } } desiredTraitsMaskForComparison = traitsMask; stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces); unsigned numCandidates = candidateFontFaces.size(); for (unsigned i = 0; i < numCandidates; ++i) face->appendFontFace(candidateFontFaces[i]); } // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over. return face->getFontData(fontDescription); }
String HTMLImageLoader::sourceURI(const AtomicString& attr) const { #if ENABLE(DASHBOARD_SUPPORT) Settings* settings = client()->sourceElement()->document()->settings(); if (settings && settings->usesDashboardBackwardCompatibilityMode() && attr.length() > 7 && attr.startsWith("url(\"") && attr.endsWith("\")")) return attr.string().substring(5, attr.length() - 7); #endif return stripLeadingAndTrailingHTMLSpaces(attr); }
bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const { Element* const & element = context.element; const CSSSelector* const & selector = context.selector; ASSERT(element); ASSERT(selector); if (selector->m_match == CSSSelector::Tag) return SelectorChecker::tagMatches(element, selector->tagQName()); if (selector->m_match == CSSSelector::Class) return element->hasClass() && element->classNames().contains(selector->value()); if (selector->m_match == CSSSelector::Id) return element->hasID() && element->idForStyleResolution() == selector->value(); if (selector->isAttributeSelector()) { const QualifiedName& attr = selector->attribute(); if (!element->hasAttributes()) return false; bool caseSensitive = !m_documentIsHTML || HTMLDocument::isCaseSensitiveAttribute(attr); if (!anyAttributeMatches(element, static_cast<CSSSelector::Match>(selector->m_match), attr, selector->value(), caseSensitive)) return false; } if (selector->m_match == CSSSelector::PseudoClass) { // Handle :not up front. if (selector->pseudoType() == CSSSelector::PseudoNot) { const CSSSelectorList* selectorList = selector->selectorList(); // FIXME: We probably should fix the parser and make it never produce :not rules with missing selector list. if (!selectorList) return false; SelectorCheckingContext subContext(context); subContext.isSubSelector = true; for (subContext.selector = selectorList->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) { // :not cannot nest. I don't really know why this is a // restriction in CSS3, but it is, so let's honor it. // the parser enforces that this never occurs ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoNot); // We select between :visited and :link when applying. We don't know which one applied (or not) yet. if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled)) return true; if (!checkOne(subContext)) return true; } } else if (context.hasScrollbarPseudo) { // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each // (since there are no elements involved). return checkScrollbarPseudoClass(context, element->document(), selector); } else if (context.hasSelectionPseudo) { if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) return !element->document()->page()->focusController()->isActive(); } // Normal element pseudo class checking. switch (selector->pseudoType()) { // Pseudo classes: case CSSSelector::PseudoNot: break; // Already handled up above. case CSSSelector::PseudoEmpty: { bool result = true; for (Node* n = element->firstChild(); n; n = n->nextSibling()) { if (n->isElementNode()) { result = false; break; } if (n->isTextNode()) { Text* textNode = toText(n); if (!textNode->data().isEmpty()) { result = false; break; } } } if (m_mode == ResolvingStyle) { element->setStyleAffectedByEmpty(); if (context.elementStyle) context.elementStyle->setEmptyState(result); else if (element->renderStyle() && (element->document()->styleSheetCollection()->usesSiblingRules() || element->renderStyle()->unique())) element->renderStyle()->setEmptyState(result); } return result; } case CSSSelector::PseudoFirstChild: // first-child matches the first child that is an element if (Element* parentElement = element->parentElement()) { bool result = isFirstChildElement(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); parentElement->setChildrenAffectedByFirstChildRules(); if (result && childStyle) childStyle->setFirstChildState(); } return result; } break; case CSSSelector::PseudoFirstOfType: // first-of-type matches the first element of its type if (Element* parentElement = element->parentElement()) { bool result = isFirstOfType(element, element->tagQName()); if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByForwardPositionalRules(); return result; } break; case CSSSelector::PseudoLastChild: // last-child matches the last child that is an element if (Element* parentElement = element->parentElement()) { bool result = parentElement->isFinishedParsingChildren() && isLastChildElement(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); parentElement->setChildrenAffectedByLastChildRules(); if (result && childStyle) childStyle->setLastChildState(); } return result; } break; case CSSSelector::PseudoLastOfType: // last-of-type matches the last element of its type if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByBackwardPositionalRules(); if (!parentElement->isFinishedParsingChildren()) return false; return isLastOfType(element, element->tagQName()); } break; case CSSSelector::PseudoOnlyChild: if (Element* parentElement = element->parentElement()) { bool firstChild = isFirstChildElement(element); bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && isLastChildElement(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); parentElement->setChildrenAffectedByFirstChildRules(); parentElement->setChildrenAffectedByLastChildRules(); if (firstChild && childStyle) childStyle->setFirstChildState(); if (onlyChild && childStyle) childStyle->setLastChildState(); } return onlyChild; } break; case CSSSelector::PseudoOnlyOfType: // FIXME: This selector is very slow. if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) { parentElement->setChildrenAffectedByForwardPositionalRules(); parentElement->setChildrenAffectedByBackwardPositionalRules(); } if (!parentElement->isFinishedParsingChildren()) return false; return isFirstOfType(element, element->tagQName()) && isLastOfType(element, element->tagQName()); } break; case CSSSelector::PseudoNthChild: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { int count = 1 + countElementsBefore(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); element->setChildIndex(count); if (childStyle) childStyle->setUnique(); parentElement->setChildrenAffectedByForwardPositionalRules(); } if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoNthOfType: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { int count = 1 + countElementsOfTypeBefore(element, element->tagQName()); if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByForwardPositionalRules(); if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoNthLastChild: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByBackwardPositionalRules(); if (!parentElement->isFinishedParsingChildren()) return false; int count = 1 + countElementsAfter(element); if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoNthLastOfType: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByBackwardPositionalRules(); if (!parentElement->isFinishedParsingChildren()) return false; int count = 1 + countElementsOfTypeAfter(element, element->tagQName()); if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoTarget: if (element == element->document()->cssTarget()) return true; break; case CSSSelector::PseudoAny: { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; PseudoId ignoreDynamicPseudo = NOPSEUDO; for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { if (match(subContext, ignoreDynamicPseudo) == SelectorMatches) return true; } } break; case CSSSelector::PseudoAutofill: if (!element->isFormControlElement()) break; if (HTMLInputElement* inputElement = element->toInputElement()) return inputElement->isAutofilled(); break; case CSSSelector::PseudoAnyLink: case CSSSelector::PseudoLink: // :visited and :link matches are separated later when applying the style. Here both classes match all links... return element->isLink(); case CSSSelector::PseudoVisited: // ...except if :visited matching is disabled for ancestor/sibling matching. return element->isLink() && context.visitedMatchType == VisitedMatchEnabled; case CSSSelector::PseudoDrag: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByDrag(); else element->setChildrenAffectedByDrag(true); } if (element->renderer() && element->renderer()->isDragging()) return true; break; case CSSSelector::PseudoFocus: return matchesFocusPseudoClass(element); case CSSSelector::PseudoHover: // If we're in quirks mode, then hover should never match anchors with no // href and *:hover should not match anything. This is important for sites like wsj.com. if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !isHTMLAnchorElement(element)) || element->isLink()) { if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByHover(); else element->setChildrenAffectedByHover(true); } if (element->hovered() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoHover)) return true; } break; case CSSSelector::PseudoActive: // If we're in quirks mode, then :active should never match anchors with no // href and *:active should not match anything. if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !isHTMLAnchorElement(element)) || element->isLink()) { if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByActive(); else element->setChildrenAffectedByActive(true); } if (element->active() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoActive)) return true; } break; case CSSSelector::PseudoEnabled: if (element->isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) return !element->isDisabledFormControl(); break; case CSSSelector::PseudoFullPageMedia: return element->document() && element->document()->isMediaDocument(); break; case CSSSelector::PseudoDefault: return element->isDefaultButtonForForm(); case CSSSelector::PseudoDisabled: if (element->isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) return element->isDisabledFormControl(); break; case CSSSelector::PseudoReadOnly: return element->matchesReadOnlyPseudoClass(); case CSSSelector::PseudoReadWrite: return element->matchesReadWritePseudoClass(); case CSSSelector::PseudoOptional: return element->isOptionalFormControl(); case CSSSelector::PseudoRequired: return element->isRequiredFormControl(); case CSSSelector::PseudoValid: element->document()->setContainsValidityStyleRules(); return element->willValidate() && element->isValidFormControlElement(); case CSSSelector::PseudoInvalid: element->document()->setContainsValidityStyleRules(); return element->willValidate() && !element->isValidFormControlElement(); case CSSSelector::PseudoChecked: { // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just // obey the CSS spec here in the test for matching the pseudo. HTMLInputElement* inputElement = element->toInputElement(); if (inputElement && inputElement->shouldAppearChecked() && !inputElement->shouldAppearIndeterminate()) return true; if (isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected()) return true; break; } case CSSSelector::PseudoIndeterminate: return element->shouldAppearIndeterminate(); case CSSSelector::PseudoRoot: if (element == element->document()->documentElement()) return true; break; case CSSSelector::PseudoLang: { AtomicString value; #if ENABLE(VIDEO_TRACK) if (element->isWebVTTElement()) value = toWebVTTElement(element)->language(); else #endif value = element->computeInheritedLanguage(); const AtomicString& argument = selector->argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') break; return true; } #if ENABLE(FULLSCREEN_API) case CSSSelector::PseudoFullScreen: // While a Document is in the fullscreen state, and the document's current fullscreen // element is an element in the document, the 'full-screen' pseudoclass applies to // that element. Also, an <iframe>, <object> or <embed> element whose child browsing // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied. if (element->isFrameElementBase() && element->containsFullScreenElement()) return true; if (!element->document()->webkitIsFullScreen()) return false; return element == element->document()->webkitCurrentFullScreenElement(); case CSSSelector::PseudoAnimatingFullScreenTransition: if (element != element->document()->webkitCurrentFullScreenElement()) return false; return element->document()->isAnimatingFullScreen(); case CSSSelector::PseudoFullScreenAncestor: return element->containsFullScreenElement(); case CSSSelector::PseudoFullScreenDocument: // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies // to all elements of that Document. if (!element->document()->webkitIsFullScreen()) return false; return true; #endif #if ENABLE(IFRAME_SEAMLESS) case CSSSelector::PseudoSeamlessDocument: // While a document is rendered in a seamless iframe, the 'seamless-document' pseudoclass applies // to all elements of that Document. return element->document()->shouldDisplaySeamlesslyWithParent(); #endif case CSSSelector::PseudoInRange: element->document()->setContainsValidityStyleRules(); return element->isInRange(); case CSSSelector::PseudoOutOfRange: element->document()->setContainsValidityStyleRules(); return element->isOutOfRange(); #if ENABLE(VIDEO_TRACK) case CSSSelector::PseudoFutureCue: return (element->isWebVTTElement() && !toWebVTTElement(element)->isPastNode()); case CSSSelector::PseudoPastCue: return (element->isWebVTTElement() && toWebVTTElement(element)->isPastNode()); #endif case CSSSelector::PseudoScope: { const Node* contextualReferenceNode = !context.scope || context.behaviorAtBoundary == CrossesBoundary ? element->document()->documentElement() : context.scope; if (element == contextualReferenceNode) return true; break; } case CSSSelector::PseudoHorizontal: case CSSSelector::PseudoVertical: case CSSSelector::PseudoDecrement: case CSSSelector::PseudoIncrement: case CSSSelector::PseudoStart: case CSSSelector::PseudoEnd: case CSSSelector::PseudoDoubleButton: case CSSSelector::PseudoSingleButton: case CSSSelector::PseudoNoButton: case CSSSelector::PseudoCornerPresent: return false; case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: default: ASSERT_NOT_REACHED(); break; } return false; } #if ENABLE(VIDEO_TRACK) else if (selector->m_match == CSSSelector::PseudoElement && selector->pseudoType() == CSSSelector::PseudoCue) { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; PseudoId ignoreDynamicPseudo = NOPSEUDO; const CSSSelector* const & selector = context.selector; for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { if (match(subContext, ignoreDynamicPseudo) == SelectorMatches) return true; } return false; } #endif // ### add the rest of the checks... return true; }