Changeset 110935 in webkit


Ignore:
Timestamp:
Mar 15, 2012 8:20:26 PM (12 years ago)
Author:
shinyak@chromium.org
Message:

[Crash] Adding <content> into a ShadowRoot causes crash.
https://bugs.webkit.org/show_bug.cgi?id=80020

Reviewed by Hajime Morita.

Source/WebCore:

The problem is <content> tries to select host children though it is not prepared.
Since populating host children for insertion points is performed just before
attaching a shadow tree, we should recalculate whole shadow tree if <content> is
appended as a child.

However, element->appendChild() does not know the element is in a shadow tree or not.
We have to ensure reattaching whole shadow tree here.

So this patch adds some phases to HTMLContentSelector so that we can check node
distribution algorihm is begin processed or not. If not we cannot select anything,
but we have to enable a flag to reattach whole shadow tree.

Tests: fast/dom/shadow/shadow-content-crash-expected.html

fast/dom/shadow/shadow-content-crash.html

  • dom/ShadowTree.cpp:

(WebCore::ShadowTree::attach):
(WebCore::ShadowTree::insertionPointFor):

  • dom/ShadowTree.h:

(WebCore):
(ShadowTree):
(WebCore::ShadowTree::selector):

  • html/shadow/HTMLContentSelector.cpp:

(WebCore::HTMLContentSelector::HTMLContentSelector):
(WebCore::HTMLContentSelector::select):
(WebCore::HTMLContentSelector::willSelect):
(WebCore):
(WebCore::HTMLContentSelector::didSelect):
(WebCore::HTMLContentSelector::populateIfNecessary):

  • html/shadow/HTMLContentSelector.h:

(HTMLContentSelector):
(WebCore::HTMLContentSelector::isSelecting):
(WebCore):
(WebCore::HTMLContentSelector::hasPopulated):

  • html/shadow/InsertionPoint.cpp:

(WebCore::InsertionPoint::distributeHostChildren):
(WebCore::InsertionPoint::clearDistribution):

