| /* |
| * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) |
| * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All |
| * rights reserved. |
| * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |
| * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| * (http://www.torchmobile.com/) |
| * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
| * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
| * Copyright (C) 2012 Google 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. |
| */ |
| |
| #include "third_party/blink/renderer/core/css/css_default_style_sheets.h" |
| |
| #include "third_party/blink/public/resources/grit/blink_resources.h" |
| #include "third_party/blink/renderer/core/css/media_query_evaluator.h" |
| #include "third_party/blink/renderer/core/css/rule_set.h" |
| #include "third_party/blink/renderer/core/css/style_sheet_contents.h" |
| #include "third_party/blink/renderer/core/frame/settings.h" |
| #include "third_party/blink/renderer/core/html/html_anchor_element.h" |
| #include "third_party/blink/renderer/core/html/html_html_element.h" |
| #include "third_party/blink/renderer/core/layout/layout_theme.h" |
| #include "third_party/blink/renderer/core/mathml_names.h" |
| #include "third_party/blink/renderer/platform/data_resource_helper.h" |
| #include "third_party/blink/renderer/platform/heap/heap.h" |
| #include "third_party/blink/renderer/platform/runtime_enabled_features.h" |
| #include "third_party/blink/renderer/platform/wtf/leak_annotations.h" |
| #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" |
| |
| namespace blink { |
| |
| CSSDefaultStyleSheets& CSSDefaultStyleSheets::Instance() { |
| DEFINE_STATIC_LOCAL(Persistent<CSSDefaultStyleSheets>, |
| css_default_style_sheets, |
| (MakeGarbageCollected<CSSDefaultStyleSheets>())); |
| return *css_default_style_sheets; |
| } |
| |
| static const MediaQueryEvaluator& ScreenEval() { |
| DEFINE_STATIC_LOCAL(const Persistent<MediaQueryEvaluator>, static_screen_eval, |
| (MakeGarbageCollected<MediaQueryEvaluator>("screen"))); |
| return *static_screen_eval; |
| } |
| |
| static const MediaQueryEvaluator& PrintEval() { |
| DEFINE_STATIC_LOCAL(const Persistent<MediaQueryEvaluator>, static_print_eval, |
| (MakeGarbageCollected<MediaQueryEvaluator>("print"))); |
| return *static_print_eval; |
| } |
| |
| static const MediaQueryEvaluator& ForcedColorsEval() { |
| // We use "ua-forced-colors" here instead of "forced-colors" to indicate that |
| // this is a UA hack for the "forced-colors" media query. |
| DEFINE_STATIC_LOCAL( |
| Persistent<MediaQueryEvaluator>, forced_colors_eval, |
| (MakeGarbageCollected<MediaQueryEvaluator>("ua-forced-colors"))); |
| return *forced_colors_eval; |
| } |
| |
| static StyleSheetContents* ParseUASheet(const String& str) { |
| // UA stylesheets always parse in the insecure context mode. |
| auto* sheet = MakeGarbageCollected<StyleSheetContents>( |
| MakeGarbageCollected<CSSParserContext>( |
| kUASheetMode, SecureContextMode::kInsecureContext)); |
| sheet->ParseString(str); |
| // User Agent stylesheets are parsed once for the lifetime of the renderer |
| // process and are intentionally leaked. |
| LEAK_SANITIZER_IGNORE_OBJECT(sheet); |
| return sheet; |
| } |
| |
| CSSDefaultStyleSheets::CSSDefaultStyleSheets() |
| : media_controls_style_sheet_loader_(nullptr) { |
| // Predefined @counter-style rules |
| String predefined_counter_styles_sheet = |
| RuntimeEnabledFeatures::CSSAtRuleCounterStyleEnabled() |
| ? UncompressResourceAsASCIIString( |
| IDR_UASTYLE_PREDEFINED_COUNTER_STYLES_CSS) |
| : String(); |
| // Strict-mode rules. |
| String default_rules = UncompressResourceAsASCIIString(IDR_UASTYLE_HTML_CSS) + |
| LayoutTheme::GetTheme().ExtraDefaultStyleSheet() + |
| predefined_counter_styles_sheet; |
| |
| default_style_sheet_ = ParseUASheet(default_rules); |
| |
| // Quirks-mode rules. |
| String quirks_rules = |
| UncompressResourceAsASCIIString(IDR_UASTYLE_QUIRKS_CSS) + |
| LayoutTheme::GetTheme().ExtraQuirksStyleSheet(); |
| quirks_style_sheet_ = ParseUASheet(quirks_rules); |
| |
| InitializeDefaultStyles(); |
| |
| #if DCHECK_IS_ON() |
| default_style_->CompactRulesIfNeeded(); |
| default_mathml_style_->CompactRulesIfNeeded(); |
| default_svg_style_->CompactRulesIfNeeded(); |
| default_quirks_style_->CompactRulesIfNeeded(); |
| default_print_style_->CompactRulesIfNeeded(); |
| DCHECK(default_style_->UniversalRules()->IsEmpty()); |
| DCHECK(default_mathml_style_->UniversalRules()->IsEmpty()); |
| DCHECK(default_svg_style_->UniversalRules()->IsEmpty()); |
| DCHECK(default_quirks_style_->UniversalRules()->IsEmpty()); |
| DCHECK(default_print_style_->UniversalRules()->IsEmpty()); |
| #endif |
| } |
| |
| void CSSDefaultStyleSheets::PrepareForLeakDetection() { |
| // Clear the optional style sheets. |
| mobile_viewport_style_sheet_.Clear(); |
| television_viewport_style_sheet_.Clear(); |
| xhtml_mobile_profile_style_sheet_.Clear(); |
| svg_style_sheet_.Clear(); |
| mathml_style_sheet_.Clear(); |
| media_controls_style_sheet_.Clear(); |
| text_track_style_sheet_.Clear(); |
| forced_colors_style_sheet_.Clear(); |
| fullscreen_style_sheet_.Clear(); |
| webxr_overlay_style_sheet_.Clear(); |
| marker_style_sheet_.Clear(); |
| // Recreate the default style sheet to clean up possible SVG resources. |
| String default_rules = UncompressResourceAsASCIIString(IDR_UASTYLE_HTML_CSS) + |
| LayoutTheme::GetTheme().ExtraDefaultStyleSheet(); |
| default_style_sheet_ = ParseUASheet(default_rules); |
| |
| // Initialize the styles that have the lazily loaded style sheets. |
| InitializeDefaultStyles(); |
| default_view_source_style_.Clear(); |
| } |
| |
| void CSSDefaultStyleSheets::InitializeDefaultStyles() { |
| // This must be called only from constructor / PrepareForLeakDetection. |
| default_style_ = MakeGarbageCollected<RuleSet>(); |
| default_mathml_style_ = MakeGarbageCollected<RuleSet>(); |
| default_svg_style_ = MakeGarbageCollected<RuleSet>(); |
| default_quirks_style_ = MakeGarbageCollected<RuleSet>(); |
| default_print_style_ = MakeGarbageCollected<RuleSet>(); |
| default_media_controls_style_ = MakeGarbageCollected<RuleSet>(); |
| default_forced_color_style_.Clear(); |
| default_pseudo_element_style_.Clear(); |
| |
| default_style_->AddRulesFromSheet(DefaultStyleSheet(), ScreenEval()); |
| default_quirks_style_->AddRulesFromSheet(QuirksStyleSheet(), ScreenEval()); |
| default_print_style_->AddRulesFromSheet(DefaultStyleSheet(), PrintEval()); |
| } |
| |
| RuleSet* CSSDefaultStyleSheets::DefaultViewSourceStyle() { |
| if (!default_view_source_style_) { |
| default_view_source_style_ = MakeGarbageCollected<RuleSet>(); |
| // Loaded stylesheet is leaked on purpose. |
| StyleSheetContents* stylesheet = ParseUASheet( |
| UncompressResourceAsASCIIString(IDR_UASTYLE_VIEW_SOURCE_CSS)); |
| default_view_source_style_->AddRulesFromSheet(stylesheet, ScreenEval()); |
| } |
| return default_view_source_style_; |
| } |
| |
| StyleSheetContents* |
| CSSDefaultStyleSheets::EnsureXHTMLMobileProfileStyleSheet() { |
| if (!xhtml_mobile_profile_style_sheet_) { |
| xhtml_mobile_profile_style_sheet_ = |
| ParseUASheet(UncompressResourceAsASCIIString(IDR_UASTYLE_XHTMLMP_CSS)); |
| } |
| return xhtml_mobile_profile_style_sheet_; |
| } |
| |
| StyleSheetContents* CSSDefaultStyleSheets::EnsureMobileViewportStyleSheet() { |
| if (!mobile_viewport_style_sheet_) { |
| mobile_viewport_style_sheet_ = ParseUASheet( |
| UncompressResourceAsASCIIString(IDR_UASTYLE_VIEWPORT_ANDROID_CSS)); |
| } |
| return mobile_viewport_style_sheet_; |
| } |
| |
| StyleSheetContents* |
| CSSDefaultStyleSheets::EnsureTelevisionViewportStyleSheet() { |
| if (!television_viewport_style_sheet_) { |
| television_viewport_style_sheet_ = ParseUASheet( |
| UncompressResourceAsASCIIString(IDR_UASTYLE_VIEWPORT_TELEVISION_CSS)); |
| } |
| return television_viewport_style_sheet_; |
| } |
| |
| static void AddTextTrackCSSProperties(StringBuilder* builder, |
| CSSPropertyID propertyId, |
| String value) { |
| builder->Append(CSSProperty::Get(propertyId).GetPropertyNameString()); |
| builder->Append(": "); |
| builder->Append(value); |
| builder->Append("; "); |
| } |
| |
| bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForElement( |
| const Element& element) { |
| bool changed_default_style = false; |
| // FIXME: We should assert that the sheet only styles SVG elements. |
| if (element.IsSVGElement() && !svg_style_sheet_) { |
| svg_style_sheet_ = |
| ParseUASheet(UncompressResourceAsASCIIString(IDR_UASTYLE_SVG_CSS)); |
| default_svg_style_->AddRulesFromSheet(SvgStyleSheet(), ScreenEval()); |
| default_print_style_->AddRulesFromSheet(SvgStyleSheet(), PrintEval()); |
| if (default_forced_color_style_) { |
| default_forced_color_style_->AddRulesFromSheet(SvgStyleSheet(), |
| ForcedColorsEval()); |
| } |
| changed_default_style = true; |
| } |
| |
| // FIXME: We should assert that the sheet only styles MathML elements. |
| if (element.namespaceURI() == mathml_names::kNamespaceURI && |
| !mathml_style_sheet_) { |
| mathml_style_sheet_ = ParseUASheet( |
| RuntimeEnabledFeatures::MathMLCoreEnabled() |
| ? UncompressResourceAsASCIIString(IDR_UASTYLE_MATHML_CSS) |
| : UncompressResourceAsASCIIString(IDR_UASTYLE_MATHML_FALLBACK_CSS)); |
| default_mathml_style_->AddRulesFromSheet(MathmlStyleSheet(), ScreenEval()); |
| default_print_style_->AddRulesFromSheet(MathmlStyleSheet(), PrintEval()); |
| changed_default_style = true; |
| } |
| |
| if (!media_controls_style_sheet_ && HasMediaControlsStyleSheetLoader() && |
| (IsA<HTMLVideoElement>(element) || IsA<HTMLAudioElement>(element))) { |
| // FIXME: We should assert that this sheet only contains rules for <video> |
| // and <audio>. |
| media_controls_style_sheet_ = |
| ParseUASheet(media_controls_style_sheet_loader_->GetUAStyleSheet()); |
| default_media_controls_style_->AddRulesFromSheet(MediaControlsStyleSheet(), |
| ScreenEval()); |
| default_print_style_->AddRulesFromSheet(MediaControlsStyleSheet(), |
| PrintEval()); |
| if (default_forced_color_style_) { |
| default_forced_color_style_->AddRulesFromSheet(MediaControlsStyleSheet(), |
| ForcedColorsEval()); |
| } |
| changed_default_style = true; |
| } |
| |
| if (!text_track_style_sheet_ && IsA<HTMLVideoElement>(element)) { |
| Settings* settings = element.GetDocument().GetSettings(); |
| if (settings) { |
| StringBuilder builder; |
| builder.Append("video::-webkit-media-text-track-display { "); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kBackgroundColor, |
| settings->GetTextTrackWindowColor()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kPadding, |
| settings->GetTextTrackWindowPadding()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kBorderRadius, |
| settings->GetTextTrackWindowRadius()); |
| builder.Append(" } video::cue { "); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kBackgroundColor, |
| settings->GetTextTrackBackgroundColor()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kFontFamily, |
| settings->GetTextTrackFontFamily()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kFontStyle, |
| settings->GetTextTrackFontStyle()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kFontVariant, |
| settings->GetTextTrackFontVariant()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kColor, |
| settings->GetTextTrackTextColor()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kTextShadow, |
| settings->GetTextTrackTextShadow()); |
| AddTextTrackCSSProperties(&builder, CSSPropertyID::kFontSize, |
| settings->GetTextTrackTextSize()); |
| builder.Append(" } "); |
| text_track_style_sheet_ = ParseUASheet(builder.ToString()); |
| default_media_controls_style_->AddRulesFromSheet(text_track_style_sheet_, |
| ScreenEval()); |
| default_print_style_->AddRulesFromSheet(text_track_style_sheet_, |
| PrintEval()); |
| changed_default_style = true; |
| } |
| } |
| |
| DCHECK(!default_style_->Features().HasIdsInSelectors()); |
| return changed_default_style; |
| } |
| |
| bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetsForPseudoElement( |
| PseudoId pseudo_id) { |
| switch (pseudo_id) { |
| case kPseudoIdMarker: { |
| if (marker_style_sheet_) |
| return false; |
| marker_style_sheet_ = |
| ParseUASheet(UncompressResourceAsASCIIString(IDR_UASTYLE_MARKER_CSS)); |
| if (!default_pseudo_element_style_) |
| default_pseudo_element_style_ = MakeGarbageCollected<RuleSet>(); |
| default_pseudo_element_style_->AddRulesFromSheet(MarkerStyleSheet(), |
| ScreenEval()); |
| return true; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| void CSSDefaultStyleSheets::SetMediaControlsStyleSheetLoader( |
| std::unique_ptr<UAStyleSheetLoader> loader) { |
| media_controls_style_sheet_loader_.swap(loader); |
| } |
| |
| bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetForXrOverlay() { |
| if (webxr_overlay_style_sheet_) |
| return false; |
| |
| webxr_overlay_style_sheet_ = ParseUASheet( |
| UncompressResourceAsASCIIString(IDR_UASTYLE_WEBXR_OVERLAY_CSS)); |
| default_style_->AddRulesFromSheet(webxr_overlay_style_sheet_, ScreenEval()); |
| default_print_style_->AddRulesFromSheet(webxr_overlay_style_sheet_, |
| PrintEval()); |
| if (default_forced_color_style_) { |
| default_forced_color_style_->AddRulesFromSheet(webxr_overlay_style_sheet_, |
| ForcedColorsEval()); |
| } |
| return true; |
| } |
| |
| void CSSDefaultStyleSheets::EnsureDefaultStyleSheetForFullscreen() { |
| if (fullscreen_style_sheet_) |
| return; |
| |
| String fullscreen_rules = |
| UncompressResourceAsASCIIString(IDR_UASTYLE_FULLSCREEN_CSS) + |
| LayoutTheme::GetTheme().ExtraFullscreenStyleSheet(); |
| fullscreen_style_sheet_ = ParseUASheet(fullscreen_rules); |
| default_style_->AddRulesFromSheet(FullscreenStyleSheet(), ScreenEval()); |
| default_quirks_style_->AddRulesFromSheet(FullscreenStyleSheet(), |
| ScreenEval()); |
| } |
| |
| bool CSSDefaultStyleSheets::EnsureDefaultStyleSheetForForcedColors() { |
| if (forced_colors_style_sheet_) |
| return false; |
| |
| String forced_colors_rules = |
| RuntimeEnabledFeatures::ForcedColorsEnabled() |
| ? UncompressResourceAsASCIIString(IDR_UASTYLE_THEME_FORCED_COLORS_CSS) |
| : String(); |
| forced_colors_style_sheet_ = ParseUASheet(forced_colors_rules); |
| |
| if (!default_forced_color_style_) |
| default_forced_color_style_ = MakeGarbageCollected<RuleSet>(); |
| default_forced_color_style_->AddRulesFromSheet(DefaultStyleSheet(), |
| ForcedColorsEval()); |
| default_forced_color_style_->AddRulesFromSheet(ForcedColorsStyleSheet(), |
| ForcedColorsEval()); |
| if (svg_style_sheet_) { |
| default_forced_color_style_->AddRulesFromSheet(SvgStyleSheet(), |
| ForcedColorsEval()); |
| } |
| if (media_controls_style_sheet_) { |
| default_forced_color_style_->AddRulesFromSheet(MediaControlsStyleSheet(), |
| ForcedColorsEval()); |
| } |
| if (webxr_overlay_style_sheet_) { |
| default_forced_color_style_->AddRulesFromSheet(webxr_overlay_style_sheet_, |
| ForcedColorsEval()); |
| } |
| |
| return true; |
| } |
| |
| void CSSDefaultStyleSheets::CollectFeaturesTo(const Document& document, |
| RuleFeatureSet& features) { |
| if (DefaultStyle()) |
| features.Add(DefaultStyle()->Features()); |
| if (DefaultMediaControlsStyle()) |
| features.Add(DefaultMediaControlsStyle()->Features()); |
| if (DefaultMathMLStyle()) |
| features.Add(DefaultMathMLStyle()->Features()); |
| if (document.IsViewSource() && DefaultViewSourceStyle()) |
| features.Add(DefaultViewSourceStyle()->Features()); |
| } |
| |
| void CSSDefaultStyleSheets::Trace(Visitor* visitor) const { |
| visitor->Trace(default_style_); |
| visitor->Trace(default_mathml_style_); |
| visitor->Trace(default_svg_style_); |
| visitor->Trace(default_quirks_style_); |
| visitor->Trace(default_print_style_); |
| visitor->Trace(default_view_source_style_); |
| visitor->Trace(default_forced_color_style_); |
| visitor->Trace(default_media_controls_style_); |
| visitor->Trace(default_style_sheet_); |
| visitor->Trace(default_pseudo_element_style_); |
| visitor->Trace(mobile_viewport_style_sheet_); |
| visitor->Trace(television_viewport_style_sheet_); |
| visitor->Trace(xhtml_mobile_profile_style_sheet_); |
| visitor->Trace(quirks_style_sheet_); |
| visitor->Trace(svg_style_sheet_); |
| visitor->Trace(mathml_style_sheet_); |
| visitor->Trace(media_controls_style_sheet_); |
| visitor->Trace(text_track_style_sheet_); |
| visitor->Trace(forced_colors_style_sheet_); |
| visitor->Trace(fullscreen_style_sheet_); |
| visitor->Trace(webxr_overlay_style_sheet_); |
| visitor->Trace(marker_style_sheet_); |
| } |
| |
| } // namespace blink |