Changeset 208403 in webkit


Ignore:
Timestamp:
Nov 4, 2016 3:53:33 PM (7 years ago)
Author:
rniwa@webkit.org
Message:

Load stylesheets in link elements inside a connected shadow tree
https://bugs.webkit.org/show_bug.cgi?id=160683
<rdar://problem/29040652>

Reviewed by Antti Koivisto.

Source/WebCore:

Allow external stylesheets within a shadow tree by storing the appropriate style scope in HTMLLinkElement
when it's connected to a document instead of always talking to document's style scope.

Tests: fast/shadow-dom/link-element-in-shadow-tree.html

fast/shadow-dom/selected-stylesheet-in-shadow-tree.html

  • html/HTMLLinkElement.cpp: (WebCore::HTMLLinkElement::HTMLLinkElement): (WebCore::HTMLLinkElement::~HTMLLinkElement): (WebCore::HTMLLinkElement::setDisabledState): Exit early when the element is not in a document as invoking didChangeActiveStyleSheetCandidates would require having a valid m_styleScope and process() already exits early when inDocument() is false. (WebCore::HTMLLinkElement::parseAttribute): (WebCore::HTMLLinkElement::process): Removed the early exit for when the element is in a shadow tree. (WebCore::HTMLLinkElement::insertedInto): Exit early unless this element has just become connected to a document instead of whenever its self-inclusive ancestor is inserted into a container. (WebCore::HTMLLinkElement::removedFrom): Ditto for removal. Also call removeStyleSheetCandidateNode after calling removePendingSheet since the latter depends on m_styleScope being not null. (WebCore::HTMLLinkElement::addPendingSheet): (WebCore::HTMLLinkElement::removePendingSheet):
  • html/HTMLLinkElement.h:
  • html/HTMLStyleElement.cpp: (WebCore::HTMLStyleElement::insertedInto): Only call inline style owner's insertedIntoDocument if this element has just become connected to a document. (WebCore::HTMLStyleElement::removedFrom): Ditto for the removal.
  • style/StyleScope.h:
  • svg/SVGStyleElement.cpp: (WebCore::SVGStyleElement::insertedInto): Ditto. (WebCore::SVGStyleElement::removedFrom): Ditto for the removal.

LayoutTests:

Added W3C style testharness.js tests for loading stylesheets via a link element inside a ahadow tree.

  • fast/shadow-dom/link-element-in-shadow-tree-expected.txt: Added.
  • fast/shadow-dom/link-element-in-shadow-tree.html: Added.
  • fast/shadow-dom/resources/green-host.css: Added.
  • fast/shadow-dom/selected-stylesheet-in-shadow-tree-expected.txt: Added.
  • fast/shadow-dom/selected-stylesheet-in-shadow-tree.html: Added.