LayoutTests:

  • fast/dom/shadow/shadow-content-crash-expected.html: Added.
  • fast/dom/shadow/shadow-content-crash.html: Added.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r110934 r110935  
     12012-03-15  Shinya Kawanaka  <shinyak@chromium.org>
     2
     3        [Crash] Adding <content> into a ShadowRoot causes crash.
     4        https://bugs.webkit.org/show_bug.cgi?id=80020
     5
     6        Reviewed by Hajime Morita.
     7
     8        * fast/dom/shadow/shadow-content-crash-expected.html: Added.
     9        * fast/dom/shadow/shadow-content-crash.html: Added.
     10
    1112012-03-15  Mike Lawther  <mikelawther@chromium.org>
    212
  • trunk/Source/WebCore/ChangeLog

    r110934 r110935  
     12012-03-15  Shinya Kawanaka  <shinyak@chromium.org>
     2
     3        [Crash] Adding <content> into a ShadowRoot causes crash.
     4        https://bugs.webkit.org/show_bug.cgi?id=80020
     5
     6        Reviewed by Hajime Morita.
     7
     8        The problem is <content> tries to select host children though it is not prepared.
     9        Since populating host children for insertion points is performed just before
     10        attaching a shadow tree, we should recalculate whole shadow tree if <content> is
     11        appended as a child.
     12
     13        However, element->appendChild() does not know the element is in a shadow tree or not.
     14        We have to ensure reattaching whole shadow tree here.
     15
     16        So this patch adds some phases to HTMLContentSelector so that we can check node
     17        distribution algorihm is begin processed or not. If not we cannot select anything,
     18        but we have to enable a flag to reattach whole shadow tree.
     19
     20        Tests: fast/dom/shadow/shadow-content-crash-expected.html
     21               fast/dom/shadow/shadow-content-crash.html
     22
     23        * dom/ShadowTree.cpp:
     24        (WebCore::ShadowTree::attach):
     25        (WebCore::ShadowTree::insertionPointFor):
     26        * dom/ShadowTree.h:
     27        (WebCore):
     28        (ShadowTree):
     29        (WebCore::ShadowTree::selector):
     30        * html/shadow/HTMLContentSelector.cpp:
     31        (WebCore::HTMLContentSelector::HTMLContentSelector):
     32        (WebCore::HTMLContentSelector::select):
     33        (WebCore::HTMLContentSelector::willSelect):
     34        (WebCore):
     35        (WebCore::HTMLContentSelector::didSelect):
     36        (WebCore::HTMLContentSelector::populateIfNecessary):
     37        * html/shadow/HTMLContentSelector.h:
     38        (HTMLContentSelector):
     39        (WebCore::HTMLContentSelector::isSelecting):
     40        (WebCore):
     41        (WebCore::HTMLContentSelector::hasPopulated):
     42        * html/shadow/InsertionPoint.cpp:
     43        (WebCore::InsertionPoint::distributeHostChildren):
     44        (WebCore::InsertionPoint::clearDistribution):
     45
    1462012-03-15  Mike Lawther  <mikelawther@chromium.org>
    247
  • trunk/Source/WebCore/dom/ShadowTree.cpp

    r110374 r110935  
    3131#include "Document.h"
    3232#include "Element.h"
    33 #include "HTMLContentSelector.h"
    3433#include "HTMLShadowElement.h"
    3534#include "InspectorInstrumentation.h"
     
    179178    // Children of m_selector is populated lazily in
    180179    // ensureSelector(), and here we just ensure that it is in clean state.
    181     ASSERT(!selector() || !selector()->hasCandidates());
    182 
     180    ASSERT(!selector().hasPopulated());
     181
     182    selector().willSelect();
    183183    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
    184184        if (!root->attached())
    185185            root->attach();
    186186    }
    187 
    188     if (HTMLContentSelector* contentSelector = selector())
    189         contentSelector->didSelect();
     187    selector().didSelect();
    190188}
    191189
     
    223221    }
    224222
    225     if (!m_selector)
    226         return 0;
    227     HTMLContentSelection* found = m_selector->findFor(node);
     223    HTMLContentSelection* found = selector().findFor(node);
    228224    if (!found)
    229225        return 0;
     
    318314}
    319315
    320 HTMLContentSelector* ShadowTree::ensureSelector()
    321 {
    322     if (!m_selector)
    323         m_selector = adoptPtr(new HTMLContentSelector());
    324     m_selector->willSelectOver(host());
    325     return m_selector.get();
    326 }
    327 
    328316} // namespace
  • trunk/Source/WebCore/dom/ShadowTree.h

    r110161 r110935  
    2929
    3030#include "ExceptionCode.h"
     31#include "HTMLContentSelector.h"
    3132#include "ShadowRoot.h"
    3233#include <wtf/DoublyLinkedList.h>
     
    3940class Node;
    4041class Element;
    41 class HTMLContentSelector;
    4242class InsertionPoint;
    4343class TreeScope;
     
    4747    ShadowTree();
    4848    ~ShadowTree();
     49
     50    Element* host() const;
    4951
    5052    bool hasShadowRoot() const;
     
    8082    InsertionPoint* insertionPointFor(Node*) const;
    8183
    82     HTMLContentSelector* selector() const;
    83     HTMLContentSelector* ensureSelector();
     84    HTMLContentSelector& selector();
     85    const HTMLContentSelector& selector() const;
    8486
    8587private:
    86     Element* host() const;
    8788
    8889    DoublyLinkedList<ShadowRoot> m_shadowRoots;
    89     OwnPtr<HTMLContentSelector> m_selector;
     90    HTMLContentSelector m_selector;
    9091    bool m_needsRecalculateContent : 1;
    9192    WTF_MAKE_NONCOPYABLE(ShadowTree);
     
    107108}
    108109
    109 inline HTMLContentSelector* ShadowTree::selector() const
     110inline HTMLContentSelector& ShadowTree::selector()
    110111{
    111     return m_selector.get();
     112    return m_selector;
     113}
     114
     115inline const HTMLContentSelector& ShadowTree::selector() const
     116{
     117    return m_selector;
    112118}
    113119
  • trunk/Source/WebCore/html/shadow/HTMLContentSelector.cpp

    r109313 r110935  
    101101
    102102HTMLContentSelector::HTMLContentSelector()
     103    : m_phase(SelectionPrevented)
    103104{
    104105}
     
    111112void HTMLContentSelector::select(InsertionPoint* insertionPoint, HTMLContentSelectionList* selections)
    112113{
     114    ASSERT(m_phase == HostChildrenPopulated);
    113115    ASSERT(selections->isEmpty());
    114116
     
    142144}
    143145
     146void HTMLContentSelector::willSelect()
     147{
     148    m_phase = SelectionStarted;
     149}
     150
    144151void HTMLContentSelector::didSelect()
    145152{
     153    ASSERT(m_phase != SelectionPrevented);
     154    m_phase = SelectionPrevented;
    146155    m_candidates.clear();
    147156}
    148157
    149 void HTMLContentSelector::willSelectOver(Element* shadowHost)
     158void HTMLContentSelector::populateIfNecessary(Element* shadowHost)
    150159{
    151     if (!m_candidates.isEmpty())
     160    if (hasPopulated())
    152161        return;
     162
     163    ASSERT(m_candidates.isEmpty());
    153164    ASSERT(shadowHost);
     165    ASSERT(m_phase == SelectionStarted);
     166
     167    m_phase = HostChildrenPopulated;
    154168    for (Node* node = shadowHost->firstChild(); node; node = node->nextSibling())
    155169        m_candidates.append(node);
  • trunk/Source/WebCore/html/shadow/HTMLContentSelector.h

    r109313 r110935  
    135135    HTMLContentSelection* findFor(Node* key) const;
    136136
    137     void willSelectOver(Element* shadowHost);
     137    void willSelect();
     138    bool isSelecting() const;
    138139    void didSelect();
    139     bool hasCandidates() const { return !m_candidates.isEmpty(); }
     140
     141    void populateIfNecessary(Element* shadowHost);
     142    bool hasPopulated() const;
    140143
    141144private:
     145    enum SelectingPhase {
     146        SelectionPrevented,
     147        SelectionStarted,
     148        HostChildrenPopulated,
     149    };
     150
    142151    void removeFromSet(HTMLContentSelectionList*);
    143152    void addToSet(HTMLContentSelectionList*);
     
    145154    Vector<RefPtr<Node> > m_candidates;
    146155    HTMLContentSelectionSet m_selectionSet;
     156    SelectingPhase m_phase;
    147157};
     158
     159inline bool HTMLContentSelector::isSelecting() const
     160{
     161    return m_phase != SelectionPrevented;
     162}
     163
     164inline bool HTMLContentSelector::hasPopulated() const
     165{
     166    return m_phase == HostChildrenPopulated;
     167}
    148168
    149169}
  • trunk/Source/WebCore/html/shadow/InsertionPoint.cpp

    r110161 r110935  
    110110inline void InsertionPoint::distributeHostChildren(ShadowTree* tree)
    111111{
    112     HTMLContentSelector* selector = tree->ensureSelector();
    113     selector->unselect(&m_selections);
    114     selector->select(this, &m_selections);
     112    if (!tree->selector().isSelecting()) {
     113        // If HTMLContentSelector is not int selecting phase, it means InsertionPoint is attached from
     114        // non-ShadowTree node. To run distribute algorithm, we have to reattach ShadowTree.
     115        tree->setNeedsReattachHostChildrenAndShadow();
     116        return;
     117    }
     118
     119    tree->selector().populateIfNecessary(tree->host());
     120    tree->selector().unselect(&m_selections);
     121    tree->selector().select(this, &m_selections);
    115122}
    116123
    117124inline void InsertionPoint::clearDistribution(ShadowTree* tree)
    118125{
    119     if (HTMLContentSelector* selector = tree->selector())
    120         selector->unselect(&m_selections);
     126    tree->selector().unselect(&m_selections);
    121127}
    122128
Note: See TracChangeset for help on using the changeset viewer.