Changeset 126717 in webkit


Ignore:
Timestamp:
Aug 26, 2012 4:48:39 PM (12 years ago)
Author:
Antti Koivisto
Message:

Remove parent pointer from StyleSheetContents and StyleRuleImport
https://bugs.webkit.org/show_bug.cgi?id=94926

Reviewed by Andreas Kling.

To be able to cache and share @imported stylesheets in the future there must not be any parent
pointers in the stylesheet tree.

Parent pointers are used during loading to invoke load completion callbacks and for
accessing document context information (like the security origin). They are not used after
the sheet load is complete. Instead of keeping the parent pointers around indefinitely as part of the
stylesheet data structure we just keep a pointer to the root CSSStyleSheet for the duration of the load.

This patch doesn't enable any new caching or generally change the behavior.

  • css/CSSStyleSheet.cpp:

(WebCore::CSSStyleSheet::insertRule):
(WebCore::CSSStyleSheet::rootStyleSheet):
(WebCore):
(WebCore::CSSStyleSheet::ownerDocument):

  • css/CSSStyleSheet.h:

(CSSStyleSheet):

  • css/StyleRuleImport.cpp:

(WebCore::StyleRuleImport::LoadContext::LoadContext):

Simplify by making StyleRuleImport CachedStyleSheetClient directly. LoadContext contains
fields that can be thrown away after load completes.

(WebCore):
(WebCore::StyleRuleImport::StyleRuleImport):
(WebCore::StyleRuleImport::~StyleRuleImport):
(WebCore::StyleRuleImport::setCSSStyleSheet):
(WebCore::StyleRuleImport::isLoading):
(WebCore::StyleRuleImport::hadLoadError):
(WebCore::StyleRuleImport::requestStyleSheet):

  • css/StyleRuleImport.h:

(StyleRuleImport):
(LoadContext):

  • css/StyleSheetContents.cpp:

(WebCore::StyleSheetContents::StyleSheetContents):

Remove now unnecessary constructor.

(WebCore::StyleSheetContents::isCacheable):
(WebCore::StyleSheetContents::parserAppendRule):
(WebCore::StyleSheetContents::clearRules):
(WebCore::StyleSheetContents::wrapperInsertRule):
(WebCore::StyleSheetContents::wrapperDeleteRule):
(WebCore::StyleSheetContents::requestImportedStyleSheets):
(WebCore):
(WebCore::StyleSheetContents::parseAuthorStyleSheet):
(WebCore::StyleSheetContents::parseStringAtLine):
(WebCore::StyleSheetContents::checkImportedSheetLoadCompleted):
(WebCore::StyleSheetContents::checkLoadCompleted):
(WebCore::StyleSheetContents::getAncestors):
(WebCore::StyleSheetContents::hasImportCycle):

Move the cycle checking to the root stylesheet so we don't need to pass the entire chain around.
The extra work here is unlikely to cause problems, massive import trees don't really occur in
practice.

  • css/StyleSheetContents.h:

(WebCore::StyleSheetContents::create):
(StyleSheetContents):

  • dom/ProcessingInstruction.cpp:

(WebCore::ProcessingInstruction::parseStyleSheet):

  • dom/StyleElement.cpp:

(WebCore::StyleElement::createSheet):

  • html/HTMLLinkElement.cpp:

(WebCore::HTMLLinkElement::setCSSStyleSheet):

