Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
      6  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      7  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
     11  * Copyright (C) 2012 Google Inc. All rights reserved.
     12  *
     13  * This library is free software; you can redistribute it and/or
     14  * modify it under the terms of the GNU Library General Public
     15  * License as published by the Free Software Foundation; either
     16  * version 2 of the License, or (at your option) any later version.
     17  *
     18  * This library is distributed in the hope that it will be useful,
     19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21  * Library General Public License for more details.
     22  *
     23  * You should have received a copy of the GNU Library General Public License
     24  * along with this library; see the file COPYING.LIB.  If not, write to
     25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     26  * Boston, MA 02110-1301, USA.
     27  */
     28 
     29 #include "config.h"
     30 #include "core/css/CSSDefaultStyleSheets.h"
     31 
     32 #include "core/MathMLNames.h"
     33 #include "core/UserAgentStyleSheets.h"
     34 #include "core/css/MediaQueryEvaluator.h"
     35 #include "core/css/RuleSet.h"
     36 #include "core/css/StyleSheetContents.h"
     37 #include "core/dom/FullscreenElementStack.h"
     38 #include "core/html/HTMLAnchorElement.h"
     39 #include "core/html/HTMLHtmlElement.h"
     40 #include "core/rendering/RenderTheme.h"
     41 #include "wtf/LeakAnnotations.h"
     42 
     43 namespace WebCore {
     44 
     45 using namespace HTMLNames;
     46 
     47 CSSDefaultStyleSheets& CSSDefaultStyleSheets::instance()
     48 {
     49 #if ENABLE(OILPAN)
     50     DEFINE_STATIC_LOCAL(Persistent<CSSDefaultStyleSheets>, cssDefaultStyleSheets, (new CSSDefaultStyleSheets()));
     51     return *cssDefaultStyleSheets;
     52 #else
     53     DEFINE_STATIC_LOCAL(CSSDefaultStyleSheets, cssDefaultStyleSheets, ());
     54     return cssDefaultStyleSheets;
     55 #endif
     56 }
     57 
     58 static const MediaQueryEvaluator& screenEval()
     59 {
     60     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
     61     return staticScreenEval;
     62 }
     63 
     64 static const MediaQueryEvaluator& printEval()
     65 {
     66     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
     67     return staticPrintEval;
     68 }
     69 
     70 static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const String& str)
     71 {
     72     RefPtrWillBeRawPtr<StyleSheetContents> sheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0));
     73     sheet->parseString(str);
     74     // User Agent stylesheets are parsed once for the lifetime of the renderer
     75     // and are intentionally leaked.
     76     WTF_ANNOTATE_LEAKING_OBJECT_PTR(sheet.get());
     77     return sheet.release();
     78 }
     79 
     80 static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const char* characters, unsigned size)
     81 {
     82     return parseUASheet(String(characters, size));
     83 }
     84 
     85 CSSDefaultStyleSheets::CSSDefaultStyleSheets()
     86     : m_defaultStyle(nullptr)
     87     , m_defaultViewportStyle(nullptr)
     88     , m_defaultQuirksStyle(nullptr)
     89     , m_defaultPrintStyle(nullptr)
     90     , m_defaultViewSourceStyle(nullptr)
     91     , m_defaultXHTMLMobileProfileStyle(nullptr)
     92     , m_defaultTransitionStyle(nullptr)
     93     , m_defaultStyleSheet(nullptr)
     94     , m_viewportStyleSheet(nullptr)
     95     , m_quirksStyleSheet(nullptr)
     96     , m_svgStyleSheet(nullptr)
     97     , m_mathmlStyleSheet(nullptr)
     98     , m_mediaControlsStyleSheet(nullptr)
     99     , m_fullscreenStyleSheet(nullptr)
    100 {
    101     m_defaultStyle = RuleSet::create();
    102     m_defaultViewportStyle = RuleSet::create();
    103     m_defaultPrintStyle = RuleSet::create();
    104     m_defaultQuirksStyle = RuleSet::create();
    105 
    106     // Strict-mode rules.
    107     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::theme().extraDefaultStyleSheet();
    108     m_defaultStyleSheet = parseUASheet(defaultRules);
    109     m_defaultStyle->addRulesFromSheet(defaultStyleSheet(), screenEval());
    110 #if OS(ANDROID)
    111     String viewportRules(viewportAndroidUserAgentStyleSheet, sizeof(viewportAndroidUserAgentStyleSheet));
    112 #else
    113     String viewportRules;
    114 #endif
    115     m_viewportStyleSheet = parseUASheet(viewportRules);
    116     m_defaultViewportStyle->addRulesFromSheet(viewportStyleSheet(), screenEval());
    117     m_defaultPrintStyle->addRulesFromSheet(defaultStyleSheet(), printEval());
    118 
    119     // Quirks-mode rules.
    120     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::theme().extraQuirksStyleSheet();
    121     m_quirksStyleSheet = parseUASheet(quirksRules);
    122     m_defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet(), screenEval());
    123 }
    124 
    125 RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle()
    126 {
    127     if (!m_defaultViewSourceStyle) {
    128         m_defaultViewSourceStyle = RuleSet::create();
    129         // Loaded stylesheet is leaked on purpose.
    130         RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet));
    131         m_defaultViewSourceStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval());
    132     }
    133     return m_defaultViewSourceStyle.get();
    134 }
    135 
    136 RuleSet* CSSDefaultStyleSheets::defaultTransitionStyle()
    137 {
    138     if (!m_defaultTransitionStyle) {
    139         m_defaultTransitionStyle = RuleSet::create();
    140         // Loaded stylesheet is leaked on purpose.
    141         RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(navigationTransitionsUserAgentStyleSheet, sizeof(navigationTransitionsUserAgentStyleSheet));
    142         m_defaultTransitionStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval());
    143     }
    144     return m_defaultTransitionStyle.get();
    145 }
    146 
    147 RuleSet* CSSDefaultStyleSheets::defaultXHTMLMobileProfileStyle()
    148 {
    149     if (!m_defaultXHTMLMobileProfileStyle) {
    150         m_defaultXHTMLMobileProfileStyle = RuleSet::create();
    151         // Loaded stylesheet is leaked on purpose.
    152         RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(xhtmlmpUserAgentStyleSheet, sizeof(xhtmlmpUserAgentStyleSheet));
    153         m_defaultXHTMLMobileProfileStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval());
    154     }
    155     return m_defaultXHTMLMobileProfileStyle.get();
    156 }
    157 
    158 void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element* element, bool& changedDefaultStyle)
    159 {
    160     // FIXME: We should assert that the sheet only styles SVG elements.
    161     if (element->isSVGElement() && !m_svgStyleSheet) {
    162         m_svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
    163         m_defaultStyle->addRulesFromSheet(svgStyleSheet(), screenEval());
    164         m_defaultPrintStyle->addRulesFromSheet(svgStyleSheet(), printEval());
    165         changedDefaultStyle = true;
    166     }
    167 
    168     // FIXME: We should assert that the sheet only styles MathML elements.
    169     if (element->namespaceURI() == MathMLNames::mathmlNamespaceURI
    170         && !m_mathmlStyleSheet) {
    171         m_mathmlStyleSheet = parseUASheet(mathmlUserAgentStyleSheet,
    172             sizeof(mathmlUserAgentStyleSheet));
    173         m_defaultStyle->addRulesFromSheet(mathmlStyleSheet(), screenEval());
    174         m_defaultPrintStyle->addRulesFromSheet(mathmlStyleSheet(), printEval());
    175         changedDefaultStyle = true;
    176     }
    177 
    178     // FIXME: We should assert that this sheet only contains rules for <video> and <audio>.
    179     if (!m_mediaControlsStyleSheet && (isHTMLVideoElement(*element) || isHTMLAudioElement(*element))) {
    180         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::theme().extraMediaControlsStyleSheet();
    181         m_mediaControlsStyleSheet = parseUASheet(mediaRules);
    182         m_defaultStyle->addRulesFromSheet(mediaControlsStyleSheet(), screenEval());
    183         m_defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet(), printEval());
    184         changedDefaultStyle = true;
    185     }
    186 
    187     // FIXME: This only works because we Force recalc the entire document so the new sheet
    188     // is loaded for <html> and the correct styles apply to everyone.
    189     if (!m_fullscreenStyleSheet && FullscreenElementStack::isFullScreen(element->document())) {
    190         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::theme().extraFullScreenStyleSheet();
    191         m_fullscreenStyleSheet = parseUASheet(fullscreenRules);
    192         m_defaultStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval());
    193         m_defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval());
    194         changedDefaultStyle = true;
    195     }
    196 
    197     ASSERT(!m_defaultStyle->features().hasIdsInSelectors());
    198     ASSERT(m_defaultStyle->features().siblingRules.isEmpty());
    199 }
    200 
    201 void CSSDefaultStyleSheets::trace(Visitor* visitor)
    202 {
    203     visitor->trace(m_defaultStyle);
    204     visitor->trace(m_defaultViewportStyle);
    205     visitor->trace(m_defaultQuirksStyle);
    206     visitor->trace(m_defaultPrintStyle);
    207     visitor->trace(m_defaultViewSourceStyle);
    208     visitor->trace(m_defaultXHTMLMobileProfileStyle);
    209     visitor->trace(m_defaultTransitionStyle);
    210     visitor->trace(m_defaultStyleSheet);
    211     visitor->trace(m_viewportStyleSheet);
    212     visitor->trace(m_quirksStyleSheet);
    213     visitor->trace(m_svgStyleSheet);
    214     visitor->trace(m_mathmlStyleSheet);
    215     visitor->trace(m_mediaControlsStyleSheet);
    216     visitor->trace(m_fullscreenStyleSheet);
    217 }
    218 
    219 } // namespace WebCore
    220