Home | History | Annotate | Download | only in css
      1 /*
      2  * (C) 1999-2003 Lars Knoll (knoll (at) kde.org)
      3  * (C) 2002-2003 Dirk Mueller (mueller (at) kde.org)
      4  * Copyright (C) 2002, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  */
     21 
     22 #include "config.h"
     23 #include "CSSImportRule.h"
     24 
     25 #include "CachedCSSStyleSheet.h"
     26 #include "CachedResourceLoader.h"
     27 #include "Document.h"
     28 #include "SecurityOrigin.h"
     29 #include "Settings.h"
     30 #include <wtf/StdLibExtras.h>
     31 
     32 namespace WebCore {
     33 
     34 CSSImportRule::CSSImportRule(CSSStyleSheet* parent, const String& href, PassRefPtr<MediaList> media)
     35     : CSSRule(parent)
     36     , m_strHref(href)
     37     , m_lstMedia(media)
     38     , m_cachedSheet(0)
     39     , m_loading(false)
     40 {
     41     if (m_lstMedia)
     42         m_lstMedia->setParent(this);
     43     else
     44         m_lstMedia = MediaList::create(this, String());
     45 }
     46 
     47 CSSImportRule::~CSSImportRule()
     48 {
     49     if (m_lstMedia)
     50         m_lstMedia->setParent(0);
     51     if (m_styleSheet)
     52         m_styleSheet->setParent(0);
     53     if (m_cachedSheet)
     54         m_cachedSheet->removeClient(this);
     55 }
     56 
     57 void CSSImportRule::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet)
     58 {
     59     if (m_styleSheet)
     60         m_styleSheet->setParent(0);
     61     m_styleSheet = CSSStyleSheet::create(this, href, baseURL, charset);
     62 
     63     bool crossOriginCSS = false;
     64     bool validMIMEType = false;
     65     CSSStyleSheet* parent = parentStyleSheet();
     66     bool strict = !parent || parent->useStrictParsing();
     67     bool enforceMIMEType = strict;
     68     bool needsSiteSpecificQuirks = parent && parent->document() && parent->document()->settings() && parent->document()->settings()->needsSiteSpecificQuirks();
     69 
     70 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
     71     if (enforceMIMEType && needsSiteSpecificQuirks) {
     72         // Covers both http and https, with or without "www."
     73         if (baseURL.string().contains("mcafee.com/japan/", false))
     74             enforceMIMEType = false;
     75     }
     76 #endif
     77 
     78     String sheetText = sheet->sheetText(enforceMIMEType, &validMIMEType);
     79     m_styleSheet->parseString(sheetText, strict);
     80 
     81     if (!parent || !parent->document() || !parent->document()->securityOrigin()->canRequest(baseURL))
     82         crossOriginCSS = true;
     83 
     84     if (crossOriginCSS && !validMIMEType && !m_styleSheet->hasSyntacticallyValidCSSHeader())
     85         m_styleSheet = CSSStyleSheet::create(this, href, baseURL, charset);
     86 
     87     if (strict && needsSiteSpecificQuirks) {
     88         // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>.
     89         DEFINE_STATIC_LOCAL(const String, slashKHTMLFixesDotCss, ("/KHTMLFixes.css"));
     90         DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, ("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"));
     91         // There are two variants of KHTMLFixes.css. One is equal to mediaWikiKHTMLFixesStyleSheet,
     92         // while the other lacks the second trailing newline.
     93         if (baseURL.string().endsWith(slashKHTMLFixesDotCss) && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText)
     94                 && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) {
     95             ASSERT(m_styleSheet->length() == 1);
     96             ExceptionCode ec;
     97             m_styleSheet->deleteRule(0, ec);
     98         }
     99     }
    100 
    101     m_loading = false;
    102 
    103     if (parent)
    104         parent->checkLoaded();
    105 }
    106 
    107 bool CSSImportRule::isLoading() const
    108 {
    109     return m_loading || (m_styleSheet && m_styleSheet->isLoading());
    110 }
    111 
    112 void CSSImportRule::insertedIntoParent()
    113 {
    114     CSSStyleSheet* parentSheet = parentStyleSheet();
    115     if (!parentSheet || !parentSheet->document())
    116         return;
    117 
    118     CachedResourceLoader* cachedResourceLoader = parentSheet->document()->cachedResourceLoader();
    119     if (!cachedResourceLoader)
    120         return;
    121 
    122     String absHref = m_strHref;
    123     if (!parentSheet->finalURL().isNull())
    124         // use parent styleheet's URL as the base URL
    125         absHref = KURL(parentSheet->finalURL(), m_strHref).string();
    126 
    127     // Check for a cycle in our import chain.  If we encounter a stylesheet
    128     // in our parent chain with the same URL, then just bail.
    129     StyleBase* root = this;
    130     for (StyleBase* curr = parent(); curr; curr = curr->parent()) {
    131         // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL.
    132         if (curr->isCSSStyleSheet() && absHref == static_cast<CSSStyleSheet*>(curr)->finalURL().string())
    133             return;
    134         root = curr;
    135     }
    136 
    137     if (parentSheet->isUserStyleSheet())
    138         m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(absHref, parentSheet->charset());
    139     else
    140         m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(absHref, parentSheet->charset());
    141     if (m_cachedSheet) {
    142         // if the import rule is issued dynamically, the sheet may be
    143         // removed from the pending sheet count, so let the doc know
    144         // the sheet being imported is pending.
    145         if (parentSheet && parentSheet->loadCompleted() && root == parentSheet)
    146             parentSheet->document()->addPendingSheet();
    147         m_loading = true;
    148         m_cachedSheet->addClient(this);
    149     }
    150 }
    151 
    152 String CSSImportRule::cssText() const
    153 {
    154     String result = "@import url(\"";
    155     result += m_strHref;
    156     result += "\")";
    157 
    158     if (m_lstMedia) {
    159         result += " ";
    160         result += m_lstMedia->mediaText();
    161     }
    162     result += ";";
    163 
    164     return result;
    165 }
    166 
    167 void CSSImportRule::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
    168 {
    169     if (m_styleSheet)
    170         addSubresourceURL(urls, m_styleSheet->baseURL());
    171 }
    172 
    173 #ifdef ANDROID_INSTRUMENT
    174 void* CSSImportRule::operator new(size_t size)
    175 {
    176     return StyleBase::operator new(size);
    177 }
    178 
    179 void* CSSImportRule::operator new[](size_t size)
    180 {
    181     return StyleBase::operator new[](size);
    182 }
    183 
    184 void CSSImportRule::operator delete(void* p, size_t size)
    185 {
    186     StyleBase::operator delete(p, size);
    187 }
    188 
    189 void CSSImportRule::operator delete[](void* p, size_t size)
    190 {
    191     StyleBase::operator delete[](p, size);
    192 }
    193 #endif
    194 
    195 } // namespace WebCore
    196