Location:
trunk/Source/WebCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r126716 r126717  
     12012-08-26  Antti Koivisto  <antti@apple.com>
     2
     3        Remove parent pointer from StyleSheetContents and StyleRuleImport
     4        https://bugs.webkit.org/show_bug.cgi?id=94926
     5
     6        Reviewed by Andreas Kling.
     7
     8        To be able to cache and share @imported stylesheets in the future there must not be any parent
     9        pointers in the stylesheet tree.
     10
     11        Parent pointers are used during loading to invoke load completion callbacks and for
     12        accessing document context information (like the security origin). They are not used after
     13        the sheet load is complete. Instead of keeping the parent pointers around indefinitely as part of the
     14        stylesheet data structure we just keep a pointer to the root CSSStyleSheet for the duration of the load.
     15       
     16        This patch doesn't enable any new caching or generally change the behavior.
     17
     18        * css/CSSStyleSheet.cpp:
     19        (WebCore::CSSStyleSheet::insertRule):
     20        (WebCore::CSSStyleSheet::rootStyleSheet):
     21        (WebCore):
     22        (WebCore::CSSStyleSheet::ownerDocument):
     23        * css/CSSStyleSheet.h:
     24        (CSSStyleSheet):
     25        * css/StyleRuleImport.cpp:
     26        (WebCore::StyleRuleImport::LoadContext::LoadContext):
     27       
     28            Simplify by making StyleRuleImport CachedStyleSheetClient directly. LoadContext contains
     29            fields that can be thrown away after load completes.
     30
     31        (WebCore):
     32        (WebCore::StyleRuleImport::StyleRuleImport):
     33        (WebCore::StyleRuleImport::~StyleRuleImport):
     34        (WebCore::StyleRuleImport::setCSSStyleSheet):
     35        (WebCore::StyleRuleImport::isLoading):
     36        (WebCore::StyleRuleImport::hadLoadError):
     37        (WebCore::StyleRuleImport::requestStyleSheet):
     38        * css/StyleRuleImport.h:
     39        (StyleRuleImport):
     40        (LoadContext):
     41        * css/StyleSheetContents.cpp:
     42        (WebCore::StyleSheetContents::StyleSheetContents):
     43       
     44            Remove now unnecessary constructor.
     45
     46        (WebCore::StyleSheetContents::isCacheable):
     47        (WebCore::StyleSheetContents::parserAppendRule):
     48        (WebCore::StyleSheetContents::clearRules):
     49        (WebCore::StyleSheetContents::wrapperInsertRule):
     50        (WebCore::StyleSheetContents::wrapperDeleteRule):
     51        (WebCore::StyleSheetContents::requestImportedStyleSheets):
     52        (WebCore):
     53        (WebCore::StyleSheetContents::parseAuthorStyleSheet):
     54        (WebCore::StyleSheetContents::parseStringAtLine):
     55        (WebCore::StyleSheetContents::checkImportedSheetLoadCompleted):
     56        (WebCore::StyleSheetContents::checkLoadCompleted):
     57        (WebCore::StyleSheetContents::getAncestors):
     58        (WebCore::StyleSheetContents::hasImportCycle):
     59       
     60            Move the cycle checking to the root stylesheet so we don't need to pass the entire chain around.
     61            The extra work here is unlikely to cause problems, massive import trees don't really occur in
     62            practice.
     63
     64        * css/StyleSheetContents.h:
     65        (WebCore::StyleSheetContents::create):
     66        (StyleSheetContents):
     67        * dom/ProcessingInstruction.cpp:
     68        (WebCore::ProcessingInstruction::parseStyleSheet):
     69        * dom/StyleElement.cpp:
     70        (WebCore::StyleElement::createSheet):
     71        * html/HTMLLinkElement.cpp:
     72        (WebCore::HTMLLinkElement::setCSSStyleSheet):
     73
    1742012-08-26  Andreas Kling  <kling@webkit.org>
    275
  • trunk/Source/WebCore/css/CSSStyleSheet.cpp

    r126656 r126717  
    3838#include "SecurityOrigin.h"
    3939#include "StyleRule.h"
     40#include "StyleRuleImport.h"
    4041#include "StyleSheetContents.h"
    4142#include <wtf/text/StringBuilder.h>
     
    284285        ec = HIERARCHY_REQUEST_ERR;
    285286        return 0;
    286     }       
     287    }
     288    if (rule->isImportRule())
     289        static_cast<StyleRuleImport*>(rule.get())->requestStyleSheet(rootStyleSheet(), m_contents->parserContext());
     290
    287291    if (!m_childRuleCSSOMWrappers.isEmpty())
    288292        m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>());
     
    371375}
    372376
    373 Document* CSSStyleSheet::ownerDocument() const
     377CSSStyleSheet* CSSStyleSheet::rootStyleSheet() const
    374378{
    375379    const CSSStyleSheet* root = this;
    376380    while (root->parentStyleSheet())
    377381        root = root->parentStyleSheet();
     382    return const_cast<CSSStyleSheet*>(root);
     383}
     384
     385Document* CSSStyleSheet::ownerDocument() const
     386{
     387    const CSSStyleSheet* root = rootStyleSheet();
    378388    return root->ownerNode() ? root->ownerNode()->document() : 0;
    379389}
  • trunk/Source/WebCore/css/CSSStyleSheet.h

    r125805 r126717  
    8282   
    8383    void clearOwnerRule() { m_ownerRule = 0; }
     84    CSSStyleSheet* rootStyleSheet() const;
    8485    Document* ownerDocument() const;
    8586    MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); }
  • trunk/Source/WebCore/css/StyleRuleImport.cpp

    r126154 r126717  
    3333namespace WebCore {
    3434
     35StyleRuleImport::LoadContext::LoadContext(CSSStyleSheet* rootStyleSheet, const CSSParserContext& parentParserContext)
     36    : rootStyleSheet(rootStyleSheet)
     37    , parentParserContext(parentParserContext)
     38{
     39}
     40
    3541PassRefPtr<StyleRuleImport> StyleRuleImport::create(const String& href, PassRefPtr<MediaQuerySet> media)
    3642{
     
    4046StyleRuleImport::StyleRuleImport(const String& href, PassRefPtr<MediaQuerySet> media)
    4147    : StyleRuleBase(Import, 0)
    42     , m_parentStyleSheet(0)
    43     , m_styleSheetClient(this)
    4448    , m_strHref(href)
    4549    , m_mediaQueries(media)
    4650    , m_cachedSheet(0)
    47     , m_loading(false)
    4851{
    4952    if (!m_mediaQueries)
     
    5356StyleRuleImport::~StyleRuleImport()
    5457{
    55     if (m_styleSheet)
    56         m_styleSheet->clearOwnerRule();
    5758    if (m_cachedSheet)
    58         m_cachedSheet->removeClient(&m_styleSheetClient);
     59        m_cachedSheet->removeClient(this);
    5960}
    6061
    61 void StyleRuleImport::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* cachedStyleSheet)
     62void StyleRuleImport::setCSSStyleSheet(const String& url, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*)
    6263{
    63     if (m_styleSheet)
    64         m_styleSheet->clearOwnerRule();
     64    ASSERT(m_loadContext);
     65    ASSERT(!m_styleSheet);
     66    ASSERT(m_cachedSheet);
    6567
    66     CSSParserContext context = m_parentStyleSheet ? m_parentStyleSheet->parserContext() : CSSStrictMode;
    67     context.charset = charset;
     68    OwnPtr<LoadContext> loadContext = m_loadContext.release();
     69
     70    CSSParserContext parserContext = loadContext->parentParserContext;
    6871    if (!baseURL.isNull())
    69         context.baseURL = baseURL;
     72        parserContext.baseURL = baseURL;
     73    parserContext.charset = charset;
    7074
    71     m_styleSheet = StyleSheetContents::create(this, href, context);
     75    m_styleSheet = StyleSheetContents::create(url, parserContext);
     76    m_styleSheet->parseAuthorStyleSheet(m_cachedSheet.get(), loadContext->rootStyleSheet.get());
    7277
    73     Document* document = m_parentStyleSheet ? m_parentStyleSheet->singleOwnerDocument() : 0;
    74     m_styleSheet->parseAuthorStyleSheet(cachedStyleSheet, document ? document->securityOrigin() : 0);
    75 
    76     m_loading = false;
    77 
    78     if (m_parentStyleSheet) {
    79         m_parentStyleSheet->notifyLoadedSheet(cachedStyleSheet);
    80         m_parentStyleSheet->checkLoaded();
    81     }
     78    loadContext->rootStyleSheet->contents()->checkLoadCompleted();
    8279}
    8380
    8481bool StyleRuleImport::isLoading() const
    8582{
    86     return m_loading || (m_styleSheet && m_styleSheet->isLoading());
     83    return m_loadContext || (m_styleSheet && m_styleSheet->isLoading());
    8784}
    8885
    89 void StyleRuleImport::requestStyleSheet()
     86bool StyleRuleImport::hadLoadError() const
    9087{
    91     if (!m_parentStyleSheet)
     88    return m_cachedSheet && m_cachedSheet->errorOccurred();
     89}
     90
     91void StyleRuleImport::requestStyleSheet(CSSStyleSheet* rootSheet, const CSSParserContext& parserContext)
     92{
     93    ASSERT(!rootSheet->parentStyleSheet());
     94    ASSERT(!m_cachedSheet);
     95
     96    Node* ownerNode = rootSheet->ownerNode();
     97    if (!ownerNode)
    9298        return;
    93     Document* document = m_parentStyleSheet->singleOwnerDocument();
    94     if (!document)
     99    Document* document = ownerNode->document();
     100
     101    KURL resolvedURL;
     102    if (!parserContext.baseURL.isNull())
     103        resolvedURL = KURL(parserContext.baseURL, m_strHref);
     104    else
     105        resolvedURL = document->completeURL(m_strHref);
     106
     107    StyleSheetContents* rootSheetContents = rootSheet->contents();
     108    if (rootSheetContents->hasImportCycle(this, resolvedURL, document->baseURL()))
    95109        return;
    96110
     111    ResourceRequest request(resolvedURL);
    97112    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    98     if (!cachedResourceLoader)
     113    if (rootSheetContents->isUserStyleSheet())
     114        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parserContext.charset);
     115    else
     116        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parserContext.charset);
     117
     118    if (!m_cachedSheet)
    99119        return;
     120    // if the import rule is issued dynamically, the sheet may be
     121    // removed from the pending sheet count, so let the doc know
     122    // the sheet being imported is pending.
     123    if (rootSheetContents->loadCompleted())
     124        ownerNode->startLoadingDynamicSheet();
    100125
    101     KURL absURL;
    102     if (!m_parentStyleSheet->baseURL().isNull())
    103         // use parent styleheet's URL as the base URL
    104         absURL = KURL(m_parentStyleSheet->baseURL(), m_strHref);
    105     else
    106         absURL = document->completeURL(m_strHref);
    107 
    108     // Check for a cycle in our import chain.  If we encounter a stylesheet
    109     // in our parent chain with the same URL, then just bail.
    110     StyleSheetContents* rootSheet = m_parentStyleSheet;
    111     for (StyleSheetContents* sheet = m_parentStyleSheet; sheet; sheet = sheet->parentStyleSheet()) {
    112         if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL())
    113             || equalIgnoringFragmentIdentifier(absURL, document->completeURL(sheet->originalURL())))
    114             return;
    115         rootSheet = sheet;
    116     }
    117 
    118     ResourceRequest request(absURL);
    119     if (m_parentStyleSheet->isUserStyleSheet())
    120         m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, m_parentStyleSheet->charset());
    121     else
    122         m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, m_parentStyleSheet->charset());
    123     if (m_cachedSheet) {
    124         // if the import rule is issued dynamically, the sheet may be
    125         // removed from the pending sheet count, so let the doc know
    126         // the sheet being imported is pending.
    127         if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() && rootSheet == m_parentStyleSheet)
    128             m_parentStyleSheet->startLoadingDynamicSheet();
    129         m_loading = true;
    130         m_cachedSheet->addClient(&m_styleSheetClient);
    131     }
     126    m_loadContext = adoptPtr(new LoadContext(rootSheet, parserContext));
     127    m_cachedSheet->addClient(this);
    132128}
    133129
  • trunk/Source/WebCore/css/StyleRuleImport.h

    r124435 r126717  
    2323#define StyleRuleImport_h
    2424
     25#include "CSSParserMode.h"
    2526#include "CachedResourceHandle.h"
    2627#include "CachedStyleSheetClient.h"
     
    3435class StyleSheetContents;
    3536
    36 class StyleRuleImport : public StyleRuleBase {
     37class StyleRuleImport : public StyleRuleBase, public CachedStyleSheetClient {
    3738public:
    3839    static PassRefPtr<StyleRuleImport> create(const String& href, PassRefPtr<MediaQuerySet>);
    3940
    40     ~StyleRuleImport();
    41    
    42     StyleSheetContents* parentStyleSheet() const { return m_parentStyleSheet; }
    43     void setParentStyleSheet(StyleSheetContents* sheet) { ASSERT(sheet); m_parentStyleSheet = sheet; }
    44     void clearParentStyleSheet() { m_parentStyleSheet = 0; }
     41    virtual ~StyleRuleImport();
    4542
    4643    String href() const { return m_strHref; }
     
    4845
    4946    bool isLoading() const;
     47    bool hadLoadError() const;
    5048    MediaQuerySet* mediaQueries() { return m_mediaQueries.get(); }
    5149
    52     void requestStyleSheet();
     50    void requestStyleSheet(CSSStyleSheet* rootSheet, const CSSParserContext&);
    5351
    5452    void reportDescendantMemoryUsage(MemoryObjectInfo*) const;
    5553
    5654private:
    57     // NOTE: We put the CachedStyleSheetClient in a member instead of inheriting from it
    58     // to avoid adding a vptr to StyleRuleImport.
    59     class ImportedStyleSheetClient : public CachedStyleSheetClient {
    60     public:
    61         ImportedStyleSheetClient(StyleRuleImport* ownerRule) : m_ownerRule(ownerRule) { }
    62         virtual ~ImportedStyleSheetClient() { }
    63         virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet)
    64         {
    65             m_ownerRule->setCSSStyleSheet(href, baseURL, charset, sheet);
    66         }
    67     private:
    68         StyleRuleImport* m_ownerRule;
    69     };
    70 
    71     void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*);
    72     friend class ImportedStyleSheetClient;
    73 
    7455    StyleRuleImport(const String& href, PassRefPtr<MediaQuerySet>);
    7556
    76     StyleSheetContents* m_parentStyleSheet;
     57    virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*);
    7758
    78     ImportedStyleSheetClient m_styleSheetClient;
    7959    String m_strHref;
    8060    RefPtr<MediaQuerySet> m_mediaQueries;
    8161    RefPtr<StyleSheetContents> m_styleSheet;
     62
    8263    CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet;
    83     bool m_loading;
     64    struct LoadContext {
     65        LoadContext(CSSStyleSheet* rootStyleSheet, const CSSParserContext& parentParserContext);
     66        RefPtr<CSSStyleSheet> rootStyleSheet;
     67        CSSParserContext parentParserContext;
     68    };
     69    OwnPtr<LoadContext> m_loadContext;
    8470};
    8571
  • trunk/Source/WebCore/css/StyleSheetContents.cpp

    r126154 r126717  
    5555}
    5656
    57 StyleSheetContents::StyleSheetContents(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext& context)
    58     : m_ownerRule(ownerRule)
    59     , m_originalURL(originalURL)
     57StyleSheetContents::StyleSheetContents(const String& originalURL, const CSSParserContext& context)
     58    : m_originalURL(originalURL)
    6059    , m_loadCompleted(false)
    61     , m_isUserStyleSheet(ownerRule && ownerRule->parentStyleSheet() && ownerRule->parentStyleSheet()->isUserStyleSheet())
    6260    , m_hasSyntacticallyValidCSSHeader(true)
    6361    , m_didLoadErrorOccur(false)
     
    7169StyleSheetContents::StyleSheetContents(const StyleSheetContents& o)
    7270    : RefCounted<StyleSheetContents>()
    73     , m_ownerRule(0)
    7471    , m_originalURL(o.m_originalURL)
    7572    , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule)
     
    104101    // FIXME: Support copying import rules.
    105102    if (!m_importRules.isEmpty())
    106         return false;
    107     // FIXME: Support cached stylesheets in import rules.
    108     if (m_ownerRule)
    109103        return false;
    110104    // This would require dealing with multiple clients for load callbacks.
     
    130124        ASSERT(m_childRules.isEmpty());
    131125        m_importRules.append(static_cast<StyleRuleImport*>(rule.get()));
    132         m_importRules.last()->setParentStyleSheet(this);
    133         m_importRules.last()->requestStyleSheet();
    134126        return;
    135127    }
     
    170162void StyleSheetContents::clearRules()
    171163{
    172     for (unsigned i = 0; i < m_importRules.size(); ++i) {
    173         ASSERT(m_importRules.at(i)->parentStyleSheet() == this);
    174         m_importRules[i]->clearParentStyleSheet();
    175     }
    176164    m_importRules.clear();
    177165    m_childRules.clear();
     
    208196            return false;
    209197        m_importRules.insert(childVectorIndex, static_cast<StyleRuleImport*>(rule.get()));
    210         m_importRules[childVectorIndex]->setParentStyleSheet(this);
    211         m_importRules[childVectorIndex]->requestStyleSheet();
    212         // FIXME: Stylesheet doesn't actually change meaningfully before the imported sheets are loaded.
    213198        return true;
    214199    }
     
    236221    }
    237222    if (childVectorIndex < m_importRules.size()) {
    238         m_importRules[childVectorIndex]->clearParentStyleSheet();
    239223        m_importRules.remove(childVectorIndex);
    240224        return;
     
    267251}
    268252
    269 void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet, const SecurityOrigin* securityOrigin)
    270 {
     253void StyleSheetContents::requestImportedStyleSheets(CSSStyleSheet* rootSheet)
     254{
     255    ASSERT(!rootSheet->parentStyleSheet());
     256    for (unsigned i = 0; i < m_importRules.size(); ++i)
     257        m_importRules[i]->requestStyleSheet(rootSheet, parserContext());
     258}
     259
     260void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cachedStyleSheet, CSSStyleSheet* rootSheet)
     261{
     262    if (cachedStyleSheet->errorOccurred()) {
     263        m_didLoadErrorOccur = true;
     264        return;
     265    }
     266    Document* ownerDocument = rootSheet->ownerDocument();
     267    if (!ownerDocument)
     268        return;
    271269    // Check to see if we should enforce the MIME type of the CSS resource in strict mode.
    272270    // Running in iWeb 2 is one example of where we don't want to - <rdar://problem/6099748>
     
    282280    // This prevents an attacker playing games by injecting CSS strings into HTML, XML, JSON, etc. etc.
    283281    if (!hasValidMIMEType && !hasSyntacticallyValidCSSHeader()) {
     282        const SecurityOrigin* securityOrigin = ownerDocument->securityOrigin();
    284283        bool isCrossOriginCSS = !securityOrigin || !securityOrigin->canRequest(baseURL());
    285284        if (isCrossOriginCSS) {
     
    295294        // while the other lacks the second trailing newline.
    296295        if (baseURL().string().endsWith(slashKHTMLFixesDotCss) && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText)
    297             && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1)
     296            && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) {
    298297            clearRules();
    299     }
     298            return;
     299        }
     300    }
     301
     302    requestImportedStyleSheets(rootSheet);
    300303}
    301304
     
    310313    p.parseSheet(this, sheetText, startLineNumber);
    311314
     315    if (!m_clients.isEmpty()) {
     316        ASSERT(m_clients.size() == 1);
     317        requestImportedStyleSheets(m_clients[0]);
     318    }
    312319    return true;
    313320}
     
    322329}
    323330
    324 void StyleSheetContents::checkLoaded()
    325 {
    326     if (isLoading())
    327         return;
    328 
    329     // Avoid |this| being deleted by scripts that run via
    330     // ScriptableDocumentParser::executeScriptsWaitingForStylesheets().
    331     // See <rdar://problem/6622300>.
    332     RefPtr<StyleSheetContents> protector(this);
    333     StyleSheetContents* parentSheet = parentStyleSheet();
    334     if (parentSheet) {
    335         parentSheet->checkLoaded();
    336         m_loadCompleted = true;
    337         return;
    338     }
    339     RefPtr<Node> ownerNode = singleOwnerNode();
    340     if (!ownerNode) {
    341         m_loadCompleted = true;
    342         return;
    343     }
     331bool StyleSheetContents::checkImportedSheetLoadCompleted()
     332{
     333    for (unsigned i = 0; i < m_importRules.size(); ++i) {
     334        StyleRuleImport* importRule = m_importRules[i].get();
     335        if (importRule->isLoading())
     336            return false;
     337        if (importRule->styleSheet() && !importRule->styleSheet()->checkImportedSheetLoadCompleted())
     338            return false;
     339        if (importRule->hadLoadError())
     340            m_didLoadErrorOccur = true;
     341    }
     342    m_loadCompleted = true;
     343    return true;
     344}
     345
     346void StyleSheetContents::checkLoadCompleted()
     347{
     348    if (m_clients.isEmpty())
     349        return;
     350    if (!checkImportedSheetLoadCompleted())
     351        return;
     352
     353    ASSERT(hasOneClient());
     354    ASSERT(!m_clients[0]->parentStyleSheet());
     355    RefPtr<Node> ownerNode = m_clients[0]->ownerNode();
     356    if (!ownerNode)
     357        return;
     358   
    344359    m_loadCompleted = ownerNode->sheetLoaded();
    345360    if (m_loadCompleted)
     
    347362}
    348363
    349 void StyleSheetContents::notifyLoadedSheet(const CachedCSSStyleSheet* sheet)
    350 {
    351     ASSERT(sheet);
    352     m_didLoadErrorOccur |= sheet->errorOccurred();
    353 }
    354 
    355 void StyleSheetContents::startLoadingDynamicSheet()
    356 {
    357     if (Node* owner = singleOwnerNode())
    358         owner->startLoadingDynamicSheet();
    359 }
    360 
    361 StyleSheetContents* StyleSheetContents::rootStyleSheet() const
    362 {
    363     const StyleSheetContents* root = this;
    364     while (root->parentStyleSheet())
    365         root = root->parentStyleSheet();
    366     return const_cast<StyleSheetContents*>(root);
    367 }
    368 
    369 Node* StyleSheetContents::singleOwnerNode() const
    370 {
    371     StyleSheetContents* root = rootStyleSheet();
    372     if (root->m_clients.isEmpty())
    373         return 0;
    374     ASSERT(root->m_clients.size() == 1);
    375     return root->m_clients[0]->ownerNode();
    376 }
    377 
    378 Document* StyleSheetContents::singleOwnerDocument() const
    379 {
    380     Node* ownerNode = singleOwnerNode();
    381     return ownerNode ? ownerNode->document() : 0;
     364bool StyleSheetContents::getAncestors(const StyleRuleImport* importRule, Vector<const StyleSheetContents*>& result) const
     365{
     366    result.append(this);
     367    for (unsigned i = 0; i < m_importRules.size(); ++i) {
     368        if (m_importRules[i] == importRule)
     369            return true;
     370    }
     371    for (unsigned i = 0; i < m_importRules.size(); ++i) {
     372        if (m_importRules[i]->styleSheet() && m_importRules[i]->styleSheet()->getAncestors(importRule, result))
     373            return true;
     374    }
     375    result.removeLast();
     376    return false;
     377}
     378
     379bool StyleSheetContents::hasImportCycle(const StyleRuleImport* importRule, const KURL& importURL, const KURL& documentBaseURL) const
     380{
     381    Vector<const StyleSheetContents*> ancestors;
     382    getAncestors(importRule, ancestors);
     383
     384    KURL parentBaseURL = documentBaseURL;
     385    for (unsigned i = 0; i < ancestors.size(); ++i) {
     386        if (equalIgnoringFragmentIdentifier(importURL, ancestors[i]->baseURL()))
     387            return true;
     388        if (equalIgnoringFragmentIdentifier(importURL, KURL(parentBaseURL, ancestors[i]->originalURL())))
     389            return true;
     390        parentBaseURL = ancestors[i]->baseURL();
     391    }
     392    return false;
    382393}
    383394
     
    452463}
    453464
    454 StyleSheetContents* StyleSheetContents::parentStyleSheet() const
    455 {
    456     return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0;
    457 }
    458 
    459465void StyleSheetContents::registerClient(CSSStyleSheet* sheet)
    460466{
  • trunk/Source/WebCore/css/StyleSheetContents.h

    r125805 r126717  
    4545    static PassRefPtr<StyleSheetContents> create(const CSSParserContext& context = CSSParserContext(CSSStrictMode))
    4646    {
    47         return adoptRef(new StyleSheetContents(0, String(), context));
     47        return adoptRef(new StyleSheetContents(String(), context));
    4848    }
    4949    static PassRefPtr<StyleSheetContents> create(const String& originalURL, const CSSParserContext& context)
    5050    {
    51         return adoptRef(new StyleSheetContents(0, originalURL, context));
    52     }
    53     static PassRefPtr<StyleSheetContents> create(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext& context)
    54     {
    55         return adoptRef(new StyleSheetContents(ownerRule, originalURL, context));
     51        return adoptRef(new StyleSheetContents(originalURL, context));
    5652    }
    5753
     
    6258    const AtomicString& determineNamespace(const AtomicString& prefix);
    6359
    64     void parseAuthorStyleSheet(const CachedCSSStyleSheet*, const SecurityOrigin*);
     60    void parseAuthorStyleSheet(const CachedCSSStyleSheet*, CSSStyleSheet* rootSheet);
    6561    bool parseString(const String&);
    6662    bool parseStringAtLine(const String&, int startLineNumber);
     
    7066    bool isLoading() const;
    7167
    72     void checkLoaded();
    73     void startLoadingDynamicSheet();
    74 
    75     StyleSheetContents* rootStyleSheet() const;
    76     Node* singleOwnerNode() const;
    77     Document* singleOwnerDocument() const;
     68    void checkLoadCompleted();
    7869
    7970    const String& charset() const { return m_parserContext.charset; }
     
    10394    const Vector<RefPtr<StyleRuleImport> >& importRules() const { return m_importRules; }
    10495
    105     void notifyLoadedSheet(const CachedCSSStyleSheet*);
    106    
    107     StyleSheetContents* parentStyleSheet() const;
    108     StyleRuleImport* ownerRule() const { return m_ownerRule; }
    109     void clearOwnerRule() { m_ownerRule = 0; }
    110    
     96    bool hasImportCycle(const StyleRuleImport* importRule, const KURL& importURL, const KURL& documentBaseURL) const;
     97
    11198    // Note that href is the URL that started the redirect chain that led to
    11299    // this style sheet. This property probably isn't useful for much except
     
    124111    bool wrapperInsertRule(PassRefPtr<StyleRuleBase>, unsigned index);
    125112    void wrapperDeleteRule(unsigned index);
     113
     114    void requestImportedStyleSheets(CSSStyleSheet* rootSheet);
    126115
    127116    PassRefPtr<StyleSheetContents> copy() const { return adoptRef(new StyleSheetContents(*this)); }
     
    141130
    142131private:
    143     StyleSheetContents(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext&);
     132    StyleSheetContents(const String& originalURL, const CSSParserContext&);
    144133    StyleSheetContents(const StyleSheetContents&);
    145134
    146135    void clearCharsetRule();
    147136
    148     StyleRuleImport* m_ownerRule;
     137    bool checkImportedSheetLoadCompleted();
     138    bool getAncestors(const StyleRuleImport*, Vector<const StyleSheetContents*>& result) const;
    149139
    150140    String m_originalURL;
  • trunk/Source/WebCore/dom/ProcessingInstruction.cpp

    r126127 r126717  
    255255
    256256    if (m_isCSS)
    257         static_cast<CSSStyleSheet*>(m_sheet.get())->contents()->checkLoaded();
     257        static_cast<CSSStyleSheet*>(m_sheet.get())->contents()->checkLoadCompleted();
    258258#if ENABLE(XSLT)
    259259    else if (m_isXSL)
  • trunk/Source/WebCore/dom/StyleElement.cpp

    r118585 r126717  
    182182
    183183    if (m_sheet)
    184         m_sheet->contents()->checkLoaded();
     184        m_sheet->contents()->checkLoadCompleted();
    185185}
    186186
  • trunk/Source/WebCore/html/HTMLLinkElement.cpp

    r125988 r126717  
    324324    m_sheet->setTitle(title());
    325325
    326     styleSheet->parseAuthorStyleSheet(cachedStyleSheet, document()->securityOrigin());
     326    styleSheet->parseAuthorStyleSheet(cachedStyleSheet, m_sheet.get());
    327327
    328328    m_loading = false;
    329     styleSheet->notifyLoadedSheet(cachedStyleSheet);
    330     styleSheet->checkLoaded();
     329    styleSheet->checkLoadCompleted();
    331330
    332331#if ENABLE(PARSED_STYLE_SHEET_CACHING)
Note: See TracChangeset for help on using the changeset viewer.