diff options
Diffstat (limited to 'WebCore/dom')
81 files changed, 2658 insertions, 4158 deletions
diff --git a/WebCore/dom/Attr.idl b/WebCore/dom/Attr.idl index 42ac04c..ccbfada 100644 --- a/WebCore/dom/Attr.idl +++ b/WebCore/dom/Attr.idl @@ -25,7 +25,7 @@ module core { GenerateNativeConverter, InterfaceUUID=EEE8E22B-22C3-4e50-95F4-5E0B8AAD8231, ImplementationUUID=41B16348-D8E7-4d21-BFDB-125705B7E91F - ] Attr : EventTargetNode { + ] Attr : Node { // DOM Level 1 diff --git a/WebCore/dom/CharacterData.cpp b/WebCore/dom/CharacterData.cpp index 0ce4170..54e1888 100644 --- a/WebCore/dom/CharacterData.cpp +++ b/WebCore/dom/CharacterData.cpp @@ -31,13 +31,13 @@ namespace WebCore { CharacterData::CharacterData(Document *doc, bool isText) - : EventTargetNode(doc, false, false, isText) + : Node(doc, false, false, isText) , m_data(StringImpl::empty()) { } CharacterData::CharacterData(Document* document, const String& text, bool isText) - : EventTargetNode(document, false, false, isText) + : Node(document, false, false, isText) { m_data = text.impl() ? text.impl() : StringImpl::empty(); } @@ -224,7 +224,7 @@ bool CharacterData::rendererIsNeeded(RenderStyle *style) { if (!m_data || !length()) return false; - return EventTargetNode::rendererIsNeeded(style); + return Node::rendererIsNeeded(style); } bool CharacterData::offsetInCharacters() const diff --git a/WebCore/dom/CharacterData.h b/WebCore/dom/CharacterData.h index 412650e..d9e55c0 100644 --- a/WebCore/dom/CharacterData.h +++ b/WebCore/dom/CharacterData.h @@ -23,11 +23,11 @@ #ifndef CharacterData_h #define CharacterData_h -#include "EventTargetNode.h" +#include "Node.h" namespace WebCore { -class CharacterData : public EventTargetNode { +class CharacterData : public Node { public: CharacterData(Document*, const String& text, bool isText = false); CharacterData(Document*, bool isText = false); diff --git a/WebCore/dom/CharacterData.idl b/WebCore/dom/CharacterData.idl index 74dc483..7c8c7ac 100644 --- a/WebCore/dom/CharacterData.idl +++ b/WebCore/dom/CharacterData.idl @@ -23,7 +23,7 @@ module core { GenerateConstructor, InterfaceUUID=149159F4-D2BA-4040-8137-6BF6424C972A, ImplementationUUID=E2095280-B9BD-446a-8C03-79F78417CDFF - ] CharacterData : EventTargetNode { + ] CharacterData : Node { attribute [ConvertNullToNullString] DOMString data setter raises(DOMException); diff --git a/WebCore/dom/WorkerTask.cpp b/WebCore/dom/ClientRect.cpp index 4a22c59..c69a2ab 100644 --- a/WebCore/dom/WorkerTask.cpp +++ b/WebCore/dom/ClientRect.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,17 +25,17 @@ */ #include "config.h" - -#if ENABLE(WORKERS) - -#include "WorkerTask.h" +#include "ClientRect.h" namespace WebCore { -WorkerTask::~WorkerTask() +ClientRect::ClientRect() { } -} // namespace WebCore +ClientRect::ClientRect(const IntRect& rect) + : m_rect(rect) +{ +} -#endif // ENABLE(WORKERS) +} // namespace WebCore diff --git a/WebCore/dom/ClientRect.h b/WebCore/dom/ClientRect.h new file mode 100644 index 0000000..349ea85 --- /dev/null +++ b/WebCore/dom/ClientRect.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ClientRect_h +#define ClientRect_h + +#include "FloatRect.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + + class IntRect; + + class ClientRect : public RefCounted<ClientRect> { + public: + static PassRefPtr<ClientRect> create() { return adoptRef(new ClientRect); } + static PassRefPtr<ClientRect> create(const IntRect& rect) { return adoptRef(new ClientRect(rect)); } + + float top() const { return m_rect.y(); } + float right() const { return m_rect.right(); } + float bottom() const { return m_rect.bottom(); } + float left() const { return m_rect.x(); } + float width() const { return m_rect.width(); } + float height() const { return m_rect.height(); } + + private: + ClientRect(); + ClientRect(const IntRect&); + + FloatRect m_rect; + }; + +} // namespace WebCore + +#endif // ClientRect_h diff --git a/WebCore/dom/WorkerTask.h b/WebCore/dom/ClientRect.idl index a842ce2..6f0598f 100644 --- a/WebCore/dom/WorkerTask.h +++ b/WebCore/dom/ClientRect.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,25 +24,17 @@ * */ -#ifndef WorkerTask_h -#define WorkerTask_h - -#if ENABLE(WORKERS) - -#include <wtf/Threading.h> - -namespace WebCore { - - class WorkerContext; - - class WorkerTask : public ThreadSafeShared<WorkerTask> { - public: - virtual ~WorkerTask(); - virtual void performTask(WorkerContext*) = 0; +module view { + + interface [ + GenerateConstructor + ] ClientRect { + readonly attribute float top; + readonly attribute float right; + readonly attribute float bottom; + readonly attribute float left; + readonly attribute float width; + readonly attribute float height; }; -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // WorkerTask_h +} diff --git a/WebCore/dom/ClientRectList.cpp b/WebCore/dom/ClientRectList.cpp new file mode 100644 index 0000000..95ec758 --- /dev/null +++ b/WebCore/dom/ClientRectList.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "config.h" +#include "ClientRectList.h" + +#include "ExceptionCode.h" +#include "ClientRect.h" + +namespace WebCore { + +ClientRectList::ClientRectList() +{ +} + +ClientRectList::ClientRectList(const Vector<FloatQuad>& quads) +{ + m_list.reserveInitialCapacity(quads.size()); + for (size_t i = 0; i < quads.size(); ++i) + m_list.append(ClientRect::create(quads[i].enclosingBoundingBox())); +} + +ClientRectList::~ClientRectList() +{ +} + +unsigned ClientRectList::length() const +{ + return m_list.size(); +} + +ClientRect* ClientRectList::item(unsigned index) +{ + if (index >= m_list.size()) { + // FIXME: this should throw an exception. + // ec = INDEX_SIZE_ERR; + return 0; + } + + return m_list[index].get(); +} + +} // namespace WebCore diff --git a/WebCore/dom/WorkerLocation.h b/WebCore/dom/ClientRectList.h index 52c31ad..03915b1 100644 --- a/WebCore/dom/WorkerLocation.h +++ b/WebCore/dom/ClientRectList.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,50 +24,34 @@ * */ -#ifndef WorkerLocation_h -#define WorkerLocation_h +#ifndef ClientRectList_h +#define ClientRectList_h -#if ENABLE(WORKERS) - -#include "KURL.h" +#include "FloatQuad.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> +#include <wtf/Vector.h> namespace WebCore { - class String; + class ClientRect; - class WorkerLocation : public RefCounted<WorkerLocation> { + class ClientRectList : public RefCounted<ClientRectList> { public: - static PassRefPtr<WorkerLocation> create(const KURL& url) - { - return adoptRef(new WorkerLocation(url)); - } - - const KURL& url() const { return m_url; } - - String href() const; + static PassRefPtr<ClientRectList> create() { return adoptRef(new ClientRectList); } + static PassRefPtr<ClientRectList> create(const Vector<FloatQuad>& quads) { return adoptRef(new ClientRectList(quads)); } + ~ClientRectList(); - // URI decomposition attributes - String protocol() const; - String host() const; - String hostname() const; - String port() const; - String pathname() const; - String search() const; - String hash() const; - - String toString() const; + unsigned length() const; + ClientRect* item(unsigned index); private: - WorkerLocation(const KURL& url) : m_url(url) { } + ClientRectList(); + ClientRectList(const Vector<FloatQuad>&); - KURL m_url; - }; + Vector<RefPtr<ClientRect> > m_list; + }; } // namespace WebCore -#endif // ENABLE(WORKERS) - -#endif // WorkerLocation_h +#endif // ClientRectList_h diff --git a/WebCore/dom/Worker.idl b/WebCore/dom/ClientRectList.idl index 2ef9b62..8230f6c 100644 --- a/WebCore/dom/Worker.idl +++ b/WebCore/dom/ClientRectList.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,25 +24,15 @@ * */ -module threads { +module view { - interface [CustomMarkFunction, Conditional=WORKERS] Worker { - - attribute EventListener onerror; - attribute EventListener onmessage; - void postMessage(in DOMString message); - - void terminate(); - - // EventTarget interface - [Custom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [Custom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - boolean dispatchEvent(in Event evt) - raises(EventException); + interface [ + GenerateConstructor, + HasIndexGetter + ] ClientRectList { + readonly attribute unsigned long length; + ClientRect item(in [IsIndex] unsigned long index); + // FIXME: Fix list behavior to allow custom exceptions to be thrown. }; } diff --git a/WebCore/dom/Clipboard.cpp b/WebCore/dom/Clipboard.cpp index f7a52ef..6d1bc15 100644 --- a/WebCore/dom/Clipboard.cpp +++ b/WebCore/dom/Clipboard.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "Clipboard.h" +#include "CachedImage.h" #include "DOMImplementation.h" #include "Frame.h" #include "FrameLoader.h" diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp index 958fc4e..91b633f 100644 --- a/WebCore/dom/ContainerNode.cpp +++ b/WebCore/dom/ContainerNode.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -32,6 +32,7 @@ #include "FrameView.h" #include "InlineTextBox.h" #include "MutationEvent.h" +#include "Page.h" #include "RenderTheme.h" #include "RootInlineBox.h" #include <wtf/CurrentTime.h> @@ -42,16 +43,10 @@ static void dispatchChildInsertionEvents(Node*, ExceptionCode&); static void dispatchChildRemovalEvents(Node*, ExceptionCode&); typedef Vector<std::pair<NodeCallback, RefPtr<Node> > > NodeCallbackQueue; -static NodeCallbackQueue* s_postAttachCallbackQueue = 0; +static NodeCallbackQueue* s_postAttachCallbackQueue; -static size_t s_attachDepth = 0; - -ContainerNode::ContainerNode(Document* doc, bool isElement) - : EventTargetNode(doc, isElement, true) - , m_firstChild(0) - , m_lastChild(0) -{ -} +static size_t s_attachDepth; +static bool s_shouldReEnableMemoryCacheCallsAfterAttach; void ContainerNode::removeAllChildren() { @@ -98,9 +93,8 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce return true; RefPtr<Node> next = refChild; - RefPtr<Node> prev = refChild->previousSibling(); + RefPtr<Node> refChildPreviousSibling = refChild->previousSibling(); - int childCountDelta = 0; RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; while (child) { RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0; @@ -128,8 +122,6 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce ASSERT(!child->nextSibling()); ASSERT(!child->previousSibling()); - childCountDelta++; - // Add child before "next". forbidEventDispatch(); Node* prev = next->previousSibling(); @@ -149,6 +141,7 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce allowEventDispatch(); // Dispatch the mutation events. + childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1); dispatchChildInsertionEvents(child.get(), ec); // Add child to the rendering tree. @@ -163,8 +156,6 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce } document()->setDocumentChanged(true); - if (childCountDelta) - childrenChanged(false, prev.get(), next.get(), childCountDelta); dispatchSubtreeModifiedEvent(); return true; } @@ -222,7 +213,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce if (Node* oldParent = child->parentNode()) oldParent->removeChild(child.get(), ec); if (ec) - return 0; + return false; // Due to arbitrary code running in response to a DOM mutation event it's // possible that "prev" is no longer a child of "this". @@ -288,7 +279,7 @@ void ContainerNode::willRemove() { for (Node *n = m_firstChild; n != 0; n = n->nextSibling()) n->willRemove(); - EventTargetNode::willRemove(); + Node::willRemove(); } static ExceptionCode willRemoveChild(Node *child) @@ -392,25 +383,25 @@ bool ContainerNode::removeChildren() if (!m_firstChild) return false; - Node* n; + // The container node can be removed from event handlers. + RefPtr<Node> protect(this); - // do any prep work needed before actually starting to detach - // and remove... e.g. stop loading frames, fire unload events - for (n = m_firstChild; n; n = n->nextSibling()) - willRemoveChild(n); + // Do any prep work needed before actually starting to detach + // and remove... e.g. stop loading frames, fire unload events. + // FIXME: Adding new children from event handlers can cause an infinite loop here. + for (RefPtr<Node> n = m_firstChild; n; n = n->nextSibling()) + willRemoveChild(n.get()); // exclude this node when looking for removed focusedNode since only children will be removed document()->removeFocusedNodeOfSubtree(this, true); forbidEventDispatch(); int childCountDelta = 0; - while ((n = m_firstChild) != 0) { + while (RefPtr<Node> n = m_firstChild) { childCountDelta--; - Node *next = n->nextSibling(); + Node* next = n->nextSibling(); - n->ref(); - // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744) n->setPreviousSibling(0); n->setNextSibling(0); @@ -425,8 +416,6 @@ bool ContainerNode::removeChildren() if (n->inDocument()) n->removedFromDocument(); - - n->deref(); } allowEventDispatch(); @@ -461,7 +450,6 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo return true; // Now actually add the child(ren) - int childCountDelta = 0; RefPtr<Node> prev = lastChild(); RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; while (child) { @@ -482,7 +470,6 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo } // Append child to the end of the list - childCountDelta++; forbidEventDispatch(); child->setParent(this); if (m_lastChild) { @@ -494,6 +481,7 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo allowEventDispatch(); // Dispatch the mutation events + childrenChanged(false, prev.get(), 0, 1); dispatchChildInsertionEvents(child.get(), ec); // Add child to the rendering tree @@ -508,7 +496,6 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo } document()->setDocumentChanged(true); - childrenChanged(false, prev.get(), 0, childCountDelta); dispatchSubtreeModifiedEvent(); return true; } @@ -539,13 +526,29 @@ ContainerNode* ContainerNode::addChild(PassRefPtr<Node> newChild) void ContainerNode::suspendPostAttachCallbacks() { + if (!s_attachDepth) { + ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach); + if (Page* page = document()->page()) { + if (page->areMemoryCacheClientCallsEnabled()) { + page->setMemoryCacheClientCallsEnabled(false); + s_shouldReEnableMemoryCacheCallsAfterAttach = true; + } + } + } ++s_attachDepth; } void ContainerNode::resumePostAttachCallbacks() { - if (s_attachDepth == 1 && s_postAttachCallbackQueue) - dispatchPostAttachCallbacks(); + if (s_attachDepth == 1) { + if (s_postAttachCallbackQueue) + dispatchPostAttachCallbacks(); + if (s_shouldReEnableMemoryCacheCallsAfterAttach) { + s_shouldReEnableMemoryCacheCallsAfterAttach = false; + if (Page* page = document()->page()) + page->setMemoryCacheClientCallsEnabled(true); + } + } --s_attachDepth; } @@ -573,15 +576,13 @@ void ContainerNode::dispatchPostAttachCallbacks() void ContainerNode::attach() { - ++s_attachDepth; + suspendPostAttachCallbacks(); for (Node* child = m_firstChild; child; child = child->nextSibling()) child->attach(); - EventTargetNode::attach(); + Node::attach(); - if (s_attachDepth == 1 && s_postAttachCallbackQueue) - dispatchPostAttachCallbacks(); - --s_attachDepth; + resumePostAttachCallbacks(); } void ContainerNode::detach() @@ -589,39 +590,40 @@ void ContainerNode::detach() for (Node* child = m_firstChild; child; child = child->nextSibling()) child->detach(); setHasChangedChild(false); - EventTargetNode::detach(); + Node::detach(); } void ContainerNode::insertedIntoDocument() { - EventTargetNode::insertedIntoDocument(); - for (Node *child = m_firstChild; child; child = child->nextSibling()) + Node::insertedIntoDocument(); + insertedIntoTree(false); + for (Node* child = m_firstChild; child; child = child->nextSibling()) child->insertedIntoDocument(); } void ContainerNode::removedFromDocument() { - EventTargetNode::removedFromDocument(); - for (Node *child = m_firstChild; child; child = child->nextSibling()) + Node::removedFromDocument(); + setInDocument(false); + removedFromTree(false); + for (Node* child = m_firstChild; child; child = child->nextSibling()) child->removedFromDocument(); } void ContainerNode::insertedIntoTree(bool deep) { - EventTargetNode::insertedIntoTree(deep); - if (deep) { - for (Node *child = m_firstChild; child; child = child->nextSibling()) - child->insertedIntoTree(deep); - } + if (!deep) + return; + for (Node* child = m_firstChild; child; child = child->nextSibling()) + child->insertedIntoTree(true); } void ContainerNode::removedFromTree(bool deep) { - EventTargetNode::removedFromTree(deep); - if (deep) { - for (Node *child = m_firstChild; child; child = child->nextSibling()) - child->removedFromTree(deep); - } + if (!deep) + return; + for (Node* child = m_firstChild; child; child = child->nextSibling()) + child->removedFromTree(true); } void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) @@ -677,13 +679,14 @@ bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const if (!o) break; } + ASSERT(o); if (!o->isInline() || o->isReplaced()) { point = o->localToAbsolute(); return true; } - if (p->element() && p->element() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) { + if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) { // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor } else if ((o->isText() && !o->isBR()) || o->isReplaced()) { point = o->container()->localToAbsolute(); @@ -713,9 +716,8 @@ bool ContainerNode::getLowerRightCorner(FloatPoint& point) const if (!renderer()) return false; - RenderObject *o = renderer(); - if (!o->isInline() || o->isReplaced()) - { + RenderObject* o = renderer(); + if (!o->isInline() || o->isReplaced()) { RenderBox* box = toRenderBox(o); point = o->localToAbsolute(); point.move(box->width(), box->height()); @@ -729,8 +731,8 @@ bool ContainerNode::getLowerRightCorner(FloatPoint& point) const else if (o->previousSibling()) o = o->previousSibling(); else { - RenderObject *prev = 0; - while(!prev) { + RenderObject* prev = 0; + while (!prev) { o = o->parent(); if (!o) return false; @@ -738,12 +740,13 @@ bool ContainerNode::getLowerRightCorner(FloatPoint& point) const } o = prev; } + ASSERT(o); if (o->isText() || o->isReplaced()) { point = o->container()->localToAbsolute(); if (o->isText()) { RenderText* text = toRenderText(o); IntRect linesBox = text->linesBoundingBox(); - point.move(linesBox.x() + linesBox.width(), linesBox.height()); + point.move(linesBox.x() + linesBox.width(), linesBox.y() + linesBox.height()); } else { RenderBox* box = toRenderBox(o); point.move(box->x() + box->width(), box->y() + box->height()); @@ -762,8 +765,7 @@ IntRect ContainerNode::getRect() const // If we've found one corner, but not the other, // then we should just return a point at the corner that we did find. - if (foundUpperLeft != foundLowerRight) - { + if (foundUpperLeft != foundLowerRight) { if (foundUpperLeft) lowerRight = upperLeft; else @@ -781,7 +783,7 @@ void ContainerNode::setFocus(bool received) if (focused() == received) return; - EventTargetNode::setFocus(received); + Node::setFocus(received); // note that we need to recalc the style setChanged(); @@ -791,7 +793,7 @@ void ContainerNode::setActive(bool down, bool pause) { if (down == active()) return; - EventTargetNode::setActive(down); + Node::setActive(down); // note that we need to recalc the style // FIXME: Move to Element @@ -834,7 +836,7 @@ void ContainerNode::setHovered(bool over) { if (over == hovered()) return; - EventTargetNode::setHovered(over); + Node::setHovered(over); // note that we need to recalc the style // FIXME: Move to Element @@ -876,11 +878,11 @@ static void dispatchChildInsertionEvents(Node* child, ExceptionCode& ec) else c->insertedIntoTree(true); - if (c->parentNode() && - doc->hasListenerType(Document::DOMNODEINSERTED_LISTENER) && - c->isEventTargetNode()) { + doc->incDOMTreeVersion(); + + if (c->parentNode() && doc->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) { ec = 0; - EventTargetNodeCast(c.get())->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, false, + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, false, c->parentNode(), String(), String(), String(), 0), ec); if (ec) return; @@ -889,11 +891,8 @@ static void dispatchChildInsertionEvents(Node* child, ExceptionCode& ec) // dispatch the DOMNodeInsertedIntoDocument event to all descendants if (c->inDocument() && doc->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) for (; c; c = c->traverseNextNode(child)) { - if (!c->isEventTargetNode()) - continue; - ec = 0; - EventTargetNodeCast(c.get())->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false, false, + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false, false, 0, String(), String(), String(), 0), ec); if (ec) return; @@ -908,12 +907,12 @@ static void dispatchChildRemovalEvents(Node* child, ExceptionCode& ec) // update auxiliary doc info (e.g. iterators) to note that node is being removed doc->nodeWillBeRemoved(child); + doc->incDOMTreeVersion(); + // dispatch pre-removal mutation events - if (c->parentNode() && - doc->hasListenerType(Document::DOMNODEREMOVED_LISTENER) && - c->isEventTargetNode()) { + if (c->parentNode() && doc->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) { ec = 0; - EventTargetNodeCast(c.get())->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, false, + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, false, c->parentNode(), String(), String(), String(), 0), ec); if (ec) return; @@ -922,10 +921,8 @@ static void dispatchChildRemovalEvents(Node* child, ExceptionCode& ec) // dispatch the DOMNodeRemovedFromDocument event to all descendants if (c->inDocument() && doc->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) for (; c; c = c->traverseNextNode(child)) { - if (!c->isEventTargetNode()) - continue; ec = 0; - EventTargetNodeCast(c.get())->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false, false, + c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false, false, 0, String(), String(), String(), 0), ec); if (ec) return; diff --git a/WebCore/dom/ContainerNode.h b/WebCore/dom/ContainerNode.h index 91ca49a..3ad932c 100644 --- a/WebCore/dom/ContainerNode.h +++ b/WebCore/dom/ContainerNode.h @@ -24,7 +24,7 @@ #ifndef ContainerNode_h #define ContainerNode_h -#include "EventTargetNode.h" +#include "Node.h" #include "FloatPoint.h" namespace WebCore { @@ -36,7 +36,7 @@ namespace Private { void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer* container); }; -class ContainerNode : public EventTargetNode { +class ContainerNode : public Node { public: ContainerNode(Document*, bool isElement = false); virtual ~ContainerNode(); @@ -75,8 +75,8 @@ public: protected: static void queuePostAttachCallback(NodeCallback, Node*); - static void suspendPostAttachCallbacks(); - static void resumePostAttachCallbacks(); + void suspendPostAttachCallbacks(); + void resumePostAttachCallbacks(); template<class GenericNode, class GenericNodeContainer> friend void appendChildToContainer(GenericNode* child, GenericNodeContainer* container); @@ -96,7 +96,14 @@ private: Node* m_firstChild; Node* m_lastChild; }; - + +inline ContainerNode::ContainerNode(Document* document, bool isElement) + : Node(document, isElement, true) + , m_firstChild(0) + , m_lastChild(0) +{ +} + inline unsigned Node::containerChildNodeCount() const { ASSERT(isContainerNode()); diff --git a/WebCore/dom/DOMImplementation.cpp b/WebCore/dom/DOMImplementation.cpp index 738575f..4f29f96 100644 --- a/WebCore/dom/DOMImplementation.cpp +++ b/WebCore/dom/DOMImplementation.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "DOMImplementation.h" +#include "ContentType.h" #include "CSSStyleSheet.h" #include "DocumentType.h" #include "Element.h" @@ -347,7 +348,7 @@ PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame #if ENABLE(VIDEO) // Check to see if the type can be played by our MediaPlayer, if so create a MediaDocument - if (MediaPlayer::supportsType(type)) + if (MediaPlayer::supportsType(ContentType(type))) return MediaDocument::create(frame); #endif diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index a687df8..2e2dd9a 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * (C) 2006 Alexey Proskuryakov (ap@webkit.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2008 David Levin (levin@chromium.org) * @@ -38,7 +38,6 @@ #include "Console.h" #include "CookieJar.h" #include "DOMImplementation.h" -#include "DOMTimer.h" #include "DOMWindow.h" #include "DocLoader.h" #include "DocumentFragment.h" @@ -94,6 +93,7 @@ #include "ProgressEvent.h" #include "RegisteredEventListener.h" #include "RenderArena.h" +#include "RenderTextControl.h" #include "RenderView.h" #include "RenderWidget.h" #include "ScriptController.h" @@ -294,6 +294,17 @@ static bool acceptsEditingFocus(Node *node) return frame->editor()->shouldBeginEditing(rangeOfContents(root).get()); } +static bool disableRangeMutation(Page* page) +{ +#if PLATFORM(MAC) + // Disable Range mutation on document modifications in Tiger and Leopard Mail + // See <rdar://problem/5865171> + return page && (page->settings()->needsLeopardMailQuirks() || page->settings()->needsTigerMailQuirks()); +#else + return false; +#endif +} + static HashSet<Document*>* changedDocuments = 0; Document::Document(Frame* frame, bool isXHTML) @@ -303,7 +314,6 @@ Document::Document(Frame* frame, bool isXHTML) , m_frameElementsShouldIgnoreScrolling(false) , m_title("") , m_titleSetExplicitly(false) - , m_imageLoadEventTimer(this, &Document::imageLoadEventTimerFired) , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) #if ENABLE(XSLT) , m_transformSource(0) @@ -334,9 +344,6 @@ Document::Document(Frame* frame, bool isXHTML) , m_hasOpenDatabases(false) #endif , m_usingGeolocation(false) -#if USE(LOW_BANDWIDTH_DISPLAY) - , m_inLowBandwidthDisplay(false) -#endif #ifdef ANDROID_MOBILE , mExtraLayoutDelay(0) #endif @@ -555,7 +562,7 @@ PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionC if (m_isXHTML) return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), this, 0, false); - return createElement(QualifiedName(nullAtom, name, nullAtom), false, ec); + return createElement(QualifiedName(nullAtom, name, nullAtom), false); } PassRefPtr<DocumentFragment> Document::createDocumentFragment() @@ -772,7 +779,7 @@ bool Document::hasPrefixNamespaceMismatch(const QualifiedName& qName) } // FIXME: This should really be in a possible ElementFactory class -PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser, ExceptionCode& ec) +PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser) { RefPtr<Element> e; @@ -790,19 +797,10 @@ PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool cre if (!e) e = new Element(qName, document()); - - // FIXME: The element factories should be fixed to not ignore qName.prefix() - // Instead they should pass the entire qName into element creation so we don't - // need to manually set the prefix after creation. - // Then this code can become ASSERT(qName == e.qname()); - // and Document::createElement can stop taking ExceptionCode& as well. - if (e && !qName.prefix().isNull()) { - ec = 0; - e->setPrefix(qName.prefix(), ec); - if (ec) - return 0; - } - + + // <image> uses imgTag so we need a special rule. + ASSERT((qName.matches(imageTag) && e->tagQName().matches(imgTag) && e->tagQName().prefix() == qName.prefix()) || qName == e->tagQName()); + return e.release(); } @@ -818,7 +816,7 @@ PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const return 0; } - return createElement(qName, false, ec); + return createElement(qName, false); } Element* Document::getElementById(const AtomicString& elementId) const @@ -861,7 +859,7 @@ String Document::readyState() const return String(); } -String Document::inputEncoding() const +String Document::encoding() const { if (TextResourceDecoder* d = decoder()) return d->encoding().name(); @@ -920,8 +918,12 @@ Element* Document::elementFromPoint(int x, int y) const if (!renderer()) return 0; - HitTestRequest request(true, true); - HitTestResult result(IntPoint(x, y)); + HitTestRequest request(HitTestRequest::ReadOnly | + HitTestRequest::Active); + + float zoomFactor = frame() ? frame()->pageZoomFactor() : 1.0f; + + HitTestResult result(roundedIntPoint(FloatPoint(x * zoomFactor, y * zoomFactor))); renderView()->layer()->hitTest(request, result); Node* n = result.innerNode(); @@ -999,9 +1001,8 @@ void Document::setTitle(const String& title, Element* titleElement) m_titleElement = 0; else if (!m_titleElement) { if (HTMLElement* headElement = head()) { + m_titleElement = createElement(titleTag, false); ExceptionCode ec = 0; - m_titleElement = createElement("title", ec); - ASSERT(!ec); headElement->appendChild(m_titleElement, ec); ASSERT(!ec); } @@ -1120,8 +1121,8 @@ void Document::setDocumentChanged(bool b) void Document::recalcStyle(StyleChange change) { // we should not enter style recalc while painting - if (frame() && frame()->view() && frame()->view()->isPainting()) { - ASSERT(!frame()->view()->isPainting()); + if (view() && view()->isPainting()) { + ASSERT(!view()->isPainting()); return; } @@ -1130,6 +1131,8 @@ void Document::recalcStyle(StyleChange change) m_inStyleRecalc = true; suspendPostAttachCallbacks(); + if (view()) + view()->pauseScheduledEvents(); #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CalculateStyleTimeCounter); @@ -1172,8 +1175,6 @@ void Document::recalcStyle(StyleChange change) StyleChange ch = diff(documentStyle.get(), renderer()->style()); if (renderer() && ch != NoChange) renderer()->setStyle(documentStyle.release()); - if (change != Force) - change = ch; } for (Node* n = firstChild(); n; n = n->nextSibling()) @@ -1184,17 +1185,27 @@ void Document::recalcStyle(StyleChange change) android::TimeCounter::record(android::TimeCounter::CalculateStyleTimeCounter, __FUNCTION__); #endif - if (changed() && view()) - view()->layout(); + if (view()) { + if (changed()) + view()->layout(); +#if USE(ACCELERATED_COMPOSITING) + else { + // If we didn't update compositing layers because of layout(), we need to do so here. + view()->updateCompositingLayers(); + } +#endif + } bail_out: setChanged(NoStyleChange); setHasChangedChild(false); setDocumentChanged(false); - + + if (view()) + view()->resumeScheduledEvents(); resumePostAttachCallbacks(); m_inStyleRecalc = false; - + // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished. if (m_closeAfterStyleRecalc) { m_closeAfterStyleRecalc = false; @@ -1237,7 +1248,6 @@ void Document::updateLayout() if (Element* oe = ownerElement()) oe->document()->updateLayout(); - // FIXME: Dave Hyatt's pretty sure we can remove this because layout calls recalcStyle as needed. updateRendering(); // Only do a layout if changes have occurred that make it necessary. @@ -1290,6 +1300,9 @@ void Document::attach() // Create the rendering tree setRenderer(new (m_renderArena) RenderView(this, view())); +#if USE(ACCELERATED_COMPOSITING) + renderView()->didMoveOnscreen(); +#endif if (!m_styleSelector) { bool matchAuthorAndUserStyles = true; @@ -1318,15 +1331,13 @@ void Document::detach() RenderObject* render = renderer(); + // Send out documentWillBecomeInactive() notifications to registered elements, + // in order to stop media elements + documentWillBecomeInactive(); + // indicate destruction mode, i.e. attached() but renderer == 0 setRenderer(0); - - // Empty out these lists as a performance optimization, since detaching - // all the individual render objects will cause all the RenderImage - // objects to remove themselves from the lists. - m_imageLoadEventDispatchSoonList.clear(); - m_imageLoadEventDispatchingList.clear(); - + m_hoverNode = 0; m_focusedNode = 0; m_activeNode = 0; @@ -1360,11 +1371,8 @@ void Document::removeAllEventListenersFromAllNodes() m_windowEventListeners[i]->setRemoved(true); m_windowEventListeners.clear(); removeAllDisconnectedNodeEventListeners(); - for (Node *n = this; n; n = n->traverseNextNode()) { - if (!n->isEventTargetNode()) - continue; - EventTargetNodeCast(n)->removeAllEventListeners(); - } + for (Node* node = this; node; node = node->traverseNextNode()) + node->removeAllEventListeners(); } void Document::registerDisconnectedNodeWithEventListeners(Node* node) @@ -1381,13 +1389,13 @@ void Document::removeAllDisconnectedNodeEventListeners() { HashSet<Node*>::iterator end = m_disconnectedNodesWithEventListeners.end(); for (HashSet<Node*>::iterator i = m_disconnectedNodesWithEventListeners.begin(); i != end; ++i) - EventTargetNodeCast(*i)->removeAllEventListeners(); + (*i)->removeAllEventListeners(); m_disconnectedNodesWithEventListeners.clear(); } RenderView* Document::renderView() const { - return static_cast<RenderView*>(renderer()); + return toRenderView(renderer()); } void Document::clearAXObjectCache() @@ -1499,7 +1507,7 @@ void Document::implicitOpen() setParsing(true); } -HTMLElement* Document::body() +HTMLElement* Document::body() const { Node* de = documentElement(); if (!de) @@ -1609,8 +1617,8 @@ void Document::implicitClose() if (f) f->animation()->resumeAnimations(this); - dispatchImageLoadEventsNow(); - this->dispatchWindowEvent(eventNames().loadEvent, false, false); + ImageLoader::dispatchPendingLoadEvents(); + dispatchWindowEvent(eventNames().loadEvent, false, false); if (f) f->loader()->handledOnloadEvents(); #ifdef INSTRUMENT_LAYOUT_SCHEDULING @@ -1692,8 +1700,8 @@ bool Document::shouldScheduleLayout() // (a) Only schedule a layout once the stylesheets are loaded. // (b) Only schedule layout once we have a body element. - return haveStylesheetsLoaded() - && body() || (documentElement() && !documentElement()->hasTagName(htmlTag)); + return (haveStylesheetsLoaded() && body()) || + (documentElement() && !documentElement()->hasTagName(htmlTag)); } int Document::minimumLayoutDelay() @@ -1713,28 +1721,30 @@ int Document::elapsedTime() const return static_cast<int>((currentTime() - m_startTime) * 1000); } -void Document::write(const String& text, Document* ownerDocument) +void Document::write(const SegmentedString& text, Document* ownerDocument) { #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("Beginning a document.write at %d\n", elapsedTime()); #endif - - if (!m_tokenizer) { + + if (!m_tokenizer) open(ownerDocument); - ASSERT(m_tokenizer); - if (!m_tokenizer) - return; - write("<html>", ownerDocument); - } + + ASSERT(m_tokenizer); m_tokenizer->write(text, false); - + #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("Ending a document.write at %d\n", elapsedTime()); #endif } +void Document::write(const String& text, Document* ownerDocument) +{ + write(SegmentedString(text), ownerDocument); +} + void Document::writeln(const String& text, Document* ownerDocument) { write(text, ownerDocument); @@ -1817,6 +1827,11 @@ void Document::updateBaseURL() m_mappedElementSheet->setHref(m_baseURL.string()); } +String Document::userAgent(const KURL& url) const +{ + return frame() ? frame()->loader()->userAgent(url) : String(); +} + void Document::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet) { m_sheet = CSSStyleSheet::create(this, url, charset); @@ -2097,7 +2112,7 @@ MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& r HitTestResult result(documentPoint); renderView()->layer()->hitTest(request, result); - if (!request.readonly) + if (!request.readOnly()) updateRendering(); return MouseEventWithHitTestResults(event, result); @@ -2553,21 +2568,23 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) // Dispatch a change event for text fields or textareas that have been edited RenderObject* r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer()); - if (r && (r->isTextArea() || r->isTextField()) && r->isEdited()) { - EventTargetNodeCast(oldFocusedNode.get())->dispatchEventForType(eventNames().changeEvent, true, false); - if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer()))) - r->setEdited(false); + if (r && r->isTextControl() && toRenderTextControl(r)->isEdited()) { + oldFocusedNode->dispatchEventForType(eventNames().changeEvent, true, false); + if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer()))) { + if (r->isTextControl()) + toRenderTextControl(r)->setEdited(false); + } } // Dispatch the blur event and let the node do any other blur related activities (important for text fields) - EventTargetNodeCast(oldFocusedNode.get())->dispatchBlurEvent(); + oldFocusedNode->dispatchBlurEvent(); if (m_focusedNode) { // handler shifted focus focusChangeBlocked = true; newFocusedNode = 0; } - EventTargetNodeCast(oldFocusedNode.get())->dispatchUIEvent(eventNames().DOMFocusOutEvent); + oldFocusedNode->dispatchUIEvent(eventNames().DOMFocusOutEvent); if (m_focusedNode) { // handler shifted focus focusChangeBlocked = true; @@ -2590,14 +2607,14 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) m_focusedNode = newFocusedNode.get(); // Dispatch the focus event and let the node do any other focus related activities (important for text fields) - EventTargetNodeCast(m_focusedNode.get())->dispatchFocusEvent(); + m_focusedNode->dispatchFocusEvent(); if (m_focusedNode != newFocusedNode) { // handler shifted focus focusChangeBlocked = true; goto SetFocusedNodeDone; } - EventTargetNodeCast(m_focusedNode.get())->dispatchUIEvent(eventNames().DOMFocusInEvent); + m_focusedNode->dispatchUIEvent(eventNames().DOMFocusInEvent); if (m_focusedNode != newFocusedNode) { // handler shifted focus focusChangeBlocked = true; @@ -2637,7 +2654,7 @@ SetFocusedNodeDone: return !focusChangeBlocked; } -void Document::setCSSTarget(Node* n) +void Document::setCSSTarget(Element* n) { if (m_cssTarget) m_cssTarget->setChanged(); @@ -2646,11 +2663,6 @@ void Document::setCSSTarget(Node* n) n->setChanged(); } -Node* Document::getCSSTarget() const -{ - return m_cssTarget; -} - void Document::attachNodeIterator(NodeIterator *ni) { m_nodeIterators.add(ni); @@ -2663,7 +2675,7 @@ void Document::detachNodeIterator(NodeIterator *ni) void Document::nodeChildrenChanged(ContainerNode* container) { - if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) { + if (!disableRangeMutation(page())) { HashSet<Range*>::const_iterator end = m_ranges.end(); for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) (*it)->nodeChildrenChanged(container); @@ -2676,7 +2688,7 @@ void Document::nodeWillBeRemoved(Node* n) for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it) (*it)->nodeWillBeRemoved(n); - if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) { + if (!disableRangeMutation(page())) { HashSet<Range*>::const_iterator rangesEnd = m_ranges.end(); for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != rangesEnd; ++it) (*it)->nodeWillBeRemoved(n); @@ -2690,7 +2702,7 @@ void Document::nodeWillBeRemoved(Node* n) void Document::textInserted(Node* text, unsigned offset, unsigned length) { - if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) { + if (!disableRangeMutation(page())) { HashSet<Range*>::const_iterator end = m_ranges.end(); for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) (*it)->textInserted(text, offset, length); @@ -2702,7 +2714,7 @@ void Document::textInserted(Node* text, unsigned offset, unsigned length) void Document::textRemoved(Node* text, unsigned offset, unsigned length) { - if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) { + if (!disableRangeMutation(page())) { HashSet<Range*>::const_iterator end = m_ranges.end(); for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) (*it)->textRemoved(text, offset, length); @@ -2715,7 +2727,7 @@ void Document::textRemoved(Node* text, unsigned offset, unsigned length) void Document::textNodesMerged(Text* oldNode, unsigned offset) { - if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) { + if (!disableRangeMutation(page())) { NodeWithIndex oldNodeWithIndex(oldNode); HashSet<Range*>::const_iterator end = m_ranges.end(); for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) @@ -2727,7 +2739,7 @@ void Document::textNodesMerged(Text* oldNode, unsigned offset) void Document::textNodeSplit(Text* oldNode) { - if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) { + if (!disableRangeMutation(page())) { HashSet<Range*>::const_iterator end = m_ranges.end(); for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it) (*it)->textNodeSplit(oldNode); @@ -2956,66 +2968,6 @@ void Document::setWindowInlineEventListenerForTypeAndAttribute(const AtomicStrin setWindowInlineEventListenerForType(eventType, createEventListener(attr->localName().string(), attr->value(), 0)); } -void Document::dispatchImageLoadEventSoon(ImageLoader* image) -{ - m_imageLoadEventDispatchSoonList.append(image); - if (!m_imageLoadEventTimer.isActive()) - m_imageLoadEventTimer.startOneShot(0); -} - -void Document::removeImage(ImageLoader* image) -{ - // Remove instances of this image from both lists. - // Use loops because we allow multiple instances to get into the lists. - size_t size = m_imageLoadEventDispatchSoonList.size(); - for (size_t i = 0; i < size; ++i) { - if (m_imageLoadEventDispatchSoonList[i] == image) - m_imageLoadEventDispatchSoonList[i] = 0; - } - size = m_imageLoadEventDispatchingList.size(); - for (size_t i = 0; i < size; ++i) { - if (m_imageLoadEventDispatchingList[i] == image) - m_imageLoadEventDispatchingList[i] = 0; - } - if (m_imageLoadEventDispatchSoonList.isEmpty()) - m_imageLoadEventTimer.stop(); -} - -void Document::dispatchImageLoadEventsNow() -{ - // Need to avoid re-entering this function; if new dispatches are - // scheduled before the parent finishes processing the list, they - // will set a timer and eventually be processed. - if (!m_imageLoadEventDispatchingList.isEmpty()) - return; -#ifdef BUILDING_ON_LEOPARD - bool shouldReenableMemoryCacheClientCalls = false; - if (settings() && settings()->needsIChatMemoryCacheCallsQuirk() && page()->areMemoryCacheClientCallsEnabled()) { - shouldReenableMemoryCacheClientCalls = true; - page()->setMemoryCacheClientCallsEnabled(false); - } -#endif - m_imageLoadEventTimer.stop(); - - m_imageLoadEventDispatchingList = m_imageLoadEventDispatchSoonList; - m_imageLoadEventDispatchSoonList.clear(); - size_t size = m_imageLoadEventDispatchingList.size(); - for (size_t i = 0; i < size; ++i) { - if (ImageLoader* image = m_imageLoadEventDispatchingList[i]) - image->dispatchLoadEvent(); - } - m_imageLoadEventDispatchingList.clear(); -#ifdef BUILDING_ON_LEOPARD - if (shouldReenableMemoryCacheClientCalls && page()) - page()->setMemoryCacheClientCallsEnabled(true); -#endif -} - -void Document::imageLoadEventTimerFired(Timer<Document>*) -{ - dispatchImageLoadEventsNow(); -} - Element* Document::ownerElement() const { if (!frame()) @@ -3262,9 +3214,10 @@ KURL Document::completeURL(const String& url) const // See also [CSS]StyleSheet::completeURL(const String&) if (url.isNull()) return KURL(); + const KURL& baseURL = ((m_baseURL.isEmpty() || m_baseURL == blankURL()) && parentDocument()) ? parentDocument()->baseURL() : m_baseURL; if (!m_decoder) - return KURL(m_baseURL, url); - return KURL(m_baseURL, url, m_decoder->encoding()); + return KURL(baseURL, url); + return KURL(baseURL, url, m_decoder->encoding()); } void Document::setInPageCache(bool flag) @@ -3288,6 +3241,11 @@ void Document::setInPageCache(bool flag) void Document::documentWillBecomeInactive() { +#if USE(ACCELERATED_COMPOSITING) + if (renderer()) + renderView()->willMoveOffscreen(); +#endif + HashSet<Element*>::iterator end = m_documentActivationCallbackElements.end(); for (HashSet<Element*>::iterator i = m_documentActivationCallbackElements.begin(); i != end; ++i) (*i)->documentWillBecomeInactive(); @@ -3298,6 +3256,11 @@ void Document::documentDidBecomeActive() HashSet<Element*>::iterator end = m_documentActivationCallbackElements.end(); for (HashSet<Element*>::iterator i = m_documentActivationCallbackElements.begin(); i != end; ++i) (*i)->documentDidBecomeActive(); + +#if USE(ACCELERATED_COMPOSITING) + if (renderer()) + renderView()->didMoveOnscreen(); +#endif } void Document::registerForDocumentActivationCallbacks(Element* e) @@ -4005,7 +3968,7 @@ void Document::finishedParsing() Vector<String> Document::formElementsState() const { Vector<String> stateVector; - stateVector.reserveCapacity(m_formElementsWithState.size() * 3); + stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3); typedef ListHashSet<FormControlElementWithState*>::const_iterator Iterator; Iterator end = m_formElementsWithState.end(); for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) { @@ -4225,6 +4188,20 @@ void Document::initSecurityContext() securityOrigin()->grantLoadLocalResources(); } + if (Settings* settings = this->settings()) { + if (!settings->isWebSecurityEnabled()) { + // Web security is turned off. We should let this document access every + // other document. This is used primary by testing harnesses for web + // sites. + securityOrigin()->grantUniversalAccess(); + + } else if (settings->allowUniversalAccessFromFileURLs() && securityOrigin()->isLocal()) { + // Some clients want file:// URLs to have universal access, but that + // setting is dangerous for other clients. + securityOrigin()->grantUniversalAccess(); + } + } + if (!securityOrigin()->isEmpty()) return; @@ -4235,7 +4212,7 @@ void Document::initSecurityContext() if (!ownerFrame) ownerFrame = m_frame->loader()->opener(); - if (ownerFrame && ownerFrame->document()) { + if (ownerFrame) { m_cookieURL = ownerFrame->document()->cookieURL(); // We alias the SecurityOrigins to match Firefox, see Bug 15313 // https://bugs.webkit.org/show_bug.cgi?id=15313 @@ -4428,22 +4405,6 @@ void Document::removeTouchEventListener(Node* node) #endif -void Document::addTimeout(int timeoutId, DOMTimer* timer) -{ - ASSERT(!m_timeouts.contains(timeoutId)); - m_timeouts.set(timeoutId, timer); -} - -void Document::removeTimeout(int timeoutId) -{ - m_timeouts.remove(timeoutId); -} - -DOMTimer* Document::findTimeout(int timeoutId) -{ - return m_timeouts.get(timeoutId); -} - void Document::reportException(const String& errorMessage, int lineNumber, const String& sourceURL) { if (DOMWindow* window = domWindow()) @@ -4471,6 +4432,12 @@ void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const page()->inspectorController()->resourceRetrievedByXMLHttpRequest(identifier, sourceString); } +void Document::scriptImported(unsigned long identifier, const String& sourceString) +{ + if (page()) + page()->inspectorController()->scriptImported(identifier, sourceString); +} + class ScriptExecutionContextTaskTimer : public TimerBase { public: ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassRefPtr<ScriptExecutionContext::Task> task) @@ -4541,4 +4508,24 @@ Element* Document::findAnchor(const String& name) return 0; } +String Document::displayStringModifiedByEncoding(const String& str) const +{ + if (m_decoder) + return m_decoder->encoding().displayString(str.impl()); + return str; +} + +PassRefPtr<StringImpl> Document::displayStringModifiedByEncoding(PassRefPtr<StringImpl> str) const +{ + if (m_decoder) + return m_decoder->encoding().displayString(str); + return str; +} + +void Document::displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const +{ + if (m_decoder) + m_decoder->encoding().displayBuffer(buffer, len); +} + } // namespace WebCore diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index ce8116d..3d232ec 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * (C) 2006 Alexey Proskuryakov (ap@webkit.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -33,7 +33,6 @@ #include "HTMLFormElement.h" #include "ScriptExecutionContext.h" #include "StringHash.h" -#include "TextResourceDecoder.h" #include "Timer.h" #include <wtf/HashCountedSet.h> #include <wtf/ListHashSet.h> @@ -63,7 +62,6 @@ namespace WebCore { class Database; class DOMImplementation; class DOMSelection; - class DOMTimer; class DOMWindow; class DatabaseThread; class DocLoader; @@ -77,6 +75,7 @@ namespace WebCore { class FormControlElementWithState; class Frame; class FrameView; + class HitTestRequest; class HTMLCanvasElement; class HTMLDocument; class HTMLElement; @@ -84,7 +83,6 @@ namespace WebCore { class HTMLHeadElement; class HTMLInputElement; class HTMLMapElement; - class ImageLoader; class IntPoint; class JSNode; class MouseEventWithHitTestResults; @@ -98,6 +96,7 @@ namespace WebCore { class RenderArena; class RenderView; class SecurityOrigin; + class SegmentedString; class Settings; class StyleSheet; class StyleSheetList; @@ -125,7 +124,6 @@ namespace WebCore { #if ENABLE(DASHBOARD_SUPPORT) struct DashboardRegionValue; #endif - struct HitTestRequest; typedef int ExceptionCode; @@ -235,18 +233,20 @@ public: PassRefPtr<EntityReference> createEntityReference(const String& name, ExceptionCode&); PassRefPtr<Node> importNode(Node* importedNode, bool deep, ExceptionCode&); virtual PassRefPtr<Element> createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode&); - PassRefPtr<Element> createElement(const QualifiedName&, bool createdByParser, ExceptionCode& ec); + PassRefPtr<Element> createElement(const QualifiedName&, bool createdByParser); Element* getElementById(const AtomicString&) const; bool hasElementWithId(AtomicStringImpl* id) const; bool containsMultipleElementsWithId(const AtomicString& elementId) { return m_duplicateIds.contains(elementId.impl()); } Element* elementFromPoint(int x, int y) const; String readyState() const; - String inputEncoding() const; - String defaultCharset() const; - String charset() const { return inputEncoding(); } - String characterSet() const { return inputEncoding(); } + String defaultCharset() const; + + // Synonyms backing similar DOM attributes. Use Document::encoding() to avoid virtual dispatch. + String inputEncoding() const { return Document::encoding(); } + String charset() const { return Document::encoding(); } + String characterSet() const { return Document::encoding(); } void setCharset(const String&); @@ -314,6 +314,7 @@ public: #if ENABLE(WML) virtual bool isWMLDocument() const { return false; } #endif + virtual bool isFrameSet() const { return false; } CSSStyleSelector* styleSelector() const { return m_styleSelector; } @@ -330,11 +331,7 @@ public: */ bool haveStylesheetsLoaded() const { - return m_pendingStylesheets <= 0 || m_ignorePendingStylesheets -#if USE(LOW_BANDWIDTH_DISPLAY) - || m_inLowBandwidthDisplay -#endif - ; + return m_pendingStylesheets <= 0 || m_ignorePendingStylesheets; } /** @@ -426,6 +423,7 @@ public: void implicitClose(); void cancelParsing(); + void write(const SegmentedString& text, Document* ownerDocument = 0); void write(const String& text, Document* ownerDocument = 0); void writeln(const String& text, Document* ownerDocument = 0); void finishParsing(); @@ -446,6 +444,8 @@ public: KURL completeURL(const String&) const; + virtual String userAgent(const KURL&) const; + // from cachedObjectClient virtual void setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet*); @@ -532,8 +532,8 @@ public: void activeChainNodeDetached(Node*); // Updates for :target (CSS3 selector). - void setCSSTarget(Node*); - Node* getCSSTarget() const; + void setCSSTarget(Element*); + Element* cssTarget() const { return m_cssTarget; } void setDocumentChanged(bool); @@ -644,11 +644,7 @@ public: */ void processMetadataSettings(const String& content); #endif - - void dispatchImageLoadEventSoon(ImageLoader*); - void dispatchImageLoadEventsNow(); - void removeImage(ImageLoader*); - + // Returns the owning element in the parent document. // Returns 0 if this is the top level document. Element* ownerElement() const; @@ -692,7 +688,7 @@ public: void removeImageMap(HTMLMapElement*); HTMLMapElement* getImageMap(const String& url) const; - HTMLElement* body(); + HTMLElement* body() const; void setBody(PassRefPtr<HTMLElement>, ExceptionCode&); HTMLHeadElement* head(); @@ -776,13 +772,7 @@ public: void setUseSecureKeyboardEntryWhenActive(bool); bool useSecureKeyboardEntryWhenActive() const; - -#if USE(LOW_BANDWIDTH_DISPLAY) - void setDocLoader(DocLoader* loader) { m_docLoader = loader; } - bool inLowBandwidthDisplay() const { return m_inLowBandwidthDisplay; } - void setLowBandwidthDisplay(bool lowBandWidth) { m_inLowBandwidthDisplay = lowBandWidth; } -#endif - + void addNodeListCache() { ++m_numNodeListCaches; } void removeNodeListCache() { ASSERT(m_numNodeListCaches > 0); --m_numNodeListCaches; } bool hasNodeListCaches() const { return m_numNodeListCaches; } @@ -809,12 +799,9 @@ public: virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL); virtual void addMessage(MessageDestination, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); virtual void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString); + virtual void scriptImported(unsigned long, const String&); virtual void postTask(PassRefPtr<Task>); // Executes the task on context's thread asynchronously. - void addTimeout(int timeoutId, DOMTimer*); - void removeTimeout(int timeoutId); - DOMTimer* findTimeout(int timeoutId); - protected: Document(Frame*, bool isXHTML); @@ -837,6 +824,8 @@ private: virtual const KURL& virtualURL() const; // Same as url(), but needed for ScriptExecutionContext to implement it without a performance loss for direct calls. virtual KURL virtualCompleteURL(const String&) const; // Same as completeURL() for the same reason as above. + String encoding() const; + CSSStyleSelector* m_styleSelector; bool m_didCalculateStyleSelector; @@ -953,13 +942,9 @@ private: mutable AXObjectCache* m_axObjectCache; - Vector<ImageLoader*> m_imageLoadEventDispatchSoonList; - Vector<ImageLoader*> m_imageLoadEventDispatchingList; - Timer<Document> m_imageLoadEventTimer; - Timer<Document> m_updateFocusAppearanceTimer; - Node* m_cssTarget; + Element* m_cssTarget; bool m_processingLoadEvent; double m_startTime; @@ -1008,20 +993,9 @@ public: void setDecoder(PassRefPtr<TextResourceDecoder>); TextResourceDecoder* decoder() const { return m_decoder.get(); } - String displayStringModifiedByEncoding(const String& str) const { - if (m_decoder) - return m_decoder->encoding().displayString(str.impl()); - return str; - } - PassRefPtr<StringImpl> displayStringModifiedByEncoding(PassRefPtr<StringImpl> str) const { - if (m_decoder) - return m_decoder->encoding().displayString(str); - return str; - } - void displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const { - if (m_decoder) - m_decoder->encoding().displayBuffer(buffer, len); - } + String displayStringModifiedByEncoding(const String&) const; + PassRefPtr<StringImpl> displayStringModifiedByEncoding(PassRefPtr<StringImpl>) const; + void displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const; // Quirk for the benefit of Apple's Dictionary application. void setFrameElementsShouldIgnoreScrolling(bool ignore) { m_frameElementsShouldIgnoreScrolling = ignore; } @@ -1079,7 +1053,6 @@ protected: private: void updateTitle(); void removeAllDisconnectedNodeEventListeners(); - void imageLoadEventTimerFired(Timer<Document>*); void updateFocusAppearanceTimerFired(Timer<Document>*); void updateBaseURL(); @@ -1152,16 +1125,9 @@ private: #endif bool m_usingGeolocation; - -#if USE(LOW_BANDWIDTH_DISPLAY) - bool m_inLowBandwidthDisplay; -#endif #ifdef ANDROID_MOBILE int mExtraLayoutDelay; #endif - - typedef HashMap<int, DOMTimer*> TimeoutsMap; - TimeoutsMap m_timeouts; }; inline bool Document::hasElementWithId(AtomicStringImpl* id) const diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl index dfdfe46..3543cc7 100644 --- a/WebCore/dom/Document.idl +++ b/WebCore/dom/Document.idl @@ -28,11 +28,11 @@ module core { InlineGetOwnPropertySlot, InterfaceUUID=48BB95FC-2D08-4c54-BE65-7558736A4CAE, ImplementationUUID=FF5CBE81-F817-429c-A6C2-0CCCD2328062 - ] Document : EventTargetNode { + ] Document : Node { // DOM Level 1 Core readonly attribute DocumentType doctype; - readonly attribute DOMImplementation implementation; + readonly attribute [V8Custom] DOMImplementation implementation; readonly attribute Element documentElement; [ReturnsNew] Element createElement(in [ConvertNullToNullString] DOMString tagName) @@ -122,11 +122,11 @@ module core { in XPathNSResolver resolver) raises(DOMException); XPathNSResolver createNSResolver(in Node nodeResolver); - [OldStyleObjC] XPathResult evaluate(in DOMString expression, - in Node contextNode, - in XPathNSResolver resolver, - in unsigned short type, - in XPathResult inResult) + [OldStyleObjC, V8Custom] XPathResult evaluate(in DOMString expression, + in Node contextNode, + in XPathNSResolver resolver, + in unsigned short type, + in XPathResult inResult) raises(DOMException); #endif // ENABLE_XPATH #endif // !defined(LANGUAGE_COM) @@ -226,7 +226,7 @@ module core { #if !defined(LANGUAGE_COM) #if !defined(LANGUAGE_OBJECTIVE_C) - DOMObject getCSSCanvasContext(in DOMString contextId, in DOMString name, in long width, in long height); + [V8Custom] DOMObject getCSSCanvasContext(in DOMString contextId, in DOMString name, in long width, in long height); #endif #endif @@ -234,9 +234,9 @@ module core { NodeList getElementsByClassName(in DOMString tagname); // NodeSelector - Selector API - Element querySelector(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + Element querySelector(in DOMString selectors) raises(DOMException); - NodeList querySelectorAll(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + NodeList querySelectorAll(in DOMString selectors) raises(DOMException); #if ENABLE_WML diff --git a/WebCore/dom/DocumentFragment.idl b/WebCore/dom/DocumentFragment.idl index 2cdcdf8..ff6232f 100644 --- a/WebCore/dom/DocumentFragment.idl +++ b/WebCore/dom/DocumentFragment.idl @@ -23,12 +23,11 @@ module core { GenerateConstructor, InterfaceUUID=F5C8DAF0-D728-4b2b-9D9C-630621B07D35, ImplementationUUID=E57BF71F-3FAA-495c-A307-E288F8E5B2EC - ] DocumentFragment : EventTargetNode { + ] DocumentFragment : Node { // NodeSelector - Selector API - // FIXME: add support for NSResolver in languages other than JS - Element querySelector(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + Element querySelector(in DOMString selectors) raises(DOMException); - NodeList querySelectorAll(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + NodeList querySelectorAll(in DOMString selectors) raises(DOMException); }; diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 781179d..dbec884 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -29,6 +29,8 @@ #include "AXObjectCache.h" #include "CSSStyleSelector.h" #include "CString.h" +#include "ClientRect.h" +#include "ClientRectList.h" #include "Document.h" #include "Editor.h" #include "ElementRareData.h" @@ -44,6 +46,9 @@ #include "Page.h" #include "PlatformString.h" #include "RenderBlock.h" +#if ENABLE(SVG) +#include "SVGNames.h" +#endif #include "SelectionController.h" #include "TextIterator.h" #include "XMLNames.h" @@ -83,27 +88,32 @@ NodeRareData* Element::createRareData() PassRefPtr<Node> Element::cloneNode(bool deep) { - ExceptionCode ec = 0; - RefPtr<Element> clone = document()->createElementNS(namespaceURI(), nodeName(), ec); - ASSERT(!ec); - - // clone attributes + return deep ? cloneElementWithChildren() : cloneElementWithoutChildren(); +} + +PassRefPtr<Element> Element::cloneElementWithChildren() +{ + RefPtr<Element> clone = cloneElementWithoutChildren(); + cloneChildNodes(clone.get()); + return clone.release(); +} + +PassRefPtr<Element> Element::cloneElementWithoutChildren() +{ + RefPtr<Element> clone = document()->createElement(tagQName(), false); + // This will catch HTML elements in the wrong namespace that are not correctly copied. + // This is a sanity check as HTML overloads some of the DOM methods. + ASSERT(isHTMLElement() == clone->isHTMLElement()); + + // Clone attributes. if (namedAttrMap) clone->attributes()->setAttributes(*namedAttrMap); clone->copyNonAttributeProperties(this); - if (deep) - cloneChildNodes(clone.get()); - return clone.release(); } -PassRefPtr<Element> Element::cloneElement() -{ - return static_pointer_cast<Element>(cloneNode(false)); -} - void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec) { if (namedAttrMap) { @@ -189,9 +199,9 @@ void Element::scrollIntoView(bool alignToTop) if (renderer()) { // Align to the top / bottom and to the closest edge. if (alignToTop) - renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways); + renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); else - renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignBottomAlways); + renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways); } } @@ -201,9 +211,9 @@ void Element::scrollIntoViewIfNeeded(bool centerIfNeeded) IntRect bounds = getRect(); if (renderer()) { if (centerIfNeeded) - renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignCenterIfNeeded, RenderLayer::gAlignCenterIfNeeded); + renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded); else - renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded); + renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); } } @@ -274,7 +284,7 @@ static int adjustForAbsoluteZoom(int value, RenderObject* renderer) int Element::offsetLeft() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) + if (RenderBoxModelObject* rend = renderBoxModelObject()) return adjustForLocalZoom(rend->offsetLeft(), rend); return 0; } @@ -282,7 +292,7 @@ int Element::offsetLeft() int Element::offsetTop() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) + if (RenderBoxModelObject* rend = renderBoxModelObject()) return adjustForLocalZoom(rend->offsetTop(), rend); return 0; } @@ -290,7 +300,7 @@ int Element::offsetTop() int Element::offsetWidth() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) + if (RenderBoxModelObject* rend = renderBoxModelObject()) return adjustForAbsoluteZoom(rend->offsetWidth(), rend); return 0; } @@ -298,7 +308,7 @@ int Element::offsetWidth() int Element::offsetHeight() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) + if (RenderBoxModelObject* rend = renderBoxModelObject()) return adjustForAbsoluteZoom(rend->offsetHeight(), rend); return 0; } @@ -306,9 +316,9 @@ int Element::offsetHeight() Element* Element::offsetParent() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) + if (RenderObject* rend = renderer()) if (RenderObject* offsetParent = rend->offsetParent()) - return static_cast<Element*>(offsetParent->element()); + return static_cast<Element*>(offsetParent->node()); return 0; } @@ -340,14 +350,11 @@ int Element::clientWidth() if ((!inCompatMode && document()->documentElement() == this) || (inCompatMode && isHTMLElement() && document()->body() == this)) { if (FrameView* view = document()->view()) - return view->layoutWidth(); + return adjustForAbsoluteZoom(view->layoutWidth(), document()->renderer()); } - - if (RenderBox* rend = renderBox()) { - if (!rend->isRenderInline()) - return adjustForAbsoluteZoom(rend->clientWidth(), rend); - } + if (RenderBox* rend = renderBox()) + return adjustForAbsoluteZoom(rend->clientWidth(), rend); return 0; } @@ -362,13 +369,11 @@ int Element::clientHeight() if ((!inCompatMode && document()->documentElement() == this) || (inCompatMode && isHTMLElement() && document()->body() == this)) { if (FrameView* view = document()->view()) - return view->layoutHeight(); + return adjustForAbsoluteZoom(view->layoutHeight(), document()->renderer()); } - if (RenderBox* rend = renderBox()) { - if (!rend->isRenderInline()) - return adjustForAbsoluteZoom(rend->clientHeight(), rend); - } + if (RenderBox* rend = renderBox()) + return adjustForAbsoluteZoom(rend->clientHeight(), rend); return 0; } @@ -405,23 +410,67 @@ void Element::setScrollTop(int newTop) int Element::scrollWidth() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) { - if (rend->hasOverflowClip() || !rend->isRenderInline()) - return adjustForAbsoluteZoom(rend->scrollWidth(), rend); - } + if (RenderBox* rend = renderBox()) + return adjustForAbsoluteZoom(rend->scrollWidth(), rend); return 0; } int Element::scrollHeight() { document()->updateLayoutIgnorePendingStylesheets(); - if (RenderBox* rend = renderBox()) { - if (rend->hasOverflowClip() || !rend->isRenderInline()) - return adjustForAbsoluteZoom(rend->scrollHeight(), rend); - } + if (RenderBox* rend = renderBox()) + return adjustForAbsoluteZoom(rend->scrollHeight(), rend); return 0; } +PassRefPtr<ClientRectList> Element::getClientRects() const +{ + document()->updateLayoutIgnorePendingStylesheets(); + + RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject(); + if (!renderBoxModelObject) + return ClientRectList::create(); + + // FIXME: Handle SVG elements. + // FIXME: Handle table/inline-table with a caption. + + Vector<FloatQuad> quads; + renderBoxModelObject->absoluteQuads(quads); + + if (FrameView* view = document()->view()) { + IntRect visibleContentRect = view->visibleContentRect(); + for (size_t i = 0; i < quads.size(); ++i) + quads[i].move(-visibleContentRect.x(), -visibleContentRect.y()); + } + + return ClientRectList::create(quads); +} + +PassRefPtr<ClientRect> Element::getBoundingClientRect() const +{ + document()->updateLayoutIgnorePendingStylesheets(); + RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject(); + if (!renderBoxModelObject) + return ClientRect::create(); + + Vector<FloatQuad> quads; + renderBoxModelObject->absoluteQuads(quads); + + if (quads.isEmpty()) + return ClientRect::create(); + + IntRect result = quads[0].enclosingBoundingBox(); + for (size_t i = 1; i < quads.size(); ++i) + result.unite(quads[i].enclosingBoundingBox()); + + if (FrameView* view = document()->view()) { + IntRect visibleContentRect = view->visibleContentRect(); + result.move(-visibleContentRect.x(), -visibleContentRect.y()); + } + + return ClientRect::create(result); +} + static inline bool shouldIgnoreAttributeCase(const Element* e) { return e && e->document()->isHTMLDocument() && e->isHTMLElement(); @@ -1105,18 +1154,17 @@ void Element::updateFocusAppearance(bool /*restorePreviousSelection*/) return; // FIXME: We should restore the previous selection if there is one. - Selection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? Selection(Position(this, 0), DOWNSTREAM) : Selection::selectionFromContentsOfNode(this); + VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this); if (frame->shouldChangeSelection(newSelection)) { frame->selection()->setSelection(newSelection); frame->revealSelection(); } -#ifdef ANDROID_SCROLL_FIX - // We handle the scrolling the screen with our navigation code, - // so ignore this call to put the rectangle on screen. } -#else - } else if (renderer() && !renderer()->isWidget()) + // FIXME: I'm not sure all devices will want this off, but this is + // currently turned off for Andriod. +#if !ENABLE(DIRECTIONAL_PAD_NAVIGATION) + else if (renderer() && !renderer()->isWidget()) renderer()->enclosingLayer()->scrollRectToVisible(getRect()); #endif } diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h index e9bab28..b9b391a 100644 --- a/WebCore/dom/Element.h +++ b/WebCore/dom/Element.h @@ -36,6 +36,8 @@ class Attribute; class CSSStyleDeclaration; class ElementRareData; class IntSize; +class ClientRect; +class ClientRectList; class Element : public ContainerNode { public: @@ -82,6 +84,9 @@ public: int scrollWidth(); int scrollHeight(); + PassRefPtr<ClientRectList> getClientRects() const; + PassRefPtr<ClientRect> getBoundingClientRect() const; + void removeAttribute(const String& name, ExceptionCode&); void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&); @@ -110,20 +115,18 @@ public: // DOM methods overridden from parent classes virtual NodeType nodeType() const; - virtual PassRefPtr<Node> cloneNode(bool deep); virtual String nodeName() const; virtual void insertedIntoDocument(); virtual void removedFromDocument(); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - PassRefPtr<Element> cloneElement(); + PassRefPtr<Element> cloneElementWithChildren(); + PassRefPtr<Element> cloneElementWithoutChildren(); void normalizeAttributes(); virtual bool isFormControlElement() const { return false; } virtual bool isFormControlElementWithState() const { return false; } - virtual bool isInputTypeHidden() const { return false; } - virtual bool isPasswordField() const { return false; } String nodeNamePreservingCase() const; @@ -215,6 +218,10 @@ private: virtual const AtomicString& virtualLocalName() const { return localName(); } virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); } + // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren + // are used instead. + virtual PassRefPtr<Node> cloneNode(bool deep); + QualifiedName m_tagName; virtual NodeRareData* createRareData(); diff --git a/WebCore/dom/Element.idl b/WebCore/dom/Element.idl index ae2c1b8..889eaf0 100644 --- a/WebCore/dom/Element.idl +++ b/WebCore/dom/Element.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> * * This library is free software; you can redistribute it and/or @@ -26,7 +26,7 @@ module core { InlineGetOwnPropertySlot, InterfaceUUID=FEFE9C21-E58C-4b5b-821A-61A514613763, ImplementationUUID=12E5B08E-A680-4baf-9D1E-108AEF7ABBFB - ] Element : EventTargetNode { + ] Element : Node { // DOM Level 1 Core @@ -104,13 +104,13 @@ module core { NodeList getElementsByClassName(in DOMString name); // NodeSelector - Selector API - Element querySelector(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + Element querySelector(in DOMString selectors) raises(DOMException); - NodeList querySelectorAll(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + NodeList querySelectorAll(in DOMString selectors) raises(DOMException); - // ElementTraversal API #if !defined(LANGUAGE_COM) + // ElementTraversal API readonly attribute Element firstElementChild; readonly attribute Element lastElementChild; readonly attribute Element previousElementSibling; @@ -118,6 +118,12 @@ module core { readonly attribute unsigned long childElementCount; #endif +#if defined(LANGUAGE_JAVASCRIPT) + // CSSOM View Module API + ClientRectList getClientRects(); + ClientRect getBoundingClientRect(); +#endif + #if defined(LANGUAGE_OBJECTIVE_C) // Objective-C extensions readonly attribute DOMString innerText; diff --git a/WebCore/dom/EventException.idl b/WebCore/dom/EventException.idl index 61cfd65..f948078 100644 --- a/WebCore/dom/EventException.idl +++ b/WebCore/dom/EventException.idl @@ -30,7 +30,8 @@ module events { // Introduced in DOM Level 2: interface [ - GenerateConstructor + GenerateConstructor, + NoStaticTables ] EventException { readonly attribute unsigned short code; diff --git a/WebCore/dom/EventListener.h b/WebCore/dom/EventListener.h index 24fce86..b7daa6d 100644 --- a/WebCore/dom/EventListener.h +++ b/WebCore/dom/EventListener.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +23,10 @@ #include <wtf/RefCounted.h> +namespace JSC { + class JSObject; +} + namespace WebCore { class Event; @@ -31,10 +35,21 @@ namespace WebCore { public: virtual ~EventListener() { } virtual void handleEvent(Event*, bool isWindowEvent = false) = 0; - virtual bool isInline() const { return false; } virtual bool wasCreatedFromMarkup() const { return false; } + +#if USE(JSC) + virtual JSC::JSObject* function() const { return 0; } + virtual void mark() { } +#endif + + bool isInline() const { return virtualIsInline(); } + + private: + virtual bool virtualIsInline() const { return false; } }; + inline void markIfNotNull(EventListener* listener) { if (listener) listener->mark(); } + } #endif diff --git a/WebCore/dom/EventListener.idl b/WebCore/dom/EventListener.idl index 9d28703..9dc2e0a 100644 --- a/WebCore/dom/EventListener.idl +++ b/WebCore/dom/EventListener.idl @@ -22,6 +22,7 @@ module events { // Introduced in DOM Level 2: interface [ + NoStaticTables, ObjCProtocol, InterfaceUUID=B04F2AE3-71E2-4ebe-ABFE-EF4938354082, ImplementationUUID=DDFDD342-A78B-4f19-8F32-A5DF51B56E08 diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h index d6f2314..28a66bc 100644 --- a/WebCore/dom/EventNames.h +++ b/WebCore/dom/EventNames.h @@ -108,24 +108,26 @@ namespace WebCore { macro(webkitBeforeTextInserted) \ macro(webkitEditableContentChanged) \ \ - macro(canshowcurrentframe) \ macro(canplay) \ macro(canplaythrough) \ - macro(dataunavailable) \ macro(durationchange) \ macro(emptied) \ macro(ended) \ - macro(loadedfirstframe) \ + macro(loadeddata) \ macro(loadedmetadata) \ macro(pause) \ macro(play) \ + macro(playing) \ macro(ratechange) \ + macro(seeked) \ + macro(seeking) \ macro(timeupdate) \ macro(volumechange) \ macro(waiting) \ \ macro(progress) \ macro(stalled) \ + macro(suspend) \ \ macro(webkitAnimationEnd) \ macro(webkitAnimationStart) \ diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index dcebd64..6717a02 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -44,7 +44,7 @@ EventTarget::~EventTarget() { } -EventTargetNode* EventTarget::toNode() +Node* EventTarget::toNode() { return 0; } diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index 3a3ec84..81d2c5a 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -40,8 +40,8 @@ namespace WebCore { class DOMApplicationCache; class Event; class EventListener; - class EventTargetNode; class MessagePort; + class Node; class ScriptExecutionContext; class SVGElementInstance; class Worker; @@ -54,7 +54,7 @@ namespace WebCore { class EventTarget { public: virtual MessagePort* toMessagePort(); - virtual EventTargetNode* toNode(); + virtual Node* toNode(); virtual XMLHttpRequest* toXMLHttpRequest(); virtual XMLHttpRequestUpload* toXMLHttpRequestUpload(); #if ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/dom/EventTarget.idl b/WebCore/dom/EventTarget.idl index d3f46f7..844dc32 100644 --- a/WebCore/dom/EventTarget.idl +++ b/WebCore/dom/EventTarget.idl @@ -26,13 +26,13 @@ module events { PureInterface, InterfaceUUID=1D71C7EC-0BA0-4044-BDFD-56B3E8F5F9D4 ] EventTarget { - [OldStyleObjC, EventTargetNodeCast] void addEventListener(in DOMString type, + [OldStyleObjC] void addEventListener(in DOMString type, in EventListener listener, in boolean useCapture); - [OldStyleObjC, EventTargetNodeCast] void removeEventListener(in DOMString type, + [OldStyleObjC] void removeEventListener(in DOMString type, in EventListener listener, in boolean useCapture); - [EventTargetNodeCast] boolean dispatchEvent(in Event event) + boolean dispatchEvent(in Event event) raises(EventException); }; diff --git a/WebCore/dom/EventTargetNode.cpp b/WebCore/dom/EventTargetNode.cpp deleted file mode 100644 index d3d9a32..0000000 --- a/WebCore/dom/EventTargetNode.cpp +++ /dev/null @@ -1,1241 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "EventTargetNode.h" - -#include "Document.h" -#include "EventException.h" -#include "EventHandler.h" -#include "EventListener.h" -#include "EventNames.h" -#include "Frame.h" -#include "FrameView.h" -#include "KeyboardEvent.h" -#include "MouseEvent.h" -#include "MutationEvent.h" -#include "NodeRareData.h" -#include "Page.h" -#include "PlatformMouseEvent.h" -#include "PlatformWheelEvent.h" -#include "ProgressEvent.h" -#include "RegisteredEventListener.h" -#include "ScriptController.h" -#include "TextEvent.h" -#include "WebKitAnimationEvent.h" -#include "WebKitTransitionEvent.h" -#include "WheelEvent.h" -#include <wtf/HashSet.h> - -#if ENABLE(DOM_STORAGE) -#include "StorageEvent.h" -#endif - -#if ENABLE(SVG) -#include "SVGElementInstance.h" -#include "SVGUseElement.h" -#endif - -namespace WebCore { - -static HashSet<EventTargetNode*>* gNodesDispatchingSimulatedClicks = 0; - -EventTargetNode::EventTargetNode(Document* doc, bool isElement, bool isContainer, bool isText) - : Node(doc, isElement, isContainer, isText) -{ -} - -EventTargetNode::~EventTargetNode() -{ - if (!eventListeners().isEmpty() && !inDocument()) - document()->unregisterDisconnectedNodeWithEventListeners(this); -} - -ScriptExecutionContext* EventTargetNode::scriptExecutionContext() const -{ - return document(); -} - -const RegisteredEventListenerVector& EventTargetNode::eventListeners() const -{ - if (hasRareData()) { - if (RegisteredEventListenerVector* listeners = rareData()->listeners()) - return *listeners; - } - static const RegisteredEventListenerVector* emptyListenersVector = new RegisteredEventListenerVector; - return *emptyListenersVector; -} - -void EventTargetNode::insertedIntoDocument() -{ - if (!eventListeners().isEmpty()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - - Node::insertedIntoDocument(); -} - -void EventTargetNode::removedFromDocument() -{ - if (!eventListeners().isEmpty()) - document()->registerDisconnectedNodeWithEventListeners(this); - - Node::removedFromDocument(); -} - -void EventTargetNode::willMoveToNewOwnerDocument() -{ - if (!eventListeners().isEmpty()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - - Node::willMoveToNewOwnerDocument(); -} - -void EventTargetNode::didMoveToNewOwnerDocument() -{ - if (!eventListeners().isEmpty()) - document()->registerDisconnectedNodeWithEventListeners(this); - - Node::didMoveToNewOwnerDocument(); -} - -static inline void updateSVGElementInstancesAfterEventListenerChange(EventTargetNode* referenceNode) -{ - ASSERT(referenceNode); - -#if ENABLE(SVG) - if (!referenceNode->isSVGElement()) - return; - - // Elements living inside a <use> shadow tree, never cause any updates! - if (referenceNode->shadowTreeRootNode()) - return; - - // We're possibly (a child of) an element that is referenced by a <use> client - // If an event listeners changes on a referenced element, update all instances. - for (Node* node = referenceNode; node; node = node->parentNode()) { - if (!node->hasID() || !node->isSVGElement()) - continue; - - SVGElementInstance::invalidateAllInstancesOfElement(static_cast<SVGElement*>(node)); - break; - } -#endif -} - -void EventTargetNode::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) -{ - Document* document = this->document(); - if (!document->attached()) - return; - - document->addListenerTypeIfNeeded(eventType); - - RegisteredEventListenerVector& listeners = ensureRareData()->ensureListeners(); - - // Remove existing identical listener set with identical arguments. - // The DOM2 spec says that "duplicate instances are discarded" in this case. - removeEventListener(eventType, listener.get(), useCapture); - - // adding the first one - if (listeners.isEmpty() && !inDocument()) - document->registerDisconnectedNodeWithEventListeners(this); - - listeners.append(RegisteredEventListener::create(eventType, listener, useCapture)); - updateSVGElementInstancesAfterEventListenerChange(this); - -#if ENABLE(TOUCH_EVENTS) // Android - if (eventType == eventNames().touchstartEvent || - eventType == eventNames().touchendEvent || - eventType == eventNames().touchmoveEvent || - eventType == eventNames().touchcancelEvent) - document->addTouchEventListener(this); -#endif -} - -void EventTargetNode::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) -{ - if (!hasRareData()) - return; - - RegisteredEventListenerVector* listeners = rareData()->listeners(); - if (!listeners) - return; - - size_t size = listeners->size(); - for (size_t i = 0; i < size; ++i) { - RegisteredEventListener& r = *listeners->at(i); - if (r.eventType() == eventType && r.listener() == listener && r.useCapture() == useCapture) { - r.setRemoved(true); - listeners->remove(i); - - // removed last - if (listeners->isEmpty() && !inDocument()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - - updateSVGElementInstancesAfterEventListenerChange(this); - -#if ENABLE(TOUCH_EVENTS) // Android - if (eventType == eventNames().touchstartEvent || - eventType == eventNames().touchendEvent || - eventType == eventNames().touchmoveEvent || - eventType == eventNames().touchcancelEvent) - document()->removeTouchEventListener(this); -#endif - return; - } - } -} - -void EventTargetNode::removeAllEventListeners() -{ - if (!hasRareData()) - return; - - RegisteredEventListenerVector* listeners = rareData()->listeners(); - if (!listeners) - return; - -#if ENABLE(TOUCH_EVENTS) // Android - document()->removeTouchEventListener(this); -#endif - size_t size = listeners->size(); - for (size_t i = 0; i < size; ++i) - listeners->at(i)->setRemoved(true); - listeners->clear(); -} - -void EventTargetNode::handleLocalEvents(Event* event, bool useCapture) -{ - if (disabled() && event->isMouseEvent()) - return; - - RegisteredEventListenerVector listenersCopy = eventListeners(); - size_t size = listenersCopy.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listenersCopy[i]; - if (r.eventType() == event->type() && r.useCapture() == useCapture && !r.removed()) - r.listener()->handleEvent(event, false); - } -} - -#if ENABLE(SVG) -static inline SVGElementInstance* eventTargetAsSVGElementInstance(EventTargetNode* referenceNode) -{ - ASSERT(referenceNode); - if (!referenceNode->isSVGElement()) - return 0; - - // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included - // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects - for (Node* n = referenceNode; n; n = n->parentNode()) { - if (!n->isShadowNode() || !n->isSVGElement()) - continue; - - Node* shadowTreeParentElement = n->shadowParentNode(); - ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag)); - - if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode)) - return instance; - } - - return 0; -} -#endif - -static inline EventTarget* eventTargetRespectingSVGTargetRules(EventTargetNode* referenceNode) -{ - ASSERT(referenceNode); - -#if ENABLE(SVG) - if (SVGElementInstance* instance = eventTargetAsSVGElementInstance(referenceNode)) { - ASSERT(instance->shadowTreeElement() == referenceNode); - return instance; - } -#endif - - return referenceNode; -} - -bool EventTargetNode::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec) -{ - RefPtr<Event> evt(e); - ASSERT(!eventDispatchForbidden()); - if (!evt || evt->type().isEmpty()) { - ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; - return false; - } - - evt->setTarget(eventTargetRespectingSVGTargetRules(this)); - - RefPtr<FrameView> view = document()->view(); - return dispatchGenericEvent(evt.release()); -} - -bool EventTargetNode::dispatchGenericEvent(PassRefPtr<Event> prpEvent) -{ - RefPtr<Event> event(prpEvent); - - ASSERT(!eventDispatchForbidden()); - ASSERT(event->target()); - ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null. - - // Make a vector of ancestors to send the event to. - // If the node is not in a document just send the event to it. - // Be sure to ref all of nodes since event handlers could result in the last reference going away. - RefPtr<EventTargetNode> thisNode(this); - Vector<RefPtr<ContainerNode> > ancestors; - if (inDocument()) { - for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) { -#if ENABLE(SVG) - // Skip <use> shadow tree elements. - if (ancestor->isSVGElement() && ancestor->isShadowNode()) - continue; -#endif - ancestors.append(ancestor); - } - } - - // Set up a pointer to indicate whether to dispatch window events. - // We don't dispatch load events to the window. That quirk was originally - // added because Mozilla doesn't propagate load events to the window object. - Document* documentForWindowEvents = 0; - if (event->type() != eventNames().loadEvent) { - EventTargetNode* topLevelContainer = ancestors.isEmpty() ? this : ancestors.last().get(); - if (topLevelContainer->isDocumentNode()) - documentForWindowEvents = static_cast<Document*>(topLevelContainer); - } - - // Give the target node a chance to do some work before DOM event handlers get a crack. - void* data = preDispatchEventHandler(event.get()); - if (event->propagationStopped()) - goto doneDispatching; - - // Trigger capturing event handlers, starting at the top and working our way down. - event->setEventPhase(Event::CAPTURING_PHASE); - - if (documentForWindowEvents) { - event->setCurrentTarget(documentForWindowEvents); - documentForWindowEvents->handleWindowEvent(event.get(), true); - if (event->propagationStopped()) - goto doneDispatching; - } - for (size_t i = ancestors.size(); i; --i) { - ContainerNode* ancestor = ancestors[i - 1].get(); - event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); - ancestor->handleLocalEvents(event.get(), true); - if (event->propagationStopped()) - goto doneDispatching; - } - - event->setEventPhase(Event::AT_TARGET); - - // We do want capturing event listeners to be invoked here, even though - // that violates some versions of the DOM specification; Mozilla does it. - event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this)); - handleLocalEvents(event.get(), true); - if (event->propagationStopped()) - goto doneDispatching; - handleLocalEvents(event.get(), false); - if (event->propagationStopped()) - goto doneDispatching; - - if (event->bubbles() && !event->cancelBubble()) { - // Trigger bubbling event handlers, starting at the bottom and working our way up. - event->setEventPhase(Event::BUBBLING_PHASE); - - size_t size = ancestors.size(); - for (size_t i = 0; i < size; ++i) { - ContainerNode* ancestor = ancestors[i].get(); - event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); - ancestor->handleLocalEvents(event.get(), false); - if (event->propagationStopped() || event->cancelBubble()) - goto doneDispatching; - } - if (documentForWindowEvents) { - event->setCurrentTarget(documentForWindowEvents); - documentForWindowEvents->handleWindowEvent(event.get(), false); - if (event->propagationStopped() || event->cancelBubble()) - goto doneDispatching; - } - } - -doneDispatching: - event->setCurrentTarget(0); - event->setEventPhase(0); - - // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler. - postDispatchEventHandler(event.get(), data); - - // Call default event handlers. While the DOM does have a concept of preventing - // default handling, the detail of which handlers are called is an internal - // implementation detail and not part of the DOM. - if (!event->defaultPrevented() && !event->defaultHandled()) { - // Non-bubbling events call only one default event handler, the one for the target. - defaultEventHandler(event.get()); - ASSERT(!event->defaultPrevented()); - if (event->defaultHandled()) - goto doneWithDefault; - // For bubbling events, call default event handlers on the same targets in the - // same order as the bubbling phase. - if (event->bubbles()) { - size_t size = ancestors.size(); - for (size_t i = 0; i < size; ++i) { - ContainerNode* ancestor = ancestors[i].get(); - ancestor->defaultEventHandler(event.get()); - ASSERT(!event->defaultPrevented()); - if (event->defaultHandled()) - goto doneWithDefault; - } - } - } - -doneWithDefault: - Document::updateDocumentsRendering(); - - return !event->defaultPrevented(); -} - -bool EventTargetNode::dispatchSubtreeModifiedEvent() -{ - ASSERT(!eventDispatchForbidden()); - - document()->incDOMTreeVersion(); - - notifyNodeListsAttributeChanged(); // FIXME: Can do better some day. Really only care about the name attribute changing. - - if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER)) - return false; - ExceptionCode ec = 0; - return dispatchEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true, false, 0, String(), String(), String(), 0), ec); -} - -void EventTargetNode::dispatchWindowEvent(PassRefPtr<Event> e) -{ - ASSERT(!eventDispatchForbidden()); - RefPtr<Event> evt(e); - RefPtr<Document> doc = document(); - evt->setTarget(doc); - doc->handleWindowEvent(evt.get(), true); - doc->handleWindowEvent(evt.get(), false); -} - -void EventTargetNode::dispatchWindowEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg) -{ - ASSERT(!eventDispatchForbidden()); - RefPtr<Document> doc = document(); - dispatchWindowEvent(Event::create(eventType, canBubbleArg, cancelableArg)); - - if (eventType == eventNames().loadEvent) { - // For onload events, send a separate load event to the enclosing frame only. - // This is a DOM extension and is independent of bubbling/capturing rules of - // the DOM. - Element* ownerElement = doc->ownerElement(); - if (ownerElement) { - RefPtr<Event> ownerEvent = Event::create(eventType, false, cancelableArg); - ownerEvent->setTarget(ownerElement); - ownerElement->dispatchGenericEvent(ownerEvent.release()); - } - } -} - -bool EventTargetNode::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent) -{ - ASSERT(!eventDispatchForbidden()); - ASSERT(eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent); - - bool cancelable = eventType == eventNames().DOMActivateEvent; - - ExceptionCode ec = 0; - RefPtr<UIEvent> evt = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail); - evt->setUnderlyingEvent(underlyingEvent); - return dispatchEvent(evt.release(), ec); -} - -bool EventTargetNode::dispatchKeyEvent(const PlatformKeyboardEvent& key) -{ - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; - RefPtr<KeyboardEvent> keyboardEvent = KeyboardEvent::create(key, document()->defaultView()); - bool r = dispatchEvent(keyboardEvent, ec); - - // we want to return false if default is prevented (already taken care of) - // or if the element is default-handled by the DOM. Otherwise we let it just - // let it get handled by AppKit - if (keyboardEvent->defaultHandled()) - r = false; - - return r; -} - -bool EventTargetNode::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType, - int detail, Node* relatedTarget) -{ - ASSERT(!eventDispatchForbidden()); - - IntPoint contentsPos; - if (FrameView* view = document()->view()) - contentsPos = view->windowToContents(event.pos()); - - short button = event.button(); - - ASSERT(event.eventType() == MouseEventMoved || button != NoButton); - - return dispatchMouseEvent(eventType, button, detail, - contentsPos.x(), contentsPos.y(), event.globalX(), event.globalY(), - event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), - false, relatedTarget); -} - -void EventTargetNode::dispatchSimulatedMouseEvent(const AtomicString& eventType, - PassRefPtr<Event> underlyingEvent) -{ - ASSERT(!eventDispatchForbidden()); - - bool ctrlKey = false; - bool altKey = false; - bool shiftKey = false; - bool metaKey = false; - if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) { - ctrlKey = keyStateEvent->ctrlKey(); - altKey = keyStateEvent->altKey(); - shiftKey = keyStateEvent->shiftKey(); - metaKey = keyStateEvent->metaKey(); - } - - // Like Gecko, we just pass 0 for everything when we make a fake mouse event. - // Internet Explorer instead gives the current mouse position and state. - dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0, - ctrlKey, altKey, shiftKey, metaKey, true, 0, underlyingEvent); -} - -void EventTargetNode::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook) -{ - if (!gNodesDispatchingSimulatedClicks) - gNodesDispatchingSimulatedClicks = new HashSet<EventTargetNode*>; - else if (gNodesDispatchingSimulatedClicks->contains(this)) - return; - - gNodesDispatchingSimulatedClicks->add(this); - - // send mousedown and mouseup before the click, if requested - if (sendMouseEvents) - dispatchSimulatedMouseEvent(eventNames().mousedownEvent, event.get()); - setActive(true, showPressedLook); - if (sendMouseEvents) - dispatchSimulatedMouseEvent(eventNames().mouseupEvent, event.get()); - setActive(false); - - // always send click - dispatchSimulatedMouseEvent(eventNames().clickEvent, event); - - gNodesDispatchingSimulatedClicks->remove(this); -} - -bool EventTargetNode::dispatchMouseEvent(const AtomicString& eventType, int button, int detail, - int pageX, int pageY, int screenX, int screenY, - bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent) -{ - ASSERT(!eventDispatchForbidden()); - if (disabled()) // Don't even send DOM events for disabled controls.. - return true; - - if (eventType.isEmpty()) - return false; // Shouldn't happen. - - // Dispatching the first event can easily result in this node being destroyed. - // Since we dispatch up to three events here, we need to make sure we're referenced - // so the pointer will be good for the two subsequent ones. - RefPtr<Node> protect(this); - - bool cancelable = eventType != eventNames().mousemoveEvent; - - ExceptionCode ec = 0; - - bool swallowEvent = false; - - // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored. - RefPtr<EventTargetNode> relatedTarget = (relatedTargetArg && relatedTargetArg->isEventTargetNode()) - ? static_cast<EventTargetNode*>(relatedTargetArg) : 0; - - if (Frame* frame = document()->frame()) { - float pageZoom = frame->pageZoomFactor(); - if (pageZoom != 1.0f) { - // Adjust our pageX and pageY to account for the page zoom. - pageX = lroundf(pageX / pageZoom); - pageY = lroundf(pageY / pageZoom); - } - } - - RefPtr<Event> mouseEvent = MouseEvent::create(eventType, - true, cancelable, document()->defaultView(), - detail, screenX, screenY, pageX, pageY, - ctrlKey, altKey, shiftKey, metaKey, button, - relatedTarget, 0, isSimulated); - mouseEvent->setUnderlyingEvent(underlyingEvent.get()); - - dispatchEvent(mouseEvent, ec); - bool defaultHandled = mouseEvent->defaultHandled(); - bool defaultPrevented = mouseEvent->defaultPrevented(); - if (defaultHandled || defaultPrevented) - swallowEvent = true; - - // Special case: If it's a double click event, we also send the dblclick event. This is not part - // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated - // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same. - if (eventType == eventNames().clickEvent && detail == 2) { - RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent, - true, cancelable, document()->defaultView(), - detail, screenX, screenY, pageX, pageY, - ctrlKey, altKey, shiftKey, metaKey, button, - relatedTarget, 0, isSimulated); - doubleClickEvent->setUnderlyingEvent(underlyingEvent.get()); - if (defaultHandled) - doubleClickEvent->setDefaultHandled(); - dispatchEvent(doubleClickEvent, ec); - if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented()) - swallowEvent = true; - } - - return swallowEvent; -} - -void EventTargetNode::dispatchWheelEvent(PlatformWheelEvent& e) -{ - ASSERT(!eventDispatchForbidden()); - if (e.deltaX() == 0 && e.deltaY() == 0) - return; - - FrameView* view = document()->view(); - if (!view) - return; - - IntPoint pos = view->windowToContents(e.pos()); - - // Convert the deltas from pixels to lines if we have a pixel scroll event. - float deltaX = e.deltaX(); - float deltaY = e.deltaY(); - - // FIXME: Should we do anything with a ScrollByPageWheelEvent here? - // It will be treated like a line scroll of 1 right now. - if (e.granularity() == ScrollByPixelWheelEvent) { - deltaX /= cMouseWheelPixelsPerLineStep; - deltaY /= cMouseWheelPixelsPerLineStep; - } - - RefPtr<WheelEvent> we = WheelEvent::create(e.deltaX(), e.deltaY(), - document()->defaultView(), e.globalX(), e.globalY(), pos.x(), pos.y(), - e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey()); - ExceptionCode ec = 0; - if (!dispatchEvent(we.release(), ec)) - e.accept(); -} - -bool EventTargetNode::dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime) -{ - ASSERT(!eventDispatchForbidden()); - - ExceptionCode ec = 0; - return dispatchEvent(WebKitAnimationEvent::create(eventType, animationName, elapsedTime), ec); -} - -bool EventTargetNode::dispatchWebKitTransitionEvent(const AtomicString& eventType, const String& propertyName, double elapsedTime) -{ - ASSERT(!eventDispatchForbidden()); - - ExceptionCode ec = 0; - return dispatchEvent(WebKitTransitionEvent::create(eventType, propertyName, elapsedTime), ec); -} - -void EventTargetNode::dispatchFocusEvent() -{ - dispatchEventForType(eventNames().focusEvent, false, false); -} - -void EventTargetNode::dispatchBlurEvent() -{ - dispatchEventForType(eventNames().blurEvent, false, false); -} - -bool EventTargetNode::dispatchEventForType(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg) -{ - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; - return dispatchEvent(Event::create(eventType, canBubbleArg, cancelableArg), ec); -} - -bool EventTargetNode::dispatchProgressEvent(const AtomicString &eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg) -{ - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; - return dispatchEvent(ProgressEvent::create(eventType, lengthComputableArg, loadedArg, totalArg), ec); -} - -void EventTargetNode::dispatchStorageEvent(const AtomicString &eventType, const String& key, const String& oldValue, const String& newValue, Frame* source) -{ -#if ENABLE(DOM_STORAGE) - ASSERT(!eventDispatchForbidden()); - ExceptionCode ec = 0; - dispatchEvent(StorageEvent::create(eventType, key, oldValue, newValue, source->document()->documentURI(), source->domWindow()), ec); -#endif -} - -void EventTargetNode::removeInlineEventListenerForType(const AtomicString& eventType) -{ - if (!hasRareData()) - return; - - RegisteredEventListenerVector* listeners = rareData()->listeners(); - if (!listeners) - return; - - size_t size = listeners->size(); - for (size_t i = 0; i < size; ++i) { - RegisteredEventListener& r = *listeners->at(i); - if (r.eventType() != eventType || !r.listener()->isInline()) - continue; - - r.setRemoved(true); - listeners->remove(i); - - // removed last - if (listeners->isEmpty() && !inDocument()) - document()->unregisterDisconnectedNodeWithEventListeners(this); - - updateSVGElementInstancesAfterEventListenerChange(this); - return; - } -} - -void EventTargetNode::setInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener> listener) -{ - // In case we are the only one holding a reference to it, we don't want removeInlineEventListenerForType to destroy it. - removeInlineEventListenerForType(eventType); - if (listener) - addEventListener(eventType, listener, false); -} - -void EventTargetNode::setInlineEventListenerForTypeAndAttribute(const AtomicString& eventType, Attribute* attr) -{ - setInlineEventListenerForType(eventType, document()->createEventListener(attr->localName().string(), attr->value(), this)); -} - -EventListener* EventTargetNode::inlineEventListenerForType(const AtomicString& eventType) const -{ - const RegisteredEventListenerVector& listeners = eventListeners(); - size_t size = listeners.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listeners[i]; - if (r.eventType() == eventType && r.listener()->isInline()) - return r.listener(); - } - return 0; -} - -#ifdef ANDROID -EventListener *EventTargetNode::getEventListener(const AtomicString &eventType) -{ - const RegisteredEventListenerVector& listeners = eventListeners(); - size_t size = listeners.size(); - for (size_t i = 0; i < size; ++i) { - const RegisteredEventListener& r = *listeners[i]; - if (r.eventType() == eventType) - return r.listener(); - } - return 0; -} -#endif - -bool EventTargetNode::disabled() const -{ - return false; -} - -void EventTargetNode::defaultEventHandler(Event* event) -{ - if (event->target() != this) - return; - const AtomicString& eventType = event->type(); - if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) { - if (event->isKeyboardEvent()) - if (Frame* frame = document()->frame()) - frame->eventHandler()->defaultKeyboardEventHandler(static_cast<KeyboardEvent*>(event)); - } else if (eventType == eventNames().clickEvent) { - int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0; - dispatchUIEvent(eventNames().DOMActivateEvent, detail, event); - } else if (eventType == eventNames().contextmenuEvent) { - if (Frame* frame = document()->frame()) - if (Page* page = frame->page()) - page->contextMenuController()->handleContextMenuEvent(event); - } else if (eventType == eventNames().textInputEvent) { - if (event->isTextEvent()) - if (Frame* frame = document()->frame()) - frame->eventHandler()->defaultTextInputEventHandler(static_cast<TextEvent*>(event)); - } -} - -EventListener* EventTargetNode::onabort() const -{ - return inlineEventListenerForType(eventNames().abortEvent); -} - -void EventTargetNode::setOnabort(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().abortEvent, eventListener); -} - -EventListener* EventTargetNode::onblur() const -{ - return inlineEventListenerForType(eventNames().blurEvent); -} - -void EventTargetNode::setOnblur(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().blurEvent, eventListener); -} - -EventListener* EventTargetNode::onchange() const -{ - return inlineEventListenerForType(eventNames().changeEvent); -} - -void EventTargetNode::setOnchange(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().changeEvent, eventListener); -} - -EventListener* EventTargetNode::onclick() const -{ - return inlineEventListenerForType(eventNames().clickEvent); -} - -void EventTargetNode::setOnclick(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().clickEvent, eventListener); -} - -EventListener* EventTargetNode::oncontextmenu() const -{ - return inlineEventListenerForType(eventNames().contextmenuEvent); -} - -void EventTargetNode::setOncontextmenu(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().contextmenuEvent, eventListener); -} - -EventListener* EventTargetNode::ondblclick() const -{ - return inlineEventListenerForType(eventNames().dblclickEvent); -} - -void EventTargetNode::setOndblclick(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dblclickEvent, eventListener); -} - -EventListener* EventTargetNode::onerror() const -{ - return inlineEventListenerForType(eventNames().errorEvent); -} - -void EventTargetNode::setOnerror(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().errorEvent, eventListener); -} - -EventListener* EventTargetNode::onfocus() const -{ - return inlineEventListenerForType(eventNames().focusEvent); -} - -void EventTargetNode::setOnfocus(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().focusEvent, eventListener); -} - -EventListener* EventTargetNode::oninput() const -{ - return inlineEventListenerForType(eventNames().inputEvent); -} - -void EventTargetNode::setOninput(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().inputEvent, eventListener); -} - -EventListener* EventTargetNode::onkeydown() const -{ - return inlineEventListenerForType(eventNames().keydownEvent); -} - -void EventTargetNode::setOnkeydown(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().keydownEvent, eventListener); -} - -EventListener* EventTargetNode::onkeypress() const -{ - return inlineEventListenerForType(eventNames().keypressEvent); -} - -void EventTargetNode::setOnkeypress(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().keypressEvent, eventListener); -} - -EventListener* EventTargetNode::onkeyup() const -{ - return inlineEventListenerForType(eventNames().keyupEvent); -} - -void EventTargetNode::setOnkeyup(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().keyupEvent, eventListener); -} - -EventListener* EventTargetNode::onload() const -{ - return inlineEventListenerForType(eventNames().loadEvent); -} - -void EventTargetNode::setOnload(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().loadEvent, eventListener); -} - -EventListener* EventTargetNode::onmousedown() const -{ - return inlineEventListenerForType(eventNames().mousedownEvent); -} - -void EventTargetNode::setOnmousedown(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().mousedownEvent, eventListener); -} - -EventListener* EventTargetNode::onmousemove() const -{ - return inlineEventListenerForType(eventNames().mousemoveEvent); -} - -void EventTargetNode::setOnmousemove(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().mousemoveEvent, eventListener); -} - -EventListener* EventTargetNode::onmouseout() const -{ - return inlineEventListenerForType(eventNames().mouseoutEvent); -} - -void EventTargetNode::setOnmouseout(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().mouseoutEvent, eventListener); -} - -EventListener* EventTargetNode::onmouseover() const -{ - return inlineEventListenerForType(eventNames().mouseoverEvent); -} - -void EventTargetNode::setOnmouseover(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().mouseoverEvent, eventListener); -} - -EventListener* EventTargetNode::onmouseup() const -{ - return inlineEventListenerForType(eventNames().mouseupEvent); -} - -void EventTargetNode::setOnmouseup(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().mouseupEvent, eventListener); -} - -EventListener* EventTargetNode::onmousewheel() const -{ - return inlineEventListenerForType(eventNames().mousewheelEvent); -} - -void EventTargetNode::setOnmousewheel(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().mousewheelEvent, eventListener); -} - -EventListener* EventTargetNode::onbeforecut() const -{ - return inlineEventListenerForType(eventNames().beforecutEvent); -} - -void EventTargetNode::setOnbeforecut(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().beforecutEvent, eventListener); -} - -EventListener* EventTargetNode::oncut() const -{ - return inlineEventListenerForType(eventNames().cutEvent); -} - -void EventTargetNode::setOncut(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().cutEvent, eventListener); -} - -EventListener* EventTargetNode::onbeforecopy() const -{ - return inlineEventListenerForType(eventNames().beforecopyEvent); -} - -void EventTargetNode::setOnbeforecopy(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().beforecopyEvent, eventListener); -} - -EventListener* EventTargetNode::oncopy() const -{ - return inlineEventListenerForType(eventNames().copyEvent); -} - -void EventTargetNode::setOncopy(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().copyEvent, eventListener); -} - -EventListener* EventTargetNode::onbeforepaste() const -{ - return inlineEventListenerForType(eventNames().beforepasteEvent); -} - -void EventTargetNode::setOnbeforepaste(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().beforepasteEvent, eventListener); -} - -EventListener* EventTargetNode::onpaste() const -{ - return inlineEventListenerForType(eventNames().pasteEvent); -} - -void EventTargetNode::setOnpaste(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().pasteEvent, eventListener); -} - -EventListener* EventTargetNode::ondragenter() const -{ - return inlineEventListenerForType(eventNames().dragenterEvent); -} - -void EventTargetNode::setOndragenter(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dragenterEvent, eventListener); -} - -EventListener* EventTargetNode::ondragover() const -{ - return inlineEventListenerForType(eventNames().dragoverEvent); -} - -void EventTargetNode::setOndragover(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dragoverEvent, eventListener); -} - -EventListener* EventTargetNode::ondragleave() const -{ - return inlineEventListenerForType(eventNames().dragleaveEvent); -} - -void EventTargetNode::setOndragleave(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dragleaveEvent, eventListener); -} - -EventListener* EventTargetNode::ondrop() const -{ - return inlineEventListenerForType(eventNames().dropEvent); -} - -void EventTargetNode::setOndrop(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dropEvent, eventListener); -} - -EventListener* EventTargetNode::ondragstart() const -{ - return inlineEventListenerForType(eventNames().dragstartEvent); -} - -void EventTargetNode::setOndragstart(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dragstartEvent, eventListener); -} - -EventListener* EventTargetNode::ondrag() const -{ - return inlineEventListenerForType(eventNames().dragEvent); -} - -void EventTargetNode::setOndrag(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dragEvent, eventListener); -} - -EventListener* EventTargetNode::ondragend() const -{ - return inlineEventListenerForType(eventNames().dragendEvent); -} - -void EventTargetNode::setOndragend(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().dragendEvent, eventListener); -} - -EventListener* EventTargetNode::onreset() const -{ - return inlineEventListenerForType(eventNames().resetEvent); -} - -void EventTargetNode::setOnreset(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().resetEvent, eventListener); -} - -EventListener* EventTargetNode::onresize() const -{ - return inlineEventListenerForType(eventNames().resizeEvent); -} - -void EventTargetNode::setOnresize(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().resizeEvent, eventListener); -} - -EventListener* EventTargetNode::onscroll() const -{ - return inlineEventListenerForType(eventNames().scrollEvent); -} - -void EventTargetNode::setOnscroll(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().scrollEvent, eventListener); -} - -EventListener* EventTargetNode::onsearch() const -{ - return inlineEventListenerForType(eventNames().searchEvent); -} - -void EventTargetNode::setOnsearch(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().searchEvent, eventListener); -} - -EventListener* EventTargetNode::onselect() const -{ - return inlineEventListenerForType(eventNames().selectEvent); -} - -void EventTargetNode::setOnselect(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().selectEvent, eventListener); -} - -EventListener* EventTargetNode::onselectstart() const -{ - return inlineEventListenerForType(eventNames().selectstartEvent); -} - -void EventTargetNode::setOnselectstart(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().selectstartEvent, eventListener); -} - -EventListener* EventTargetNode::onsubmit() const -{ - return inlineEventListenerForType(eventNames().submitEvent); -} - -void EventTargetNode::setOnsubmit(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().submitEvent, eventListener); -} - -EventListener* EventTargetNode::onunload() const -{ - return inlineEventListenerForType(eventNames().unloadEvent); -} - -void EventTargetNode::setOnunload(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().unloadEvent, eventListener); -} - -#if ENABLE(TOUCH_EVENTS) // Android -EventListener* EventTargetNode::ontouchstart() const -{ - return inlineEventListenerForType(eventNames().touchstartEvent); -} - -void EventTargetNode::setOntouchstart(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().touchstartEvent, eventListener); -} - -EventListener* EventTargetNode::ontouchend() const -{ - return inlineEventListenerForType(eventNames().touchendEvent); -} - -void EventTargetNode::setOntouchend(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().touchendEvent, eventListener); -} - -EventListener* EventTargetNode::ontouchmove() const -{ - return inlineEventListenerForType(eventNames().touchmoveEvent); -} - -void EventTargetNode::setOntouchmove(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().touchmoveEvent, eventListener); -} - -EventListener* EventTargetNode::ontouchcancel() const -{ - return inlineEventListenerForType(eventNames().touchcancelEvent); -} - -void EventTargetNode::setOntouchcancel(PassRefPtr<EventListener> eventListener) -{ - setInlineEventListenerForType(eventNames().touchcancelEvent, eventListener); -} - -#endif - -} // namespace WebCore diff --git a/WebCore/dom/EventTargetNode.h b/WebCore/dom/EventTargetNode.h deleted file mode 100644 index 1814b7b..0000000 --- a/WebCore/dom/EventTargetNode.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef EventTargetNode_h -#define EventTargetNode_h - -#include "EventTarget.h" -#include "Node.h" - -namespace WebCore { - -class Attribute; -class Frame; -class RegisteredEventListener; - -typedef Vector<RefPtr<RegisteredEventListener> > RegisteredEventListenerVector; - -class EventTargetNode : public Node, public EventTarget { -public: - EventTargetNode(Document*, bool isElement = false, bool isContainer = false, bool isText = false); - virtual ~EventTargetNode(); - - virtual bool isEventTargetNode() const { return true; } - virtual EventTargetNode* toNode() { return this; } - - virtual ScriptExecutionContext* scriptExecutionContext() const; - - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); - void removeAllEventListeners(); - -#ifdef ANDROID - EventListener* getEventListener(const AtomicString& eventType); -#endif - void setInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener>); - void setInlineEventListenerForTypeAndAttribute(const AtomicString& eventType, Attribute*); - void removeInlineEventListenerForType(const AtomicString& eventType); - bool dispatchEventForType(const AtomicString& eventType, bool canBubble, bool cancelable); - EventListener* inlineEventListenerForType(const AtomicString& eventType) const; - - bool dispatchSubtreeModifiedEvent(); - void dispatchWindowEvent(PassRefPtr<Event>); - void dispatchWindowEvent(const AtomicString& eventType, bool canBubble, bool cancelable); - bool dispatchUIEvent(const AtomicString& eventType, int detail = 0, PassRefPtr<Event> underlyingEvent = 0); - bool dispatchKeyEvent(const PlatformKeyboardEvent&); - void dispatchWheelEvent(PlatformWheelEvent&); - bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, - int clickCount = 0, Node* relatedTarget = 0); - bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount, - int pageX, int pageY, int screenX, int screenY, - bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - bool isSimulated = false, Node* relatedTarget = 0, PassRefPtr<Event> underlyingEvent = 0); - void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent = 0); - void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true); - bool dispatchProgressEvent(const AtomicString &eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg); - void dispatchStorageEvent(const AtomicString &eventType, const String& key, const String& oldValue, const String& newValue, Frame* source); - bool dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime); - bool dispatchWebKitTransitionEvent(const AtomicString& eventType, const String& propertyName, double elapsedTime); - bool dispatchGenericEvent(PassRefPtr<Event>); - - virtual void handleLocalEvents(Event*, bool useCapture); - - virtual void dispatchFocusEvent(); - virtual void dispatchBlurEvent(); - - virtual void insertedIntoDocument(); - virtual void removedFromDocument(); - virtual void willMoveToNewOwnerDocument(); - virtual void didMoveToNewOwnerDocument(); - - /** - * Perform the default action for an event e.g. submitting a form - */ - virtual void defaultEventHandler(Event*); - - /** - * Used for disabled form elements; if true, prevents mouse events from being dispatched - * to event listeners, and prevents DOMActivate events from being sent at all. - */ - virtual bool disabled() const; - - const RegisteredEventListenerVector& eventListeners() const; - - EventListener* onabort() const; - void setOnabort(PassRefPtr<EventListener>); - EventListener* onblur() const; - void setOnblur(PassRefPtr<EventListener>); - EventListener* onchange() const; - void setOnchange(PassRefPtr<EventListener>); - EventListener* onclick() const; - void setOnclick(PassRefPtr<EventListener>); - EventListener* oncontextmenu() const; - void setOncontextmenu(PassRefPtr<EventListener>); - EventListener* ondblclick() const; - void setOndblclick(PassRefPtr<EventListener>); - EventListener* onerror() const; - void setOnerror(PassRefPtr<EventListener>); - EventListener* onfocus() const; - void setOnfocus(PassRefPtr<EventListener>); - EventListener* oninput() const; - void setOninput(PassRefPtr<EventListener>); - EventListener* onkeydown() const; - void setOnkeydown(PassRefPtr<EventListener>); - EventListener* onkeypress() const; - void setOnkeypress(PassRefPtr<EventListener>); - EventListener* onkeyup() const; - void setOnkeyup(PassRefPtr<EventListener>); - EventListener* onload() const; - void setOnload(PassRefPtr<EventListener>); - EventListener* onmousedown() const; - void setOnmousedown(PassRefPtr<EventListener>); - EventListener* onmousemove() const; - void setOnmousemove(PassRefPtr<EventListener>); - EventListener* onmouseout() const; - void setOnmouseout(PassRefPtr<EventListener>); - EventListener* onmouseover() const; - void setOnmouseover(PassRefPtr<EventListener>); - EventListener* onmouseup() const; - void setOnmouseup(PassRefPtr<EventListener>); - EventListener* onmousewheel() const; - void setOnmousewheel(PassRefPtr<EventListener>); - EventListener* onbeforecut() const; - void setOnbeforecut(PassRefPtr<EventListener>); - EventListener* oncut() const; - void setOncut(PassRefPtr<EventListener>); - EventListener* onbeforecopy() const; - void setOnbeforecopy(PassRefPtr<EventListener>); - EventListener* oncopy() const; - void setOncopy(PassRefPtr<EventListener>); - EventListener* onbeforepaste() const; - void setOnbeforepaste(PassRefPtr<EventListener>); - EventListener* onpaste() const; - void setOnpaste(PassRefPtr<EventListener>); - EventListener* ondragenter() const; - void setOndragenter(PassRefPtr<EventListener>); - EventListener* ondragover() const; - void setOndragover(PassRefPtr<EventListener>); - EventListener* ondragleave() const; - void setOndragleave(PassRefPtr<EventListener>); - EventListener* ondrop() const; - void setOndrop(PassRefPtr<EventListener>); - EventListener* ondragstart() const; - void setOndragstart(PassRefPtr<EventListener>); - EventListener* ondrag() const; - void setOndrag(PassRefPtr<EventListener>); - EventListener* ondragend() const; - void setOndragend(PassRefPtr<EventListener>); - EventListener* onreset() const; - void setOnreset(PassRefPtr<EventListener>); - EventListener* onresize() const; - void setOnresize(PassRefPtr<EventListener>); - EventListener* onscroll() const; - void setOnscroll(PassRefPtr<EventListener>); - EventListener* onsearch() const; - void setOnsearch(PassRefPtr<EventListener>); - EventListener* onselect() const; - void setOnselect(PassRefPtr<EventListener>); - EventListener* onselectstart() const; - void setOnselectstart(PassRefPtr<EventListener>); - EventListener* onsubmit() const; - void setOnsubmit(PassRefPtr<EventListener>); - EventListener* onunload() const; - void setOnunload(PassRefPtr<EventListener>); -#if ENABLE(TOUCH_EVENTS) // Android - EventListener* ontouchstart() const; - void setOntouchstart(PassRefPtr<EventListener>); - EventListener* ontouchend() const; - void setOntouchend(PassRefPtr<EventListener>); - EventListener* ontouchmove() const; - void setOntouchmove(PassRefPtr<EventListener>); - EventListener* ontouchcancel() const; - void setOntouchcancel(PassRefPtr<EventListener>); -#endif - - using Node::ref; - using Node::deref; - -private: - virtual void refEventTarget() { ref(); } - virtual void derefEventTarget() { deref(); } -}; - -inline EventTargetNode* EventTargetNodeCast(Node* n) -{ - ASSERT(n->isEventTargetNode()); - return static_cast<EventTargetNode*>(n); -} - -inline const EventTargetNode* EventTargetNodeCast(const Node* n) -{ - ASSERT(n->isEventTargetNode()); - return static_cast<const EventTargetNode*>(n); -} - -} // namespace WebCore - -#endif // EventTargetNode_h diff --git a/WebCore/dom/EventTargetNode.idl b/WebCore/dom/EventTargetNode.idl deleted file mode 100644 index acb2e95..0000000 --- a/WebCore/dom/EventTargetNode.idl +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -module core { - - interface [ - CustomPushEventHandlerScope, - GenerateNativeConverter - ] EventTargetNode : Node { - // EventTarget - attribute [DontEnum, ProtectedListener] EventListener onabort; - attribute [DontEnum, ProtectedListener] EventListener onblur; - attribute [DontEnum, ProtectedListener] EventListener onchange; - attribute [DontEnum, ProtectedListener] EventListener onclick; - attribute [DontEnum, ProtectedListener] EventListener oncontextmenu; - attribute [DontEnum, ProtectedListener] EventListener ondblclick; - attribute [DontEnum, ProtectedListener] EventListener onerror; - attribute [DontEnum, ProtectedListener] EventListener onfocus; - attribute [DontEnum, ProtectedListener] EventListener oninput; - attribute [DontEnum, ProtectedListener] EventListener onkeydown; - attribute [DontEnum, ProtectedListener] EventListener onkeypress; - attribute [DontEnum, ProtectedListener] EventListener onkeyup; - attribute [DontEnum, ProtectedListener] EventListener onload; - attribute [DontEnum, ProtectedListener] EventListener onmousedown; - attribute [DontEnum, ProtectedListener] EventListener onmousemove; - attribute [DontEnum, ProtectedListener] EventListener onmouseout; - attribute [DontEnum, ProtectedListener] EventListener onmouseover; - attribute [DontEnum, ProtectedListener] EventListener onmouseup; - attribute [DontEnum, ProtectedListener] EventListener onmousewheel; - attribute [DontEnum, ProtectedListener] EventListener onbeforecut; - attribute [DontEnum, ProtectedListener] EventListener oncut; - attribute [DontEnum, ProtectedListener] EventListener onbeforecopy; - attribute [DontEnum, ProtectedListener] EventListener oncopy; - attribute [DontEnum, ProtectedListener] EventListener onbeforepaste; - attribute [DontEnum, ProtectedListener] EventListener onpaste; - attribute [DontEnum, ProtectedListener] EventListener ondragenter; - attribute [DontEnum, ProtectedListener] EventListener ondragover; - attribute [DontEnum, ProtectedListener] EventListener ondragleave; - attribute [DontEnum, ProtectedListener] EventListener ondrop; - attribute [DontEnum, ProtectedListener] EventListener ondragstart; - attribute [DontEnum, ProtectedListener] EventListener ondrag; - attribute [DontEnum, ProtectedListener] EventListener ondragend; - attribute [DontEnum, ProtectedListener] EventListener onreset; - attribute [DontEnum, ProtectedListener] EventListener onresize; - attribute [DontEnum, ProtectedListener] EventListener onscroll; - attribute [DontEnum, ProtectedListener] EventListener onsearch; - attribute [DontEnum, ProtectedListener] EventListener onselect; - attribute [DontEnum, ProtectedListener] EventListener onselectstart; - attribute [DontEnum, ProtectedListener] EventListener onsubmit; - attribute [DontEnum, ProtectedListener] EventListener onunload; -#if ENABLE_TOUCH_EVENTS - attribute [DontEnum, ProtectedListener] EventListener ontouchstart; - attribute [DontEnum, ProtectedListener] EventListener ontouchend; - attribute [DontEnum, ProtectedListener] EventListener ontouchmove; - attribute [DontEnum, ProtectedListener] EventListener ontouchcancel; -#endif - - [Custom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [Custom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - boolean dispatchEvent(in Event event) - raises(EventException); - }; - -} diff --git a/WebCore/dom/ExceptionCode.cpp b/WebCore/dom/ExceptionCode.cpp index fa0a7a7..8ce1643 100644 --- a/WebCore/dom/ExceptionCode.cpp +++ b/WebCore/dom/ExceptionCode.cpp @@ -71,7 +71,8 @@ static const char* const eventExceptionNames[] = { }; static const char* const xmlHttpRequestExceptionNames[] = { - "NETWORK_ERR" + "NETWORK_ERR", + "ABORT_ERR" }; #if ENABLE(XPATH) diff --git a/WebCore/dom/FormControlElement.h b/WebCore/dom/FormControlElement.h index 881c9fd..dc77ada 100644 --- a/WebCore/dom/FormControlElement.h +++ b/WebCore/dom/FormControlElement.h @@ -30,6 +30,10 @@ class FormControlElement { public: virtual ~FormControlElement() { } + virtual bool isEnabled() const = 0; + virtual bool isReadOnlyControl() const = 0; + virtual bool isTextControl() const = 0; + virtual bool valueMatchesRenderer() const = 0; virtual void setValueMatchesRenderer(bool value = true) = 0; diff --git a/WebCore/dom/GenericWorkerTask.h b/WebCore/dom/GenericWorkerTask.h deleted file mode 100644 index 79fd148..0000000 --- a/WebCore/dom/GenericWorkerTask.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2009, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GenericWorkerTask_h -#define GenericWorkerTask_h - -#if ENABLE(WORKERS) - -#include "WorkerMessagingProxy.h" -#include "ScriptExecutionContext.h" -#include <wtf/PassRefPtr.h> - -namespace WebCore { - class GenericWorkerTaskBase : public ScriptExecutionContext::Task { - protected: - GenericWorkerTaskBase(WorkerMessagingProxy* messagingProxy) : m_messagingProxy(messagingProxy) - { - } - - bool canPerformTask() - { - return !m_messagingProxy->askedToTerminate(); - } - - WorkerMessagingProxy* m_messagingProxy; - }; - - template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6> - class GenericWorkerTask6 : public GenericWorkerTaskBase { - public: - typedef void (*Method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6); - typedef GenericWorkerTask6<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6> GenericWorkerTask; - - static PassRefPtr<GenericWorkerTask> create(WorkerMessagingProxy* messagingProxy, Method method, const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6) - { - return adoptRef(new GenericWorkerTask(messagingProxy, method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6)); - } - - private: - GenericWorkerTask6(WorkerMessagingProxy* messagingProxy, Method method, const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6) - : GenericWorkerTaskBase(messagingProxy) - , m_method(method) - , m_parameter1(parameter1) - , m_parameter2(parameter2) - , m_parameter3(parameter3) - , m_parameter4(parameter4) - , m_parameter5(parameter5) - , m_parameter6(parameter6) - { - } - - virtual void performTask(ScriptExecutionContext* context) - { - if (!canPerformTask()) - return; - (*m_method)(context, m_parameter1, m_parameter2, m_parameter3, m_parameter4, m_parameter5, m_parameter6); - } - - private: - Method m_method; - P1 m_parameter1; - P2 m_parameter2; - P3 m_parameter3; - P4 m_parameter4; - P5 m_parameter5; - P6 m_parameter6; - }; - - template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6> - PassRefPtr<GenericWorkerTask6<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6> > createCallbackTask( - WorkerMessagingProxy* messagingProxy, - void (*method)(ScriptExecutionContext*, MP1, MP2, MP3, MP4, MP5, MP6), - const P1& parameter1, const P2& parameter2, const P3& parameter3, const P4& parameter4, const P5& parameter5, const P6& parameter6) - { - return GenericWorkerTask6<P1, MP1, P2, MP2, P3, MP3, P4, MP4, P5, MP5, P6, MP6>::create(messagingProxy, method, parameter1, parameter2, parameter3, parameter4, parameter5, parameter6); - } - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // GenericWorkerTask_h diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp index 47c1a28..6b733cb 100644 --- a/WebCore/dom/InputElement.cpp +++ b/WebCore/dom/InputElement.cpp @@ -114,7 +114,7 @@ void InputElement::updateSelectionRange(InputElementData& data, int start, int e if (!data.inputElement()->isTextField()) return; - if (RenderTextControl* renderer = static_cast<RenderTextControl*>(data.element()->renderer())) + if (RenderTextControl* renderer = toRenderTextControl(data.element()->renderer())) renderer->setSelectionRange(start, end); } @@ -218,7 +218,7 @@ void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, Documen // Make sure that the text to be inserted will not violate the maxLength. int oldLength = numGraphemeClusters(data.inputElement()->value().impl()); ASSERT(oldLength <= data.maxLength()); - int selectionLength = numGraphemeClusters(plainText(document->frame()->selection()->selection().toRange().get()).impl()); + int selectionLength = numGraphemeClusters(plainText(document->frame()->selection()->selection().toNormalizedRange().get()).impl()); ASSERT(oldLength >= selectionLength); int maxNewLength = data.maxLength() - (oldLength - selectionLength); diff --git a/WebCore/dom/InputElement.h b/WebCore/dom/InputElement.h index c64f131..40c972f 100644 --- a/WebCore/dom/InputElement.h +++ b/WebCore/dom/InputElement.h @@ -36,6 +36,10 @@ class InputElement { public: virtual ~InputElement() { } + virtual bool isAutofilled() const = 0; + virtual bool isChecked() const = 0; + virtual bool isIndeterminate() const = 0; + virtual bool isInputTypeHidden() const = 0; virtual bool isPasswordField() const = 0; virtual bool isSearchField() const = 0; virtual bool isTextField() const = 0; diff --git a/WebCore/dom/MessagePort.cpp b/WebCore/dom/MessagePort.cpp index 0607bea..312a1f3 100644 --- a/WebCore/dom/MessagePort.cpp +++ b/WebCore/dom/MessagePort.cpp @@ -137,6 +137,7 @@ void MessagePort::postMessage(const String& message, MessagePort* dataPort, Exce ec = INVALID_ACCESS_ERR; return; } + ec = 0; newMessagePort = dataPort->clone(ec); if (ec) return; diff --git a/WebCore/dom/MouseEvent.cpp b/WebCore/dom/MouseEvent.cpp index 1c97522..bdd39d3 100644 --- a/WebCore/dom/MouseEvent.cpp +++ b/WebCore/dom/MouseEvent.cpp @@ -36,7 +36,7 @@ MouseEvent::MouseEvent() MouseEvent::MouseEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, int detail, int screenX, int screenY, int pageX, int pageY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - unsigned short button, PassRefPtr<EventTargetNode> relatedTarget, + unsigned short button, PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard> clipboard, bool isSimulated) : MouseRelatedEvent(eventType, canBubble, cancelable, view, detail, screenX, screenY, pageX, pageY, ctrlKey, altKey, shiftKey, metaKey, isSimulated) @@ -54,7 +54,7 @@ MouseEvent::~MouseEvent() void MouseEvent::initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, int detail, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - unsigned short button, PassRefPtr<EventTargetNode> relatedTarget) + unsigned short button, PassRefPtr<EventTarget> relatedTarget) { if (dispatched()) return; @@ -101,7 +101,7 @@ Node* MouseEvent::toElement() const { // MSIE extension - "the object toward which the user is moving the mouse pointer" if (type() == eventNames().mouseoutEvent) - return relatedTarget(); + return relatedTarget() ? relatedTarget()->toNode() : 0; return target() ? target()->toNode() : 0; } @@ -110,7 +110,7 @@ Node* MouseEvent::fromElement() const { // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?) if (type() != eventNames().mouseoutEvent) - return relatedTarget(); + return relatedTarget() ? relatedTarget()->toNode() : 0; return target() ? target()->toNode() : 0; } diff --git a/WebCore/dom/MouseEvent.h b/WebCore/dom/MouseEvent.h index aa3eee5..7454b04 100644 --- a/WebCore/dom/MouseEvent.h +++ b/WebCore/dom/MouseEvent.h @@ -25,7 +25,6 @@ #define MouseEvent_h #include "Clipboard.h" -#include "EventTargetNode.h" #include "MouseRelatedEvent.h" namespace WebCore { @@ -40,7 +39,7 @@ namespace WebCore { static PassRefPtr<MouseEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView> view, int detail, int screenX, int screenY, int pageX, int pageY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button, - PassRefPtr<EventTargetNode> relatedTarget, PassRefPtr<Clipboard> clipboard = 0, bool isSimulated = false) + PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard> clipboard = 0, bool isSimulated = false) { return adoptRef(new MouseEvent(type, canBubble, cancelable, view, detail, screenX, screenY, pageX, pageY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget, clipboard, isSimulated)); @@ -50,13 +49,13 @@ namespace WebCore { void initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, int detail, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, - unsigned short button, PassRefPtr<EventTargetNode> relatedTarget); + unsigned short button, PassRefPtr<EventTarget> relatedTarget); // WinIE uses 1,4,2 for left/middle/right but not for click (just for mousedown/up, maybe others), // but we will match the standard DOM. unsigned short button() const { return m_button; } bool buttonDown() const { return m_buttonDown; } - EventTargetNode* relatedTarget() const { return m_relatedTarget.get(); } + EventTarget* relatedTarget() const { return m_relatedTarget.get(); } Clipboard* clipboard() const { return m_clipboard.get(); } @@ -74,11 +73,11 @@ namespace WebCore { MouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<AbstractView>, int detail, int screenX, int screenY, int pageX, int pageY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button, - PassRefPtr<EventTargetNode> relatedTarget, PassRefPtr<Clipboard> clipboard, bool isSimulated); + PassRefPtr<EventTarget> relatedTarget, PassRefPtr<Clipboard> clipboard, bool isSimulated); unsigned short m_button; bool m_buttonDown; - RefPtr<EventTargetNode> m_relatedTarget; + RefPtr<EventTarget> m_relatedTarget; RefPtr<Clipboard> m_clipboard; }; diff --git a/WebCore/dom/MouseRelatedEvent.cpp b/WebCore/dom/MouseRelatedEvent.cpp index a69c8a7..c66b0a8 100644 --- a/WebCore/dom/MouseRelatedEvent.cpp +++ b/WebCore/dom/MouseRelatedEvent.cpp @@ -97,6 +97,8 @@ void MouseRelatedEvent::initCoordinates() m_layerY = m_pageY; m_offsetX = m_pageX; m_offsetY = m_pageY; + + computePageLocation(); } void MouseRelatedEvent::initCoordinates(int clientX, int clientY) @@ -112,6 +114,14 @@ void MouseRelatedEvent::initCoordinates(int clientX, int clientY) m_layerY = m_pageY; m_offsetX = m_pageX; m_offsetY = m_pageY; + + computePageLocation(); +} + +void MouseRelatedEvent::computePageLocation() +{ + float zoomFactor = (view() && view()->frame()) ? view()->frame()->pageZoomFactor() : 1.0f; + setAbsoluteLocation(roundedIntPoint(FloatPoint(pageX() * zoomFactor, pageY() * zoomFactor))); } void MouseRelatedEvent::receivedTarget() @@ -133,9 +143,10 @@ void MouseRelatedEvent::receivedTarget() // Adjust offsetX/Y to be relative to the target's position. if (!isSimulated()) { if (RenderObject* r = targ->renderer()) { - FloatPoint absPos = r->absoluteToLocal(FloatPoint(m_pageX, m_pageY), false, true); - m_offsetX = absPos.x(); - m_offsetY = absPos.y(); + FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true); + float zoomFactor = (view() && view()->frame()) ? view()->frame()->pageZoomFactor() : 1.0f; + m_offsetX = lroundf(localPos.x() / zoomFactor); + m_offsetY = lroundf(localPos.y() / zoomFactor); } } @@ -151,8 +162,8 @@ void MouseRelatedEvent::receivedTarget() RenderLayer* layer = n->renderer()->enclosingLayer(); layer->updateLayerPosition(); for (; layer; layer = layer->parent()) { - m_layerX -= layer->xPos(); - m_layerY -= layer->yPos(); + m_layerX -= layer->x(); + m_layerY -= layer->y(); } } } diff --git a/WebCore/dom/MouseRelatedEvent.h b/WebCore/dom/MouseRelatedEvent.h index 35c65dd..7649aa9 100644 --- a/WebCore/dom/MouseRelatedEvent.h +++ b/WebCore/dom/MouseRelatedEvent.h @@ -26,6 +26,7 @@ #ifndef MouseRelatedEvent_h #define MouseRelatedEvent_h +#include "IntPoint.h" #include "UIEventWithKeyState.h" namespace WebCore { @@ -33,6 +34,8 @@ namespace WebCore { // Internal only: Helper class for what's common between mouse and wheel events. class MouseRelatedEvent : public UIEventWithKeyState { public: + // Note that these values are adjusted to counter the effects of zoom, so that values + // exposed via DOM APIs are invariant under zooming. int screenX() const { return m_screenX; } int screenY() const { return m_screenY; } int clientX() const { return m_clientX; } @@ -46,6 +49,11 @@ namespace WebCore { virtual int pageY() const; int x() const; int y() const; + + // Page point in "absolute" coordinates (i.e. post-zoomed, page-relative coords, + // usable with RenderObject::absoluteToLocal). + IntPoint absoluteLocation() const { return m_absoluteLocation; } + void setAbsoluteLocation(const IntPoint& p) { m_absoluteLocation = p; } protected: MouseRelatedEvent(); @@ -56,6 +64,8 @@ namespace WebCore { void initCoordinates(); void initCoordinates(int clientX, int clientY); virtual void receivedTarget(); + + void computePageLocation(); // Expose these so MouseEvent::initMouseEvent can set them. int m_screenX; @@ -70,6 +80,7 @@ namespace WebCore { int m_layerY; int m_offsetX; int m_offsetY; + IntPoint m_absoluteLocation; bool m_isSimulated; }; diff --git a/WebCore/dom/NamedAttrMap.cpp b/WebCore/dom/NamedAttrMap.cpp index 8944b79..33c60d3 100644 --- a/WebCore/dom/NamedAttrMap.cpp +++ b/WebCore/dom/NamedAttrMap.cpp @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * (C) 2007 Eric Seidel (eric@webkit.org) * * This library is free software; you can redistribute it and/or @@ -39,9 +39,18 @@ static inline bool shouldIgnoreAttributeCase(const Element* e) return e && e->document()->isHTMLDocument() && e->isHTMLElement(); } +inline void NamedAttrMap::detachAttributesFromElement() +{ + size_t size = m_attributes.size(); + for (size_t i = 0; i < size; i++) { + if (Attr* attr = m_attributes[i]->attr()) + attr->m_element = 0; + } +} + NamedAttrMap::~NamedAttrMap() { - NamedAttrMap::clearAttributes(); // virtual function, qualify to be explicit and slightly faster + detachAttributesFromElement(); } bool NamedAttrMap::isMappedAttributeMap() const @@ -190,11 +199,7 @@ Attribute* NamedAttrMap::getAttributeItem(const QualifiedName& name) const void NamedAttrMap::clearAttributes() { - unsigned len = length(); - for (unsigned i = 0; i < len; i++) - if (Attr* attr = m_attributes[i]->attr()) - attr->m_element = 0; - + detachAttributesFromElement(); m_attributes.clear(); } @@ -203,7 +208,7 @@ void NamedAttrMap::detachFromElement() // we allow a NamedAttrMap w/o an element in case someone still has a reference // to if after the element gets deleted - but the map is now invalid m_element = 0; - clearAttributes(); + detachAttributesFromElement(); } void NamedAttrMap::setAttributes(const NamedAttrMap& other) @@ -310,4 +315,9 @@ bool NamedAttrMap::mapsEquivalent(const NamedAttrMap* otherMap) const return true; } +size_t NamedAttrMap::virtualLength() const +{ + return length(); +} + } diff --git a/WebCore/dom/NamedAttrMap.h b/WebCore/dom/NamedAttrMap.h index 693a9e5..61628e4 100644 --- a/WebCore/dom/NamedAttrMap.h +++ b/WebCore/dom/NamedAttrMap.h @@ -1,11 +1,9 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,7 +27,6 @@ #include "Attribute.h" #include "NamedNodeMap.h" -#include <wtf/RefPtr.h> #include <wtf/Vector.h> #ifdef __OBJC__ @@ -50,28 +47,12 @@ public: void setAttributes(const NamedAttrMap&); - // DOM methods & attributes for NamedNodeMap - - virtual PassRefPtr<Node> getNamedItem(const String& name) const; - virtual PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode&); - - virtual PassRefPtr<Node> getNamedItemNS(const String& namespaceURI, const String& localName) const; - virtual PassRefPtr<Node> removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode&); - - virtual PassRefPtr<Node> getNamedItem(const QualifiedName& name) const; - virtual PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode&); - virtual PassRefPtr<Node> setNamedItem(Node* arg, ExceptionCode&); - - virtual PassRefPtr<Node> item(unsigned index) const; size_t length() const { return m_attributes.size(); } - - // Other methods (not part of DOM) Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); } - Attribute* getAttributeItem(const QualifiedName& name) const; - Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const; - + Attribute* getAttributeItem(const QualifiedName&) const; + void shrinkToLength() { m_attributes.shrinkCapacity(length()); } - void reserveCapacity(unsigned capacity) { m_attributes.reserveCapacity(capacity); } + void reserveInitialCapacity(unsigned capacity) { m_attributes.reserveInitialCapacity(capacity); } // used during parsing: only inserts if not already there // no error checking! @@ -83,20 +64,38 @@ public: } virtual bool isMappedAttributeMap() const; - - const AtomicString& id() const { return m_id; } - void setID(const AtomicString& _id) { m_id = _id; } + const AtomicString& id() const { return m_id; } + void setID(const AtomicString& newId) { m_id = newId; } + bool mapsEquivalent(const NamedAttrMap* otherMap) const; - // These functions are internal, and do no error checking. + // These functions do no error checking. void addAttribute(PassRefPtr<Attribute>); - void removeAttribute(const QualifiedName& name); + void removeAttribute(const QualifiedName&); protected: virtual void clearAttributes(); + Element* element() const { return m_element; } + +private: + void detachAttributesFromElement(); void detachFromElement(); + Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const; + + virtual PassRefPtr<Node> getNamedItem(const String& name) const; + virtual PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode&); + + virtual PassRefPtr<Node> getNamedItemNS(const String& namespaceURI, const String& localName) const; + virtual PassRefPtr<Node> removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode&); + + virtual PassRefPtr<Node> getNamedItem(const QualifiedName& name) const; + virtual PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode&); + virtual PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&); + + virtual PassRefPtr<Node> item(unsigned index) const; + virtual size_t virtualLength() const; Element* m_element; Vector<RefPtr<Attribute> > m_attributes; diff --git a/WebCore/dom/NamedMappedAttrMap.cpp b/WebCore/dom/NamedMappedAttrMap.cpp index bc2d999..cff4997 100644 --- a/WebCore/dom/NamedMappedAttrMap.cpp +++ b/WebCore/dom/NamedMappedAttrMap.cpp @@ -75,12 +75,12 @@ bool NamedMappedAttrMap::mapsEquivalent(const NamedMappedAttrMap* otherMap) cons void NamedMappedAttrMap::setClass(const String& classStr) { - if (!m_element->hasClass()) { + if (!element()->hasClass()) { m_classNames.clear(); return; } - m_classNames.set(classStr, m_element->document()->inCompatMode()); + m_classNames.set(classStr, element()->document()->inCompatMode()); } } diff --git a/WebCore/dom/NamedMappedAttrMap.h b/WebCore/dom/NamedMappedAttrMap.h index c4deddc..9267f89 100644 --- a/WebCore/dom/NamedMappedAttrMap.h +++ b/WebCore/dom/NamedMappedAttrMap.h @@ -4,7 +4,7 @@ * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) * (C) 2007 David Smith (catfish.man@gmail.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,32 +27,33 @@ #define NamedMappedAttrMap_h #include "ClassNames.h" -#include "MappedAttribute.h" +#include "MappedAttribute.h" // This header is not required for the NamedMappedAttrMap definition. Should remove it. #include "NamedAttrMap.h" namespace WebCore { class NamedMappedAttrMap : public NamedAttrMap { -private: - NamedMappedAttrMap(Element* element) : NamedAttrMap(element), m_mappedAttributeCount(0) { } public: static PassRefPtr<NamedMappedAttrMap> create(Element* element = 0) { return adoptRef(new NamedMappedAttrMap(element)); } - virtual void clearAttributes(); - virtual bool isMappedAttributeMap() const; - void clearClass() { m_classNames.clear(); } void setClass(const String&); const ClassNames& classNames() const { return m_classNames; } - virtual bool hasMappedAttributes() const { return m_mappedAttributeCount > 0; } + bool hasMappedAttributes() const { return m_mappedAttributeCount > 0; } void declRemoved() { m_mappedAttributeCount--; } void declAdded() { m_mappedAttributeCount++; } - + bool mapsEquivalent(const NamedMappedAttrMap*) const; - int declCount() const; private: + NamedMappedAttrMap(Element* element) : NamedAttrMap(element), m_mappedAttributeCount(0) { } + + virtual void clearAttributes(); + virtual bool isMappedAttributeMap() const; + + int declCount() const; + ClassNames m_classNames; int m_mappedAttributeCount; }; diff --git a/WebCore/dom/NamedNodeMap.h b/WebCore/dom/NamedNodeMap.h index 504af69..08e6efb 100644 --- a/WebCore/dom/NamedNodeMap.h +++ b/WebCore/dom/NamedNodeMap.h @@ -56,7 +56,10 @@ public: virtual PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&) = 0; virtual PassRefPtr<Node> item(unsigned index) const = 0; - virtual size_t length() const = 0; + size_t length() const { return virtualLength(); } + +private: + virtual size_t virtualLength() const = 0; }; } //namespace diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index eb591a7..bd8f497 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or @@ -44,25 +44,55 @@ #include "Document.h" #include "DynamicNodeList.h" #include "Element.h" +#include "Event.h" +#include "EventException.h" +#include "EventHandler.h" +#include "EventListener.h" +#include "EventNames.h" #include "ExceptionCode.h" #include "Frame.h" +#include "FrameView.h" #include "HTMLNames.h" #include "JSDOMBinding.h" +#include "KeyboardEvent.h" #include "Logging.h" +#include "MouseEvent.h" +#include "MutationEvent.h" #include "NameNodeList.h" #include "NamedAttrMap.h" #include "NodeRareData.h" +#include "Page.h" +#include "PlatformMouseEvent.h" +#include "PlatformWheelEvent.h" #include "ProcessingInstruction.h" +#include "ProgressEvent.h" +#include "RegisteredEventListener.h" #include "RenderObject.h" #include "ScriptController.h" #include "SelectorNodeList.h" #include "StringBuilder.h" #include "TagNodeList.h" #include "Text.h" +#include "TextEvent.h" +#include "UIEvent.h" +#include "UIEventWithKeyState.h" +#include "WebKitAnimationEvent.h" +#include "WebKitTransitionEvent.h" +#include "WheelEvent.h" #include "XMLNames.h" #include "htmlediting.h" +#include <wtf/HashSet.h> #include <wtf/RefCountedLeakCounter.h> +#if ENABLE(DOM_STORAGE) +#include "StorageEvent.h" +#endif + +#if ENABLE(SVG) +#include "SVGElementInstance.h" +#include "SVGUseElement.h" +#endif + #define DUMP_NODE_STATISTICS 0 using namespace std; @@ -71,6 +101,8 @@ namespace WebCore { using namespace HTMLNames; +static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0; + bool Node::isSupported(const String& feature, const String& version) { return DOMImplementation::hasFeature(feature, version); @@ -255,9 +287,9 @@ Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 ) // style in cases where you need to. StyleChange ch = NoInherit; EDisplay display1 = s1 ? s1->display() : NONE; - bool fl1 = s1 && s1->hasPseudoStyle(RenderStyle::FIRST_LETTER); + bool fl1 = s1 && s1->hasPseudoStyle(FIRST_LETTER); EDisplay display2 = s2 ? s2->display() : NONE; - bool fl2 = s2 && s2->hasPseudoStyle(RenderStyle::FIRST_LETTER); + bool fl2 = s2 && s2->hasPseudoStyle(FIRST_LETTER); if (display1 != display2 || fl1 != fl2 || (s1 && s2 && !s1->contentDataEquivalent(s2))) ch = Detach; @@ -270,21 +302,21 @@ Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 ) // If the pseudoStyles have changed, we want any StyleChange that is not NoChange // because setStyle will do the right thing with anything else. - if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::BEFORE)) { - RenderStyle* ps2 = s2->getCachedPseudoStyle(RenderStyle::BEFORE); + if (ch == NoChange && s1->hasPseudoStyle(BEFORE)) { + RenderStyle* ps2 = s2->getCachedPseudoStyle(BEFORE); if (!ps2) ch = NoInherit; else { - RenderStyle* ps1 = s1->getCachedPseudoStyle(RenderStyle::BEFORE); + RenderStyle* ps1 = s1->getCachedPseudoStyle(BEFORE); ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit; } } - if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::AFTER)) { - RenderStyle* ps2 = s2->getCachedPseudoStyle(RenderStyle::AFTER); + if (ch == NoChange && s1->hasPseudoStyle(AFTER)) { + RenderStyle* ps2 = s2->getCachedPseudoStyle(AFTER); if (!ps2) ch = NoInherit; else { - RenderStyle* ps1 = s1->getCachedPseudoStyle(RenderStyle::AFTER); + RenderStyle* ps1 = s1->getCachedPseudoStyle(AFTER); ch = ps2 && *ps1 == *ps2 ? NoChange : NoInherit; } } @@ -348,6 +380,9 @@ Node::~Node() liveNodeSet.remove(this); #endif + if (!eventListeners().isEmpty() && !inDocument()) + document()->unregisterDisconnectedNodeWithEventListeners(this); + if (!hasRareData()) ASSERT(!NodeRareData::rareDataMap().contains(this)); else { @@ -583,7 +618,12 @@ bool Node::shouldUseInputMethod() const RenderBox* Node::renderBox() const { - return m_renderer && m_renderer->isBox() ? static_cast<RenderBox*>(m_renderer) : 0; + return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0; +} + +RenderBoxModelObject* Node::renderBoxModelObject() const +{ + return m_renderer && m_renderer->isBoxModelObject() ? toRenderBoxModelObject(m_renderer) : 0; } IntRect Node::getRect() const @@ -1081,21 +1121,6 @@ void Node::detach() m_inDetach = false; } -void Node::insertedIntoDocument() -{ - setInDocument(true); - insertedIntoTree(false); -} - -void Node::removedFromDocument() -{ - if (m_document && m_document->getCSSTarget() == this) - m_document->setCSSTarget(0); - - setInDocument(false); - removedFromTree(false); -} - Node *Node::previousEditable() const { Node *node = previousLeafNode(); @@ -1317,7 +1342,7 @@ bool Node::isBlockFlow() const bool Node::isBlockFlowOrBlockTable() const { - return renderer() && (renderer()->isBlockFlow() || renderer()->isTable() && !renderer()->isInline()); + return renderer() && (renderer()->isBlockFlow() || (renderer()->isTable() && !renderer()->isInline())); } bool Node::isEditableBlock() const @@ -1984,6 +2009,36 @@ unsigned short Node::compareDocumentPosition(Node* otherNode) DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS; } +FloatPoint Node::convertToPage(const FloatPoint& p) const +{ + // If there is a renderer, just ask it to do the conversion + if (renderer()) + return renderer()->localToAbsolute(p, false, true); + + // Otherwise go up the tree looking for a renderer + Element *parent = ancestorElement(); + if (parent) + return parent->convertToPage(p); + + // No parent - no conversion needed + return p; +} + +FloatPoint Node::convertFromPage(const FloatPoint& p) const +{ + // If there is a renderer, just ask it to do the conversion + if (renderer()) + return renderer()->absoluteToLocal(p, false, true); + + // Otherwise go up the tree looking for a renderer + Element *parent = ancestorElement(); + if (parent) + return parent->convertFromPage(p); + + // No parent - no conversion needed + return p; +} + #if !defined(NDEBUG) || defined(ANDROID_DOM_LOGGING) static void appendAttributeDesc(const Node* node, String& string, const QualifiedName& name, const char* attrDesc) @@ -2177,6 +2232,1157 @@ size_t Node::reportDOMNodesSize() // -------- +ScriptExecutionContext* Node::scriptExecutionContext() const +{ + return document(); +} + +const RegisteredEventListenerVector& Node::eventListeners() const +{ + if (hasRareData()) { + if (RegisteredEventListenerVector* listeners = rareData()->listeners()) + return *listeners; + } + static const RegisteredEventListenerVector* emptyListenersVector = new RegisteredEventListenerVector; + return *emptyListenersVector; +} + +void Node::insertedIntoDocument() +{ + if (!eventListeners().isEmpty()) + document()->unregisterDisconnectedNodeWithEventListeners(this); + + setInDocument(true); +} + +void Node::removedFromDocument() +{ + if (!eventListeners().isEmpty()) + document()->registerDisconnectedNodeWithEventListeners(this); + + setInDocument(false); +} + +void Node::willMoveToNewOwnerDocument() +{ + if (!eventListeners().isEmpty()) + document()->unregisterDisconnectedNodeWithEventListeners(this); +} + +void Node::didMoveToNewOwnerDocument() +{ + if (!eventListeners().isEmpty()) + document()->registerDisconnectedNodeWithEventListeners(this); +} + +static inline void updateSVGElementInstancesAfterEventListenerChange(Node* referenceNode) +{ + ASSERT(referenceNode); + +#if ENABLE(SVG) + if (!referenceNode->isSVGElement()) + return; + + // Elements living inside a <use> shadow tree, never cause any updates! + if (referenceNode->shadowTreeRootNode()) + return; + + // We're possibly (a child of) an element that is referenced by a <use> client + // If an event listeners changes on a referenced element, update all instances. + for (Node* node = referenceNode; node; node = node->parentNode()) { + if (!node->hasID() || !node->isSVGElement()) + continue; + + SVGElementInstance::invalidateAllInstancesOfElement(static_cast<SVGElement*>(node)); + break; + } +#endif +} + +void Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) +{ + Document* document = this->document(); + if (!document->attached()) + return; + + document->addListenerTypeIfNeeded(eventType); + + RegisteredEventListenerVector& listeners = ensureRareData()->ensureListeners(); + + // Remove existing identical listener set with identical arguments. + // The DOM2 spec says that "duplicate instances are discarded" in this case. + removeEventListener(eventType, listener.get(), useCapture); + + // adding the first one + if (listeners.isEmpty() && !inDocument()) + document->registerDisconnectedNodeWithEventListeners(this); + + listeners.append(RegisteredEventListener::create(eventType, listener, useCapture)); + updateSVGElementInstancesAfterEventListenerChange(this); + +#if ENABLE(TOUCH_EVENTS) // Android + if (eventType == eventNames().touchstartEvent || + eventType == eventNames().touchendEvent || + eventType == eventNames().touchmoveEvent || + eventType == eventNames().touchcancelEvent) + document->addTouchEventListener(this); +#endif +} + +void Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +{ + if (!hasRareData()) + return; + + RegisteredEventListenerVector* listeners = rareData()->listeners(); + if (!listeners) + return; + + size_t size = listeners->size(); + for (size_t i = 0; i < size; ++i) { + RegisteredEventListener& r = *listeners->at(i); + if (r.eventType() == eventType && r.listener() == listener && r.useCapture() == useCapture) { + r.setRemoved(true); + listeners->remove(i); + + // removed last + if (listeners->isEmpty() && !inDocument()) + document()->unregisterDisconnectedNodeWithEventListeners(this); + + updateSVGElementInstancesAfterEventListenerChange(this); +#if ENABLE(TOUCH_EVENTS) // Android + if (eventType == eventNames().touchstartEvent || + eventType == eventNames().touchendEvent || + eventType == eventNames().touchmoveEvent || + eventType == eventNames().touchcancelEvent) + document()->removeTouchEventListener(this); +#endif + return; + } + } +} + +void Node::removeAllEventListenersSlowCase() +{ + ASSERT(hasRareData()); + + RegisteredEventListenerVector* listeners = rareData()->listeners(); + if (!listeners) + return; + +#if ENABLE(TOUCH_EVENTS) // Android + document()->removeTouchEventListener(this); +#endif + + size_t size = listeners->size(); + for (size_t i = 0; i < size; ++i) + listeners->at(i)->setRemoved(true); + listeners->clear(); +} + +void Node::handleLocalEvents(Event* event, bool useCapture) +{ + if (disabled() && event->isMouseEvent()) + return; + + RegisteredEventListenerVector listenersCopy = eventListeners(); + size_t size = listenersCopy.size(); + for (size_t i = 0; i < size; ++i) { + const RegisteredEventListener& r = *listenersCopy[i]; + if (r.eventType() == event->type() && r.useCapture() == useCapture && !r.removed()) + r.listener()->handleEvent(event, false); + } +} + +#if ENABLE(SVG) +static inline SVGElementInstance* eventTargetAsSVGElementInstance(Node* referenceNode) +{ + ASSERT(referenceNode); + if (!referenceNode->isSVGElement()) + return 0; + + // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included + // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects + for (Node* n = referenceNode; n; n = n->parentNode()) { + if (!n->isShadowNode() || !n->isSVGElement()) + continue; + + Node* shadowTreeParentElement = n->shadowParentNode(); + ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag)); + + if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode)) + return instance; + } + + return 0; +} +#endif + +static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode) +{ + ASSERT(referenceNode); + +#if ENABLE(SVG) + if (SVGElementInstance* instance = eventTargetAsSVGElementInstance(referenceNode)) { + ASSERT(instance->shadowTreeElement() == referenceNode); + return instance; + } +#endif + + return referenceNode; +} + +bool Node::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec) +{ + RefPtr<Event> evt(e); + ASSERT(!eventDispatchForbidden()); + if (!evt || evt->type().isEmpty()) { + ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; + return false; + } + + evt->setTarget(eventTargetRespectingSVGTargetRules(this)); + + RefPtr<FrameView> view = document()->view(); + return dispatchGenericEvent(evt.release()); +} + +bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) +{ + RefPtr<Event> event(prpEvent); + + ASSERT(!eventDispatchForbidden()); + ASSERT(event->target()); + ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null. + + // Make a vector of ancestors to send the event to. + // If the node is not in a document just send the event to it. + // Be sure to ref all of nodes since event handlers could result in the last reference going away. + RefPtr<Node> thisNode(this); + Vector<RefPtr<ContainerNode> > ancestors; + if (inDocument()) { + for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) { +#if ENABLE(SVG) + // Skip <use> shadow tree elements. + if (ancestor->isSVGElement() && ancestor->isShadowNode()) + continue; +#endif + ancestors.append(ancestor); + } + } + + // Set up a pointer to indicate whether to dispatch window events. + // We don't dispatch load events to the window. That quirk was originally + // added because Mozilla doesn't propagate load events to the window object. + Document* documentForWindowEvents = 0; + if (event->type() != eventNames().loadEvent) { + Node* topLevelContainer = ancestors.isEmpty() ? this : ancestors.last().get(); + if (topLevelContainer->isDocumentNode()) + documentForWindowEvents = static_cast<Document*>(topLevelContainer); + } + + // Give the target node a chance to do some work before DOM event handlers get a crack. + void* data = preDispatchEventHandler(event.get()); + if (event->propagationStopped()) + goto doneDispatching; + + // Trigger capturing event handlers, starting at the top and working our way down. + event->setEventPhase(Event::CAPTURING_PHASE); + + if (documentForWindowEvents) { + event->setCurrentTarget(documentForWindowEvents); + documentForWindowEvents->handleWindowEvent(event.get(), true); + if (event->propagationStopped()) + goto doneDispatching; + } + for (size_t i = ancestors.size(); i; --i) { + ContainerNode* ancestor = ancestors[i - 1].get(); + event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); + ancestor->handleLocalEvents(event.get(), true); + if (event->propagationStopped()) + goto doneDispatching; + } + + event->setEventPhase(Event::AT_TARGET); + + // We do want capturing event listeners to be invoked here, even though + // that violates some versions of the DOM specification; Mozilla does it. + event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this)); + handleLocalEvents(event.get(), true); + if (event->propagationStopped()) + goto doneDispatching; + handleLocalEvents(event.get(), false); + if (event->propagationStopped()) + goto doneDispatching; + + if (event->bubbles() && !event->cancelBubble()) { + // Trigger bubbling event handlers, starting at the bottom and working our way up. + event->setEventPhase(Event::BUBBLING_PHASE); + + size_t size = ancestors.size(); + for (size_t i = 0; i < size; ++i) { + ContainerNode* ancestor = ancestors[i].get(); + event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor)); + ancestor->handleLocalEvents(event.get(), false); + if (event->propagationStopped() || event->cancelBubble()) + goto doneDispatching; + } + if (documentForWindowEvents) { + event->setCurrentTarget(documentForWindowEvents); + documentForWindowEvents->handleWindowEvent(event.get(), false); + if (event->propagationStopped() || event->cancelBubble()) + goto doneDispatching; + } + } + +doneDispatching: + event->setCurrentTarget(0); + event->setEventPhase(0); + + // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler. + postDispatchEventHandler(event.get(), data); + + // Call default event handlers. While the DOM does have a concept of preventing + // default handling, the detail of which handlers are called is an internal + // implementation detail and not part of the DOM. + if (!event->defaultPrevented() && !event->defaultHandled()) { + // Non-bubbling events call only one default event handler, the one for the target. + defaultEventHandler(event.get()); + ASSERT(!event->defaultPrevented()); + if (event->defaultHandled()) + goto doneWithDefault; + // For bubbling events, call default event handlers on the same targets in the + // same order as the bubbling phase. + if (event->bubbles()) { + size_t size = ancestors.size(); + for (size_t i = 0; i < size; ++i) { + ContainerNode* ancestor = ancestors[i].get(); + ancestor->defaultEventHandler(event.get()); + ASSERT(!event->defaultPrevented()); + if (event->defaultHandled()) + goto doneWithDefault; + } + } + } + +doneWithDefault: + Document::updateDocumentsRendering(); + + return !event->defaultPrevented(); +} + +bool Node::dispatchSubtreeModifiedEvent() +{ + ASSERT(!eventDispatchForbidden()); + + document()->incDOMTreeVersion(); + + notifyNodeListsAttributeChanged(); // FIXME: Can do better some day. Really only care about the name attribute changing. + + if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER)) + return false; + ExceptionCode ec = 0; + return dispatchEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true, false, 0, String(), String(), String(), 0), ec); +} + +void Node::dispatchWindowEvent(PassRefPtr<Event> e) +{ + ASSERT(!eventDispatchForbidden()); + RefPtr<Event> evt(e); + RefPtr<Document> doc = document(); + evt->setTarget(doc); + doc->handleWindowEvent(evt.get(), true); + doc->handleWindowEvent(evt.get(), false); +} + +void Node::dispatchWindowEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg) +{ + ASSERT(!eventDispatchForbidden()); + RefPtr<Document> doc = document(); + dispatchWindowEvent(Event::create(eventType, canBubbleArg, cancelableArg)); + + if (eventType == eventNames().loadEvent) { + // For onload events, send a separate load event to the enclosing frame only. + // This is a DOM extension and is independent of bubbling/capturing rules of + // the DOM. + Element* ownerElement = doc->ownerElement(); + if (ownerElement) { + RefPtr<Event> ownerEvent = Event::create(eventType, false, cancelableArg); + ownerEvent->setTarget(ownerElement); + ownerElement->dispatchGenericEvent(ownerEvent.release()); + } + } +} + +bool Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent) +{ + ASSERT(!eventDispatchForbidden()); + ASSERT(eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent); + + bool cancelable = eventType == eventNames().DOMActivateEvent; + + ExceptionCode ec = 0; + RefPtr<UIEvent> evt = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail); + evt->setUnderlyingEvent(underlyingEvent); + return dispatchEvent(evt.release(), ec); +} + +bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& key) +{ + ASSERT(!eventDispatchForbidden()); + ExceptionCode ec = 0; + RefPtr<KeyboardEvent> keyboardEvent = KeyboardEvent::create(key, document()->defaultView()); + bool r = dispatchEvent(keyboardEvent, ec); + + // we want to return false if default is prevented (already taken care of) + // or if the element is default-handled by the DOM. Otherwise we let it just + // let it get handled by AppKit + if (keyboardEvent->defaultHandled()) + r = false; + + return r; +} + +bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType, + int detail, Node* relatedTarget) +{ + ASSERT(!eventDispatchForbidden()); + + IntPoint contentsPos; + if (FrameView* view = document()->view()) + contentsPos = view->windowToContents(event.pos()); + + short button = event.button(); + + ASSERT(event.eventType() == MouseEventMoved || button != NoButton); + + return dispatchMouseEvent(eventType, button, detail, + contentsPos.x(), contentsPos.y(), event.globalX(), event.globalY(), + event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), + false, relatedTarget); +} + +void Node::dispatchSimulatedMouseEvent(const AtomicString& eventType, + PassRefPtr<Event> underlyingEvent) +{ + ASSERT(!eventDispatchForbidden()); + + bool ctrlKey = false; + bool altKey = false; + bool shiftKey = false; + bool metaKey = false; + if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) { + ctrlKey = keyStateEvent->ctrlKey(); + altKey = keyStateEvent->altKey(); + shiftKey = keyStateEvent->shiftKey(); + metaKey = keyStateEvent->metaKey(); + } + + // Like Gecko, we just pass 0 for everything when we make a fake mouse event. + // Internet Explorer instead gives the current mouse position and state. + dispatchMouseEvent(eventType, 0, 0, 0, 0, 0, 0, + ctrlKey, altKey, shiftKey, metaKey, true, 0, underlyingEvent); +} + +void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook) +{ + if (!gNodesDispatchingSimulatedClicks) + gNodesDispatchingSimulatedClicks = new HashSet<Node*>; + else if (gNodesDispatchingSimulatedClicks->contains(this)) + return; + + gNodesDispatchingSimulatedClicks->add(this); + + // send mousedown and mouseup before the click, if requested + if (sendMouseEvents) + dispatchSimulatedMouseEvent(eventNames().mousedownEvent, event.get()); + setActive(true, showPressedLook); + if (sendMouseEvents) + dispatchSimulatedMouseEvent(eventNames().mouseupEvent, event.get()); + setActive(false); + + // always send click + dispatchSimulatedMouseEvent(eventNames().clickEvent, event); + + gNodesDispatchingSimulatedClicks->remove(this); +} + +bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int detail, + int pageX, int pageY, int screenX, int screenY, + bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, + bool isSimulated, Node* relatedTargetArg, PassRefPtr<Event> underlyingEvent) +{ + ASSERT(!eventDispatchForbidden()); + if (disabled()) // Don't even send DOM events for disabled controls.. + return true; + + if (eventType.isEmpty()) + return false; // Shouldn't happen. + + // Dispatching the first event can easily result in this node being destroyed. + // Since we dispatch up to three events here, we need to make sure we're referenced + // so the pointer will be good for the two subsequent ones. + RefPtr<Node> protect(this); + + bool cancelable = eventType != eventNames().mousemoveEvent; + + ExceptionCode ec = 0; + + bool swallowEvent = false; + + // Attempting to dispatch with a non-EventTarget relatedTarget causes the relatedTarget to be silently ignored. + RefPtr<Node> relatedTarget = relatedTargetArg; + + int adjustedPageX = pageX; + int adjustedPageY = pageY; + if (Frame* frame = document()->frame()) { + float pageZoom = frame->pageZoomFactor(); + if (pageZoom != 1.0f) { + // Adjust our pageX and pageY to account for the page zoom. + adjustedPageX = lroundf(pageX / pageZoom); + adjustedPageY = lroundf(pageY / pageZoom); + } + } + + RefPtr<MouseEvent> mouseEvent = MouseEvent::create(eventType, + true, cancelable, document()->defaultView(), + detail, screenX, screenY, adjustedPageX, adjustedPageY, + ctrlKey, altKey, shiftKey, metaKey, button, + relatedTarget, 0, isSimulated); + mouseEvent->setUnderlyingEvent(underlyingEvent.get()); + mouseEvent->setAbsoluteLocation(IntPoint(pageX, pageY)); + + dispatchEvent(mouseEvent, ec); + bool defaultHandled = mouseEvent->defaultHandled(); + bool defaultPrevented = mouseEvent->defaultPrevented(); + if (defaultHandled || defaultPrevented) + swallowEvent = true; + + // Special case: If it's a double click event, we also send the dblclick event. This is not part + // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated + // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same. + if (eventType == eventNames().clickEvent && detail == 2) { + RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent, + true, cancelable, document()->defaultView(), + detail, screenX, screenY, pageX, pageY, + ctrlKey, altKey, shiftKey, metaKey, button, + relatedTarget, 0, isSimulated); + doubleClickEvent->setUnderlyingEvent(underlyingEvent.get()); + if (defaultHandled) + doubleClickEvent->setDefaultHandled(); + dispatchEvent(doubleClickEvent, ec); + if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented()) + swallowEvent = true; + } + + return swallowEvent; +} + +void Node::dispatchWheelEvent(PlatformWheelEvent& e) +{ + ASSERT(!eventDispatchForbidden()); + if (e.deltaX() == 0 && e.deltaY() == 0) + return; + + FrameView* view = document()->view(); + if (!view) + return; + + IntPoint pos = view->windowToContents(e.pos()); + + int adjustedPageX = pos.x(); + int adjustedPageY = pos.y(); + if (Frame* frame = document()->frame()) { + float pageZoom = frame->pageZoomFactor(); + if (pageZoom != 1.0f) { + // Adjust our pageX and pageY to account for the page zoom. + adjustedPageX = lroundf(pos.x() / pageZoom); + adjustedPageY = lroundf(pos.y() / pageZoom); + } + } + + RefPtr<WheelEvent> we = WheelEvent::create(e.wheelTicksX(), e.wheelTicksY(), + document()->defaultView(), e.globalX(), e.globalY(), adjustedPageX, adjustedPageY, + e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey()); + + we->setAbsoluteLocation(IntPoint(pos.x(), pos.y())); + + ExceptionCode ec = 0; + if (!dispatchEvent(we.release(), ec)) + e.accept(); +} + +bool Node::dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime) +{ + ASSERT(!eventDispatchForbidden()); + + ExceptionCode ec = 0; + return dispatchEvent(WebKitAnimationEvent::create(eventType, animationName, elapsedTime), ec); +} + +bool Node::dispatchWebKitTransitionEvent(const AtomicString& eventType, const String& propertyName, double elapsedTime) +{ + ASSERT(!eventDispatchForbidden()); + + ExceptionCode ec = 0; + return dispatchEvent(WebKitTransitionEvent::create(eventType, propertyName, elapsedTime), ec); +} + +void Node::dispatchFocusEvent() +{ + dispatchEventForType(eventNames().focusEvent, false, false); +} + +void Node::dispatchBlurEvent() +{ + dispatchEventForType(eventNames().blurEvent, false, false); +} + +bool Node::dispatchEventForType(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg) +{ + ASSERT(!eventDispatchForbidden()); + ExceptionCode ec = 0; + return dispatchEvent(Event::create(eventType, canBubbleArg, cancelableArg), ec); +} + +bool Node::dispatchProgressEvent(const AtomicString &eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg) +{ + ASSERT(!eventDispatchForbidden()); + ExceptionCode ec = 0; + return dispatchEvent(ProgressEvent::create(eventType, lengthComputableArg, loadedArg, totalArg), ec); +} + +void Node::dispatchStorageEvent(const AtomicString &eventType, const String& key, const String& oldValue, const String& newValue, Frame* source) +{ +#if ENABLE(DOM_STORAGE) + ASSERT(!eventDispatchForbidden()); + ExceptionCode ec = 0; + dispatchEvent(StorageEvent::create(eventType, key, oldValue, newValue, source->document()->documentURI(), source->domWindow()), ec); +#endif +} + +void Node::removeInlineEventListenerForType(const AtomicString& eventType) +{ + if (!hasRareData()) + return; + + RegisteredEventListenerVector* listeners = rareData()->listeners(); + if (!listeners) + return; + + size_t size = listeners->size(); + for (size_t i = 0; i < size; ++i) { + RegisteredEventListener& r = *listeners->at(i); + if (r.eventType() != eventType || !r.listener()->isInline()) + continue; + + r.setRemoved(true); + listeners->remove(i); + + // removed last + if (listeners->isEmpty() && !inDocument()) + document()->unregisterDisconnectedNodeWithEventListeners(this); + + updateSVGElementInstancesAfterEventListenerChange(this); + return; + } +} + +void Node::setInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener> listener) +{ + // In case we are the only one holding a reference to it, we don't want removeInlineEventListenerForType to destroy it. + removeInlineEventListenerForType(eventType); + if (listener) + addEventListener(eventType, listener, false); +} + +void Node::setInlineEventListenerForTypeAndAttribute(const AtomicString& eventType, Attribute* attr) +{ + setInlineEventListenerForType(eventType, document()->createEventListener(attr->localName().string(), attr->value(), this)); +} + +EventListener* Node::inlineEventListenerForType(const AtomicString& eventType) const +{ + const RegisteredEventListenerVector& listeners = eventListeners(); + size_t size = listeners.size(); + for (size_t i = 0; i < size; ++i) { + const RegisteredEventListener& r = *listeners[i]; + if (r.eventType() == eventType && r.listener()->isInline()) + return r.listener(); + } + return 0; +} + +bool Node::disabled() const +{ + return false; +} + +void Node::defaultEventHandler(Event* event) +{ + if (event->target() != this) + return; + const AtomicString& eventType = event->type(); + if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) { + if (event->isKeyboardEvent()) + if (Frame* frame = document()->frame()) + frame->eventHandler()->defaultKeyboardEventHandler(static_cast<KeyboardEvent*>(event)); + } else if (eventType == eventNames().clickEvent) { + int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0; + dispatchUIEvent(eventNames().DOMActivateEvent, detail, event); + } else if (eventType == eventNames().contextmenuEvent) { + if (Frame* frame = document()->frame()) + if (Page* page = frame->page()) + page->contextMenuController()->handleContextMenuEvent(event); + } else if (eventType == eventNames().textInputEvent) { + if (event->isTextEvent()) + if (Frame* frame = document()->frame()) + frame->eventHandler()->defaultTextInputEventHandler(static_cast<TextEvent*>(event)); + } +} + +EventListener* Node::onabort() const +{ + return inlineEventListenerForType(eventNames().abortEvent); +} + +void Node::setOnabort(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().abortEvent, eventListener); +} + +EventListener* Node::onblur() const +{ + return inlineEventListenerForType(eventNames().blurEvent); +} + +void Node::setOnblur(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().blurEvent, eventListener); +} + +EventListener* Node::onchange() const +{ + return inlineEventListenerForType(eventNames().changeEvent); +} + +void Node::setOnchange(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().changeEvent, eventListener); +} + +EventListener* Node::onclick() const +{ + return inlineEventListenerForType(eventNames().clickEvent); +} + +void Node::setOnclick(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().clickEvent, eventListener); +} + +EventListener* Node::oncontextmenu() const +{ + return inlineEventListenerForType(eventNames().contextmenuEvent); +} + +void Node::setOncontextmenu(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().contextmenuEvent, eventListener); +} + +EventListener* Node::ondblclick() const +{ + return inlineEventListenerForType(eventNames().dblclickEvent); +} + +void Node::setOndblclick(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dblclickEvent, eventListener); +} + +EventListener* Node::onerror() const +{ + return inlineEventListenerForType(eventNames().errorEvent); +} + +void Node::setOnerror(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().errorEvent, eventListener); +} + +EventListener* Node::onfocus() const +{ + return inlineEventListenerForType(eventNames().focusEvent); +} + +void Node::setOnfocus(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().focusEvent, eventListener); +} + +EventListener* Node::oninput() const +{ + return inlineEventListenerForType(eventNames().inputEvent); +} + +void Node::setOninput(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().inputEvent, eventListener); +} + +EventListener* Node::onkeydown() const +{ + return inlineEventListenerForType(eventNames().keydownEvent); +} + +void Node::setOnkeydown(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().keydownEvent, eventListener); +} + +EventListener* Node::onkeypress() const +{ + return inlineEventListenerForType(eventNames().keypressEvent); +} + +void Node::setOnkeypress(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().keypressEvent, eventListener); +} + +EventListener* Node::onkeyup() const +{ + return inlineEventListenerForType(eventNames().keyupEvent); +} + +void Node::setOnkeyup(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().keyupEvent, eventListener); +} + +EventListener* Node::onload() const +{ + return inlineEventListenerForType(eventNames().loadEvent); +} + +void Node::setOnload(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().loadEvent, eventListener); +} + +EventListener* Node::onmousedown() const +{ + return inlineEventListenerForType(eventNames().mousedownEvent); +} + +void Node::setOnmousedown(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().mousedownEvent, eventListener); +} + +EventListener* Node::onmousemove() const +{ + return inlineEventListenerForType(eventNames().mousemoveEvent); +} + +void Node::setOnmousemove(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().mousemoveEvent, eventListener); +} + +EventListener* Node::onmouseout() const +{ + return inlineEventListenerForType(eventNames().mouseoutEvent); +} + +void Node::setOnmouseout(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().mouseoutEvent, eventListener); +} + +EventListener* Node::onmouseover() const +{ + return inlineEventListenerForType(eventNames().mouseoverEvent); +} + +void Node::setOnmouseover(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().mouseoverEvent, eventListener); +} + +EventListener* Node::onmouseup() const +{ + return inlineEventListenerForType(eventNames().mouseupEvent); +} + +void Node::setOnmouseup(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().mouseupEvent, eventListener); +} + +EventListener* Node::onmousewheel() const +{ + return inlineEventListenerForType(eventNames().mousewheelEvent); +} + +void Node::setOnmousewheel(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().mousewheelEvent, eventListener); +} + +EventListener* Node::onbeforecut() const +{ + return inlineEventListenerForType(eventNames().beforecutEvent); +} + +void Node::setOnbeforecut(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().beforecutEvent, eventListener); +} + +EventListener* Node::oncut() const +{ + return inlineEventListenerForType(eventNames().cutEvent); +} + +void Node::setOncut(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().cutEvent, eventListener); +} + +EventListener* Node::onbeforecopy() const +{ + return inlineEventListenerForType(eventNames().beforecopyEvent); +} + +void Node::setOnbeforecopy(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().beforecopyEvent, eventListener); +} + +EventListener* Node::oncopy() const +{ + return inlineEventListenerForType(eventNames().copyEvent); +} + +void Node::setOncopy(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().copyEvent, eventListener); +} + +EventListener* Node::onbeforepaste() const +{ + return inlineEventListenerForType(eventNames().beforepasteEvent); +} + +void Node::setOnbeforepaste(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().beforepasteEvent, eventListener); +} + +EventListener* Node::onpaste() const +{ + return inlineEventListenerForType(eventNames().pasteEvent); +} + +void Node::setOnpaste(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().pasteEvent, eventListener); +} + +EventListener* Node::ondragenter() const +{ + return inlineEventListenerForType(eventNames().dragenterEvent); +} + +void Node::setOndragenter(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dragenterEvent, eventListener); +} + +EventListener* Node::ondragover() const +{ + return inlineEventListenerForType(eventNames().dragoverEvent); +} + +void Node::setOndragover(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dragoverEvent, eventListener); +} + +EventListener* Node::ondragleave() const +{ + return inlineEventListenerForType(eventNames().dragleaveEvent); +} + +void Node::setOndragleave(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dragleaveEvent, eventListener); +} + +EventListener* Node::ondrop() const +{ + return inlineEventListenerForType(eventNames().dropEvent); +} + +void Node::setOndrop(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dropEvent, eventListener); +} + +EventListener* Node::ondragstart() const +{ + return inlineEventListenerForType(eventNames().dragstartEvent); +} + +void Node::setOndragstart(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dragstartEvent, eventListener); +} + +EventListener* Node::ondrag() const +{ + return inlineEventListenerForType(eventNames().dragEvent); +} + +void Node::setOndrag(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dragEvent, eventListener); +} + +EventListener* Node::ondragend() const +{ + return inlineEventListenerForType(eventNames().dragendEvent); +} + +void Node::setOndragend(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().dragendEvent, eventListener); +} + +EventListener* Node::onreset() const +{ + return inlineEventListenerForType(eventNames().resetEvent); +} + +void Node::setOnreset(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().resetEvent, eventListener); +} + +EventListener* Node::onresize() const +{ + return inlineEventListenerForType(eventNames().resizeEvent); +} + +void Node::setOnresize(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().resizeEvent, eventListener); +} + +EventListener* Node::onscroll() const +{ + return inlineEventListenerForType(eventNames().scrollEvent); +} + +void Node::setOnscroll(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().scrollEvent, eventListener); +} + +EventListener* Node::onsearch() const +{ + return inlineEventListenerForType(eventNames().searchEvent); +} + +void Node::setOnsearch(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().searchEvent, eventListener); +} + +EventListener* Node::onselect() const +{ + return inlineEventListenerForType(eventNames().selectEvent); +} + +void Node::setOnselect(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().selectEvent, eventListener); +} + +EventListener* Node::onselectstart() const +{ + return inlineEventListenerForType(eventNames().selectstartEvent); +} + +void Node::setOnselectstart(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().selectstartEvent, eventListener); +} + +EventListener* Node::onsubmit() const +{ + return inlineEventListenerForType(eventNames().submitEvent); +} + +void Node::setOnsubmit(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().submitEvent, eventListener); +} + +EventListener* Node::onunload() const +{ + return inlineEventListenerForType(eventNames().unloadEvent); +} + +void Node::setOnunload(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().unloadEvent, eventListener); +} + +#if ENABLE(TOUCH_EVENTS) // Android +EventListener* Node::ontouchstart() const +{ + return inlineEventListenerForType(eventNames().touchstartEvent); +} + +void Node::setOntouchstart(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().touchstartEvent, eventListener); +} + +EventListener* Node::ontouchend() const +{ + return inlineEventListenerForType(eventNames().touchendEvent); +} + +void Node::setOntouchend(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().touchendEvent, eventListener); +} + +EventListener* Node::ontouchmove() const +{ + return inlineEventListenerForType(eventNames().touchmoveEvent); +} + +void Node::setOntouchmove(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().touchmoveEvent, eventListener); +} + +EventListener* Node::ontouchcancel() const +{ + return inlineEventListenerForType(eventNames().touchcancelEvent); +} + +void Node::setOntouchcancel(PassRefPtr<EventListener> eventListener) +{ + setInlineEventListenerForType(eventNames().touchcancelEvent, eventListener); +} +#endif // ENABLE(TOUCH_EVENT) + } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index fa9995d..01f2736 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,9 +25,11 @@ #define Node_h #include "DocPtr.h" +#include "EventTarget.h" #include "KURLHash.h" #include "PlatformString.h" #include "TreeShared.h" +#include "FloatPoint.h" #include <wtf/Assertions.h> #include <wtf/ListHashSet.h> #include <wtf/OwnPtr.h> @@ -36,30 +38,36 @@ namespace WebCore { class AtomicString; +class Attribute; class ContainerNode; class Document; class DynamicNodeList; class Element; class Event; class EventListener; +class Frame; class IntRect; class KeyboardEvent; class NSResolver; class NamedAttrMap; class NodeList; +class NodeRareData; class PlatformKeyboardEvent; class PlatformMouseEvent; class PlatformWheelEvent; class QualifiedName; +class RegisteredEventListener; class RenderArena; class RenderBox; +class RenderBoxModelObject; class RenderObject; class RenderStyle; class StringBuilder; -class NodeRareData; typedef int ExceptionCode; +typedef Vector<RefPtr<RegisteredEventListener> > RegisteredEventListenerVector; + enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange, AnimationStyleChange }; const unsigned short DOCUMENT_POSITION_EQUIVALENT = 0x00; @@ -71,7 +79,7 @@ const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10; const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; // this class implements nodes, which can have a parent but no children: -class Node : public TreeShared<Node> { +class Node : public EventTarget, public TreeShared<Node> { friend class Document; public: enum NodeType { @@ -180,7 +188,6 @@ public: virtual bool isCommentNode() const { return false; } virtual bool isCharacterDataNode() const { return false; } bool isDocumentNode() const; - virtual bool isEventTargetNode() const { return false; } virtual bool isShadowNode() const { return false; } virtual Node* shadowParentNode() { return 0; } Node* shadowAncestorNode(); @@ -290,14 +297,6 @@ public: virtual bool isKeyboardFocusable(KeyboardEvent*) const; virtual bool isMouseFocusable() const; - virtual bool isAutofilled() const { return false; } - virtual bool isControl() const { return false; } // Eventually the notion of what is a control will be extensible. - virtual bool isEnabled() const { return true; } - virtual bool isChecked() const { return false; } - virtual bool isIndeterminate() const { return false; } - virtual bool isReadOnlyControl() const { return false; } - virtual bool isTextControl() const { return false; } - virtual bool isContentEditable() const; virtual bool isContentRichlyEditable() const; virtual bool shouldUseInputMethod() const; @@ -316,7 +315,7 @@ public: Document* document() const { ASSERT(this); - ASSERT(m_document || nodeType() == DOCUMENT_TYPE_NODE && !inDocument()); + ASSERT(m_document || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument())); return m_document.get(); } void setDocument(Document*); @@ -375,10 +374,10 @@ public: RenderObject* previousRenderer(); void setRenderer(RenderObject* renderer) { m_renderer = renderer; } - // Use with caution. Does no type checking. Mostly a convenience method for shadow nodes of form controls, where we know exactly - // what kind of renderer we made. + // Use these two methods with caution. RenderBox* renderBox() const; - + RenderBoxModelObject* renderBoxModelObject() const; + void checkSetPrefix(const AtomicString& prefix, ExceptionCode&); bool isDescendantOf(const Node*) const; bool contains(const Node*) const; @@ -405,6 +404,10 @@ public: // Whether or not a selection can be started in this object virtual bool canStartSelection() const; + // Getting points into and out of screen space + FloatPoint convertToPage(const FloatPoint& p) const; + FloatPoint convertFromPage(const FloatPoint& p) const; + // ----------------------------------------------------------------------------- // Integration with rendering tree @@ -507,8 +510,8 @@ public: #endif protected: - virtual void willMoveToNewOwnerDocument() { } - virtual void didMoveToNewOwnerDocument() { } + virtual void willMoveToNewOwnerDocument(); + virtual void didMoveToNewOwnerDocument(); virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { } void setTabIndexExplicitly(short); @@ -518,6 +521,160 @@ protected: NodeRareData* rareData() const; NodeRareData* ensureRareData(); +public: + virtual Node* toNode() { return this; } + + virtual ScriptExecutionContext* scriptExecutionContext() const; + + virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); + virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); + virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); + void removeAllEventListeners() { if (hasRareData()) removeAllEventListenersSlowCase(); } + + void setInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener>); + void setInlineEventListenerForTypeAndAttribute(const AtomicString& eventType, Attribute*); + void removeInlineEventListenerForType(const AtomicString& eventType); + bool dispatchEventForType(const AtomicString& eventType, bool canBubble, bool cancelable); + EventListener* inlineEventListenerForType(const AtomicString& eventType) const; + + bool dispatchSubtreeModifiedEvent(); + void dispatchWindowEvent(PassRefPtr<Event>); + void dispatchWindowEvent(const AtomicString& eventType, bool canBubble, bool cancelable); + bool dispatchUIEvent(const AtomicString& eventType, int detail = 0, PassRefPtr<Event> underlyingEvent = 0); + bool dispatchKeyEvent(const PlatformKeyboardEvent&); + void dispatchWheelEvent(PlatformWheelEvent&); + bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, + int clickCount = 0, Node* relatedTarget = 0); + bool dispatchMouseEvent(const AtomicString& eventType, int button, int clickCount, + int pageX, int pageY, int screenX, int screenY, + bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, + bool isSimulated = false, Node* relatedTarget = 0, PassRefPtr<Event> underlyingEvent = 0); + void dispatchSimulatedMouseEvent(const AtomicString& eventType, PassRefPtr<Event> underlyingEvent = 0); + void dispatchSimulatedClick(PassRefPtr<Event> underlyingEvent, bool sendMouseEvents = false, bool showPressedLook = true); + bool dispatchProgressEvent(const AtomicString &eventType, bool lengthComputableArg, unsigned loadedArg, unsigned totalArg); + void dispatchStorageEvent(const AtomicString &eventType, const String& key, const String& oldValue, const String& newValue, Frame* source); + bool dispatchWebKitAnimationEvent(const AtomicString& eventType, const String& animationName, double elapsedTime); + bool dispatchWebKitTransitionEvent(const AtomicString& eventType, const String& propertyName, double elapsedTime); + bool dispatchGenericEvent(PassRefPtr<Event>); + + virtual void handleLocalEvents(Event*, bool useCapture); + + virtual void dispatchFocusEvent(); + virtual void dispatchBlurEvent(); + + /** + * Perform the default action for an event e.g. submitting a form + */ + virtual void defaultEventHandler(Event*); + + /** + * Used for disabled form elements; if true, prevents mouse events from being dispatched + * to event listeners, and prevents DOMActivate events from being sent at all. + */ + virtual bool disabled() const; + + const RegisteredEventListenerVector& eventListeners() const; + + EventListener* onabort() const; + void setOnabort(PassRefPtr<EventListener>); + EventListener* onblur() const; + void setOnblur(PassRefPtr<EventListener>); + EventListener* onchange() const; + void setOnchange(PassRefPtr<EventListener>); + EventListener* onclick() const; + void setOnclick(PassRefPtr<EventListener>); + EventListener* oncontextmenu() const; + void setOncontextmenu(PassRefPtr<EventListener>); + EventListener* ondblclick() const; + void setOndblclick(PassRefPtr<EventListener>); + EventListener* onerror() const; + void setOnerror(PassRefPtr<EventListener>); + EventListener* onfocus() const; + void setOnfocus(PassRefPtr<EventListener>); + EventListener* oninput() const; + void setOninput(PassRefPtr<EventListener>); + EventListener* onkeydown() const; + void setOnkeydown(PassRefPtr<EventListener>); + EventListener* onkeypress() const; + void setOnkeypress(PassRefPtr<EventListener>); + EventListener* onkeyup() const; + void setOnkeyup(PassRefPtr<EventListener>); + EventListener* onload() const; + void setOnload(PassRefPtr<EventListener>); + EventListener* onmousedown() const; + void setOnmousedown(PassRefPtr<EventListener>); + EventListener* onmousemove() const; + void setOnmousemove(PassRefPtr<EventListener>); + EventListener* onmouseout() const; + void setOnmouseout(PassRefPtr<EventListener>); + EventListener* onmouseover() const; + void setOnmouseover(PassRefPtr<EventListener>); + EventListener* onmouseup() const; + void setOnmouseup(PassRefPtr<EventListener>); + EventListener* onmousewheel() const; + void setOnmousewheel(PassRefPtr<EventListener>); + EventListener* onbeforecut() const; + void setOnbeforecut(PassRefPtr<EventListener>); + EventListener* oncut() const; + void setOncut(PassRefPtr<EventListener>); + EventListener* onbeforecopy() const; + void setOnbeforecopy(PassRefPtr<EventListener>); + EventListener* oncopy() const; + void setOncopy(PassRefPtr<EventListener>); + EventListener* onbeforepaste() const; + void setOnbeforepaste(PassRefPtr<EventListener>); + EventListener* onpaste() const; + void setOnpaste(PassRefPtr<EventListener>); + EventListener* ondragenter() const; + void setOndragenter(PassRefPtr<EventListener>); + EventListener* ondragover() const; + void setOndragover(PassRefPtr<EventListener>); + EventListener* ondragleave() const; + void setOndragleave(PassRefPtr<EventListener>); + EventListener* ondrop() const; + void setOndrop(PassRefPtr<EventListener>); + EventListener* ondragstart() const; + void setOndragstart(PassRefPtr<EventListener>); + EventListener* ondrag() const; + void setOndrag(PassRefPtr<EventListener>); + EventListener* ondragend() const; + void setOndragend(PassRefPtr<EventListener>); + EventListener* onreset() const; + void setOnreset(PassRefPtr<EventListener>); + EventListener* onresize() const; + void setOnresize(PassRefPtr<EventListener>); + EventListener* onscroll() const; + void setOnscroll(PassRefPtr<EventListener>); + EventListener* onsearch() const; + void setOnsearch(PassRefPtr<EventListener>); + EventListener* onselect() const; + void setOnselect(PassRefPtr<EventListener>); + EventListener* onselectstart() const; + void setOnselectstart(PassRefPtr<EventListener>); + EventListener* onsubmit() const; + void setOnsubmit(PassRefPtr<EventListener>); + EventListener* onunload() const; + void setOnunload(PassRefPtr<EventListener>); +#if ENABLE(TOUCH_EVENTS) // Android + EventListener* ontouchstart() const; + void setOntouchstart(PassRefPtr<EventListener>); + EventListener* ontouchend() const; + void setOntouchend(PassRefPtr<EventListener>); + EventListener* ontouchmove() const; + void setOntouchmove(PassRefPtr<EventListener>); + EventListener* ontouchcancel() const; + void setOntouchcancel(PassRefPtr<EventListener>); +#endif + + using TreeShared<Node>::ref; + using TreeShared<Node>::deref; + +private: + virtual void refEventTarget() { ref(); } + virtual void derefEventTarget() { deref(); } + + void removeAllEventListenersSlowCase(); + private: virtual NodeRareData* createRareData(); Node* containerChildNode(unsigned index) const; diff --git a/WebCore/dom/Node.idl b/WebCore/dom/Node.idl index f45eaa6..0e1848d 100644 --- a/WebCore/dom/Node.idl +++ b/WebCore/dom/Node.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> * * This library is free software; you can redistribute it and/or @@ -22,6 +22,7 @@ module core { interface [ CustomMarkFunction, + CustomPushEventHandlerScope, GenerateConstructor, GenerateNativeConverter, GenerateToJS, @@ -64,15 +65,15 @@ module core { readonly attribute NamedNodeMap attributes; readonly attribute Document ownerDocument; - [OldStyleObjC, Custom] Node insertBefore(in [Return] Node newChild, + [OldStyleObjC, JSCCustom] Node insertBefore(in [Return] Node newChild, in Node refChild) raises(DOMException); - [OldStyleObjC, Custom] Node replaceChild(in Node newChild, + [OldStyleObjC, JSCCustom] Node replaceChild(in Node newChild, in [Return] Node oldChild) + raises(DOMExceptionJSC); + [JSCCustom] Node removeChild(in [Return] Node oldChild) raises(DOMException); - [Custom] Node removeChild(in [Return] Node oldChild) - raises(DOMException); - [Custom] Node appendChild(in [Return] Node newChild) + [JSCCustom] Node appendChild(in [Return] Node newChild) raises(DOMException); boolean hasChildNodes(); @@ -131,6 +132,66 @@ module core { // Objective-C extensions readonly attribute boolean isContentEditable; #endif /* defined(LANGUAGE_OBJECTIVE_C) */ + +#if !defined(LANGUAGE_OBJECTIVE_C) +#if !defined(LANGUAGE_COM) + attribute [DontEnum, ProtectedListener] EventListener onabort; + attribute [DontEnum, ProtectedListener] EventListener onblur; + attribute [DontEnum, ProtectedListener] EventListener onchange; + attribute [DontEnum, ProtectedListener] EventListener onclick; + attribute [DontEnum, ProtectedListener] EventListener oncontextmenu; + attribute [DontEnum, ProtectedListener] EventListener ondblclick; + attribute [DontEnum, ProtectedListener] EventListener onerror; + attribute [DontEnum, ProtectedListener] EventListener onfocus; + attribute [DontEnum, ProtectedListener] EventListener oninput; + attribute [DontEnum, ProtectedListener] EventListener onkeydown; + attribute [DontEnum, ProtectedListener] EventListener onkeypress; + attribute [DontEnum, ProtectedListener] EventListener onkeyup; + attribute [DontEnum, ProtectedListener] EventListener onload; + attribute [DontEnum, ProtectedListener] EventListener onmousedown; + attribute [DontEnum, ProtectedListener] EventListener onmousemove; + attribute [DontEnum, ProtectedListener] EventListener onmouseout; + attribute [DontEnum, ProtectedListener] EventListener onmouseover; + attribute [DontEnum, ProtectedListener] EventListener onmouseup; + attribute [DontEnum, ProtectedListener] EventListener onmousewheel; + attribute [DontEnum, ProtectedListener] EventListener onbeforecut; + attribute [DontEnum, ProtectedListener] EventListener oncut; + attribute [DontEnum, ProtectedListener] EventListener onbeforecopy; + attribute [DontEnum, ProtectedListener] EventListener oncopy; + attribute [DontEnum, ProtectedListener] EventListener onbeforepaste; + attribute [DontEnum, ProtectedListener] EventListener onpaste; + attribute [DontEnum, ProtectedListener] EventListener ondragenter; + attribute [DontEnum, ProtectedListener] EventListener ondragover; + attribute [DontEnum, ProtectedListener] EventListener ondragleave; + attribute [DontEnum, ProtectedListener] EventListener ondrop; + attribute [DontEnum, ProtectedListener] EventListener ondragstart; + attribute [DontEnum, ProtectedListener] EventListener ondrag; + attribute [DontEnum, ProtectedListener] EventListener ondragend; + attribute [DontEnum, ProtectedListener] EventListener onreset; + attribute [DontEnum, ProtectedListener] EventListener onresize; + attribute [DontEnum, ProtectedListener] EventListener onscroll; + attribute [DontEnum, ProtectedListener] EventListener onsearch; + attribute [DontEnum, ProtectedListener] EventListener onselect; + attribute [DontEnum, ProtectedListener] EventListener onselectstart; + attribute [DontEnum, ProtectedListener] EventListener onsubmit; + attribute [DontEnum, ProtectedListener] EventListener onunload; +#if ENABLE_TOUCH_EVENTS + attribute [DontEnum, ProtectedListener] EventListener ontouchstart; + attribute [DontEnum, ProtectedListener] EventListener ontouchend; + attribute [DontEnum, ProtectedListener] EventListener ontouchmove; + attribute [DontEnum, ProtectedListener] EventListener ontouchcancel; +#endif + + [Custom] void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + [Custom] void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + boolean dispatchEvent(in Event event) + raises(EventException); +#endif +#endif }; } diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp index faa4a13..a2591ba 100644 --- a/WebCore/dom/Position.cpp +++ b/WebCore/dom/Position.cpp @@ -43,7 +43,7 @@ namespace WebCore { using namespace HTMLNames; -static Node *nextRenderedEditable(Node *node) +static Node* nextRenderedEditable(Node* node) { while (1) { node = node->nextEditable(); @@ -52,13 +52,13 @@ static Node *nextRenderedEditable(Node *node) RenderObject* renderer = node->renderer(); if (!renderer) continue; - if (renderer->inlineBoxWrapper() || renderer->isText() && toRenderText(renderer)->firstTextBox()) + if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox())) return node; } return 0; } -static Node *previousRenderedEditable(Node *node) +static Node* previousRenderedEditable(Node* node) { while (1) { node = node->previousEditable(); @@ -67,7 +67,7 @@ static Node *previousRenderedEditable(Node *node) RenderObject* renderer = node->renderer(); if (!renderer) continue; - if (renderer->inlineBoxWrapper() || renderer->isText() && toRenderText(renderer)->firstTextBox()) + if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) || (renderer->isText() && toRenderText(renderer)->firstTextBox())) return node; } return 0; @@ -97,60 +97,69 @@ PassRefPtr<CSSComputedStyleDeclaration> Position::computedStyle() const return WebCore::computedStyle(elem); } -Position Position::previous(EUsingComposedCharacters usingComposedCharacters) const +Position Position::previous(PositionMoveType moveType) const { - Node *n = node(); + Node* n = node(); if (!n) return *this; - int o = offset(); + int o = m_offset; // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier. ASSERT(o >= 0); if (o > 0) { - Node *child = n->childNode(o - 1); - if (child) { - return Position(child, maxDeepOffset(child)); - } + Node* child = n->childNode(o - 1); + if (child) + return lastDeepEditingPositionForNode(child); + // There are two reasons child might be 0: // 1) The node is node like a text node that is not an element, and therefore has no children. // Going backward one character at a time is correct. // 2) The old offset was a bogus offset like (<br>, 1), and there is no child. // Going from 1 to 0 is correct. - return Position(n, usingComposedCharacters ? uncheckedPreviousOffset(n, o) : o - 1); + switch (moveType) { + case CodePoint: + return Position(n, o - 1); + case Character: + return Position(n, uncheckedPreviousOffset(n, o)); + case BackwardDeletion: + return Position(n, uncheckedPreviousOffsetForBackwardDeletion(n, o)); + } } - Node *parent = n->parentNode(); + Node* parent = n->parentNode(); if (!parent) return *this; return Position(parent, n->nodeIndex()); } -Position Position::next(EUsingComposedCharacters usingComposedCharacters) const +Position Position::next(PositionMoveType moveType) const { - Node *n = node(); + ASSERT(moveType != BackwardDeletion); + + Node* n = node(); if (!n) return *this; - int o = offset(); + int o = m_offset; // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier. ASSERT(o >= 0); Node* child = n->childNode(o); - if (child || !n->hasChildNodes() && o < maxDeepOffset(n)) { + if (child || (!n->hasChildNodes() && o < lastOffsetForEditing(n))) { if (child) - return Position(child, 0); - + return firstDeepEditingPositionForNode(child); + // There are two reasons child might be 0: // 1) The node is node like a text node that is not an element, and therefore has no children. // Going forward one character at a time is correct. // 2) The new offset is a bogus offset like (<br>, 1), and there is no child. // Going from 0 to 1 is correct. - return Position(n, usingComposedCharacters ? uncheckedNextOffset(n, o) : o + 1); + return Position(n, (moveType == Character) ? uncheckedNextOffset(n, o) : o + 1); } - Node *parent = n->parentNode(); + Node* parent = n->parentNode(); if (!parent) return *this; @@ -162,46 +171,61 @@ int Position::uncheckedPreviousOffset(const Node* n, int current) return n->renderer() ? n->renderer()->previousOffset(current) : current - 1; } +int Position::uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current) +{ + return n->renderer() ? n->renderer()->previousOffsetForBackwardDeletion(current) : current - 1; +} + int Position::uncheckedNextOffset(const Node* n, int current) { return n->renderer() ? n->renderer()->nextOffset(current) : current + 1; } -bool Position::atStart() const +bool Position::atFirstEditingPositionForNode() const { - Node *n = node(); - if (!n) + if (isNull()) return true; - - return offset() <= 0 && n->parent() == 0; + return m_offset <= 0; } -bool Position::atEnd() const +bool Position::atLastEditingPositionForNode() const { - Node *n = node(); - if (!n) + if (isNull()) return true; - - return n->parent() == 0 && offset() >= maxDeepOffset(n); + return m_offset >= lastOffsetForEditing(node()); +} + +bool Position::atStartOfTree() const +{ + if (isNull()) + return true; + return !node()->parentNode() && m_offset <= 0; +} + +bool Position::atEndOfTree() const +{ + if (isNull()) + return true; + return !node()->parentNode() && m_offset >= lastOffsetForEditing(node()); } int Position::renderedOffset() const { if (!node()->isTextNode()) - return offset(); + return m_offset; if (!node()->renderer()) - return offset(); + return m_offset; int result = 0; RenderText *textRenderer = toRenderText(node()->renderer()); for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { int start = box->start(); int end = box->start() + box->len(); - if (offset() < start) + if (m_offset < start) return result; - if (offset() <= end) { - result += offset() - start; + if (m_offset <= end) { + result += m_offset - start; return result; } result += box->len(); @@ -221,7 +245,7 @@ Position Position::previousCharacterPosition(EAffinity affinity) const bool rendered = isCandidate(); Position currentPos = *this; - while (!currentPos.atStart()) { + while (!currentPos.atStartOfTree()) { currentPos = currentPos.previous(); if (currentPos.node()->rootEditableElement() != fromRootEditableElement) @@ -249,7 +273,7 @@ Position Position::nextCharacterPosition(EAffinity affinity) const bool rendered = isCandidate(); Position currentPos = *this; - while (!currentPos.atEnd()) { + while (!currentPos.atEndOfTree()) { currentPos = currentPos.next(); if (currentPos.node()->rootEditableElement() != fromRootEditableElement) @@ -265,7 +289,7 @@ Position Position::nextCharacterPosition(EAffinity affinity) const return *this; } -// Whether or not [node, 0] and [node, maxDeepOffset(node)] are their own VisiblePositions. +// Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions. // If true, adjacent candidates are visually distinct. // FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate. // FIXME: Share code with isCandidate, if possible. @@ -359,7 +383,7 @@ Position Position::upstream() const // Return position after tables and nodes which have content that can be ignored. if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) { if (currentPos.atEndOfNode()) - return Position(currentNode, maxDeepOffset(currentNode)); + return lastDeepEditingPositionForNode(currentNode); continue; } @@ -396,7 +420,7 @@ Position Position::upstream() const otherBox = otherBox->nextLeafChild(); if (!otherBox) break; - if (otherBox == lastTextBox || otherBox->object() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset) + if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset)) continuesOnNextLine = false; } @@ -405,7 +429,7 @@ Position Position::upstream() const otherBox = otherBox->prevLeafChild(); if (!otherBox) break; - if (otherBox == lastTextBox || otherBox->object() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset) + if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() > textOffset)) continuesOnNextLine = false; } @@ -508,7 +532,7 @@ Position Position::downstream() const otherBox = otherBox->nextLeafChild(); if (!otherBox) break; - if (otherBox == lastTextBox || otherBox->object() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset) + if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset)) continuesOnNextLine = false; } @@ -517,7 +541,7 @@ Position Position::downstream() const otherBox = otherBox->prevLeafChild(); if (!otherBox) break; - if (otherBox == lastTextBox || otherBox->object() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset) + if (otherBox == lastTextBox || (otherBox->renderer() == textRenderer && static_cast<InlineTextBox*>(otherBox)->start() >= textOffset)) continuesOnNextLine = false; } @@ -534,7 +558,7 @@ bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* render { RenderObject* stop = renderer->nextInPreOrderAfterChildren(); for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder()) - if (o->element()) { + if (o->node()) { if ((o->isText() && toRenderText(o)->linesBoundingBox().height()) || (o->isBox() && toRenderBox(o)->borderBoundingBox().height())) return true; @@ -560,17 +584,17 @@ bool Position::isCandidate() const return false; if (renderer->isBR()) - return offset() == 0 && !nodeIsUserSelectNone(node()->parent()); + return m_offset == 0 && !nodeIsUserSelectNone(node()->parent()); if (renderer->isText()) return inRenderedText() && !nodeIsUserSelectNone(node()); if (isTableElement(node()) || editingIgnoresContent(node())) - return (offset() == 0 || offset() == maxDeepOffset(node())) && !nodeIsUserSelectNone(node()->parent()); + return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(node()->parent()); if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedNonAnonymousDescendantsWithHeight(renderer) && (toRenderBox(renderer)->height() || node()->hasTagName(bodyTag))) - return offset() == 0 && !nodeIsUserSelectNone(node()); + return atFirstEditingPositionForNode() && !nodeIsUserSelectNone(node()); return false; } @@ -586,15 +610,15 @@ bool Position::inRenderedText() const RenderText *textRenderer = toRenderText(renderer); for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { - if (offset() < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) { + if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) { // The offset we're looking for is before this node // this means the offset must be in content that is // not rendered. Return false. return false; } - if (box->containsCaretOffset(offset())) + if (box->containsCaretOffset(m_offset)) // Return false for offsets inside composed characters. - return offset() == 0 || offset() == textRenderer->nextOffset(textRenderer->previousOffset(offset())); + return m_offset == 0 || m_offset == textRenderer->nextOffset(textRenderer->previousOffset(m_offset)); } return false; @@ -622,13 +646,13 @@ bool Position::isRenderedCharacter() const RenderText* textRenderer = toRenderText(renderer); for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { - if (offset() < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) { + if (m_offset < static_cast<int>(box->start()) && !textRenderer->containsReversedText()) { // The offset we're looking for is before this node // this means the offset must be in content that is // not rendered. Return false. return false; } - if (offset() >= static_cast<int>(box->start()) && offset() < static_cast<int>(box->start() + box->len())) + if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast<int>(box->start() + box->len())) return true; } @@ -656,11 +680,11 @@ bool Position::rendersInDifferentPosition(const Position &pos) const if (node()->hasTagName(brTag)) return false; - if (offset() == pos.offset()) + if (m_offset == pos.m_offset) return false; if (!node()->isTextNode() && !pos.node()->isTextNode()) { - if (offset() != pos.offset()) + if (m_offset != pos.m_offset) return true; } } @@ -734,7 +758,7 @@ Position Position::leadingWhitespacePosition(EAffinity affinity, bool considerNo Position prev = previousCharacterPosition(affinity); if (prev != *this && prev.node()->inSameContainingBlockFlowElement(node()) && prev.node()->isTextNode()) { String string = static_cast<Text *>(prev.node())->data(); - UChar c = string[prev.offset()]; + UChar c = string[prev.m_offset]; if (considerNonCollapsibleWhitespace ? (isSpaceOrNewline(c) || c == noBreakSpace) : isCollapsibleWhitespace(c)) if (isEditablePosition(prev)) return prev; @@ -809,11 +833,11 @@ static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer) void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const { - caretOffset = offset(); + caretOffset = m_offset; RenderObject* renderer = node()->renderer(); if (!renderer->isText()) { - inlineBox = renderer->inlineBoxWrapper(); - if (!inlineBox || caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()) + inlineBox = renderer->isBox() ? toRenderBox(renderer)->inlineBoxWrapper() : 0; + if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset())) return; } else { RenderText* textRenderer = toRenderText(renderer); @@ -825,7 +849,7 @@ void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi int caretMinOffset = box->caretMinOffset(); int caretMaxOffset = box->caretMaxOffset(); - if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || caretOffset == caretMaxOffset && box->isLineBreak()) + if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak())) continue; if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) { @@ -943,7 +967,7 @@ void Position::debugPosition(const char* msg) const if (isNull()) fprintf(stderr, "Position [%s]: null\n", msg); else - fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, node()->nodeName().utf8().data(), node(), offset()); + fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, node()->nodeName().utf8().data(), node(), m_offset); } #ifndef NDEBUG @@ -957,7 +981,7 @@ void Position::formatForDebugger(char* buffer, unsigned length) const else { char s[1024]; result += "offset "; - result += String::number(offset()); + result += String::number(m_offset); result += " of "; node()->formatForDebugger(s, sizeof(s)); result += s; @@ -984,6 +1008,19 @@ Position endPosition(const Range* r) return r ? r->endPosition() : Position(); } +// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0]) +// for elements which editing "ignores". the rest of the editing code will treat [img, 0] +// as "the last position before the img" +Position firstDeepEditingPositionForNode(Node* node) +{ + return Position(node, 0); +} + +Position lastDeepEditingPositionForNode(Node* node) +{ + return Position(node, lastOffsetForEditing(node)); +} + } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h index 2624238..8efb10f 100644 --- a/WebCore/dom/Position.h +++ b/WebCore/dom/Position.h @@ -40,7 +40,11 @@ class Node; class Range; class RenderObject; -enum EUsingComposedCharacters { NotUsingComposedCharacters = false, UsingComposedCharacters = true }; +enum PositionMoveType { + CodePoint, // Move by a single code point. + Character, // Move to the next Unicode character break. + BackwardDeletion // Subject to platform conventions. +}; // FIXME: Reduce the number of operations we have on a Position. // This should be more like a humble struct, without so many different @@ -48,20 +52,36 @@ enum EUsingComposedCharacters { NotUsingComposedCharacters = false, UsingCompose class Position { public: - RefPtr<Node> container; - int posOffset; // to be renamed to offset when we get rid of offset() + Position() : m_offset(0) { } + + // This constructor should be private + Position(PassRefPtr<Node> anchorNode, int offset) + : m_anchorNode(anchorNode) + , m_offset(offset) + {} - Position() : posOffset(0) { } - Position(PassRefPtr<Node> c, int o) : container(c), posOffset(o) { } + void clear() { m_anchorNode.clear(); m_offset = 0; } - void clear() { container.clear(); posOffset = 0; } + Node* anchorNode() const { return m_anchorNode.get(); } - Node* node() const { return container.get(); } - int offset() const { return posOffset; } + // FIXME: Callers should be moved off of node(), node() is not always the container for this position. + // For nodes which editingIgnoresContent(node()) returns true, positions like [ignoredNode, 0] + // will be treated as before ignoredNode (thus node() is really after the position, not containing it). + Node* node() const { return m_anchorNode.get(); } Element* documentElement() const; - bool isNull() const { return !container; } - bool isNotNull() const { return container; } + void moveToPosition(PassRefPtr<Node> node, int offset) + { + m_anchorNode = node; + m_offset = offset; + } + void moveToOffset(int offset) + { + m_offset = offset; + } + + bool isNull() const { return !m_anchorNode; } + bool isNotNull() const { return m_anchorNode; } Element* element() const; PassRefPtr<CSSComputedStyleDeclaration> computedStyle() const; @@ -69,13 +89,19 @@ public: // Move up or down the DOM by one position. // Offsets are computed using render text for nodes that have renderers - but note that even when // using composed characters, the result may be inside a single user-visible character if a ligature is formed. - Position previous(EUsingComposedCharacters usingComposedCharacters=NotUsingComposedCharacters) const; - Position next(EUsingComposedCharacters usingComposedCharacters=NotUsingComposedCharacters) const; + Position previous(PositionMoveType = CodePoint) const; + Position next(PositionMoveType = CodePoint) const; static int uncheckedPreviousOffset(const Node*, int current); + static int uncheckedPreviousOffsetForBackwardDeletion(const Node*, int current); static int uncheckedNextOffset(const Node*, int current); - bool atStart() const; - bool atEnd() const; + // These can be either inside or just before/after the node, depending on + // if the node is ignored by editing or not. + bool atFirstEditingPositionForNode() const; + bool atLastEditingPositionForNode() const; + + bool atStartOfTree() const; + bool atEndOfTree() const; // FIXME: Make these non-member functions and put them somewhere in the editing directory. // These aren't really basic "position" operations. More high level editing helper functions. @@ -109,11 +135,20 @@ private: Position previousCharacterPosition(EAffinity) const; Position nextCharacterPosition(EAffinity) const; + + RefPtr<Node> m_anchorNode; +public: + // m_offset can be the offset inside m_anchorNode, or if editingIgnoresContent(m_anchorNode) + // returns true, then other places in editing will treat m_offset == 0 as "before the anchor" + // and m_offset > 0 as "after the anchor node". See rangeCompliantEquivalent for more info. + int m_offset; // FIXME: This should be made private. }; inline bool operator==(const Position& a, const Position& b) { - return a.container == b.container && a.posOffset == b.posOffset; + // FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the + // editing code will treat them as identical. + return a.anchorNode() == b.anchorNode() && a.m_offset == b.m_offset; } inline bool operator!=(const Position& a, const Position& b) @@ -124,6 +159,12 @@ inline bool operator!=(const Position& a, const Position& b) Position startPosition(const Range*); Position endPosition(const Range*); +// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0]) +// for elements which editing "ignores". the rest of the editing code will treat [img, 0] +// as "the last position before the img" +Position firstDeepEditingPositionForNode(Node*); +Position lastDeepEditingPositionForNode(Node*); + } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/dom/PositionIterator.cpp b/WebCore/dom/PositionIterator.cpp index 06e1e32..781d352 100644 --- a/WebCore/dom/PositionIterator.cpp +++ b/WebCore/dom/PositionIterator.cpp @@ -36,7 +36,13 @@ using namespace HTMLNames; PositionIterator::operator Position() const { - return Position(m_parent, m_child ? m_child->nodeIndex() : (m_parent->hasChildNodes() ? maxDeepOffset(m_parent) : m_offset)); + if (m_child) { + ASSERT(m_child->parentNode() == m_parent); + return positionBeforeNode(m_child); + } + if (m_parent->hasChildNodes()) + return lastDeepEditingPositionForNode(m_parent); + return Position(m_parent, m_offset); } void PositionIterator::increment() @@ -51,7 +57,7 @@ void PositionIterator::increment() return; } - if (!m_parent->hasChildNodes() && m_offset < maxDeepOffset(m_parent)) + if (!m_parent->hasChildNodes() && m_offset < lastOffsetForEditing(m_parent)) m_offset = Position::uncheckedNextOffset(m_parent, m_offset); else { m_child = m_parent; @@ -70,7 +76,7 @@ void PositionIterator::decrement() m_parent = m_child->previousSibling(); if (m_parent) { m_child = 0; - m_offset = m_parent->hasChildNodes() ? 0 : maxDeepOffset(m_parent); + m_offset = m_parent->hasChildNodes() ? 0 : lastOffsetForEditing(m_parent); } else { m_child = m_child->parentNode(); m_parent = m_child->parentNode(); @@ -85,7 +91,7 @@ void PositionIterator::decrement() if (m_parent->hasChildNodes()) { m_parent = m_parent->lastChild(); if (!m_parent->hasChildNodes()) - m_offset = maxDeepOffset(m_parent); + m_offset = lastOffsetForEditing(m_parent); } else { m_child = m_parent; m_parent = m_parent->parentNode(); @@ -99,7 +105,7 @@ bool PositionIterator::atStart() const return true; if (m_parent->parentNode()) return false; - return !m_parent->hasChildNodes() && !m_offset || m_child && !m_child->previousSibling(); + return (!m_parent->hasChildNodes() && !m_offset) || (m_child && !m_child->previousSibling()); } bool PositionIterator::atEnd() const @@ -108,7 +114,7 @@ bool PositionIterator::atEnd() const return true; if (m_child) return false; - return !m_parent->parentNode() && (m_parent->hasChildNodes() || m_offset >= maxDeepOffset(m_parent)); + return !m_parent->parentNode() && (m_parent->hasChildNodes() || m_offset >= lastOffsetForEditing(m_parent)); } bool PositionIterator::atStartOfNode() const @@ -126,7 +132,7 @@ bool PositionIterator::atEndOfNode() const return true; if (m_child) return false; - return m_parent->hasChildNodes() || m_offset >= maxDeepOffset(m_parent); + return m_parent->hasChildNodes() || m_offset >= lastOffsetForEditing(m_parent); } bool PositionIterator::isCandidate() const @@ -151,7 +157,7 @@ bool PositionIterator::isCandidate() const return (atStartOfNode() || atEndOfNode()) && !Position::nodeIsUserSelectNone(m_parent->parent()); if (!m_parent->hasTagName(htmlTag) && renderer->isBlockFlow() && !Position::hasRenderedNonAnonymousDescendantsWithHeight(renderer) && - (static_cast<RenderBlock*>(renderer)->height() || m_parent->hasTagName(bodyTag))) + (toRenderBlock(renderer)->height() || m_parent->hasTagName(bodyTag))) return atStartOfNode() && !Position::nodeIsUserSelectNone(m_parent); return false; diff --git a/WebCore/dom/PositionIterator.h b/WebCore/dom/PositionIterator.h index 54f5020..98a2ccb 100644 --- a/WebCore/dom/PositionIterator.h +++ b/WebCore/dom/PositionIterator.h @@ -45,8 +45,8 @@ public: PositionIterator(const Position& pos) : m_parent(pos.node()) - , m_child(m_parent->childNode(pos.offset())) - , m_offset(m_child ? 0 : pos.offset()) + , m_child(m_parent->childNode(pos.m_offset)) + , m_offset(m_child ? 0 : pos.m_offset) { } operator Position() const; diff --git a/WebCore/dom/QualifiedName.cpp b/WebCore/dom/QualifiedName.cpp index f40f398..5953b97 100644 --- a/WebCore/dom/QualifiedName.cpp +++ b/WebCore/dom/QualifiedName.cpp @@ -1,7 +1,5 @@ -/** - * This file is part of the DOM implementation for KDE. - * - * Copyright (C) 2005, 2006 Apple Computer, Inc. +/* + * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -54,7 +52,6 @@ struct QNameComponentsTranslator { static QNameSet* gNameCache; QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n) - : m_impl(0) { if (!gNameCache) gNameCache = new QNameSet; @@ -65,28 +62,6 @@ QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const m_impl->ref(); } -QualifiedName::~QualifiedName() -{ - deref(); -} - -QualifiedName::QualifiedName(const QualifiedName& other) -{ - m_impl = other.m_impl; - ref(); -} - -const QualifiedName& QualifiedName::operator=(const QualifiedName& other) -{ - if (m_impl != other.m_impl) { - deref(); - m_impl = other.m_impl; - ref(); - } - - return *this; -} - void QualifiedName::deref() { #ifdef QNAME_DEFAULT_CONSTRUCTOR @@ -99,12 +74,6 @@ void QualifiedName::deref() m_impl->deref(); } -void QualifiedName::setPrefix(const AtomicString& prefix) -{ - QualifiedName other(prefix, localName(), namespaceURI()); - *this = other; -} - String QualifiedName::toString() const { String local = localName(); diff --git a/WebCore/dom/QualifiedName.h b/WebCore/dom/QualifiedName.h index d09cdea..13747a9 100644 --- a/WebCore/dom/QualifiedName.h +++ b/WebCore/dom/QualifiedName.h @@ -1,7 +1,5 @@ /* - * This file is part of the DOM implementation for KDE. - * - * Copyright (C) 2005 Apple Computer, Inc. + * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -19,6 +17,7 @@ * Boston, MA 02110-1301, USA. * */ + #ifndef QualifiedName_h #define QualifiedName_h @@ -26,7 +25,7 @@ #include <wtf/HashFunctions.h> namespace WebCore { - + struct QualifiedNameComponents { StringImpl* m_prefix; StringImpl* m_localName; @@ -37,32 +36,32 @@ class QualifiedName { public: class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> { public: - static PassRefPtr<QualifiedNameImpl> create(const AtomicString& p, const AtomicString& l, const AtomicString& n) + static PassRefPtr<QualifiedNameImpl> create(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI) { - return adoptRef(new QualifiedNameImpl(p, l, n)); + return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI)); } - + AtomicString m_prefix; AtomicString m_localName; AtomicString m_namespace; private: - QualifiedNameImpl(const AtomicString& p, const AtomicString& l, const AtomicString& n) - : m_prefix(p) - , m_localName(l) - , m_namespace(n) + QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI) + : m_prefix(prefix) + , m_localName(localName) + , m_namespace(namespaceURI.isEmpty() ? nullAtom : namespaceURI) { } }; QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); - ~QualifiedName(); + ~QualifiedName() { deref(); } #ifdef QNAME_DEFAULT_CONSTRUCTOR QualifiedName() : m_impl(0) { } #endif - QualifiedName(const QualifiedName&); - const QualifiedName& operator=(const QualifiedName&); + QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { ref(); } + const QualifiedName& operator=(const QualifiedName& other) { other.ref(); deref(); m_impl = other.m_impl; return *this; } bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; } bool operator!=(const QualifiedName& other) const { return !(*this == other); } @@ -70,7 +69,7 @@ public: bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); } bool hasPrefix() const { return m_impl->m_prefix != nullAtom; } - void setPrefix(const AtomicString& prefix); + void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); } const AtomicString& prefix() const { return m_impl->m_prefix; } const AtomicString& localName() const { return m_impl->m_localName; } @@ -84,7 +83,7 @@ public: static void init(); private: - void ref() { m_impl->ref(); } + void ref() const { m_impl->ref(); } void deref(); QualifiedNameImpl* m_impl; @@ -100,7 +99,6 @@ inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); } inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); } - inline unsigned hashComponents(const QualifiedNameComponents& buf) { ASSERT(sizeof(QualifiedNameComponents) % (sizeof(uint16_t) * 2) == 0); @@ -154,6 +152,7 @@ struct QualifiedNameHash { namespace WTF { template<typename T> struct DefaultHash; + template<> struct DefaultHash<WebCore::QualifiedName> { typedef WebCore::QualifiedNameHash Hash; }; diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp index b5afdd1..34b1d21 100644 --- a/WebCore/dom/Range.cpp +++ b/WebCore/dom/Range.cpp @@ -89,7 +89,7 @@ PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<N PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, const Position& start, const Position& end) { - return adoptRef(new Range(ownerDocument, start.container.get(), start.posOffset, end.container.get(), end.posOffset)); + return adoptRef(new Range(ownerDocument, start.node(), start.m_offset, end.node(), end.m_offset)); } Range::~Range() @@ -264,17 +264,17 @@ void Range::collapse(bool toStart, ExceptionCode& ec) bool Range::isPointInRange(Node* refNode, int offset, ExceptionCode& ec) { - if (!refNode) { - ec = NOT_FOUND_ERR; + if (!m_start.container()) { + ec = INVALID_STATE_ERR; return false; } - if (!m_start.container() && refNode->attached()) { - ec = INVALID_STATE_ERR; + if (!refNode) { + ec = HIERARCHY_REQUEST_ERR; return false; } - if (m_start.container() && !refNode->attached()) { + if (!refNode->attached()) { // Firefox doesn't throw an exception for this case; it returns false. return false; } @@ -299,22 +299,17 @@ short Range::comparePoint(Node* refNode, int offset, ExceptionCode& ec) // This method returns -1, 0 or 1 depending on if the point described by the // refNode node and an offset within the node is before, same as, or after the range respectively. - if (!refNode) { - ec = NOT_FOUND_ERR; - return 0; - } - - if (!m_start.container() && refNode->attached()) { + if (!m_start.container()) { ec = INVALID_STATE_ERR; return 0; } - if (m_start.container() && !refNode->attached()) { - // Firefox doesn't throw an exception for this case; it returns -1. - return -1; + if (!refNode) { + ec = HIERARCHY_REQUEST_ERR; + return 0; } - if (refNode->document() != m_ownerDocument) { + if (!refNode->attached() || refNode->document() != m_ownerDocument) { ec = WRONG_DOCUMENT_ERR; return 0; } @@ -441,11 +436,14 @@ short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB) { - ASSERT(containerA && containerB); + ASSERT(containerA); + ASSERT(containerB); + if (!containerA) return -1; if (!containerB) return 1; + // see DOM2 traversal & range section 2.5 // case 1: both points have the same container @@ -529,7 +527,7 @@ short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containe short Range::compareBoundaryPoints(const Position& a, const Position& b) { - return compareBoundaryPoints(a.container.get(), a.posOffset, b.container.get(), b.posOffset); + return compareBoundaryPoints(a.node(), a.m_offset, b.node(), b.m_offset); } bool Range::boundaryPointsValid() const @@ -556,8 +554,8 @@ bool Range::intersectsNode(Node* refNode, ExceptionCode& ec) return false; } - if (!m_start.container() && refNode->attached() - || m_start.container() && !refNode->attached() + if ((!m_start.container() && refNode->attached()) + || (m_start.container() && !refNode->attached()) || refNode->document() != m_ownerDocument) { // Firefox doesn't throw an exception for these cases; it returns false. return false; @@ -842,6 +840,17 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception processEnd = processEnd->parentNode(); } + // Collapse the range, making sure that the result is not within a node that was partially selected. + if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { + if (partialStart) + setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, ec); + else if (partialEnd) + setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec); + if (ec) + return 0; + m_end = m_start; + } + // Now add leftContents, stuff in between, and rightContents to the fragment // (or just delete the stuff in between) @@ -1592,13 +1601,16 @@ void Range::addLineBoxRects(Vector<IntRect>& rects, bool useSelectionHeight) if (!start || !end) return; - RenderObject* stop = end->nextInPreOrderAfterChildren(); + RenderObject* stop = end->childAt(m_end.offset()); + if (!stop) + stop = end->nextInPreOrderAfterChildren(); + for (RenderObject* r = start; r && r != stop; r = r->nextInPreOrder()) { // only ask leaf render objects for their line box rects if (!r->firstChild()) { int startOffset = r == start ? m_start.offset() : 0; int endOffset = r == end ? m_end.offset() : INT_MAX; - r->addLineBoxRects(rects, startOffset, endOffset, useSelectionHeight); + r->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight); } } } diff --git a/WebCore/dom/RangeBoundaryPoint.h b/WebCore/dom/RangeBoundaryPoint.h index 4cb7bf5..e39454e 100644 --- a/WebCore/dom/RangeBoundaryPoint.h +++ b/WebCore/dom/RangeBoundaryPoint.h @@ -55,6 +55,10 @@ public: private: static const int invalidOffset = -1; + // FIXME: RangeBoundaryPoint is the only file to ever use -1 as am expected offset for Position + // RangeBoundaryPoint currently needs to store a Position object to make the + // position() function be able to return a const& (and thus avoid ref-churn). + mutable Position m_position; Node* m_childBefore; }; @@ -72,7 +76,7 @@ inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container) inline Node* RangeBoundaryPoint::container() const { - return m_position.container.get(); + return m_position.node(); } inline Node* RangeBoundaryPoint::childBefore() const @@ -82,16 +86,16 @@ inline Node* RangeBoundaryPoint::childBefore() const inline const Position& RangeBoundaryPoint::position() const { - if (m_position.posOffset >= 0) + if (m_position.m_offset >= 0) return m_position; ASSERT(m_childBefore); - m_position.posOffset = m_childBefore->nodeIndex() + 1; + m_position.m_offset = m_childBefore->nodeIndex() + 1; return m_position; } inline int RangeBoundaryPoint::offset() const { - return position().posOffset; + return position().m_offset; } inline void RangeBoundaryPoint::clear() @@ -104,63 +108,59 @@ inline void RangeBoundaryPoint::set(PassRefPtr<Node> container, int offset, Node { ASSERT(offset >= 0); ASSERT(childBefore == (offset ? container->childNode(offset - 1) : 0)); - m_position.container = container; - m_position.posOffset = offset; + m_position.moveToPosition(container, offset); m_childBefore = childBefore; } inline void RangeBoundaryPoint::setOffset(int offset) { - ASSERT(m_position.container); - ASSERT(m_position.container->offsetInCharacters()); - ASSERT(m_position.posOffset >= 0); + ASSERT(m_position.node()); + ASSERT(m_position.node()->offsetInCharacters()); + ASSERT(m_position.m_offset >= 0); ASSERT(!m_childBefore); - m_position.posOffset = offset; + m_position.moveToOffset(offset); } inline void RangeBoundaryPoint::setToChild(Node* child) { ASSERT(child); ASSERT(child->parentNode()); - m_position.container = child->parentNode(); m_childBefore = child->previousSibling(); - m_position.posOffset = m_childBefore ? invalidOffset : 0; + m_position.moveToPosition(child->parentNode(), m_childBefore ? invalidOffset : 0); } inline void RangeBoundaryPoint::setToStart(PassRefPtr<Node> container) { ASSERT(container); - m_position.container = container; - m_position.posOffset = 0; + m_position.moveToPosition(container, 0); m_childBefore = 0; } inline void RangeBoundaryPoint::setToEnd(PassRefPtr<Node> container) { ASSERT(container); - m_position.container = container; - if (m_position.container->offsetInCharacters()) { - m_position.posOffset = m_position.container->maxCharacterOffset(); + if (container->offsetInCharacters()) { + m_position.moveToPosition(container, container->maxCharacterOffset()); m_childBefore = 0; } else { - m_childBefore = m_position.container->lastChild(); - m_position.posOffset = m_childBefore ? invalidOffset : 0; + m_childBefore = container->lastChild(); + m_position.moveToPosition(container, m_childBefore ? invalidOffset : 0); } } inline void RangeBoundaryPoint::childBeforeWillBeRemoved() { - ASSERT(m_position.posOffset); + ASSERT(m_position.m_offset); m_childBefore = m_childBefore->previousSibling(); if (!m_childBefore) - m_position.posOffset = 0; - else if (m_position.posOffset > 0) - --m_position.posOffset; + m_position.m_offset = 0; + else if (m_position.m_offset > 0) + --m_position.m_offset; } inline void RangeBoundaryPoint::invalidateOffset() const { - m_position.posOffset = invalidOffset; + m_position.m_offset = invalidOffset; } inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b) diff --git a/WebCore/dom/ScriptExecutionContext.cpp b/WebCore/dom/ScriptExecutionContext.cpp index 1d1aaec..c518734 100644 --- a/WebCore/dom/ScriptExecutionContext.cpp +++ b/WebCore/dom/ScriptExecutionContext.cpp @@ -175,6 +175,22 @@ void ScriptExecutionContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securi m_securityOrigin = securityOrigin; } +void ScriptExecutionContext::addTimeout(int timeoutId, DOMTimer* timer) +{ + ASSERT(!m_timeouts.contains(timeoutId)); + m_timeouts.set(timeoutId, timer); +} + +void ScriptExecutionContext::removeTimeout(int timeoutId) +{ + m_timeouts.remove(timeoutId); +} + +DOMTimer* ScriptExecutionContext::findTimeout(int timeoutId) +{ + return m_timeouts.get(timeoutId); +} + ScriptExecutionContext::Task::~Task() { } diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h index 6f09e1a..7b2f36a 100644 --- a/WebCore/dom/ScriptExecutionContext.h +++ b/WebCore/dom/ScriptExecutionContext.h @@ -37,6 +37,7 @@ namespace WebCore { class ActiveDOMObject; + class DOMTimer; class MessagePort; class SecurityOrigin; class ScriptString; @@ -58,12 +59,15 @@ namespace WebCore { const KURL& url() const { return virtualURL(); } KURL completeURL(const String& url) const { return virtualCompleteURL(url); } + virtual String userAgent(const KURL&) const = 0; + SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); } virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL) = 0; virtual void addMessage(MessageDestination, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL) = 0; virtual void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) = 0; - + virtual void scriptImported(unsigned long, const String&) = 0; + // Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked. bool canSuspendActiveDOMObjects(); // Active objects can be asked to suspend even if canSuspendActiveDOMObjects() returns 'false' - @@ -94,6 +98,10 @@ namespace WebCore { virtual void postTask(PassRefPtr<Task>) = 0; // Executes the task on context's thread asynchronously. + void addTimeout(int timeoutId, DOMTimer*); + void removeTimeout(int timeoutId); + DOMTimer* findTimeout(int timeoutId); + protected: // Explicitly override the security origin for this script context. // Note: It is dangerous to change the security origin of a script context @@ -110,6 +118,8 @@ namespace WebCore { HashMap<ActiveDOMObject*, void*> m_activeDOMObjects; + HashMap<int, DOMTimer*> m_timeouts; + virtual void refScriptExecutionContext() = 0; virtual void derefScriptExecutionContext() = 0; }; diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp index 6277ff6..5cb1af5 100644 --- a/WebCore/dom/Text.cpp +++ b/WebCore/dom/Text.cpp @@ -29,6 +29,7 @@ #if ENABLE(SVG) #include "RenderSVGInlineText.h" +#include "SVGNames.h" #endif #if ENABLE(WML) @@ -233,7 +234,11 @@ bool Text::rendererIsNeeded(RenderStyle *style) RenderObject *Text::createRenderer(RenderArena* arena, RenderStyle*) { #if ENABLE(SVG) - if (parentNode()->isSVGElement()) + if (parentNode()->isSVGElement() +#if ENABLE(SVG_FOREIGN_OBJECT) + && !parentNode()->hasTagName(SVGNames::foreignObjectTag) +#endif + ) return new (arena) RenderSVGInlineText(this, m_data); #endif diff --git a/WebCore/dom/Tokenizer.h b/WebCore/dom/Tokenizer.h index 1ed9484..f9c6dc4 100644 --- a/WebCore/dom/Tokenizer.h +++ b/WebCore/dom/Tokenizer.h @@ -37,7 +37,7 @@ namespace WebCore { // received during executing a script must be appended, hence the // extra bool to be able to distinguish between both cases. // document.write() always uses false, while the loader uses true. - virtual bool write(const SegmentedString&, bool appendData) = 0; + virtual void write(const SegmentedString&, bool appendData) = 0; virtual void finish() = 0; virtual bool isWaitingForScripts() const = 0; virtual void stopParsing() { m_parserStopped = true; } diff --git a/WebCore/dom/WheelEvent.cpp b/WebCore/dom/WheelEvent.cpp index a3c806e..2039541 100644 --- a/WebCore/dom/WheelEvent.cpp +++ b/WebCore/dom/WheelEvent.cpp @@ -34,20 +34,15 @@ WheelEvent::WheelEvent() { } -WheelEvent::WheelEvent(float wheelDeltaX, float wheelDeltaY, PassRefPtr<AbstractView> view, +WheelEvent::WheelEvent(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView> view, int screenX, int screenY, int pageX, int pageY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey) : MouseRelatedEvent(eventNames().mousewheelEvent, true, true, view, 0, screenX, screenY, pageX, pageY, ctrlKey, altKey, shiftKey, metaKey) - , m_wheelDeltaX(lroundf(wheelDeltaX) * 120) - , m_wheelDeltaY(lroundf(wheelDeltaY) * 120) // Normalize to the Windows 120 multiple + , m_wheelDeltaX(lroundf(wheelTicksX * 120)) + , m_wheelDeltaY(lroundf(wheelTicksY * 120)) // Normalize to the Windows 120 multiple { - // Rounding delta to zero makes no sense and breaks Google Maps, <http://bugs.webkit.org/show_bug.cgi?id=16078>. - if (wheelDeltaX && !m_wheelDeltaX) - m_wheelDeltaX = (wheelDeltaX > 0) ? 120 : -120; - if (wheelDeltaY && !m_wheelDeltaY) - m_wheelDeltaY = (wheelDeltaY > 0) ? 120 : -120; } void WheelEvent::initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<AbstractView> view, diff --git a/WebCore/dom/WheelEvent.h b/WebCore/dom/WheelEvent.h index 015796e..04d5421 100644 --- a/WebCore/dom/WheelEvent.h +++ b/WebCore/dom/WheelEvent.h @@ -35,11 +35,11 @@ namespace WebCore { { return adoptRef(new WheelEvent); } - static PassRefPtr<WheelEvent> create(float wheelDeltaX, float wheelDeltaY, PassRefPtr<AbstractView> view, + static PassRefPtr<WheelEvent> create(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView> view, int screenX, int screenY, int pageX, int pageY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey) { - return adoptRef(new WheelEvent(wheelDeltaX, wheelDeltaY, view, screenX, screenY, pageX, pageY, + return adoptRef(new WheelEvent(wheelTicksX, wheelTicksY, view, screenX, screenY, pageX, pageY, ctrlKey, altKey, shiftKey, metaKey)); } @@ -56,7 +56,7 @@ namespace WebCore { private: WheelEvent(); - WheelEvent(float wheelDeltaX, float wheelDeltaY, PassRefPtr<AbstractView>, + WheelEvent(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView>, int screenX, int screenY, int pageX, int pageY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey); diff --git a/WebCore/dom/Worker.cpp b/WebCore/dom/Worker.cpp deleted file mode 100644 index 6889a42..0000000 --- a/WebCore/dom/Worker.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "Worker.h" - -#include "CachedScript.h" -#include "DOMWindow.h" -#include "DocLoader.h" -#include "Document.h" -#include "EventException.h" -#include "EventListener.h" -#include "EventNames.h" -#include "ExceptionCode.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "MessageEvent.h" -#include "SecurityOrigin.h" -#include "WorkerContext.h" -#include "WorkerMessagingProxy.h" -#include "WorkerTask.h" -#include "WorkerThread.h" -#include <wtf/MainThread.h> - -namespace WebCore { - -Worker::Worker(const String& url, Document* doc, ExceptionCode& ec) - : ActiveDOMObject(doc, this) - , m_messagingProxy(new WorkerMessagingProxy(doc, this)) -{ - m_scriptURL = doc->completeURL(url); - if (url.isEmpty() || !m_scriptURL.isValid()) { - ec = SYNTAX_ERR; - return; - } - - if (!doc->securityOrigin()->canAccess(SecurityOrigin::create(m_scriptURL).get())) { - ec = SECURITY_ERR; - return; - } - - m_cachedScript = doc->docLoader()->requestScript(m_scriptURL, document()->charset()); - if (!m_cachedScript) { - dispatchErrorEvent(); - return; - } - - setPendingActivity(this); // The worker context does not exist while loading, so we much ensure that the worker object is not collected, as well as its event listeners. - m_cachedScript->addClient(this); -} - -Worker::~Worker() -{ - ASSERT(isMainThread()); - ASSERT(scriptExecutionContext()); // The context is protected by messaging proxy, so it cannot be destroyed while a Worker exists. - m_messagingProxy->workerObjectDestroyed(); -} - -Document* Worker::document() const -{ - ASSERT(scriptExecutionContext()->isDocument()); - return static_cast<Document*>(scriptExecutionContext()); -} - -void Worker::postMessage(const String& message) -{ - m_messagingProxy->postMessageToWorkerContext(message); -} - -void Worker::terminate() -{ - m_messagingProxy->terminate(); -} - -bool Worker::canSuspend() const -{ - // FIXME: It is not currently possible to suspend a worker, so pages with workers can not go into page cache. - return false; -} - -void Worker::stop() -{ - terminate(); -} - -bool Worker::hasPendingActivity() const -{ - return m_messagingProxy->workerThreadHasPendingActivity() || ActiveDOMObject::hasPendingActivity(); -} - -void Worker::notifyFinished(CachedResource* unusedResource) -{ - ASSERT_UNUSED(unusedResource, unusedResource == m_cachedScript); - - if (m_cachedScript->errorOccurred()) - dispatchErrorEvent(); - else { - String userAgent = document()->frame() ? document()->frame()->loader()->userAgent(m_scriptURL) : String(); - RefPtr<WorkerThread> thread = WorkerThread::create(m_scriptURL, userAgent, m_cachedScript->script(), m_messagingProxy); - m_messagingProxy->workerThreadCreated(thread); - thread->start(); - } - - m_cachedScript->removeClient(this); - m_cachedScript = 0; - - unsetPendingActivity(this); -} - -void Worker::dispatchErrorEvent() -{ - RefPtr<Event> evt = Event::create(eventNames().errorEvent, false, true); - if (m_onErrorListener) { - evt->setTarget(this); - evt->setCurrentTarget(this); - m_onErrorListener->handleEvent(evt.get(), true); - } - - ExceptionCode ec = 0; - dispatchEvent(evt.release(), ec); - ASSERT(!ec); -} - -void Worker::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool) -{ - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) { - ListenerVector listeners; - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } else { - ListenerVector& listeners = iter->second; - for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) - return; - } - - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } -} - -void Worker::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool) -{ - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) - return; - - ListenerVector& listeners = iter->second; - for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) { - listeners.remove(listenerIter - listeners.begin()); - return; - } - } -} - -bool Worker::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) -{ - if (!event || event->type().isEmpty()) { - ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; - return true; - } - - ListenerVector listenersCopy = m_eventListeners.get(event->type()); - for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) { - event->setTarget(this); - event->setCurrentTarget(this); - listenerIter->get()->handleEvent(event.get(), false); - } - - return !event->defaultPrevented(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/Worker.h b/WebCore/dom/Worker.h deleted file mode 100644 index 6a47bac..0000000 --- a/WebCore/dom/Worker.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef Worker_h -#define Worker_h - -#if ENABLE(WORKERS) - -#include "AtomicStringHash.h" -#include "ActiveDOMObject.h" -#include "CachedResourceClient.h" -#include "CachedResourceHandle.h" -#include "EventListener.h" -#include "EventTarget.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - - class CachedResource; - class CachedScript; - class Document; - class ScriptExecutionContext; - class String; - class WorkerMessagingProxy; - class WorkerTask; - - typedef int ExceptionCode; - - class Worker : public RefCounted<Worker>, public ActiveDOMObject, private CachedResourceClient, public EventTarget { - public: - static PassRefPtr<Worker> create(const String& url, Document* document, ExceptionCode& ec) { return adoptRef(new Worker(url, document, ec)); } - ~Worker(); - - virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); } - Document* document() const; - - virtual Worker* toWorker() { return this; } - - void postMessage(const String& message); - - void terminate(); - - virtual bool canSuspend() const; - virtual void stop(); - virtual bool hasPendingActivity() const; - - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); - - typedef Vector<RefPtr<EventListener> > ListenerVector; - typedef HashMap<AtomicString, ListenerVector> EventListenersMap; - EventListenersMap& eventListeners() { return m_eventListeners; } - - using RefCounted<Worker>::ref; - using RefCounted<Worker>::deref; - - void setOnmessage(PassRefPtr<EventListener> eventListener) { m_onMessageListener = eventListener; } - EventListener* onmessage() const { return m_onMessageListener.get(); } - - void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; } - EventListener* onerror() const { return m_onErrorListener.get(); } - - private: - Worker(const String&, Document*, ExceptionCode&); - - virtual void notifyFinished(CachedResource*); - - void dispatchErrorEvent(); - - virtual void refEventTarget() { ref(); } - virtual void derefEventTarget() { deref(); } - - KURL m_scriptURL; - CachedResourceHandle<CachedScript> m_cachedScript; - - WorkerMessagingProxy* m_messagingProxy; // The proxy outlives the worker to perform thread shutdown. - - RefPtr<EventListener> m_onMessageListener; - RefPtr<EventListener> m_onErrorListener; - EventListenersMap m_eventListeners; - }; - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // Worker_h diff --git a/WebCore/dom/WorkerContext.cpp b/WebCore/dom/WorkerContext.cpp deleted file mode 100644 index fe4643e..0000000 --- a/WebCore/dom/WorkerContext.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "WorkerContext.h" - -#include "ActiveDOMObject.h" -#include "DOMWindow.h" -#include "Event.h" -#include "EventException.h" -#include "GenericWorkerTask.h" -#include "NotImplemented.h" -#include "SecurityOrigin.h" -#include "WorkerLocation.h" -#include "WorkerMessagingProxy.h" -#include "WorkerNavigator.h" -#include "WorkerTask.h" -#include "WorkerThread.h" -#include <wtf/RefPtr.h> - -namespace WebCore { - -WorkerContext::WorkerContext(const KURL& url, const String& userAgent, WorkerThread* thread) - : m_url(url) - , m_userAgent(userAgent) - , m_location(WorkerLocation::create(url)) - , m_script(new WorkerScriptController(this)) - , m_thread(thread) -{ - setSecurityOrigin(SecurityOrigin::create(url)); -} - -WorkerContext::~WorkerContext() -{ - ASSERT(currentThread() == m_thread->threadID()); - - m_thread->messagingProxy()->workerContextDestroyed(); -} - -ScriptExecutionContext* WorkerContext::scriptExecutionContext() const -{ - return const_cast<WorkerContext*>(this); -} - -const KURL& WorkerContext::virtualURL() const -{ - return m_url; -} - -KURL WorkerContext::virtualCompleteURL(const String& url) const -{ - return completeURL(url); -} - -KURL WorkerContext::completeURL(const String& url) const -{ - // Always return a null URL when passed a null string. - // FIXME: Should we change the KURL constructor to have this behavior? - if (url.isNull()) - return KURL(); - // FIXME: does this need to provide a charset, like Document::completeURL does? - return KURL(m_location->url(), url); -} - -WorkerNavigator* WorkerContext::navigator() const -{ - if (!m_navigator) - m_navigator = WorkerNavigator::create(m_userAgent); - return m_navigator.get(); -} - -bool WorkerContext::hasPendingActivity() const -{ - ActiveDOMObjectsMap& activeObjects = activeDOMObjects(); - ActiveDOMObjectsMap::const_iterator activeObjectsEnd = activeObjects.end(); - for (ActiveDOMObjectsMap::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) { - if (iter->first->hasPendingActivity()) - return true; - } - return false; -} - -void WorkerContext::reportException(const String& errorMessage, int lineNumber, const String& sourceURL) -{ - m_thread->messagingProxy()->postWorkerException(errorMessage, lineNumber, sourceURL); -} - -static void addMessageTask(ScriptExecutionContext* context, MessageDestination destination, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) -{ - context->addMessage(destination, source, level, message, lineNumber, sourceURL); -} - -void WorkerContext::addMessage(MessageDestination destination, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) -{ - // createCallbackTask has to be a separate statement from postTaskToParentContext to make the destructor - // for message.copy() get called before postTaskToParentContext. (If they are one statement, the destructor - // gets called after postTaskToParentContext which causes a race condition.) - RefPtr<Task> task = createCallbackTask(m_thread->messagingProxy(), &addMessageTask, destination, source, level, message.copy(), lineNumber, sourceURL.copy()); - postTaskToParentContext(task.release()); -} - -void WorkerContext::resourceRetrievedByXMLHttpRequest(unsigned long, const ScriptString&) -{ - // FIXME: The implementation is pending the fixes in https://bugs.webkit.org/show_bug.cgi?id=23175 - notImplemented(); -} - -void WorkerContext::postMessage(const String& message) -{ - m_thread->messagingProxy()->postMessageToWorkerObject(message); -} - -void WorkerContext::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool) -{ - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) { - ListenerVector listeners; - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } else { - ListenerVector& listeners = iter->second; - for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) - return; - } - - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } -} - -void WorkerContext::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool) -{ - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) - return; - - ListenerVector& listeners = iter->second; - for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) { - listeners.remove(listenerIter - listeners.begin()); - return; - } - } -} - -bool WorkerContext::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) -{ - if (!event || event->type().isEmpty()) { - ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; - return true; - } - - ListenerVector listenersCopy = m_eventListeners.get(event->type()); - for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) { - event->setTarget(this); - event->setCurrentTarget(this); - listenerIter->get()->handleEvent(event.get(), false); - } - - return !event->defaultPrevented(); -} - -class ScriptExecutionContextTaskWorkerTask : public WorkerTask { -public: - static PassRefPtr<ScriptExecutionContextTaskWorkerTask> create(PassRefPtr<ScriptExecutionContext::Task> task) - { - return adoptRef(new ScriptExecutionContextTaskWorkerTask(task)); - } - -private: - ScriptExecutionContextTaskWorkerTask(PassRefPtr<ScriptExecutionContext::Task> task) - : m_task(task) - { - } - - virtual void performTask(WorkerContext* context) - { - m_task->performTask(context); - } - - RefPtr<ScriptExecutionContext::Task> m_task; -}; - -void WorkerContext::postTask(PassRefPtr<Task> task) -{ - thread()->runLoop().postTask(ScriptExecutionContextTaskWorkerTask::create(task)); -} - -void WorkerContext::postTaskToParentContext(PassRefPtr<Task> task) -{ - thread()->messagingProxy()->postTaskToParentContext(task); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/WorkerContext.h b/WebCore/dom/WorkerContext.h deleted file mode 100644 index 2e443d9..0000000 --- a/WebCore/dom/WorkerContext.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef WorkerContext_h -#define WorkerContext_h - -#if ENABLE(WORKERS) - -#include "AtomicStringHash.h" -#include "EventListener.h" -#include "EventTarget.h" -#include "ScriptExecutionContext.h" -#include "WorkerScriptController.h" -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - - class WorkerLocation; - class WorkerNavigator; - class WorkerThread; - - class WorkerContext : public RefCounted<WorkerContext>, public ScriptExecutionContext, public EventTarget { - public: - static PassRefPtr<WorkerContext> create(const KURL& url, const String& userAgent, WorkerThread* thread) - { - return adoptRef(new WorkerContext(url, userAgent, thread)); - } - - virtual ~WorkerContext(); - - virtual bool isWorkerContext() const { return true; } - - virtual ScriptExecutionContext* scriptExecutionContext() const; - - const KURL& url() const { return m_url; } - KURL completeURL(const String&) const; - - WorkerLocation* location() const { return m_location.get(); } - WorkerNavigator* navigator() const; - - WorkerScriptController* script() { return m_script.get(); } - void clearScript() { return m_script.clear(); } - WorkerThread* thread() { return m_thread; } - - bool hasPendingActivity() const; - - virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL); - virtual void addMessage(MessageDestination, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); - virtual void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString); - - virtual WorkerContext* toWorkerContext() { return this; } - - void postMessage(const String& message); - virtual void postTask(PassRefPtr<Task>); // Executes the task on context's thread asynchronously. - void postTaskToParentContext(PassRefPtr<Task>); // Executes the task in the parent's context (and thread) asynchronously. - - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); - - void setOnmessage(PassRefPtr<EventListener> eventListener) { m_onmessageListener = eventListener; } - EventListener* onmessage() const { return m_onmessageListener.get(); } - - typedef Vector<RefPtr<EventListener> > ListenerVector; - typedef HashMap<AtomicString, ListenerVector> EventListenersMap; - EventListenersMap& eventListeners() { return m_eventListeners; } - - using RefCounted<WorkerContext>::ref; - using RefCounted<WorkerContext>::deref; - - private: - virtual void refScriptExecutionContext() { ref(); } - virtual void derefScriptExecutionContext() { deref(); } - virtual void refEventTarget() { ref(); } - virtual void derefEventTarget() { deref(); } - - WorkerContext(const KURL&, const String&, WorkerThread*); - - virtual const KURL& virtualURL() const; - virtual KURL virtualCompleteURL(const String&) const; - - KURL m_url; - String m_userAgent; - RefPtr<WorkerLocation> m_location; - mutable RefPtr<WorkerNavigator> m_navigator; - - OwnPtr<WorkerScriptController> m_script; - WorkerThread* m_thread; - - RefPtr<EventListener> m_onmessageListener; - EventListenersMap m_eventListeners; - }; - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // WorkerContext_h diff --git a/WebCore/dom/WorkerContext.idl b/WebCore/dom/WorkerContext.idl deleted file mode 100644 index 6e7223c..0000000 --- a/WebCore/dom/WorkerContext.idl +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -module threads { - - interface [ - Conditional=WORKERS, - CustomGetOwnPropertySlot, - CustomMarkFunction, - ExtendsDOMGlobalObject, - LegacyParent=JSWorkerContextBase, - NoStaticTables - ] WorkerContext { -#if defined(LANGUAGE_JAVASCRIPT) - attribute [Custom] WorkerContext self; -#endif - - attribute EventListener onmessage; - void postMessage(in DOMString message); - - attribute [Replaceable] WorkerLocation location; - attribute [Replaceable] WorkerNavigator navigator; - - attribute MessageEventConstructor MessageEvent; - attribute WorkerLocationConstructor WorkerLocation; - - // EventTarget interface - [Custom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [Custom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - boolean dispatchEvent(in Event evt) - raises(EventException); - }; - -} diff --git a/WebCore/dom/WorkerLocation.cpp b/WebCore/dom/WorkerLocation.cpp deleted file mode 100644 index 115a9ad..0000000 --- a/WebCore/dom/WorkerLocation.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "WorkerLocation.h" - -#include "PlatformString.h" - -namespace WebCore { - -String WorkerLocation::href() const -{ - return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/"; -} - -String WorkerLocation::protocol() const -{ - return m_url.protocol() + ":"; -} - -String WorkerLocation::host() const -{ - return m_url.port() ? m_url.host() + ":" + String::number((static_cast<int>(m_url.port()))) : m_url.host(); -} - -String WorkerLocation::hostname() const -{ - return m_url.host(); -} - -String WorkerLocation::port() const -{ - return m_url.port() ? String::number(static_cast<int>(m_url.port())) : ""; -} - -String WorkerLocation::pathname() const -{ - return m_url.path().isEmpty() ? "/" : m_url.path(); -} - -String WorkerLocation::search() const -{ - return m_url.query(); -} - -String WorkerLocation::hash() const -{ - return m_url.ref().isNull() ? "" : "#" + m_url.ref(); -} - -String WorkerLocation::toString() const -{ - return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/"; -} - - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/WorkerLocation.idl b/WebCore/dom/WorkerLocation.idl deleted file mode 100644 index 5551f18..0000000 --- a/WebCore/dom/WorkerLocation.idl +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -module threads { - - interface [ - Conditional=WORKERS, - GenerateConstructor, - NoStaticTables - ] WorkerLocation { - readonly attribute DOMString href; - readonly attribute DOMString protocol; - readonly attribute DOMString host; - readonly attribute DOMString hostname; - readonly attribute DOMString port; - readonly attribute DOMString pathname; - readonly attribute DOMString search; - readonly attribute DOMString hash; - - [DontEnum] DOMString toString(); - }; - -} diff --git a/WebCore/dom/WorkerMessagingProxy.cpp b/WebCore/dom/WorkerMessagingProxy.cpp deleted file mode 100644 index b0d145e..0000000 --- a/WebCore/dom/WorkerMessagingProxy.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "WorkerMessagingProxy.h" - -#include "DOMWindow.h" -#include "Document.h" -#include "MessageEvent.h" -#include "Worker.h" -#include "WorkerContext.h" -#include "WorkerTask.h" -#include "WorkerThread.h" - -namespace WebCore { - -class MessageWorkerContextTask : public WorkerTask { -public: - static PassRefPtr<MessageWorkerContextTask> create(const String& message) - { - return adoptRef(new MessageWorkerContextTask(message)); - } - -private: - MessageWorkerContextTask(const String& message) - : m_message(message.copy()) - { - } - - virtual void performTask(WorkerContext* context) - { - RefPtr<Event> evt = MessageEvent::create(m_message, "", "", 0, 0); - - if (context->onmessage()) { - evt->setTarget(context); - evt->setCurrentTarget(context); - context->onmessage()->handleEvent(evt.get(), false); - } - - ExceptionCode ec = 0; - context->dispatchEvent(evt.release(), ec); - ASSERT(!ec); - - context->thread()->messagingProxy()->confirmWorkerThreadMessage(context->hasPendingActivity()); - } - -private: - String m_message; -}; - -class MessageWorkerTask : public ScriptExecutionContext::Task { -public: - static PassRefPtr<MessageWorkerTask> create(const String& message, WorkerMessagingProxy* messagingProxy) - { - return adoptRef(new MessageWorkerTask(message, messagingProxy)); - } - -private: - MessageWorkerTask(const String& message, WorkerMessagingProxy* messagingProxy) - : m_message(message.copy()) - , m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext*) - { - Worker* workerObject = m_messagingProxy->workerObject(); - if (!workerObject || m_messagingProxy->askedToTerminate()) - return; - - RefPtr<Event> evt = MessageEvent::create(m_message, "", "", 0, 0); - - if (workerObject->onmessage()) { - evt->setTarget(workerObject); - evt->setCurrentTarget(workerObject); - workerObject->onmessage()->handleEvent(evt.get(), false); - } - - ExceptionCode ec = 0; - workerObject->dispatchEvent(evt.release(), ec); - ASSERT(!ec); - } - -private: - String m_message; - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerExceptionTask : public ScriptExecutionContext::Task { -public: - static PassRefPtr<WorkerExceptionTask> create(const String& errorMessage, int lineNumber, const String& sourceURL, WorkerMessagingProxy* messagingProxy) - { - return adoptRef(new WorkerExceptionTask(errorMessage, lineNumber, sourceURL, messagingProxy)); - } - -private: - WorkerExceptionTask(const String& errorMessage, int lineNumber, const String& sourceURL, WorkerMessagingProxy* messagingProxy) - : m_errorMessage(errorMessage.copy()) - , m_lineNumber(lineNumber) - , m_sourceURL(sourceURL.copy()) - , m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext* context) - { - if (!m_messagingProxy->askedToTerminate()) - context->reportException(m_errorMessage, m_lineNumber, m_sourceURL); - } - - String m_errorMessage; - int m_lineNumber; - String m_sourceURL; - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerContextDestroyedTask : public ScriptExecutionContext::Task { -public: - static PassRefPtr<WorkerContextDestroyedTask> create(WorkerMessagingProxy* messagingProxy) - { - return adoptRef(new WorkerContextDestroyedTask(messagingProxy)); - } - -private: - WorkerContextDestroyedTask(WorkerMessagingProxy* messagingProxy) - : m_messagingProxy(messagingProxy) - { - } - - virtual void performTask(ScriptExecutionContext*) - { - m_messagingProxy->workerContextDestroyedInternal(); - } - - WorkerMessagingProxy* m_messagingProxy; -}; - -class WorkerThreadActivityReportTask : public ScriptExecutionContext::Task { -public: - static PassRefPtr<WorkerThreadActivityReportTask> create(WorkerMessagingProxy* messagingProxy, bool confirmingMessage, bool hasPendingActivity) - { - return adoptRef(new WorkerThreadActivityReportTask(messagingProxy, confirmingMessage, hasPendingActivity)); - } - -private: - WorkerThreadActivityReportTask(WorkerMessagingProxy* messagingProxy, bool confirmingMessage, bool hasPendingActivity) - : m_messagingProxy(messagingProxy) - , m_confirmingMessage(confirmingMessage) - , m_hasPendingActivity(hasPendingActivity) - { - } - - virtual void performTask(ScriptExecutionContext*) - { - m_messagingProxy->reportWorkerThreadActivityInternal(m_confirmingMessage, m_hasPendingActivity); - } - - WorkerMessagingProxy* m_messagingProxy; - bool m_confirmingMessage; - bool m_hasPendingActivity; -}; - - -WorkerMessagingProxy::WorkerMessagingProxy(PassRefPtr<ScriptExecutionContext> scriptExecutionContext, Worker* workerObject) - : m_scriptExecutionContext(scriptExecutionContext) - , m_workerObject(workerObject) - , m_unconfirmedMessageCount(0) - , m_workerThreadHadPendingActivity(false) - , m_askedToTerminate(false) -{ - ASSERT(m_workerObject); - ASSERT((m_scriptExecutionContext->isDocument() && isMainThread()) - || (m_scriptExecutionContext->isWorkerContext() && currentThread() == static_cast<WorkerContext*>(m_scriptExecutionContext.get())->thread()->threadID())); -} - -WorkerMessagingProxy::~WorkerMessagingProxy() -{ - ASSERT(!m_workerObject); - ASSERT((m_scriptExecutionContext->isDocument() && isMainThread()) - || (m_scriptExecutionContext->isWorkerContext() && currentThread() == static_cast<WorkerContext*>(m_scriptExecutionContext.get())->thread()->threadID())); -} - -void WorkerMessagingProxy::postMessageToWorkerObject(const String& message) -{ - m_scriptExecutionContext->postTask(MessageWorkerTask::create(message, this)); -} - -void WorkerMessagingProxy::postMessageToWorkerContext(const String& message) -{ - if (m_askedToTerminate) - return; - - if (m_workerThread) { - ++m_unconfirmedMessageCount; - m_workerThread->runLoop().postTask(MessageWorkerContextTask::create(message)); - } else - m_queuedEarlyTasks.append(MessageWorkerContextTask::create(message)); -} - -void WorkerMessagingProxy::postTaskToParentContext(PassRefPtr<ScriptExecutionContext::Task> task) -{ - m_scriptExecutionContext->postTask(task); -} - -void WorkerMessagingProxy::postWorkerException(const String& errorMessage, int lineNumber, const String& sourceURL) -{ - m_scriptExecutionContext->postTask(WorkerExceptionTask::create(errorMessage, lineNumber, sourceURL, this)); -} - -void WorkerMessagingProxy::workerThreadCreated(PassRefPtr<WorkerThread> workerThread) -{ - m_workerThread = workerThread; - - if (m_askedToTerminate) { - // Worker.terminate() could be called from JS before the thread was created. - m_workerThread->stop(); - } else { - unsigned taskCount = m_queuedEarlyTasks.size(); - ASSERT(!m_unconfirmedMessageCount); - m_unconfirmedMessageCount = taskCount + 1; // Worker initialization counts as a pending message. - - for (unsigned i = 0; i < taskCount; ++i) - m_workerThread->runLoop().postTask(m_queuedEarlyTasks[i]); - m_queuedEarlyTasks.clear(); - } -} - -void WorkerMessagingProxy::workerObjectDestroyed() -{ - m_workerObject = 0; - if (m_workerThread) - terminate(); - else - workerContextDestroyedInternal(); // It never existed, just do our cleanup. -} - -void WorkerMessagingProxy::workerContextDestroyed() -{ - m_scriptExecutionContext->postTask(WorkerContextDestroyedTask::create(this)); - // Will execute workerContextDestroyedInternal() on context's thread. -} - -void WorkerMessagingProxy::workerContextDestroyedInternal() -{ - // WorkerContextDestroyedTask is always the last to be performed, so the proxy is not needed for communication - // in either side any more. However, the Worker object may still exist, and it assumes that the proxy exists, too. - if (!m_workerObject) - delete this; -} - -void WorkerMessagingProxy::terminate() -{ - if (m_askedToTerminate) - return; - m_askedToTerminate = true; - - if (m_workerThread) - m_workerThread->stop(); -} - -void WorkerMessagingProxy::confirmWorkerThreadMessage(bool hasPendingActivity) -{ - m_scriptExecutionContext->postTask(WorkerThreadActivityReportTask::create(this, true, hasPendingActivity)); - // Will execute reportWorkerThreadActivityInternal() on context's thread. -} - -void WorkerMessagingProxy::reportWorkerThreadActivity(bool hasPendingActivity) -{ - m_scriptExecutionContext->postTask(WorkerThreadActivityReportTask::create(this, false, hasPendingActivity)); - // Will execute reportWorkerThreadActivityInternal() on context's thread. -} - -void WorkerMessagingProxy::reportWorkerThreadActivityInternal(bool confirmingMessage, bool hasPendingActivity) -{ - if (confirmingMessage && !m_askedToTerminate) { - ASSERT(m_unconfirmedMessageCount); - --m_unconfirmedMessageCount; - } - - m_workerThreadHadPendingActivity = hasPendingActivity; -} - -bool WorkerMessagingProxy::workerThreadHasPendingActivity() const -{ - return (m_unconfirmedMessageCount || m_workerThreadHadPendingActivity) && !m_askedToTerminate; -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/WorkerMessagingProxy.h b/WebCore/dom/WorkerMessagingProxy.h deleted file mode 100644 index e7ba8a9..0000000 --- a/WebCore/dom/WorkerMessagingProxy.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef WorkerMessagingProxy_h -#define WorkerMessagingProxy_h - -#if ENABLE(WORKERS) - -#include "ScriptExecutionContext.h" -#include <wtf/Noncopyable.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { - - class ScriptExecutionContext; - class String; - class Worker; - class WorkerTask; - class WorkerThread; - - class WorkerMessagingProxy : Noncopyable { - public: - WorkerMessagingProxy(PassRefPtr<ScriptExecutionContext>, Worker*); - - void postMessageToWorkerObject(const String& message); - void postMessageToWorkerContext(const String& message); - void postTaskToParentContext(PassRefPtr<ScriptExecutionContext::Task>); - - void postWorkerException(const String& errorMessage, int lineNumber, const String& sourceURL); - - void workerThreadCreated(PassRefPtr<WorkerThread>); - void workerObjectDestroyed(); - void workerContextDestroyed(); - - void terminate(); - - void confirmWorkerThreadMessage(bool hasPendingActivity); - void reportWorkerThreadActivity(bool hasPendingActivity); - bool workerThreadHasPendingActivity() const; - - private: - friend class GenericWorkerTaskBase; - friend class MessageWorkerTask; - friend class WorkerContextDestroyedTask; - friend class WorkerExceptionTask; - friend class WorkerThreadActivityReportTask; - - ~WorkerMessagingProxy(); - - void workerContextDestroyedInternal(); - void reportWorkerThreadActivityInternal(bool confirmingMessage, bool hasPendingActivity); - Worker* workerObject() const { return m_workerObject; } - bool askedToTerminate() { return m_askedToTerminate; } - - RefPtr<ScriptExecutionContext> m_scriptExecutionContext; - Worker* m_workerObject; - RefPtr<WorkerThread> m_workerThread; - - unsigned m_unconfirmedMessageCount; // Unconfirmed messages from worker object to worker thread. - bool m_workerThreadHadPendingActivity; // The latest confirmation from worker thread reported that it was still active. - - bool m_askedToTerminate; - - Vector<RefPtr<WorkerTask> > m_queuedEarlyTasks; // Tasks are queued here until there's a thread object created. - }; - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // WorkerMessagingProxy_h diff --git a/WebCore/dom/WorkerRunLoop.cpp b/WebCore/dom/WorkerRunLoop.cpp deleted file mode 100644 index 98c2e8d..0000000 --- a/WebCore/dom/WorkerRunLoop.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "WorkerRunLoop.h" -#include "WorkerContext.h" -#include "WorkerTask.h" -#include "WorkerThread.h" - -namespace WebCore { - -void WorkerRunLoop::run(WorkerContext* context) -{ - ASSERT(context); - ASSERT(context->thread()); - ASSERT(context->thread()->threadID() == currentThread()); - - while (true) { - RefPtr<WorkerTask> task; - if (!m_messageQueue.waitForMessage(task)) - break; - - task->performTask(context); - } -} - -void WorkerRunLoop::terminate() -{ - m_messageQueue.kill(); -} - -void WorkerRunLoop::postTask(PassRefPtr<WorkerTask> task) -{ - m_messageQueue.append(task); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/WorkerRunLoop.h b/WebCore/dom/WorkerRunLoop.h deleted file mode 100644 index 03a746b..0000000 --- a/WebCore/dom/WorkerRunLoop.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WorkerRunLoop_h -#define WorkerRunLoop_h - -#if ENABLE(WORKERS) - -#include "WorkerTask.h" -#include <wtf/MessageQueue.h> -#include <wtf/PassRefPtr.h> - -namespace WebCore { - - class WorkerContext; - - class WorkerRunLoop { - public: - WorkerRunLoop() {} - - // Blocking call. Waits for tasks and timers, invokes the callbacks. - void run(WorkerContext*); - - void terminate(); - bool terminated() { return m_messageQueue.killed(); } - - void postTask(PassRefPtr<WorkerTask>); - - private: - MessageQueue<RefPtr<WorkerTask> > m_messageQueue; - }; - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // WorkerRunLoop_h diff --git a/WebCore/dom/WorkerThread.cpp b/WebCore/dom/WorkerThread.cpp deleted file mode 100644 index a762e0b..0000000 --- a/WebCore/dom/WorkerThread.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "WorkerThread.h" - -#include "KURL.h" -#include "PlatformString.h" -#include "ScriptSourceCode.h" -#include "ScriptValue.h" -#include "Worker.h" -#include "WorkerContext.h" -#include "WorkerMessagingProxy.h" -#include "WorkerTask.h" - -#include <utility> -#include <wtf/Noncopyable.h> - -namespace WebCore { -struct WorkerThreadStartupData : Noncopyable { -public: - static std::auto_ptr<WorkerThreadStartupData> create(const KURL& scriptURL, const String& userAgent, const String& sourceCode) - { - return std::auto_ptr<WorkerThreadStartupData>(new WorkerThreadStartupData(scriptURL, userAgent, sourceCode)); - } - - KURL m_scriptURL; - String m_userAgent; - String m_sourceCode; -private: - WorkerThreadStartupData(const KURL& scriptURL, const String& userAgent, const String& sourceCode); -}; - -WorkerThreadStartupData::WorkerThreadStartupData(const KURL& scriptURL, const String& userAgent, const String& sourceCode) - : m_scriptURL(scriptURL.copy()) - , m_userAgent(userAgent.copy()) - , m_sourceCode(sourceCode.copy()) -{ -} - -PassRefPtr<WorkerThread> WorkerThread::create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerMessagingProxy* messagingProxy) -{ - return adoptRef(new WorkerThread(scriptURL, userAgent, sourceCode, messagingProxy)); -} - -WorkerThread::WorkerThread(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerMessagingProxy* messagingProxy) - : m_threadID(0) - , m_messagingProxy(messagingProxy) - , m_startupData(WorkerThreadStartupData::create(scriptURL, userAgent, sourceCode)) -{ -} - -WorkerThread::~WorkerThread() -{ -} - -bool WorkerThread::start() -{ - // Mutex protection is necessary to ensure that m_threadID is initialized when the thread starts. - MutexLocker lock(m_threadCreationMutex); - - if (m_threadID) - return true; - - m_threadID = createThread(WorkerThread::workerThreadStart, this, "WebCore::Worker"); - - return m_threadID; -} - -void* WorkerThread::workerThreadStart(void* thread) -{ - return static_cast<WorkerThread*>(thread)->workerThread(); -} - -void* WorkerThread::workerThread() -{ - { - MutexLocker lock(m_threadCreationMutex); - m_workerContext = WorkerContext::create(m_startupData->m_scriptURL, m_startupData->m_userAgent, this); - if (m_runLoop.terminated()) { - // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, - // forbidExecution() couldn't be called from stop(). - m_workerContext->script()->forbidExecution(); - } - } - - WorkerScriptController* script = m_workerContext->script(); - script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData->m_scriptURL)); - // Free the startup data to cause its member variable deref's happen on the worker's thread (since - // all ref/derefs of these objects are happening on the thread at this point). Note that - // WorkerThread::~WorkerThread happens on a different thread where it was created. - m_startupData.clear(); - - m_messagingProxy->confirmWorkerThreadMessage(m_workerContext->hasPendingActivity()); // This wasn't really a message, but it counts as one for GC. - - // Blocks until terminated. - m_runLoop.run(m_workerContext.get()); - - ThreadIdentifier threadID = m_threadID; - - m_workerContext->clearScript(); - ASSERT(m_workerContext->hasOneRef()); - // The below assignment will destroy the context, which will in turn notify messaging proxy. - // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. - m_workerContext = 0; - - // The thread object may be already destroyed from notification now, don't try to access "this". - detachThread(threadID); - - return 0; -} - -void WorkerThread::stop() -{ - // Mutex protection is necessary because stop() can be called before the context is fully created. - MutexLocker lock(m_threadCreationMutex); - - // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever. - if (m_workerContext) - m_workerContext->script()->forbidExecution(); - - // FIXME: Rudely killing the thread won't work when we allow nested workers, because they will try to post notifications of their destruction. - m_runLoop.terminate(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/dom/WorkerThread.h b/WebCore/dom/WorkerThread.h deleted file mode 100644 index 504db81..0000000 --- a/WebCore/dom/WorkerThread.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef WorkerThread_h -#define WorkerThread_h - -#if ENABLE(WORKERS) - -#include <WorkerRunLoop.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> - -namespace WebCore { - - class KURL; - class String; - class WorkerContext; - class WorkerMessagingProxy; - class WorkerTask; - struct WorkerThreadStartupData; - - class WorkerThread : public RefCounted<WorkerThread> { - public: - static PassRefPtr<WorkerThread> create(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerMessagingProxy*); - ~WorkerThread(); - - bool start(); - void stop(); - - ThreadIdentifier threadID() const { return m_threadID; } - WorkerRunLoop& runLoop() { return m_runLoop; } - WorkerMessagingProxy* messagingProxy() const { return m_messagingProxy; } - - private: - WorkerThread(const KURL&, const String& userAgent, const String& sourceCode, WorkerMessagingProxy*); - - static void* workerThreadStart(void*); - void* workerThread(); - - ThreadIdentifier m_threadID; - WorkerRunLoop m_runLoop; - WorkerMessagingProxy* m_messagingProxy; - - RefPtr<WorkerContext> m_workerContext; - Mutex m_threadCreationMutex; - - OwnPtr<WorkerThreadStartupData> m_startupData; - }; - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // WorkerThread_h diff --git a/WebCore/dom/XMLTokenizer.cpp b/WebCore/dom/XMLTokenizer.cpp index 6f57a46..1415922 100644 --- a/WebCore/dom/XMLTokenizer.cpp +++ b/WebCore/dom/XMLTokenizer.cpp @@ -64,6 +64,8 @@ using namespace std; namespace WebCore { +using namespace HTMLNames; + const int maxErrors = 25; #if ENABLE(WML) @@ -87,7 +89,7 @@ void XMLTokenizer::setCurrentNode(Node* n) m_currentNodeIsReferenced = nodeNeedsReference; } -bool XMLTokenizer::write(const SegmentedString& s, bool /*appendData*/) +void XMLTokenizer::write(const SegmentedString& s, bool /*appendData*/) { String parseString = s.toString(); @@ -95,15 +97,14 @@ bool XMLTokenizer::write(const SegmentedString& s, bool /*appendData*/) m_originalSourceForTransform += parseString; if (m_parserStopped || m_sawXSLTransform) - return false; + return; if (m_parserPaused) { m_pendingSrc.append(s); - return false; + return; } doWrite(s.toString()); - return false; } void XMLTokenizer::handleError(ErrorType type, const char* m, int lineNumber, int columnNumber) @@ -200,20 +201,20 @@ void XMLTokenizer::finish() static inline RefPtr<Element> createXHTMLParserErrorHeader(Document* doc, const String& errorMessages) { - ExceptionCode ec = 0; - RefPtr<Element> reportElement = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "parsererror", ec); - reportElement->setAttribute(HTMLNames::styleAttr, "display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black"); + RefPtr<Element> reportElement = doc->createElement(QualifiedName(nullAtom, "parsererror", xhtmlNamespaceURI), false); + reportElement->setAttribute(styleAttr, "display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black"); - RefPtr<Element> h3 = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "h3", ec); + ExceptionCode ec = 0; + RefPtr<Element> h3 = doc->createElement(h3Tag, false); reportElement->appendChild(h3.get(), ec); h3->appendChild(doc->createTextNode("This page contains the following errors:"), ec); - - RefPtr<Element> fixed = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "div", ec); + + RefPtr<Element> fixed = doc->createElement(divTag, false); reportElement->appendChild(fixed.get(), ec); - fixed->setAttribute(HTMLNames::styleAttr, "font-family:monospace;font-size:12px"); + fixed->setAttribute(styleAttr, "font-family:monospace;font-size:12px"); fixed->appendChild(doc->createTextNode(errorMessages), ec); - - h3 = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "h3", ec); + + h3 = doc->createElement(h3Tag, false); reportElement->appendChild(h3.get(), ec); h3->appendChild(doc->createTextNode("Below is a rendering of the page up to the first error."), ec); @@ -235,16 +236,16 @@ void XMLTokenizer::insertErrorMessageBlock() Document* doc = m_doc; Node* documentElement = doc->documentElement(); if (!documentElement) { - RefPtr<Node> rootElement = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "html", ec); + RefPtr<Node> rootElement = doc->createElement(htmlTag, false); doc->appendChild(rootElement, ec); - RefPtr<Node> body = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "body", ec); + RefPtr<Node> body = doc->createElement(bodyTag, false); rootElement->appendChild(body, ec); documentElement = body.get(); } #if ENABLE(SVG) else if (documentElement->namespaceURI() == SVGNames::svgNamespaceURI) { - RefPtr<Node> rootElement = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "html", ec); - RefPtr<Node> body = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "body", ec); + RefPtr<Node> rootElement = doc->createElement(htmlTag, false); + RefPtr<Node> body = doc->createElement(bodyTag, false); rootElement->appendChild(body, ec); body->appendChild(documentElement, ec); doc->appendChild(rootElement.get(), ec); @@ -253,8 +254,8 @@ void XMLTokenizer::insertErrorMessageBlock() #endif #if ENABLE(WML) else if (isWMLDocument()) { - RefPtr<Node> rootElement = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "html", ec); - RefPtr<Node> body = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "body", ec); + RefPtr<Node> rootElement = doc->createElement(htmlTag, false); + RefPtr<Node> body = doc->createElement(bodyTag, false); rootElement->appendChild(body, ec); body->appendChild(documentElement, ec); doc->appendChild(rootElement.get(), ec); @@ -266,9 +267,9 @@ void XMLTokenizer::insertErrorMessageBlock() documentElement->insertBefore(reportElement, documentElement->firstChild(), ec); #if ENABLE(XSLT) if (doc->transformSourceDocument()) { - RefPtr<Element> par = doc->createElementNS(HTMLNames::xhtmlNamespaceURI, "p", ec); + RefPtr<Element> par = doc->createElement(pTag, false); reportElement->appendChild(par, ec); - par->setAttribute(HTMLNames::styleAttr, "white-space: normal"); + par->setAttribute(styleAttr, "white-space: normal"); par->appendChild(doc->createTextNode("This document was created as the result of an XSL transformation. The line and column numbers given are from the transformed result."), ec); } #endif diff --git a/WebCore/dom/XMLTokenizer.h b/WebCore/dom/XMLTokenizer.h index c5c0847..8f35c63 100644 --- a/WebCore/dom/XMLTokenizer.h +++ b/WebCore/dom/XMLTokenizer.h @@ -169,7 +169,7 @@ namespace WebCore { enum ErrorType { warning, nonFatal, fatal }; // from Tokenizer - virtual bool write(const SegmentedString&, bool appendData); + virtual void write(const SegmentedString&, bool appendData); virtual void finish(); virtual bool isWaitingForScripts() const; virtual void stopParsing(); diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp index 24ea6e8..77a1afd 100644 --- a/WebCore/dom/XMLTokenizerLibxml2.cpp +++ b/WebCore/dom/XMLTokenizerLibxml2.cpp @@ -395,7 +395,7 @@ static void* openFunc(const char* uri) ASSERT(globalDocLoader); ASSERT(currentThread() == libxmlLoaderThread); - KURL url(uri); + KURL url(KURL(), uri); if (!shouldAllowExternalLoad(url)) return &globalDescriptor; @@ -706,7 +706,8 @@ void XMLTokenizer::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xm nb_attributes, nb_defaulted, libxmlAttributes); return; } - + + bool isFirstElement = !m_sawFirstElement; m_sawFirstElement = true; exitText(); @@ -722,14 +723,14 @@ void XMLTokenizer::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xm uri = m_defaultNamespaceURI; } - ExceptionCode ec = 0; QualifiedName qName(prefix, localName, uri); - RefPtr<Element> newElement = m_doc->createElement(qName, true, ec); + RefPtr<Element> newElement = m_doc->createElement(qName, true); if (!newElement) { stopParsing(); return; } + ExceptionCode ec = 0; handleElementNamespaces(newElement.get(), libxmlNamespaces, nb_namespaces, ec); if (ec) { stopParsing(); @@ -763,6 +764,9 @@ void XMLTokenizer::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xm setCurrentNode(newElement.get()); if (m_view && !newElement->attached()) newElement->attach(); + + if (isFirstElement && m_doc->frame()) + m_doc->frame()->loader()->dispatchDocumentElementAvailable(); } void XMLTokenizer::endElementNs() diff --git a/WebCore/dom/XMLTokenizerQt.cpp b/WebCore/dom/XMLTokenizerQt.cpp index ce50126..68bc17b 100644 --- a/WebCore/dom/XMLTokenizerQt.cpp +++ b/WebCore/dom/XMLTokenizerQt.cpp @@ -507,6 +507,8 @@ void XMLTokenizer::parseStartElement() m_sawFirstElement = true; return; } + + bool isFirstElement = !m_sawFirstElement; m_sawFirstElement = true; exitText(); @@ -520,14 +522,14 @@ void XMLTokenizer::parseStartElement() uri = m_defaultNamespaceURI; } - ExceptionCode ec = 0; QualifiedName qName(prefix, localName, uri); - RefPtr<Element> newElement = m_doc->createElement(qName, true, ec); + RefPtr<Element> newElement = m_doc->createElement(qName, true); if (!newElement) { stopParsing(); return; } + ExceptionCode ec = 0; handleElementNamespaces(newElement.get(), m_stream.namespaceDeclarations(), ec); if (ec) { stopParsing(); @@ -552,6 +554,9 @@ void XMLTokenizer::parseStartElement() setCurrentNode(newElement.get()); if (m_view && !newElement->attached()) newElement->attach(); + + if (isFirstElement && m_doc->frame()) + m_doc->frame()->loader()->dispatchDocumentElementAvailable(); } void XMLTokenizer::parseEndElement() diff --git a/WebCore/dom/make_names.pl b/WebCore/dom/make_names.pl index f9eba88..f2a7a76 100755 --- a/WebCore/dom/make_names.pl +++ b/WebCore/dom/make_names.pl @@ -93,6 +93,7 @@ sub initializeTagPropertyHash 'interfaceName' => defaultInterfaceName($_[0]), # By default, the JSInterfaceName is the same as the interfaceName. 'JSInterfaceName' => defaultInterfaceName($_[0]), + 'mapToTagName' => '', 'wrapperOnlyIfMediaIsAvailable' => 0); } @@ -217,47 +218,126 @@ sub printMacros } } -sub printConstructors +sub usesDefaultWrapper { - my $F = shift; + my $tagName = shift; + return $tagName eq $parameters{'namespace'} . "Element"; +} - print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; - for my $name (sort keys %tags) { - my $ucName = $tags{$name}{'interfaceName'}; - - # Print the method signature avoiding unused arguments' name. - print F "static PassRefPtr<$parameters{'namespace'}Element> ${name}Constructor(Document* doc"; - if ($parameters{'namespace'} eq "HTML") { - print F ", HTMLFormElement* formElement"; - if ($tags{$name}{'constructorNeedsFormElement'}) { - print F " formElement"; - } - } - print F ", bool"; - if ($tags{$name}{'constructorNeedsCreatedByParser'}) { - print F " createdByParser"; +# Build a direct mapping from the tags to the Element to create, excluding +# Element that have not constructor. +sub buildConstructorMap +{ + my %tagConstructorMap = (); + for my $tagName (keys %tags) { + my $interfaceName = $tags{$tagName}{'interfaceName'}; + next if (usesDefaultWrapper($interfaceName)); + + if ($tags{$tagName}{'mapToTagName'}) { + die "Cannot handle multiple mapToTagName for $tagName\n" if $tags{$tags{$tagName}{'mapToTagName'}}{'mapToTagName'}; + $interfaceName = $tags{ $tags{$tagName}{'mapToTagName'} }{'interfaceName'}; } - print F ")\n{\n"; - # Now call the constructor with the right parameters. - print F " return new ${ucName}($parameters{'namespace'}Names::${name}Tag, doc"; - if ($tags{$name}{'constructorNeedsFormElement'}) { - print F ", formElement"; + # Chop the string to keep the interesting part. + $interfaceName =~ s/$parameters{'namespace'}(.*)Element/$1/; + $tagConstructorMap{$tagName} = lc($interfaceName); + } + + return %tagConstructorMap; +} + +# Helper method that print the constructor's signature avoiding +# unneeded arguments. +sub printConstructorSignature +{ + my ($F, $tagName, $constructorName, $constructorTagName) = @_; + + print F "static PassRefPtr<$parameters{'namespace'}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document* doc"; + if ($parameters{'namespace'} eq "HTML") { + print F ", HTMLFormElement*"; + if ($tags{$tagName}{'constructorNeedsFormElement'}) { + print F " formElement"; } - if ($tags{$name}{'constructorNeedsCreatedByParser'}) { - print F ", createdByParser"; + } + print F ", bool"; + if ($tags{$tagName}{'constructorNeedsCreatedByParser'}) { + print F " createdByParser"; + } + print F ")\n{\n"; +} + +# Helper method to dump the constructor interior and call the +# Element constructor with the right arguments. +# The variable names should be kept in sync with the previous method. +sub printConstructorInterior +{ + my ($F, $tagName, $interfaceName, $constructorTagName) = @_; + + # Handle media elements. + if ($tags{$tagName}{'wrapperOnlyIfMediaIsAvailable'}) { + print F <<END + if (!MediaPlayer::isAvailable()) + return new HTMLElement($constructorTagName, doc); +END +; + } + + # Now call the constructor with the right parameters. + print F " return new ${interfaceName}($constructorTagName, doc"; + if ($tags{$tagName}{'constructorNeedsFormElement'}) { + print F ", formElement"; + } + if ($tags{$tagName}{'constructorNeedsCreatedByParser'}) { + print F ", createdByParser"; + } + print F ");\n}\n\n"; +} + +sub printConstructors +{ + my ($F, $tagConstructorMapRef) = @_; + my %tagConstructorMap = %$tagConstructorMapRef; + + print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; + + # This is to avoid generating the same constructor several times. + my %uniqueTags = (); + for my $tagName (sort keys %tagConstructorMap) { + my $interfaceName = $tags{$tagName}{'interfaceName'}; + + # Ignore the mapped tag + # FIXME: It could be moved inside this loop but was split for readibility. + next if (defined($uniqueTags{$interfaceName}) || $tags{$tagName}{'mapToTagName'}); + + $uniqueTags{$interfaceName} = '1'; + + printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName"); + printConstructorInterior($F, $tagName, $interfaceName, "tagName"); + } + + # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname. + for my $tagName (sort keys %tagConstructorMap) { + if ($tags{$tagName}{'mapToTagName'}) { + my $mappedName = $tags{$tagName}{'mapToTagName'}; + printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName"); + printConstructorInterior($F, $mappedName, $tags{$mappedName}{'interfaceName'}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())"); } - print F ");\n}\n\n"; } + print F "#endif\n" if $parameters{'guardFactoryWith'}; } sub printFunctionInits { - my $F = shift; + my ($F, $tagConstructorMap) = @_; + my %tagConstructorMap = %$tagConstructorMap; - for my $name (sort keys %tags) { - print F " gFunctionMap->set($parameters{'namespace'}Names::${name}Tag.localName().impl(), ${name}Constructor);\n"; + for my $tagName (sort keys %tagConstructorMap) { + if ($tags{$tagName}{'mapToTagName'}) { + print F " addTag(${tagName}Tag, $tags{$tagName}{'mapToTagName'}To${tagName}Constructor);\n"; + } else { + print F " addTag(${tagName}Tag, $tagConstructorMap{$tagName}Constructor);\n"; + } } } @@ -568,34 +648,40 @@ printElementIncludes($F); print F <<END #include <wtf/HashMap.h> -using namespace WebCore; +namespace WebCore { + +using namespace $parameters{'namespace'}Names; END ; -print F "typedef PassRefPtr<$parameters{'namespace'}Element> (*ConstructorFunction)(Document*"; +print F "typedef PassRefPtr<$parameters{'namespace'}Element> (*ConstructorFunction)(const QualifiedName&, Document*"; if ($parameters{'namespace'} eq "HTML") { - print F ", HTMLFormElement* formElement"; + print F ", HTMLFormElement*"; } print F ", bool createdByParser);\n"; - print F <<END -typedef WTF::HashMap<AtomicStringImpl*, ConstructorFunction> FunctionMap; +typedef HashMap<AtomicStringImpl*, ConstructorFunction> FunctionMap; static FunctionMap* gFunctionMap = 0; -namespace WebCore { - END ; -printConstructors($F); +my %tagConstructorMap = buildConstructorMap(); + +printConstructors($F, \%tagConstructorMap); print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'}; print F <<END +static void addTag(const QualifiedName& tag, ConstructorFunction func) +{ + gFunctionMap->set(tag.localName().impl(), func); +} + static inline void createFunctionMapIfNecessary() { if (gFunctionMap) @@ -607,7 +693,7 @@ static inline void createFunctionMapIfNecessary() END ; -printFunctionInits($F); +printFunctionInits($F, \%tagConstructorMap); print F "}\n"; print F "#endif\n" if $parameters{'guardFactoryWith'}; @@ -627,12 +713,22 @@ print F <<END if (!doc) return 0; +END +; + +if ($parameters{'namespace'} ne "HTML") { +print F <<END #if ENABLE(DASHBOARD_SUPPORT) Settings* settings = doc->settings(); if (settings && settings->usesDashboardBackwardCompatibilityMode()) return 0; #endif +END +; +} + +print F <<END createFunctionMapIfNecessary(); ConstructorFunction func = gFunctionMap->get(qName.localName().impl()); if (func) @@ -640,9 +736,9 @@ END ; if ($parameters{"namespace"} eq "HTML") { - print F " return func(doc, formElement, createdByParser);\n"; + print F " return func(qName, doc, formElement, createdByParser);\n"; } else { - print F " return func(doc, createdByParser);\n"; + print F " return func(qName, doc, createdByParser);\n"; } print F " return new $parameters{'namespace'}Element(qName, doc);\n"; |