Location:
trunk
Files:
5 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208397 r208403  
     12016-11-04  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Load stylesheets in link elements inside a connected shadow tree
     4        https://bugs.webkit.org/show_bug.cgi?id=160683
     5        <rdar://problem/29040652>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Added W3C style testharness.js tests for loading stylesheets via a link element inside a ahadow tree.
     10
     11        * fast/shadow-dom/link-element-in-shadow-tree-expected.txt: Added.
     12        * fast/shadow-dom/link-element-in-shadow-tree.html: Added.
     13        * fast/shadow-dom/resources/green-host.css: Added.
     14        * fast/shadow-dom/selected-stylesheet-in-shadow-tree-expected.txt: Added.
     15        * fast/shadow-dom/selected-stylesheet-in-shadow-tree.html: Added.
     16
    1172016-11-04  Chris Dumez  <cdumez@apple.com>
    218
  • trunk/Source/WebCore/ChangeLog

    r208399 r208403  
     12016-11-04  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Load stylesheets in link elements inside a connected shadow tree
     4        https://bugs.webkit.org/show_bug.cgi?id=160683
     5        <rdar://problem/29040652>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Allow external stylesheets within a shadow tree by storing the appropriate style scope in HTMLLinkElement
     10        when it's connected to a document instead of always talking to document's style scope.
     11
     12        Tests: fast/shadow-dom/link-element-in-shadow-tree.html
     13               fast/shadow-dom/selected-stylesheet-in-shadow-tree.html
     14
     15       * html/HTMLLinkElement.cpp:
     16       (WebCore::HTMLLinkElement::HTMLLinkElement):
     17       (WebCore::HTMLLinkElement::~HTMLLinkElement):
     18       (WebCore::HTMLLinkElement::setDisabledState): Exit early when the element is not in a document as invoking
     19       didChangeActiveStyleSheetCandidates would require having a valid m_styleScope and process() already exits
     20       early when inDocument() is false.
     21       (WebCore::HTMLLinkElement::parseAttribute):
     22       (WebCore::HTMLLinkElement::process): Removed the early exit for when the element is in a shadow tree.
     23       (WebCore::HTMLLinkElement::insertedInto): Exit early unless this element has just become connected to
     24       a document instead of whenever its self-inclusive ancestor is inserted into a container.
     25       (WebCore::HTMLLinkElement::removedFrom): Ditto for removal. Also call removeStyleSheetCandidateNode after
     26       calling removePendingSheet since the latter depends on m_styleScope being not null.
     27       (WebCore::HTMLLinkElement::addPendingSheet):
     28       (WebCore::HTMLLinkElement::removePendingSheet):
     29       * html/HTMLLinkElement.h:
     30       * html/HTMLStyleElement.cpp:
     31       (WebCore::HTMLStyleElement::insertedInto): Only call inline style owner's insertedIntoDocument if this
     32       element has just become connected to a document.
     33       (WebCore::HTMLStyleElement::removedFrom): Ditto for the removal.
     34       * style/StyleScope.h:
     35       * svg/SVGStyleElement.cpp:
     36       (WebCore::SVGStyleElement::insertedInto): Ditto.
     37       (WebCore::SVGStyleElement::removedFrom): Ditto for the removal.
     38
    1392016-11-04  Said Abou-Hallawa  <sabouhallawa@apple.com>
    240
  • trunk/Source/WebCore/html/HTMLLinkElement.cpp

    r208356 r208403  
    8181    , m_loading(false)
    8282    , m_createdByParser(createdByParser)
    83     , m_isInShadowTree(false)
    8483    , m_firedLoad(false)
    8584    , m_loadedResource(false)
     
    102101        m_cachedSheet->removeClient(*this);
    103102
    104     if (inDocument())
    105         document().styleScope().removeStyleSheetCandidateNode(*this);
     103    if (m_styleScope)
     104        m_styleScope->removeStyleSheetCandidateNode(*this);
    106105
    107106    linkLoadEventSender().cancelEvent(*this);
     
    113112    DisabledState oldDisabledState = m_disabledState;
    114113    m_disabledState = disabled ? Disabled : EnabledViaScript;
    115     if (oldDisabledState != m_disabledState) {
    116         // If we change the disabled state while the sheet is still loading, then we have to
    117         // perform three checks:
    118         if (styleSheetIsLoading()) {
    119             // Check #1: The sheet becomes disabled while loading.
    120             if (m_disabledState == Disabled)
    121                 removePendingSheet();
    122 
    123             // Check #2: An alternate sheet becomes enabled while it is still loading.
    124             if (m_relAttribute.isAlternate && m_disabledState == EnabledViaScript)
    125                 addPendingSheet(ActiveSheet);
    126 
    127             // Check #3: A main sheet becomes enabled while it was still loading and
    128             // after it was disabled via script. It takes really terrible code to make this
    129             // happen (a double toggle for no reason essentially). This happens on
    130             // virtualplastic.net, which manages to do about 12 enable/disables on only 3
    131             // sheets. :)
    132             if (!m_relAttribute.isAlternate && m_disabledState == EnabledViaScript && oldDisabledState == Disabled)
    133                 addPendingSheet(ActiveSheet);
    134 
    135             // If the sheet is already loading just bail.
    136             return;
    137         }
    138 
    139         // Load the sheet, since it's never been loaded before.
    140         if (!m_sheet && m_disabledState == EnabledViaScript)
    141             process();
    142         else
    143             document().styleScope().didChangeActiveStyleSheetCandidates();
     114    if (oldDisabledState == m_disabledState)
     115        return;
     116
     117    ASSERT(inDocument() || !styleSheetIsLoading());
     118    if (!inDocument())
     119        return;
     120
     121    // If we change the disabled state while the sheet is still loading, then we have to
     122    // perform three checks:
     123    if (styleSheetIsLoading()) {
     124        // Check #1: The sheet becomes disabled while loading.
     125        if (m_disabledState == Disabled)
     126            removePendingSheet();
     127
     128        // Check #2: An alternate sheet becomes enabled while it is still loading.
     129        if (m_relAttribute.isAlternate && m_disabledState == EnabledViaScript)
     130            addPendingSheet(ActiveSheet);
     131
     132        // Check #3: A main sheet becomes enabled while it was still loading and
     133        // after it was disabled via script. It takes really terrible code to make this
     134        // happen (a double toggle for no reason essentially). This happens on
     135        // virtualplastic.net, which manages to do about 12 enable/disables on only 3
     136        // sheets. :)
     137        if (!m_relAttribute.isAlternate && m_disabledState == EnabledViaScript && oldDisabledState == Disabled)
     138            addPendingSheet(ActiveSheet);
     139
     140        // If the sheet is already loading just bail.
     141        return;
     142    }
     143
     144    // Load the sheet, since it's never been loaded before.
     145    if (!m_sheet && m_disabledState == EnabledViaScript)
     146        process();
     147    else {
     148        ASSERT(m_styleScope);
     149        m_styleScope->didChangeActiveStyleSheetCandidates();
    144150    }
    145151}
     
    177183        process();
    178184        if (m_sheet && !isDisabled())
    179             document().styleScope().didChangeActiveStyleSheetCandidates();
     185            m_styleScope->didChangeActiveStyleSheetCandidates();
    180186        return;
    181187    }
     
    215221void HTMLLinkElement::process()
    216222{
    217     if (!inDocument() || m_isInShadowTree) {
     223    if (!inDocument()) {
    218224        ASSERT(!m_sheet);
    219225        return;
     
    284290        // we no longer contain a stylesheet, e.g. perhaps rel or type was changed
    285291        clearSheet();
    286         document().styleScope().didChangeActiveStyleSheetCandidates();
     292        m_styleScope->didChangeActiveStyleSheetCandidates();
    287293    }
    288294}
     
    298304Node::InsertionNotificationRequest HTMLLinkElement::insertedInto(ContainerNode& insertionPoint)
    299305{
     306    bool wasInDocument = inDocument();
    300307    HTMLElement::insertedInto(insertionPoint);
    301     if (!insertionPoint.inDocument())
     308    if (!insertionPoint.inDocument() || wasInDocument)
    302309        return InsertionDone;
    303310
    304     m_isInShadowTree = isInShadowTree();
    305     if (m_isInShadowTree)
    306         return InsertionDone;
    307 
    308     document().styleScope().addStyleSheetCandidateNode(*this, m_createdByParser);
     311    m_styleScope = &Style::Scope::forNode(*this);
     312    m_styleScope->addStyleSheetCandidateNode(*this, m_createdByParser);
    309313
    310314    process();
     
    315319{
    316320    HTMLElement::removedFrom(insertionPoint);
    317     if (!insertionPoint.inDocument())
    318         return;
    319 
    320     if (m_isInShadowTree) {
    321         ASSERT(!m_sheet);
    322         return;
    323     }
    324     document().styleScope().removeStyleSheetCandidateNode(*this);
     321    if (!insertionPoint.inDocument() || inDocument())
     322        return;
    325323
    326324    if (m_sheet)
     
    329327    if (styleSheetIsLoading())
    330328        removePendingSheet(RemovePendingSheetNotifyLater);
     329   
     330    if (m_styleScope) {
     331        m_styleScope->removeStyleSheetCandidateNode(*this);
     332        m_styleScope = nullptr;
     333    }
     334
    331335}
    332336
     
    545549    if (m_pendingSheetType == InactiveSheet)
    546550        return;
    547     document().styleScope().addPendingSheet();
     551    ASSERT(m_styleScope);
     552    m_styleScope->addPendingSheet();
    548553}
    549554
     
    556561        return;
    557562
     563    ASSERT(m_styleScope);
    558564    if (type == InactiveSheet) {
    559565        // Document just needs to know about the sheet for exposure through document.styleSheets
    560         document().styleScope().didChangeActiveStyleSheetCandidates();
    561         return;
    562     }
    563 
    564     document().styleScope().removePendingSheet(
     566        m_styleScope->didChangeActiveStyleSheetCandidates();
     567        return;
     568    }
     569
     570    m_styleScope->removePendingSheet(
    565571        notification == RemovePendingSheetNotifyImmediately
    566572        ? Style::Scope::RemovePendingSheetNotifyImmediately
  • trunk/Source/WebCore/html/HTMLLinkElement.h

    r208356 r208403  
    120120
    121121    LinkLoader m_linkLoader;
     122    Style::Scope* m_styleScope { nullptr };
    122123    CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet;
    123124    RefPtr<CSSStyleSheet> m_sheet;
     
    135136    bool m_loading;
    136137    bool m_createdByParser;
    137     bool m_isInShadowTree;
    138138    bool m_firedLoad;
    139139    bool m_loadedResource;
  • trunk/Source/WebCore/html/HTMLStyleElement.cpp

    r208356 r208403  
    9595Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode& insertionPoint)
    9696{
    97     HTMLElement::insertedInto(insertionPoint);
    98     if (insertionPoint.inDocument())
     97    bool wasInDocument = inDocument();
     98    auto result = HTMLElement::insertedInto(insertionPoint);
     99    if (insertionPoint.inDocument() && !wasInDocument)
    99100        m_styleSheetOwner.insertedIntoDocument(*this);
    100 
    101     return InsertionDone;
     101    return result;
    102102}
    103103
     
    105105{
    106106    HTMLElement::removedFrom(insertionPoint);
    107 
    108     if (insertionPoint.inDocument())
     107    if (insertionPoint.inDocument() && !inDocument())
    109108        m_styleSheetOwner.removedFromDocument(*this);
    110109}
  • trunk/Source/WebCore/svg/SVGStyleElement.cpp

    r208356 r208403  
    117117Node::InsertionNotificationRequest SVGStyleElement::insertedInto(ContainerNode& rootParent)
    118118{
    119     SVGElement::insertedInto(rootParent);
    120     if (rootParent.inDocument())
     119    bool wasInDocument = inDocument();
     120    auto result = SVGElement::insertedInto(rootParent);
     121    if (rootParent.inDocument() && !wasInDocument)
    121122        m_styleSheetOwner.insertedIntoDocument(*this);
    122     return InsertionDone;
     123    return result;
    123124}
    124125
     
    126127{
    127128    SVGElement::removedFrom(rootParent);
    128     if (rootParent.inDocument())
     129    if (rootParent.inDocument() && !inDocument())
    129130        m_styleSheetOwner.removedFromDocument(*this);
    130131}
Note: See TracChangeset for help on using the changeset viewer.