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 "UserAgentStyleSheets.h"
     33 #include "core/css/MediaQueryEvaluator.h"
     34 #include "core/css/RuleSet.h"
     35 #include "core/css/StyleSheetContents.h"
     36 #include "core/dom/FullscreenElementStack.h"
     37 #include "core/html/HTMLAnchorElement.h"
     38 #include "core/html/HTMLHtmlElement.h"
     39 #include "core/html/HTMLVideoElement.h"
     40 #include "core/rendering/RenderTheme.h"
     41 
     42 namespace WebCore {
     43 
     44 using namespace HTMLNames;
     45 
     46 RuleSet* CSSDefaultStyleSheets::defaultStyle;
     47 RuleSet* CSSDefaultStyleSheets::defaultQuirksStyle;
     48 RuleSet* CSSDefaultStyleSheets::defaultPrintStyle;
     49 RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle;
     50 
     51 StyleSheetContents* CSSDefaultStyleSheets::simpleDefaultStyleSheet;
     52 StyleSheetContents* CSSDefaultStyleSheets::defaultStyleSheet;
     53 StyleSheetContents* CSSDefaultStyleSheets::quirksStyleSheet;
     54 StyleSheetContents* CSSDefaultStyleSheets::svgStyleSheet;
     55 StyleSheetContents* CSSDefaultStyleSheets::mathMLStyleSheet;
     56 StyleSheetContents* CSSDefaultStyleSheets::mediaControlsStyleSheet;
     57 StyleSheetContents* CSSDefaultStyleSheets::fullscreenStyleSheet;
     58 
     59 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
     60 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}body:-webkit-seamless-document{margin:0}body:-webkit-full-page-media{background-color:black}";
     61 
     62 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
     63 {
     64     return isHTMLHtmlElement(e) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || isHTMLAnchorElement(e);
     65 }
     66 
     67 static const MediaQueryEvaluator& screenEval()
     68 {
     69     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
     70     return staticScreenEval;
     71 }
     72 
     73 static const MediaQueryEvaluator& printEval()
     74 {
     75     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
     76     return staticPrintEval;
     77 }
     78 
     79 static StyleSheetContents* parseUASheet(const String& str)
     80 {
     81     StyleSheetContents* sheet = StyleSheetContents::create(CSSParserContext(UASheetMode)).leakRef(); // leak the sheet on purpose
     82     sheet->parseString(str);
     83     return sheet;
     84 }
     85 
     86 static StyleSheetContents* parseUASheet(const char* characters, unsigned size)
     87 {
     88     return parseUASheet(String(characters, size));
     89 }
     90 
     91 void CSSDefaultStyleSheets::initDefaultStyle(Element* root)
     92 {
     93     if (!defaultStyle) {
     94         if (!root || elementCanUseSimpleDefaultStyle(root))
     95             loadSimpleDefaultStyle();
     96         else
     97             loadFullDefaultStyle();
     98     }
     99 }
    100 
    101 void CSSDefaultStyleSheets::loadFullDefaultStyle()
    102 {
    103     if (simpleDefaultStyleSheet) {
    104         ASSERT(defaultStyle);
    105         ASSERT(defaultPrintStyle == defaultStyle);
    106         delete defaultStyle;
    107         simpleDefaultStyleSheet->deref();
    108         defaultStyle = RuleSet::create().leakPtr();
    109         defaultPrintStyle = RuleSet::create().leakPtr();
    110         simpleDefaultStyleSheet = 0;
    111     } else {
    112         ASSERT(!defaultStyle);
    113         defaultStyle = RuleSet::create().leakPtr();
    114         defaultPrintStyle = RuleSet::create().leakPtr();
    115         defaultQuirksStyle = RuleSet::create().leakPtr();
    116     }
    117 
    118     // Strict-mode rules.
    119     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
    120     defaultStyleSheet = parseUASheet(defaultRules);
    121     defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval());
    122     defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval());
    123 
    124     // Quirks-mode rules.
    125     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
    126     quirksStyleSheet = parseUASheet(quirksRules);
    127     defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval());
    128 }
    129 
    130 void CSSDefaultStyleSheets::loadSimpleDefaultStyle()
    131 {
    132     ASSERT(!defaultStyle);
    133     ASSERT(!simpleDefaultStyleSheet);
    134 
    135     defaultStyle = RuleSet::create().leakPtr();
    136     // There are no media-specific rules in the simple default style.
    137     defaultPrintStyle = defaultStyle;
    138     defaultQuirksStyle = RuleSet::create().leakPtr();
    139 
    140     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
    141     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
    142 
    143     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
    144 }
    145 
    146 RuleSet* CSSDefaultStyleSheets::viewSourceStyle()
    147 {
    148     if (!defaultViewSourceStyle) {
    149         defaultViewSourceStyle = RuleSet::create().leakPtr();
    150         defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
    151     }
    152     return defaultViewSourceStyle;
    153 }
    154 
    155 
    156 void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element* element, bool& changedDefaultStyle)
    157 {
    158     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) {
    159         loadFullDefaultStyle();
    160         changedDefaultStyle = true;
    161     }
    162 
    163     // FIXME: We should assert that the sheet only styles SVG elements.
    164     if (element->isSVGElement() && !svgStyleSheet) {
    165         svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
    166         defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval());
    167         defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval());
    168         changedDefaultStyle = true;
    169     }
    170 
    171     // FIXME: We should assert that this sheet only contains rules for <video> and <audio>.
    172     if (!mediaControlsStyleSheet && (isHTMLVideoElement(element) || element->hasTagName(audioTag))) {
    173         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
    174         mediaControlsStyleSheet = parseUASheet(mediaRules);
    175         defaultStyle->addRulesFromSheet(mediaControlsStyleSheet, screenEval());
    176         defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet, printEval());
    177         changedDefaultStyle = true;
    178     }
    179 
    180     if (!fullscreenStyleSheet && FullscreenElementStack::isFullScreen(element->document())) {
    181         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
    182         fullscreenStyleSheet = parseUASheet(fullscreenRules);
    183         defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
    184         defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
    185         changedDefaultStyle = true;
    186     }
    187 
    188     ASSERT(defaultStyle->features().idsInRules.isEmpty());
    189     ASSERT(mathMLStyleSheet || defaultStyle->features().siblingRules.isEmpty());
    190 }
    191 
    192 } // namespace WebCore
    193