root/trunk/WebCore/dom/Element.h

Revision 55167, 14.2 KB (checked in by enrica@apple.com, 3 weeks ago)

WebCore: Crash in createContextualFragment when inserting a list in a non HTML document.
< rdar://problem/7666670>
 https://bugs.webkit.org/show_bug.cgi?id=35305

Reviewed by Darin Adler.

createFragmentFromMarkup did not handle correctly the case where documentElement is
not an HTMLElement. The static cast to HTMLElement was causing createContextualFragment to
crash.

Test: editing/execCommand/insert-list-xml.xhtml

* dom/Element.cpp:
(WebCore::Element::createContextualFragment): Added.
* dom/Element.h: Added createContextualFragment virtual function.
* editing/markup.cpp:
(WebCore::createFragmentFromMarkup): Removed static cast to HTMLElement.
* html/HTMLElement.cpp:
(WebCore::HTMLElement::createContextualFragment): Modified to perform only checks
that are specific for an HTMLElement object. The rest of the logic has been moved to the
corresponding method in the Element class.

LayoutTests: Crash in createContextualFragment when inserting a list in a non HTML document.
< rdar://problem/7666670>
 https://bugs.webkit.org/show_bug.cgi?id=35305

Reviewed by Darin Adler.

* editing/execCommand/insert-list-xml-expected.txt: Added.
* editing/execCommand/insert-list-xml.xhtml: Added.

  • Property svn:eol-style set to native
Line 
1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 *           (C) 2001 Peter Kelly (pmk@post.com)
5 *           (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB.  If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#ifndef Element_h
26#define Element_h
27
28#include "ContainerNode.h"
29#include "Document.h"
30#include "HTMLNames.h"
31#include "MappedAttributeEntry.h"
32#include "QualifiedName.h"
33#include "ScrollTypes.h"
34
35namespace WebCore {
36
37class Attr;
38class Attribute;
39class CSSStyleDeclaration;
40class ClientRect;
41class ClientRectList;
42class ElementRareData;
43class IntSize;
44
45class Element : public ContainerNode {
46public:
47    static PassRefPtr<Element> create(const QualifiedName&, Document*);
48    virtual ~Element();
49
50    DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
51    DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
52    DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
53    DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
54    DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
55    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
56    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
57    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
58    DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
59    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
60    DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
61    DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
62    DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
63    DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
64    DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
65    DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
66    DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
67    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
68    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
69    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
70    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
71    DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
72    DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
73    DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
74    DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
75    DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
76
77    // These four attribute event handler attributes are overridden by HTMLBodyElement
78    // and HTMLFrameSetElement to forward to the DOMWindow.
79    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
80    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
81    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
82    DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
83
84    // WebKit extensions
85    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
86    DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
87    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
88    DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
89    DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
90    DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
91    DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
92    DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
93    DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
94#if ENABLE(TOUCH_EVENTS)
95    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
96    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
97    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
98    DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
99#endif
100
101    virtual PassRefPtr<DocumentFragment> createContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
102
103    const AtomicString& getIDAttribute() const;
104    bool hasAttribute(const QualifiedName&) const;
105    const AtomicString& getAttribute(const QualifiedName&) const;
106    void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&);
107    void removeAttribute(const QualifiedName&, ExceptionCode&);
108
109    bool hasAttributes() const;
110
111    bool hasAttribute(const String& name) const;
112    bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
113
114    const AtomicString& getAttribute(const String& name) const;
115    const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
116
117    void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
118    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
119
120    const QualifiedName& idAttributeName() const;
121
122    void scrollIntoView(bool alignToTop = true);
123    void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
124
125    void scrollByLines(int lines);
126    void scrollByPages(int pages);
127
128    int offsetLeft();
129    int offsetTop();
130    int offsetWidth();
131    int offsetHeight();
132    Element* offsetParent();
133    int clientLeft();
134    int clientTop();
135    int clientWidth();
136    int clientHeight();
137    virtual int scrollLeft() const;
138    virtual int scrollTop() const;
139    virtual void setScrollLeft(int);
140    virtual void setScrollTop(int);
141    virtual int scrollWidth() const;
142    virtual int scrollHeight() const;
143
144    PassRefPtr<ClientRectList> getClientRects() const;
145    PassRefPtr<ClientRect> getBoundingClientRect() const;
146
147    void removeAttribute(const String& name, ExceptionCode&);
148    void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
149
150    PassRefPtr<Attr> getAttributeNode(const String& name);
151    PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
152    PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
153    PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
154    PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
155   
156    virtual CSSStyleDeclaration* style();
157
158    const QualifiedName& tagQName() const { return m_tagName; }
159    String tagName() const { return nodeName(); }
160    bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
161   
162    // A fast function for checking the local name against another atomic string.
163    bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
164    bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
165
166    const AtomicString& localName() const { return m_tagName.localName(); }
167    const AtomicString& prefix() const { return m_tagName.prefix(); }
168    const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
169
170    virtual KURL baseURI() const;
171
172    virtual String nodeName() const;
173
174    PassRefPtr<Element> cloneElementWithChildren();
175    PassRefPtr<Element> cloneElementWithoutChildren();
176
177    void normalizeAttributes();
178    String nodeNamePreservingCase() const;
179
180    // convenience methods which ignore exceptions
181    void setAttribute(const QualifiedName&, const AtomicString& value);
182    void setBooleanAttribute(const QualifiedName& name, bool);
183    // Please don't use setCStringAttribute in performance-sensitive code;
184    // use a static AtomicString value instead to avoid the conversion overhead.
185    void setCStringAttribute(const QualifiedName&, const char* cStringValue);
186
187    virtual NamedNodeMap* attributes() const;
188    NamedNodeMap* attributes(bool readonly) const;
189
190    // This method is called whenever an attribute is added, changed or removed.
191    virtual void attributeChanged(Attribute*, bool preserveDecls = false);
192
193    // not part of the DOM
194    void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed);
195    NamedNodeMap* attributeMap() const { return namedAttrMap.get(); }
196
197    virtual void copyNonAttributeProperties(const Element* /*source*/) { }
198
199    virtual void attach();
200    virtual void detach();
201    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
202    virtual void recalcStyle(StyleChange = NoChange);
203
204    virtual RenderStyle* computedStyle();
205
206    void dispatchAttrRemovalEvent(Attribute*);
207    void dispatchAttrAdditionEvent(Attribute*);
208
209    virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
210
211    virtual bool isURLAttribute(Attribute*) const;
212    KURL getURLAttribute(const QualifiedName&) const;
213    virtual const QualifiedName& imageSourceAttributeName() const;
214    virtual String target() const { return String(); }
215
216    virtual void focus(bool restorePreviousSelection = true);
217    virtual void updateFocusAppearance(bool restorePreviousSelection);
218    void blur();
219
220    String innerText() const;
221    String outerText() const;
222 
223    virtual String title() const;
224
225    String openTagStartToString() const;
226
227    void updateId(const AtomicString& oldId, const AtomicString& newId);
228
229    IntSize minimumSizeForResizing() const;
230    void setMinimumSizeForResizing(const IntSize&);
231
232    // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
233    virtual void documentWillBecomeInactive() { }
234    virtual void documentDidBecomeActive() { }
235
236    // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
237    virtual void mediaVolumeDidChange() { }
238
239    bool isFinishedParsingChildren() const { return m_parsingChildrenFinished; }
240    virtual void finishParsingChildren();
241    virtual void beginParsingChildren() { m_parsingChildrenFinished = false; }
242
243    // ElementTraversal API
244    Element* firstElementChild() const;
245    Element* lastElementChild() const;
246    Element* previousElementSibling() const;
247    Element* nextElementSibling() const;
248    unsigned childElementCount() const;
249
250    bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
251
252    virtual bool isFormControlElement() const { return false; }
253    virtual bool isEnabledFormControl() const { return true; }
254    virtual bool isReadOnlyFormControl() const { return false; }
255    virtual bool isTextFormControl() const { return false; }
256    virtual bool isOptionalFormControl() const { return false; }
257    virtual bool isRequiredFormControl() const { return false; }
258    virtual bool isDefaultButtonForForm() const { return false; }
259    virtual bool willValidate() const { return false; }
260    virtual bool isValidFormControlElement() { return false; }
261
262    virtual bool formControlValueMatchesRenderer() const { return false; }
263    virtual void setFormControlValueMatchesRenderer(bool) { }
264
265    virtual const AtomicString& formControlName() const { return nullAtom; }
266    virtual const AtomicString& formControlType() const { return nullAtom; }
267
268    virtual bool saveFormControlState(String&) const { return false; }
269    virtual void restoreFormControlState(const String&) { }
270
271    virtual void dispatchFormControlChangeEvent() { }
272
273protected:
274    Element(const QualifiedName&, Document*, ConstructionType);
275
276    virtual void insertedIntoDocument();
277    virtual void removedFromDocument();
278    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
279
280    // The implementation of Element::attributeChanged() calls the following two functions.
281    // They are separated to allow a different flow of control in StyledElement::attributeChanged().
282    void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
283    void updateAfterAttributeChanged(Attribute*);
284
285private:
286    void scrollByUnits(int units, ScrollGranularity);
287
288    virtual void setPrefix(const AtomicString&, ExceptionCode&);
289    virtual NodeType nodeType() const;
290    virtual bool childTypeAllowed(NodeType);
291
292    virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
293    const QualifiedName& rareIDAttributeName() const;
294   
295#ifndef NDEBUG
296    virtual void formatForDebugger(char* buffer, unsigned length) const;
297#endif
298
299    bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
300
301    virtual void createAttributeMap() const;
302
303    virtual void updateStyleAttribute() const { }
304
305#if ENABLE(SVG)
306    virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
307#endif
308
309    void cancelFocusAppearanceUpdate();
310
311    virtual const AtomicString& virtualPrefix() const { return prefix(); }
312    virtual const AtomicString& virtualLocalName() const { return localName(); }
313    virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
314   
315    // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
316    // are used instead.
317    virtual PassRefPtr<Node> cloneNode(bool deep);
318
319    QualifiedName m_tagName;
320    virtual NodeRareData* createRareData();
321
322    ElementRareData* rareData() const;
323    ElementRareData* ensureRareData();
324   
325protected:
326    mutable RefPtr<NamedNodeMap> namedAttrMap;
327};
328   
329inline bool Node::hasTagName(const QualifiedName& name) const
330{
331    return isElementNode() && static_cast<const Element*>(this)->hasTagName(name);
332}
333
334inline bool Node::hasAttributes() const
335{
336    return isElementNode() && static_cast<const Element*>(this)->hasAttributes();
337}
338
339inline NamedNodeMap* Node::attributes() const
340{
341    return isElementNode() ? static_cast<const Element*>(this)->attributes() : 0;
342}
343
344inline Element* Node::parentElement() const
345{
346    Node* parent = parentNode();
347    return parent && parent->isElementNode() ? static_cast<Element*>(parent) : 0;
348}
349
350inline const QualifiedName& Element::idAttributeName() const
351{
352    return hasRareData() ? rareIDAttributeName() : HTMLNames::idAttr;
353}
354
355inline NamedNodeMap* Element::attributes(bool readonly) const
356{
357    if (!m_isStyleAttributeValid)
358        updateStyleAttribute();
359
360#if ENABLE(SVG)
361    if (!m_areSVGAttributesValid)
362        updateAnimatedSVGAttribute(anyQName());
363#endif
364
365    if (!readonly && !namedAttrMap)
366        createAttributeMap();
367    return namedAttrMap.get();
368}
369
370inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
371{
372    if (!inDocument())
373        return;
374
375    if (oldId == newId)
376        return;
377
378    Document* doc = document();
379    if (!oldId.isEmpty())
380        doc->removeElementById(oldId, this);
381    if (!newId.isEmpty())
382        doc->addElementById(newId, this);
383}
384
385} //namespace
386
387#endif
Note: See TracBrowser for help on using the browser.