summaryrefslogtreecommitdiffstats
path: root/WebCore/dom
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/dom')
-rw-r--r--WebCore/dom/Attr.idl2
-rw-r--r--WebCore/dom/CanvasSurface.cpp180
-rw-r--r--WebCore/dom/CanvasSurface.h109
-rw-r--r--WebCore/dom/CharacterData.cpp1
-rw-r--r--WebCore/dom/Clipboard.cpp9
-rw-r--r--WebCore/dom/Clipboard.h3
-rw-r--r--WebCore/dom/ContainerNode.cpp141
-rw-r--r--WebCore/dom/CustomEvent.cpp52
-rw-r--r--WebCore/dom/CustomEvent.h57
-rw-r--r--WebCore/dom/CustomEvent.idl39
-rw-r--r--WebCore/dom/DOMCoreException.idl4
-rw-r--r--WebCore/dom/DOMImplementation.cpp20
-rw-r--r--WebCore/dom/DOMImplementation.h2
-rw-r--r--WebCore/dom/Document.cpp280
-rw-r--r--WebCore/dom/Document.h57
-rw-r--r--WebCore/dom/Document.idl10
-rw-r--r--WebCore/dom/DocumentType.cpp1
-rw-r--r--WebCore/dom/Element.cpp90
-rw-r--r--WebCore/dom/Element.h6
-rw-r--r--WebCore/dom/Element.idl10
-rw-r--r--WebCore/dom/Event.cpp33
-rw-r--r--WebCore/dom/Event.h18
-rw-r--r--WebCore/dom/Event.idl4
-rw-r--r--WebCore/dom/EventListener.h2
-rw-r--r--WebCore/dom/EventNames.h6
-rw-r--r--WebCore/dom/EventTarget.cpp28
-rw-r--r--WebCore/dom/EventTarget.h2
-rw-r--r--WebCore/dom/InputElement.cpp6
-rw-r--r--WebCore/dom/KeyboardEvent.cpp2
-rw-r--r--WebCore/dom/MessagePort.idl8
-rw-r--r--WebCore/dom/NamedNodeMap.idl4
-rw-r--r--WebCore/dom/Node.cpp66
-rw-r--r--WebCore/dom/Node.h6
-rw-r--r--WebCore/dom/Node.idl17
-rw-r--r--WebCore/dom/OptionElement.h1
-rw-r--r--WebCore/dom/Position.cpp30
-rw-r--r--WebCore/dom/Position.h2
-rw-r--r--WebCore/dom/ProcessingInstruction.cpp2
-rw-r--r--WebCore/dom/QualifiedName.cpp2
-rw-r--r--WebCore/dom/Range.cpp12
-rw-r--r--WebCore/dom/Range.h3
-rw-r--r--WebCore/dom/ScriptElement.cpp12
-rw-r--r--WebCore/dom/ScriptElement.h1
-rw-r--r--WebCore/dom/ScriptExecutionContext.cpp21
-rw-r--r--WebCore/dom/ScriptExecutionContext.h25
-rw-r--r--WebCore/dom/SelectElement.cpp128
-rw-r--r--WebCore/dom/SelectElement.h15
-rw-r--r--WebCore/dom/Text.cpp2
-rw-r--r--WebCore/dom/UserGestureIndicator.cpp45
-rw-r--r--WebCore/dom/UserGestureIndicator.h52
-rw-r--r--WebCore/dom/ViewportArguments.cpp120
-rw-r--r--WebCore/dom/ViewportArguments.h74
-rw-r--r--WebCore/dom/WheelEvent.cpp32
-rw-r--r--WebCore/dom/WheelEvent.h28
-rw-r--r--WebCore/dom/WheelEvent.idl17
-rw-r--r--WebCore/dom/XMLTokenizer.cpp12
-rw-r--r--WebCore/dom/XMLTokenizerLibxml2.cpp16
-rw-r--r--WebCore/dom/XMLTokenizerQt.cpp5
-rwxr-xr-xWebCore/dom/make_names.pl46
59 files changed, 1562 insertions, 416 deletions
diff --git a/WebCore/dom/Attr.idl b/WebCore/dom/Attr.idl
index af84478..3c73bc0 100644
--- a/WebCore/dom/Attr.idl
+++ b/WebCore/dom/Attr.idl
@@ -28,7 +28,9 @@ module core {
// DOM Level 1
readonly attribute [ConvertNullStringTo=Null] DOMString name;
+
readonly attribute boolean specified;
+
attribute [ConvertNullStringTo=Null, ConvertNullToNullString, CustomSetter] DOMString value
setter raises(DOMException);
diff --git a/WebCore/dom/CanvasSurface.cpp b/WebCore/dom/CanvasSurface.cpp
new file mode 100644
index 0000000..dc7e4e1
--- /dev/null
+++ b/WebCore/dom/CanvasSurface.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 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:
+ * 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 "CanvasSurface.h"
+
+#include "AffineTransform.h"
+#include "ExceptionCode.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "HTMLCanvasElement.h"
+#include "ImageBuffer.h"
+#include "MIMETypeRegistry.h"
+
+namespace WebCore {
+
+// These values come from the WhatWG spec.
+const int CanvasSurface::DefaultWidth = 300;
+const int CanvasSurface::DefaultHeight = 150;
+
+// Firefox limits width/height to 32767 pixels, but slows down dramatically before it
+// reaches that limit. We limit by area instead, giving us larger maximum dimensions,
+// in exchange for a smaller maximum canvas size.
+const float CanvasSurface::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
+
+CanvasSurface::CanvasSurface(float pageScaleFactor)
+ : m_size(DefaultWidth, DefaultHeight)
+ , m_pageScaleFactor(pageScaleFactor)
+ , m_originClean(true)
+ , m_hasCreatedImageBuffer(false)
+{
+}
+
+CanvasSurface::~CanvasSurface()
+{
+}
+
+void CanvasSurface::setSurfaceSize(const IntSize& size)
+{
+ m_size = size;
+ m_hasCreatedImageBuffer = false;
+ m_imageBuffer.clear();
+}
+
+String CanvasSurface::toDataURL(const String& mimeType, ExceptionCode& ec)
+{
+ if (!m_originClean) {
+ ec = SECURITY_ERR;
+ return String();
+ }
+
+ if (m_size.isEmpty() || !buffer())
+ return String("data:,");
+
+ // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread).
+ if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
+ return buffer()->toDataURL("image/png");
+
+ return buffer()->toDataURL(mimeType);
+}
+
+void CanvasSurface::willDraw(const FloatRect&)
+{
+ if (m_imageBuffer)
+ m_imageBuffer->clearImage();
+}
+
+IntRect CanvasSurface::convertLogicalToDevice(const FloatRect& logicalRect) const
+{
+ return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size()));
+}
+
+IntSize CanvasSurface::convertLogicalToDevice(const FloatSize& logicalSize) const
+{
+ float wf = ceilf(logicalSize.width() * m_pageScaleFactor);
+ float hf = ceilf(logicalSize.height() * m_pageScaleFactor);
+
+ if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea))
+ return IntSize();
+
+ return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf));
+}
+
+IntPoint CanvasSurface::convertLogicalToDevice(const FloatPoint& logicalPos) const
+{
+ float xf = logicalPos.x() * m_pageScaleFactor;
+ float yf = logicalPos.y() * m_pageScaleFactor;
+
+ return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf));
+}
+
+void CanvasSurface::createImageBuffer() const
+{
+ ASSERT(!m_imageBuffer);
+
+ m_hasCreatedImageBuffer = true;
+
+ FloatSize unscaledSize(width(), height());
+ IntSize size = convertLogicalToDevice(unscaledSize);
+ if (!size.width() || !size.height())
+ return;
+
+ m_imageBuffer = ImageBuffer::create(size);
+ // The convertLogicalToDevice MaxCanvasArea check should prevent common cases
+ // where ImageBuffer::create() returns 0, however we could still be low on memory.
+ if (!m_imageBuffer)
+ return;
+ m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height()));
+ m_imageBuffer->context()->setShadowsIgnoreTransforms(true);
+}
+
+GraphicsContext* CanvasSurface::drawingContext() const
+{
+ return buffer() ? m_imageBuffer->context() : 0;
+}
+
+ImageBuffer* CanvasSurface::buffer() const
+{
+ if (!m_hasCreatedImageBuffer)
+ createImageBuffer();
+ return m_imageBuffer.get();
+}
+
+AffineTransform CanvasSurface::baseTransform() const
+{
+ ASSERT(m_hasCreatedImageBuffer);
+ FloatSize unscaledSize(width(), height());
+ IntSize size = convertLogicalToDevice(unscaledSize);
+ AffineTransform transform;
+ if (size.width() && size.height())
+ transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height());
+ transform.multiply(m_imageBuffer->baseTransform());
+ return transform;
+}
+
+// FIXME: Everything below here relies on CanvasSurface really being
+// a HTMLCanvasElement.
+const SecurityOrigin& CanvasSurface::securityOrigin() const
+{
+ return *(static_cast<const HTMLCanvasElement*>(this)->document()->securityOrigin());
+}
+
+RenderBox* CanvasSurface::renderBox() const
+{
+ return static_cast<const HTMLCanvasElement*>(this)->renderBox();
+}
+
+RenderStyle* CanvasSurface::computedStyle()
+{
+ return static_cast<HTMLCanvasElement*>(this)->computedStyle();
+}
+
+CSSStyleSelector* CanvasSurface::styleSelector()
+{
+ return static_cast<HTMLCanvasElement*>(this)->document()->styleSelector();
+}
+
+} // namespace WebCore
diff --git a/WebCore/dom/CanvasSurface.h b/WebCore/dom/CanvasSurface.h
new file mode 100644
index 0000000..f5317e5
--- /dev/null
+++ b/WebCore/dom/CanvasSurface.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 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:
+ * 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 CanvasSurface_h
+#define CanvasSurface_h
+
+#include "AffineTransform.h"
+#include "IntSize.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class FloatPoint;
+class FloatRect;
+class FloatSize;
+class GraphicsContext;
+class ImageBuffer;
+class IntPoint;
+class String;
+
+class CSSStyleSelector;
+class RenderBox;
+class RenderStyle;
+class SecurityOrigin;
+
+typedef int ExceptionCode;
+
+class CanvasSurface : public Noncopyable {
+public:
+ CanvasSurface(float pageScaleFactor);
+ virtual ~CanvasSurface();
+
+ int width() const { return m_size.width(); }
+ int height() const { return m_size.height(); }
+
+ String toDataURL(const String& mimeType, ExceptionCode&);
+
+ const IntSize& size() const { return m_size; }
+
+ virtual void willDraw(const FloatRect&);
+
+ GraphicsContext* drawingContext() const;
+
+ ImageBuffer* buffer() const;
+
+ IntRect convertLogicalToDevice(const FloatRect&) const;
+ IntSize convertLogicalToDevice(const FloatSize&) const;
+ IntPoint convertLogicalToDevice(const FloatPoint&) const;
+
+ void setOriginTainted() { m_originClean = false; }
+ bool originClean() const { return m_originClean; }
+
+ AffineTransform baseTransform() const;
+
+ const SecurityOrigin& securityOrigin() const;
+ RenderBox* renderBox() const;
+ RenderStyle* computedStyle();
+ CSSStyleSelector* styleSelector();
+
+protected:
+ void setSurfaceSize(const IntSize&);
+ bool hasCreatedImageBuffer() const { return m_hasCreatedImageBuffer; }
+
+ static const int DefaultWidth;
+ static const int DefaultHeight;
+
+private:
+ void createImageBuffer() const;
+
+ static const float MaxCanvasArea;
+
+ IntSize m_size;
+
+ float m_pageScaleFactor;
+ bool m_originClean;
+
+ // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
+ mutable bool m_hasCreatedImageBuffer;
+ mutable OwnPtr<ImageBuffer> m_imageBuffer;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/dom/CharacterData.cpp b/WebCore/dom/CharacterData.cpp
index 3c3dc37..f5adb6c 100644
--- a/WebCore/dom/CharacterData.cpp
+++ b/WebCore/dom/CharacterData.cpp
@@ -22,7 +22,6 @@
#include "config.h"
#include "CharacterData.h"
-#include "CString.h"
#include "EventNames.h"
#include "ExceptionCode.h"
#include "MutationEvent.h"
diff --git a/WebCore/dom/Clipboard.cpp b/WebCore/dom/Clipboard.cpp
index 7f33aac..d644bcc 100644
--- a/WebCore/dom/Clipboard.cpp
+++ b/WebCore/dom/Clipboard.cpp
@@ -27,7 +27,6 @@
#include "Clipboard.h"
#include "CachedImage.h"
-#include "DOMImplementation.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "Image.h"
@@ -36,7 +35,7 @@ namespace WebCore {
Clipboard::Clipboard(ClipboardAccessPolicy policy, bool isForDragging)
: m_policy(policy)
- , m_dropEffect("none")
+ , m_dropEffect("uninitialized")
, m_effectAllowed("uninitialized")
, m_dragStarted(false)
, m_forDragging(isForDragging)
@@ -66,7 +65,7 @@ static DragOperation dragOpFromIEOp(const String& op)
if (op == "link")
return DragOperationLink;
if (op == "move")
- return DragOperationGeneric; // FIXME: Why is this DragOperationGeneric? <http://webkit.org/b/33697>
+ return (DragOperation)(DragOperationGeneric | DragOperationMove);
if (op == "copyLink")
return (DragOperation)(DragOperationCopy | DragOperationLink);
if (op == "copyMove")
@@ -110,7 +109,7 @@ DragOperation Clipboard::sourceOperation() const
DragOperation Clipboard::destinationOperation() const
{
DragOperation op = dragOpFromIEOp(m_dropEffect);
- ASSERT(op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == DragOperationGeneric || op == DragOperationMove);
+ ASSERT(op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == (DragOperation)(DragOperationGeneric | DragOperationMove) || op == DragOperationEvery);
return op;
}
@@ -122,7 +121,7 @@ void Clipboard::setSourceOperation(DragOperation op)
void Clipboard::setDestinationOperation(DragOperation op)
{
- ASSERT_ARG(op, op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == DragOperationGeneric || op == DragOperationMove);
+ ASSERT_ARG(op, op == DragOperationCopy || op == DragOperationNone || op == DragOperationLink || op == DragOperationGeneric || op == DragOperationMove || op == (DragOperation)(DragOperationGeneric | DragOperationMove));
m_dropEffect = IEOpFromDragOp(op);
}
diff --git a/WebCore/dom/Clipboard.h b/WebCore/dom/Clipboard.h
index 2f4dc6f..4018e4f 100644
--- a/WebCore/dom/Clipboard.h
+++ b/WebCore/dom/Clipboard.h
@@ -43,8 +43,9 @@ namespace WebCore {
// Is this operation a drag-drop or a copy-paste?
bool isForDragging() const { return m_forDragging; }
- String dropEffect() const { return m_dropEffect; }
+ String dropEffect() const { return dropEffectIsUninitialized() ? "none" : m_dropEffect; }
void setDropEffect(const String&);
+ bool dropEffectIsUninitialized() const { return m_dropEffect == "uninitialized"; }
String effectAllowed() const { return m_effectAllowed; }
void setEffectAllowed(const String&);
diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp
index 39cd3b4..f42b9cf 100644
--- a/WebCore/dom/ContainerNode.cpp
+++ b/WebCore/dom/ContainerNode.cpp
@@ -40,18 +40,32 @@
#include "RootInlineBox.h"
#include "loader.h"
#include <wtf/CurrentTime.h>
+#include <wtf/Vector.h>
namespace WebCore {
+static void notifyChildInserted(Node*);
static void dispatchChildInsertionEvents(Node*);
static void dispatchChildRemovalEvents(Node*);
typedef Vector<std::pair<NodeCallback, RefPtr<Node> > > NodeCallbackQueue;
+typedef Vector<RefPtr<Node>, 1> NodeVector;
static NodeCallbackQueue* s_postAttachCallbackQueue;
static size_t s_attachDepth;
static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
+static void collectTargetNodes(Node* node, NodeVector& nodes)
+{
+ if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
+ nodes.append(node);
+ return;
+ }
+
+ for (Node* child = node->firstChild(); child; child = child->nextSibling())
+ nodes.append(child);
+}
+
void ContainerNode::removeAllChildren()
{
removeAllChildrenInContainer<Node, ContainerNode>(this);
@@ -85,11 +99,9 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
return false;
}
- bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
-
- // If newChild is a DocumentFragment with no children; there's nothing to do.
- // Just return true
- if (isFragment && !newChild->firstChild())
+ NodeVector targets;
+ collectTargetNodes(newChild.get(), targets);
+ if (targets.isEmpty())
return true;
// Now actually add the child(ren)
@@ -98,16 +110,14 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
RefPtr<Node> next = refChild;
RefPtr<Node> refChildPreviousSibling = refChild->previousSibling();
-
- RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
- while (child) {
- RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ Node* child = it->get();
// If child is already present in the tree, first remove it from the old location.
if (Node* oldParent = child->parentNode())
- oldParent->removeChild(child.get(), ec);
+ oldParent->removeChild(child, ec);
if (ec)
- return 0;
+ return false;
// FIXME: After sending the mutation events, "this" could be destroyed.
// We can prevent that by doing a "ref", but first we have to make sure
@@ -130,23 +140,23 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
forbidEventDispatch();
Node* prev = next->previousSibling();
ASSERT(m_lastChild != prev);
- next->setPreviousSibling(child.get());
+ next->setPreviousSibling(child);
if (prev) {
ASSERT(m_firstChild != next);
ASSERT(prev->nextSibling() == next);
- prev->setNextSibling(child.get());
+ prev->setNextSibling(child);
} else {
ASSERT(m_firstChild == next);
- m_firstChild = child.get();
+ m_firstChild = child;
}
child->setParent(this);
child->setPreviousSibling(prev);
child->setNextSibling(next.get());
allowEventDispatch();
- // Dispatch the mutation events.
+ // Send notification about the children change.
childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1);
- dispatchChildInsertionEvents(child.get());
+ notifyChildInserted(child);
// Add child to the rendering tree.
if (attached() && !child->attached() && child->parent() == this) {
@@ -156,7 +166,9 @@ bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, Exce
child->attach();
}
- child = nextChild.release();
+ // Now that the child is attached to the render tree, dispatch
+ // the relevant mutation events.
+ dispatchChildInsertionEvents(child);
}
dispatchSubtreeModifiedEvent();
@@ -256,8 +268,7 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
child->setNextSibling(next);
allowEventDispatch();
- // Dispatch the mutation events
- dispatchChildInsertionEvents(child.get());
+ notifyChildInserted(child.get());
// Add child to the rendering tree
if (attached() && !child->attached() && child->parent() == this) {
@@ -267,6 +278,10 @@ bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, Exce
child->attach();
}
+ // Now that the child is attached to the render tree, dispatch
+ // the relevant mutation events.
+ dispatchChildInsertionEvents(child.get());
+
prev = child;
child = nextChild.release();
}
@@ -332,7 +347,14 @@ bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
}
document()->removeFocusedNodeOfSubtree(child.get());
-
+
+ // Events fired when blurring currently focused node might have moved this
+ // child into a different parent.
+ if (child->parentNode() != this) {
+ ec = NOT_FOUND_ERR;
+ return false;
+ }
+
// FIXME: After sending the mutation events, "this" could be destroyed.
// We can prevent that by doing a "ref", but first we have to make sure
// that no callers call with ref count == 0 and parent = 0 (as of this
@@ -396,33 +418,43 @@ bool ContainerNode::removeChildren()
document()->removeFocusedNodeOfSubtree(this, true);
forbidEventDispatch();
- int childCountDelta = 0;
+ Vector<RefPtr<Node> > removedChildren;
while (RefPtr<Node> n = m_firstChild) {
- childCountDelta--;
-
Node* next = n->nextSibling();
- // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744)
+ // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744).
+ // removeChild() does this after calling detach(). There is no explanation for
+ // this discrepancy between removeChild() and its optimized version removeChildren().
n->setPreviousSibling(0);
n->setNextSibling(0);
n->setParent(0);
-
+
m_firstChild = next;
if (n == m_lastChild)
m_lastChild = 0;
if (n->attached())
n->detach();
-
- if (n->inDocument())
- n->removedFromDocument();
+
+ removedChildren.append(n.release());
}
allowEventDispatch();
+ size_t removedChildrenCount = removedChildren.size();
+
// Dispatch a single post-removal mutation event denoting a modified subtree.
- childrenChanged(false, 0, 0, childCountDelta);
+ childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount));
dispatchSubtreeModifiedEvent();
+ for (size_t i = 0; i < removedChildrenCount; ++i) {
+ Node* removedChild = removedChildren[i].get();
+ if (removedChild->inDocument())
+ removedChild->removedFromDocument();
+ // removeChild() calls removedFromTree(true) if the child was not in the
+ // document. There is no explanation for this discrepancy between removeChild()
+ // and its optimized version removeChildren().
+ }
+
return true;
}
@@ -437,31 +469,26 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo
// Make sure adding the new child is ok
checkAddChild(newChild.get(), ec);
if (ec)
- return 0;
-
+ return false;
+
if (newChild == m_lastChild) // nothing to do
return newChild;
- bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE;
-
- // If newChild is a DocumentFragment with no children.... there's nothing to do.
- // Just return the document fragment
- if (isFragment && !newChild->firstChild())
+ NodeVector targets;
+ collectTargetNodes(newChild.get(), targets);
+ if (targets.isEmpty())
return true;
// Now actually add the child(ren)
RefPtr<Node> prev = lastChild();
- RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild;
- while (child) {
- // For a fragment we have more children to do.
- RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0;
-
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ Node* child = it->get();
// If child is already present in the tree, first remove it
if (Node* oldParent = child->parentNode()) {
- oldParent->removeChild(child.get(), ec);
+ oldParent->removeChild(child, ec);
if (ec)
- return 0;
-
+ return false;
+
// If the child has a parent again, just stop what we're doing, because
// that means someone is doing something with DOM mutation -- can't re-parent
// a child that already has a parent.
@@ -474,15 +501,15 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo
child->setParent(this);
if (m_lastChild) {
child->setPreviousSibling(m_lastChild);
- m_lastChild->setNextSibling(child.get());
+ m_lastChild->setNextSibling(child);
} else
- m_firstChild = child.get();
- m_lastChild = child.get();
+ m_firstChild = child;
+ m_lastChild = child;
allowEventDispatch();
- // Dispatch the mutation events
+ // Send notification about the children change.
childrenChanged(false, prev.get(), 0, 1);
- dispatchChildInsertionEvents(child.get());
+ notifyChildInserted(child);
// Add child to the rendering tree
if (attached() && !child->attached() && child->parent() == this) {
@@ -491,8 +518,10 @@ bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bo
else
child->attach();
}
-
- child = nextChild.release();
+
+ // Now that the child is attached to the render tree, dispatch
+ // the relevant mutation events.
+ dispatchChildInsertionEvents(child);
}
dispatchSubtreeModifiedEvent();
@@ -866,7 +895,7 @@ Node *ContainerNode::childNode(unsigned index) const
return n;
}
-static void dispatchChildInsertionEvents(Node* child)
+static void notifyChildInserted(Node* child)
{
ASSERT(!eventDispatchForbidden());
@@ -886,6 +915,14 @@ static void dispatchChildInsertionEvents(Node* child)
c->insertedIntoTree(true);
document->incDOMTreeVersion();
+}
+
+static void dispatchChildInsertionEvents(Node* child)
+{
+ ASSERT(!eventDispatchForbidden());
+
+ RefPtr<Node> c = child;
+ RefPtr<Document> document = child->document();
if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
diff --git a/WebCore/dom/CustomEvent.cpp b/WebCore/dom/CustomEvent.cpp
new file mode 100644
index 0000000..c377063
--- /dev/null
+++ b/WebCore/dom/CustomEvent.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "CustomEvent.h"
+
+#include "EventNames.h"
+
+namespace WebCore {
+
+CustomEvent::CustomEvent()
+{
+}
+
+void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, ScriptValue detail)
+{
+ if (dispatched())
+ return;
+
+ initEvent(type, canBubble, cancelable);
+
+ m_detail = detail;
+}
+
+bool CustomEvent::isCustomEvent() const
+{
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/dom/CustomEvent.h b/WebCore/dom/CustomEvent.h
new file mode 100644
index 0000000..d910767
--- /dev/null
+++ b/WebCore/dom/CustomEvent.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 CustomEvent_h
+#define CustomEvent_h
+
+#include "AtomicString.h"
+#include "Event.h"
+#include "ScriptValue.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CustomEvent : public Event {
+public:
+ static PassRefPtr<CustomEvent> create()
+ {
+ return adoptRef(new CustomEvent);
+ }
+
+ void initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, ScriptValue detail);
+
+ virtual bool isCustomEvent() const;
+
+ ScriptValue detail() const { return m_detail; }
+
+private:
+ CustomEvent();
+
+ ScriptValue m_detail;
+};
+
+} // namespace WebCore
+
+#endif // CustomEvent_h
diff --git a/WebCore/dom/CustomEvent.idl b/WebCore/dom/CustomEvent.idl
new file mode 100644
index 0000000..1ab468c
--- /dev/null
+++ b/WebCore/dom/CustomEvent.idl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 events {
+
+ // Introduced in DOM Level 3:
+ interface CustomEvent : Event {
+
+ readonly attribute DOMObject detail;
+
+ void initCustomEvent(in DOMString typeArg,
+ in boolean canBubbleArg,
+ in boolean cancelableArg,
+ in DOMObject detailArg);
+ };
+
+}
diff --git a/WebCore/dom/DOMCoreException.idl b/WebCore/dom/DOMCoreException.idl
index 9baea1b..2cbc589 100644
--- a/WebCore/dom/DOMCoreException.idl
+++ b/WebCore/dom/DOMCoreException.idl
@@ -28,7 +28,9 @@
module core {
- interface DOMCoreException {
+ interface [
+ NoStaticTables
+ ] DOMCoreException {
readonly attribute unsigned short code;
readonly attribute DOMString name;
diff --git a/WebCore/dom/DOMImplementation.cpp b/WebCore/dom/DOMImplementation.cpp
index f7c8242..4b7a743 100644
--- a/WebCore/dom/DOMImplementation.cpp
+++ b/WebCore/dom/DOMImplementation.cpp
@@ -31,6 +31,7 @@
#include "Element.h"
#include "ExceptionCode.h"
#include "Frame.h"
+#include "FrameLoaderClient.h"
#include "FTPDirectoryDocument.h"
#include "HTMLDocument.h"
#include "HTMLNames.h"
@@ -272,16 +273,6 @@ PassRefPtr<CSSStyleSheet> DOMImplementation::createCSSStyleSheet(const String&,
return sheet.release();
}
-PassRefPtr<Document> DOMImplementation::createDocument(Frame* frame)
-{
- return Document::create(frame);
-}
-
-PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(Frame* frame)
-{
- return HTMLDocument::create(frame);
-}
-
bool DOMImplementation::isXMLMIMEType(const String& mimeType)
{
if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
@@ -293,9 +284,10 @@ bool DOMImplementation::isXMLMIMEType(const String& mimeType)
bool DOMImplementation::isTextMIMEType(const String& mimeType)
{
- if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) ||
- (mimeType.startsWith("text/") && mimeType != "text/html" &&
- mimeType != "text/xml" && mimeType != "text/xsl"))
+ if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)
+ || mimeType == "application/json" // Render JSON as text/plain.
+ || (mimeType.startsWith("text/") && mimeType != "text/html"
+ && mimeType != "text/xml" && mimeType != "text/xsl"))
return true;
return false;
@@ -337,7 +329,7 @@ PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame
#endif
PluginData* pluginData = 0;
- if (frame && frame->page() && frame->page()->settings()->arePluginsEnabled())
+ if (frame && frame->page() && frame->loader()->allowPlugins(NotAboutToInstantiatePlugin))
pluginData = frame->page()->pluginData();
// PDF is one image type for which a plugin can override built-in support.
diff --git a/WebCore/dom/DOMImplementation.h b/WebCore/dom/DOMImplementation.h
index 9e6f9a9..b776d22 100644
--- a/WebCore/dom/DOMImplementation.h
+++ b/WebCore/dom/DOMImplementation.h
@@ -57,8 +57,6 @@ public:
// Other methods (not part of DOM)
static PassRefPtr<Document> createDocument(const String& MIMEType, Frame*, bool inViewSourceMode);
- static PassRefPtr<Document> createDocument(Frame*);
- static PassRefPtr<HTMLDocument> createHTMLDocument(Frame*);
static bool isXMLMIMEType(const String& MIMEType);
static bool isTextMIMEType(const String& MIMEType);
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp
index ae23960..5422d02 100644
--- a/WebCore/dom/Document.cpp
+++ b/WebCore/dom/Document.cpp
@@ -34,13 +34,13 @@
#include "CSSStyleSelector.h"
#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
-#include "CString.h"
#include "CachedCSSStyleSheet.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "Comment.h"
#include "Console.h"
#include "CookieJar.h"
+#include "CustomEvent.h"
#include "DOMImplementation.h"
#include "DOMWindow.h"
#include "DocLoader.h"
@@ -126,6 +126,7 @@
#include "TreeWalker.h"
#include "UIEvent.h"
#include "UserContentURLPattern.h"
+#include "ViewportArguments.h"
#include "WebKitAnimationEvent.h"
#include "WebKitTransitionEvent.h"
#include "WheelEvent.h"
@@ -408,7 +409,7 @@ Document::Document(Frame* frame, bool isXHTML, bool isHTML)
, m_normalWorldWrapperCache(0)
#endif
, m_usingGeolocation(false)
- , m_storageEventTimer(this, &Document::storageEventTimerFired)
+ , m_pendingEventTimer(this, &Document::pendingEventTimerFired)
#if ENABLE(WML)
, m_containsWMLContent(false)
#endif
@@ -448,6 +449,7 @@ Document::Document(Frame* frame, bool isXHTML, bool isHTML)
m_usesFirstLetterRules = false;
m_usesBeforeAfterRules = false;
m_usesRemUnits = false;
+ m_usesLinkRules = false;
m_gotoAnchorNeededAfterStylesheetsLoad = false;
@@ -471,7 +473,7 @@ Document::Document(Frame* frame, bool isXHTML, bool isHTML)
static int docID = 0;
m_docID = docID++;
#if ENABLE(XHTMLMP)
- m_shouldProcessNoScriptElement = settings() && !settings()->isJavaScriptEnabled();
+ m_shouldProcessNoScriptElement = m_frame->script()->canExecuteScripts(NotAboutToExecuteScript);
#endif
}
@@ -533,7 +535,7 @@ Document::~Document()
removeAllEventListeners();
#if USE(JSC)
- forgetAllDOMNodesForDocument(this);
+ destroyAllWrapperCaches();
#endif
m_tokenizer.clear();
@@ -565,15 +567,30 @@ Document::~Document()
#if USE(JSC)
Document::JSWrapperCache* Document::createWrapperCache(DOMWrapperWorld* world)
{
- JSWrapperCache* wrapperCache = new JSWrapperCache();
+ JSWrapperCache* wrapperCache = new JSWrapperCache;
m_wrapperCacheMap.set(world, wrapperCache);
if (world->isNormal()) {
ASSERT(!m_normalWorldWrapperCache);
m_normalWorldWrapperCache = wrapperCache;
}
- world->rememberDocument(this);
+ world->didCreateWrapperCache(this);
return wrapperCache;
}
+
+void Document::destroyWrapperCache(DOMWrapperWorld* world)
+{
+ Document::JSWrapperCache* wrappers = wrapperCacheMap().take(world);
+ ASSERT(wrappers);
+ delete wrappers;
+ world->didDestroyWrapperCache(this);
+}
+
+void Document::destroyAllWrapperCaches()
+{
+ JSWrapperCacheMap& wrapperCacheMap = this->wrapperCacheMap();
+ while (!wrapperCacheMap.isEmpty())
+ destroyWrapperCache(wrapperCacheMap.begin()->first);
+}
#endif
void Document::resetLinkColor()
@@ -1227,7 +1244,7 @@ void Document::setTitle(const String& title, Element* titleElement)
m_rawTitle = title;
updateTitle();
- if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag))
+ if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag) && !titleElement)
static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
}
@@ -1799,7 +1816,7 @@ void Document::close()
if (frame) {
// This code calls implicitClose() if all loading has completed.
FrameLoader* frameLoader = frame->loader();
- frameLoader->endIfNotLoadingMainResource();
+ frameLoader->writer()->endIfNotLoadingMainResource();
frameLoader->checkCompleted();
} else {
// Because we have no frame, we don't know if all loading has completed,
@@ -1866,9 +1883,9 @@ void Document::implicitClose()
ImageLoader::dispatchPendingBeforeLoadEvents();
ImageLoader::dispatchPendingLoadEvents();
dispatchWindowLoadEvent();
- dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, false), this);
+ enqueuePageshowEvent(PageshowEventNotPersisted);
if (m_pendingStateObject)
- dispatchWindowEvent(PopStateEvent::create(m_pendingStateObject.release()));
+ enqueuePopstateEvent(m_pendingStateObject.release());
if (f)
f->loader()->handledOnloadEvents();
@@ -2386,6 +2403,78 @@ void Document::processHttpEquiv(const String& equiv, const String& content)
}
}
+// Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
+static bool isSeparator(UChar c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
+}
+
+void Document::processArguments(const String& features, void* data, ArgumentsCallback callback)
+{
+ // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
+ int keyBegin, keyEnd;
+ int valueBegin, valueEnd;
+
+ int i = 0;
+ int length = features.length();
+ String buffer = features.lower();
+ while (i < length) {
+ // skip to first non-separator, but don't skip past the end of the string
+ while (isSeparator(buffer[i])) {
+ if (i >= length)
+ break;
+ i++;
+ }
+ keyBegin = i;
+
+ // skip to first separator
+ while (!isSeparator(buffer[i]))
+ i++;
+ keyEnd = i;
+
+ // skip to first '=', but don't skip past a ',' or the end of the string
+ while (buffer[i] != '=') {
+ if (buffer[i] == ',' || i >= length)
+ break;
+ i++;
+ }
+
+ // skip to first non-separator, but don't skip past a ',' or the end of the string
+ while (isSeparator(buffer[i])) {
+ if (buffer[i] == ',' || i >= length)
+ break;
+ i++;
+ }
+ valueBegin = i;
+
+ // skip to first separator
+ while (!isSeparator(buffer[i]))
+ i++;
+ valueEnd = i;
+
+ ASSERT(i <= length);
+
+ String keyString = buffer.substring(keyBegin, keyEnd - keyBegin);
+ String valueString = buffer.substring(valueBegin, valueEnd - valueBegin);
+ callback(keyString, valueString, this, data);
+ }
+}
+
+void Document::processViewport(const String& features)
+{
+ ASSERT(!features.isNull());
+
+ Frame* frame = this->frame();
+ if (!frame)
+ return;
+
+ ViewportArguments arguments;
+ processArguments(features, (void*)&arguments, &setViewportFeature);
+
+ if (frame->page())
+ frame->page()->chrome()->client()->didReceiveViewportArguments(frame, arguments);
+}
+
MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event)
{
ASSERT(!renderer() || renderer()->isRenderView());
@@ -2587,7 +2676,13 @@ void Document::updateStyleSelector()
#endif
recalcStyleSelector();
+ // This recalcStyle initiates a new recalc cycle. We need to bracket it to
+ // make sure animations get the correct update time
+ if (m_frame)
+ m_frame->animation()->beginAnimationUpdate();
recalcStyle(Force);
+ if (m_frame)
+ m_frame->animation()->endAnimationUpdate();
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!ownerElement())
@@ -2865,7 +2960,9 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
focusChangeBlocked = true;
newFocusedNode = 0;
}
- oldFocusedNode->dispatchUIEvent(eventNames().DOMFocusOutEvent, 0, 0);
+
+ oldFocusedNode->dispatchUIEvent(eventNames().focusoutEvent, 0, 0); // DOM level 3 name for the bubbling blur event.
+
if (m_focusedNode) {
// handler shifted focus
focusChangeBlocked = true;
@@ -2895,7 +2992,9 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
focusChangeBlocked = true;
goto SetFocusedNodeDone;
}
- m_focusedNode->dispatchUIEvent(eventNames().DOMFocusInEvent, 0, 0);
+
+ m_focusedNode->dispatchUIEvent(eventNames().focusinEvent, 0, 0); // DOM level 3 bubbling focus event.
+
if (m_focusedNode != newFocusedNode) {
// handler shifted focus
focusChangeBlocked = true;
@@ -3098,22 +3197,22 @@ void Document::dispatchWindowLoadEvent()
domWindow->dispatchLoadEvent();
}
-void Document::enqueueStorageEvent(PassRefPtr<Event> storageEvent)
+void Document::enqueueEvent(PassRefPtr<Event> event)
{
- m_storageEventQueue.append(storageEvent);
- if (!m_storageEventTimer.isActive())
- m_storageEventTimer.startOneShot(0);
+ m_pendingEventQueue.append(event);
+ if (!m_pendingEventTimer.isActive())
+ m_pendingEventTimer.startOneShot(0);
}
-void Document::storageEventTimerFired(Timer<Document>*)
+void Document::pendingEventTimerFired(Timer<Document>*)
{
- ASSERT(!m_storageEventTimer.isActive());
- Vector<RefPtr<Event> > storageEventQueue;
- storageEventQueue.swap(m_storageEventQueue);
+ ASSERT(!m_pendingEventTimer.isActive());
+ Vector<RefPtr<Event> > eventQueue;
+ eventQueue.swap(m_pendingEventQueue);
typedef Vector<RefPtr<Event> >::const_iterator Iterator;
- Iterator end = storageEventQueue.end();
- for (Iterator it = storageEventQueue.begin(); it != end; ++it)
+ Iterator end = eventQueue.end();
+ for (Iterator it = eventQueue.begin(); it != end; ++it)
dispatchWindowEvent(*it);
}
@@ -3122,6 +3221,8 @@ PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode&
RefPtr<Event> event;
if (eventType == "Event" || eventType == "Events" || eventType == "HTMLEvents")
event = Event::create();
+ else if (eventType == "CustomEvent")
+ event = CustomEvent::create();
else if (eventType == "KeyboardEvent" || eventType == "KeyboardEvents")
event = KeyboardEvent::create();
else if (eventType == "MessageEvent")
@@ -3160,10 +3261,9 @@ PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode&
else if (eventType == "TouchEvent")
event = TouchEvent::create();
#endif
- if (event) {
- event->setCreatedByDOM(true);
+ if (event)
return event.release();
- }
+
ec = NOT_SUPPORTED_ERR;
return 0;
}
@@ -4289,7 +4389,17 @@ void Document::finishedParsing()
{
setParsing(false);
dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false));
+
if (Frame* f = frame()) {
+ // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
+ // resource loads are complete. HTMLObjectElements can start loading their resources from
+ // post attach callbacks triggered by recalcStyle(). This means if we parse out an <object>
+ // tag and then reach the end of the document without updating styles, we might not have yet
+ // started the resource load and might fire the window load event too early. To avoid this
+ // we force the styles to be up to date before calling FrameLoader::finishedParsing().
+ // See https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
+ updateStyleIfNeeded();
+
f->loader()->finishedParsing();
#if ENABLE(INSPECTOR)
@@ -4309,13 +4419,15 @@ Vector<String> Document::formElementsState() const
typedef ListHashSet<Element*>::const_iterator Iterator;
Iterator end = m_formElementsWithState.end();
for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
- Element* e = *it;
+ Element* elementWithState = *it;
String value;
- if (e->saveFormControlState(value)) {
- stateVector.append(e->formControlName().string());
- stateVector.append(e->formControlType().string());
- stateVector.append(value);
- }
+ if (!elementWithState->shouldSaveAndRestoreFormControlState())
+ continue;
+ if (!elementWithState->saveFormControlState(value))
+ continue;
+ stateVector.append(elementWithState->formControlName().string());
+ stateVector.append(elementWithState->formControlType().string());
+ stateVector.append(value);
}
return stateVector;
}
@@ -4485,7 +4597,7 @@ void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
return;
m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard;
- m_frame->updateSecureKeyboardEntryIfActive();
+ m_frame->selection()->updateSecureKeyboardEntryIfActive();
}
bool Document::useSecureKeyboardEntryWhenActive() const
@@ -4536,7 +4648,7 @@ void Document::initSecurityContext()
} else if (!settings->allowFileAccessFromFileURLs() && securityOrigin()->isLocal()) {
// Some clients want file:// URLs to have even tighter restrictions by
// default, and not be able to access other local files.
- securityOrigin()->makeUnique();
+ securityOrigin()->enforceFilePathSeparation();
}
}
@@ -4606,7 +4718,7 @@ void Document::statePopped(SerializedScriptValue* stateObject)
return;
if (f->loader()->isComplete())
- dispatchWindowEvent(PopStateEvent::create(stateObject));
+ enqueuePopstateEvent(stateObject);
else
m_pendingStateObject = stateObject;
}
@@ -4745,70 +4857,15 @@ void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl)
void Document::reportException(const String& errorMessage, int lineNumber, const String& sourceURL)
{
- if (DOMWindow* window = domWindow())
- window->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, lineNumber, sourceURL);
-}
-
-void Document::addMessage(MessageDestination destination, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
-{
- switch (destination) {
-#if ENABLE(INSPECTOR)
- case InspectorControllerDestination:
- if (page())
- page()->inspectorController()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL);
- return;
-#endif
- case ConsoleDestination:
- if (DOMWindow* window = domWindow())
- window->console()->addMessage(source, type, level, message, lineNumber, sourceURL);
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
-void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString)
-{
-#if ENABLE(INSPECTOR)
- if (page())
- page()->inspectorController()->resourceRetrievedByXMLHttpRequest(identifier, sourceString);
-#endif
- Frame* frame = this->frame();
- if (frame) {
- FrameLoader* frameLoader = frame->loader();
- frameLoader->notifier()->didLoadResourceByXMLHttpRequest(identifier, sourceString);
- }
+ addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, lineNumber, sourceURL);
}
-void Document::scriptImported(unsigned long identifier, const String& sourceString)
+void Document::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
{
-#if ENABLE(INSPECTOR)
- if (page())
- page()->inspectorController()->scriptImported(identifier, sourceString);
-#else
- UNUSED_PARAM(identifier);
- UNUSED_PARAM(sourceString);
-#endif
+ if (DOMWindow* window = domWindow())
+ window->console()->addMessage(source, type, level, message, lineNumber, sourceURL);
}
-class ScriptExecutionContextTaskTimer : public TimerBase {
-public:
- ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassOwnPtr<ScriptExecutionContext::Task> task)
- : m_context(context)
- , m_task(task)
- {
- }
-
-private:
- virtual void fired()
- {
- m_task->performTask(m_context.get());
- delete this;
- }
-
- RefPtr<Document> m_context;
- OwnPtr<ScriptExecutionContext::Task> m_task;
-};
-
struct PerformTaskContext : Noncopyable {
PerformTaskContext(PassRefPtr<DocumentWeakReference> documentReference, PassOwnPtr<ScriptExecutionContext::Task> task)
: documentReference(documentReference)
@@ -4835,12 +4892,7 @@ static void performTask(void* ctx)
void Document::postTask(PassOwnPtr<Task> task)
{
- if (isMainThread()) {
- ScriptExecutionContextTaskTimer* timer = new ScriptExecutionContextTaskTimer(static_cast<Document*>(this), task);
- timer->startOneShot(0);
- } else {
- callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
- }
+ callOnMainThread(performTask, new PerformTaskContext(m_weakReference, task));
}
Element* Document::findAnchor(const String& name)
@@ -4886,6 +4938,26 @@ void Document::displayBufferModifiedByEncoding(UChar* buffer, unsigned len) cons
m_decoder->encoding().displayBuffer(buffer, len);
}
+void Document::enqueuePageshowEvent(PageshowEventPersistence persisted)
+{
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously.
+ dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, persisted), this);
+}
+
+void Document::enqueueHashchangeEvent(const String& /*oldURL*/, const String& /*newURL*/)
+{
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36201 Hashchange event needs to fire asynchronously.
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36335 Hashchange event is now its own interface and takes two
+ // URL arguments which we need to pass in here.
+ dispatchWindowEvent(Event::create(eventNames().hashchangeEvent, false, false));
+}
+
+void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject)
+{
+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously
+ dispatchWindowEvent(PopStateEvent::create(stateObject));
+}
+
#if ENABLE(XHTMLMP)
bool Document::isXHTMLMPDocument() const
{
@@ -4893,8 +4965,9 @@ bool Document::isXHTMLMPDocument() const
return false;
// As per section 7.2 of OMA-WAP-XHTMLMP-V1_1-20061020-A.pdf, a conforming user agent
// MUST accept XHTMLMP document identified as "application/vnd.wap.xhtml+xml"
- // and SHOULD accept it identified as "application/xhtml+xml"
- return frame()->loader()->responseMIMEType() == "application/vnd.wap.xhtml+xml" || frame()->loader()->responseMIMEType() == "application/xhtml+xml";
+ // and SHOULD accept it identified as "application/xhtml+xml" , "application/xhtml+xml" is a
+ // general MIME type for all XHTML documents, not only for XHTMLMP
+ return frame()->loader()->responseMIMEType() == "application/vnd.wap.xhtml+xml";
}
#endif
@@ -4903,6 +4976,11 @@ InspectorTimelineAgent* Document::inspectorTimelineAgent() const
{
return page() ? page()->inspectorTimelineAgent() : 0;
}
+
+InspectorController* Document::inspectorController() const
+{
+ return page() ? page()->inspectorController() : 0;
+}
#endif
} // namespace WebCore
diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h
index 3ddcaab..98d5764 100644
--- a/WebCore/dom/Document.h
+++ b/WebCore/dom/Document.h
@@ -175,6 +175,11 @@ struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
};
+enum PageshowEventPersistence {
+ PageshowEventNotPersisted = 0,
+ PageshowEventPersisted = 1
+};
+
class Document : public ContainerNode, public ScriptExecutionContext {
public:
static PassRefPtr<Document> create(Frame* frame)
@@ -435,6 +440,8 @@ public:
void setUsesBeforeAfterRules(bool b) { m_usesBeforeAfterRules = b; }
bool usesRemUnits() const { return m_usesRemUnits; }
void setUsesRemUnits(bool b) { m_usesRemUnits = b; }
+ bool usesLinkRules() const { return linkColor() != visitedLinkColor() || m_usesLinkRules; }
+ void setUsesLinkRules(bool b) { m_usesLinkRules = b; }
// Machinery for saving and restoring state when you leave and then go back to a page.
void registerFormElementWithState(Element* e) { m_formElementsWithState.add(e); }
@@ -450,6 +457,7 @@ public:
Settings* settings() const; // can be NULL
#if ENABLE(INSPECTOR)
InspectorTimelineAgent* inspectorTimelineAgent() const; // can be NULL
+ virtual InspectorController* inspectorController() const; // can be NULL
#endif
PassRefPtr<Range> createRange();
@@ -626,9 +634,6 @@ public:
void dispatchWindowEvent(PassRefPtr<Event>, PassRefPtr<EventTarget> = 0);
void dispatchWindowLoadEvent();
- void enqueueStorageEvent(PassRefPtr<Event>);
- void storageEventTimerFired(Timer<Document>*);
-
PassRefPtr<Event> createEvent(const String& eventType, ExceptionCode&);
// keep track of what types of event listeners are registered, so we don't
@@ -695,6 +700,7 @@ public:
* @param content The header value (value of the meta tag's "content" attribute)
*/
void processHttpEquiv(const String& equiv, const String& content);
+<<<<<<< HEAD
#ifdef ANDROID_META_SUPPORT
/**
@@ -703,6 +709,9 @@ public:
*/
void processMetadataSettings(const String& content);
#endif
+=======
+ void processViewport(const String& features);
+>>>>>>> webkit.org at r58033
// Returns the owning element in the parent document.
// Returns 0 if this is the top level document.
@@ -722,8 +731,28 @@ public:
String lastModified() const;
+ // The cookieURL is used to query the cookie database for this document's
+ // cookies. For example, if the cookie URL is http://example.com, we'll
+ // use the non-Secure cookies for example.com when computing
+ // document.cookie.
+ //
+ // Q: How is the cookieURL different from the document's URL?
+ // A: The two URLs are the same almost all the time. However, if one
+ // document inherits the security context of another document, it
+ // inherits its cookieURL but not its URL.
+ //
const KURL& cookieURL() const { return m_cookieURL; }
+ // The firstPartyForCookies is used to compute whether this document
+ // appears in a "third-party" context for the purpose of third-party
+ // cookie blocking. The document is in a third-party context if the
+ // cookieURL and the firstPartyForCookies are from different hosts.
+ //
+ // Note: Some ports (including possibly Apple's) only consider the
+ // document in a third-party context if the cookieURL and the
+ // firstPartyForCookies have a different registry-controlled
+ // domain.
+ //
const KURL& firstPartyForCookies() const { return m_firstPartyForCookies; }
void setFirstPartyForCookies(const KURL& url) { m_firstPartyForCookies = url; }
@@ -853,9 +882,7 @@ public:
void parseDNSPrefetchControlHeader(const String&);
virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL);
- virtual void addMessage(MessageDestination, MessageSource, MessageType, 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 addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL);
virtual void postTask(PassOwnPtr<Task>); // Executes the task on context's thread asynchronously.
#if USE(JSC)
@@ -864,6 +891,8 @@ public:
JSWrapperCacheMap& wrapperCacheMap() { return m_wrapperCacheMap; }
JSWrapperCache* getWrapperCache(DOMWrapperWorld* world);
JSWrapperCache* createWrapperCache(DOMWrapperWorld*);
+ void destroyWrapperCache(DOMWrapperWorld*);
+ void destroyAllWrapperCaches();
#endif
virtual void finishedParsing();
@@ -947,6 +976,10 @@ public:
bool containsValidityStyleRules() const { return m_containsValidityStyleRules; }
void setContainsValidityStyleRules() { m_containsValidityStyleRules = true; }
+ void enqueueEvent(PassRefPtr<Event>);
+ void enqueuePageshowEvent(PageshowEventPersistence);
+ void enqueueHashchangeEvent(const String& oldURL, const String& newURL);
+
protected:
Document(Frame*, bool isXHTML, bool isHTML);
@@ -954,6 +987,10 @@ protected:
private:
+
+ typedef void (*ArgumentsCallback)(const String& keyString, const String& valueString, Document*, void* data);
+ void processArguments(const String& features, void* data, ArgumentsCallback);
+
virtual bool isDocument() const { return true; }
virtual void removedLastRef();
virtual void determineParseMode() { }
@@ -986,6 +1023,9 @@ private:
void createStyleSelector();
+ void enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject);
+ void pendingEventTimerFired(Timer<Document>*);
+
OwnPtr<CSSStyleSelector> m_styleSelector;
bool m_didCalculateStyleSelector;
@@ -1082,6 +1122,7 @@ private:
bool m_usesFirstLetterRules;
bool m_usesBeforeAfterRules;
bool m_usesRemUnits;
+ bool m_usesLinkRules;
bool m_gotoAnchorNeededAfterStylesheetsLoad;
bool m_isDNSPrefetchEnabled;
bool m_haveExplicitlyDisabledDNSPrefetch;
@@ -1205,8 +1246,8 @@ private:
bool m_usingGeolocation;
- Timer<Document> m_storageEventTimer;
- Vector<RefPtr<Event> > m_storageEventQueue;
+ Timer<Document> m_pendingEventTimer;
+ Vector<RefPtr<Event> > m_pendingEventQueue;
#if ENABLE(WML)
bool m_containsWMLContent;
diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl
index 26ed7fd..88bd639 100644
--- a/WebCore/dom/Document.idl
+++ b/WebCore/dom/Document.idl
@@ -306,12 +306,10 @@ module core {
attribute [DontEnum] EventListener onreset;
attribute [DontEnum] EventListener onsearch;
attribute [DontEnum] EventListener onselectstart;
-#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS
- attribute [DontEnum] EventListener ontouchstart;
- attribute [DontEnum] EventListener ontouchmove;
- attribute [DontEnum] EventListener ontouchend;
- attribute [DontEnum] EventListener ontouchcancel;
-#endif
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchstart;
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchmove;
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchend;
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchcancel;
#endif
};
diff --git a/WebCore/dom/DocumentType.cpp b/WebCore/dom/DocumentType.cpp
index b8185e7..9012b68 100644
--- a/WebCore/dom/DocumentType.cpp
+++ b/WebCore/dom/DocumentType.cpp
@@ -23,7 +23,6 @@
#include "config.h"
#include "DocumentType.h"
-#include "DOMImplementation.h"
#include "Document.h"
#include "NamedNodeMap.h"
diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp
index 9e4b48d..3363e95 100644
--- a/WebCore/dom/Element.cpp
+++ b/WebCore/dom/Element.cpp
@@ -31,10 +31,10 @@
#include "CSSParser.h"
#include "CSSSelectorList.h"
#include "CSSStyleSelector.h"
-#include "CString.h"
#include "ClientRect.h"
#include "ClientRectList.h"
#include "Document.h"
+#include "DocumentFragment.h"
#include "ElementRareData.h"
#include "ExceptionCode.h"
#include "FocusController.h"
@@ -42,6 +42,7 @@
#include "FrameView.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
+#include "HTMLTokenizer.h"
#include "InspectorController.h"
#include "NamedNodeMap.h"
#include "NodeList.h"
@@ -51,6 +52,8 @@
#include "RenderWidget.h"
#include "TextIterator.h"
#include "XMLNames.h"
+#include "XMLTokenizer.h"
+#include <wtf/text/CString.h>
#if ENABLE(SVG)
#include "SVGNames.h"
@@ -93,6 +96,51 @@ NodeRareData* Element::createRareData()
{
return new ElementRareData;
}
+
+PassRefPtr<DocumentFragment> Element::createContextualFragment(const String& markup, FragmentScriptingPermission scriptingPermission)
+{
+ RefPtr<DocumentFragment> fragment = DocumentFragment::create(document());
+
+ if (document()->isHTMLDocument())
+ parseHTMLDocumentFragment(markup, fragment.get(), scriptingPermission);
+ else {
+ if (!parseXMLDocumentFragment(markup, fragment.get(), this, scriptingPermission))
+ // FIXME: We should propagate a syntax error exception out here.
+ return 0;
+ }
+
+ // Exceptions are ignored because none ought to happen here.
+ ExceptionCode ignoredExceptionCode;
+
+ // We need to pop <html> and <body> elements and remove <head> to
+ // accommodate folks passing complete HTML documents to make the
+ // child of an element.
+
+ RefPtr<Node> nextNode;
+ for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) {
+ nextNode = node->nextSibling();
+ if (node->hasTagName(htmlTag) || node->hasTagName(bodyTag)) {
+ Node* firstChild = node->firstChild();
+ if (firstChild)
+ nextNode = firstChild;
+ RefPtr<Node> nextChild;
+ for (RefPtr<Node> child = firstChild; child; child = nextChild) {
+ nextChild = child->nextSibling();
+ node->removeChild(child.get(), ignoredExceptionCode);
+ ASSERT(!ignoredExceptionCode);
+ fragment->insertBefore(child, node.get(), ignoredExceptionCode);
+ ASSERT(!ignoredExceptionCode);
+ }
+ fragment->removeChild(node.get(), ignoredExceptionCode);
+ ASSERT(!ignoredExceptionCode);
+ } else if (node->hasTagName(headTag)) {
+ fragment->removeChild(node.get(), ignoredExceptionCode);
+ ASSERT(!ignoredExceptionCode);
+ }
+ }
+
+ return fragment.release();
+}
PassRefPtr<Node> Element::cloneNode(bool deep)
{
@@ -600,7 +648,8 @@ void Element::updateAfterAttributeChanged(Attribute* attr)
} else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
// If the content of an element changes due to an attribute change, notify accessibility.
document()->axObjectCache()->contentChanged(renderer());
- }
+ } else if (attrName == aria_selectedAttr)
+ document()->axObjectCache()->selectedChildrenChanged(renderer());
}
void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
@@ -813,18 +862,25 @@ bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderS
if (!renderer() || !currentStyle)
return false;
- RenderStyle::PseudoStyleCache pseudoStyleCache;
- currentStyle->getPseudoStyleCache(pseudoStyleCache);
- size_t cacheSize = pseudoStyleCache.size();
+ const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
+ if (!pseudoStyleCache)
+ return false;
+
+ size_t cacheSize = pseudoStyleCache->size();
for (size_t i = 0; i < cacheSize; ++i) {
RefPtr<RenderStyle> newPseudoStyle;
- PseudoId pseudoId = pseudoStyleCache[i]->styleType();
- if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
+ PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
+ if (pseudoId == VISITED_LINK) {
+ newPseudoStyle = newStyle->getCachedPseudoStyle(VISITED_LINK); // This pseudo-style was aggressively computed already when we first called styleForElement on the new style.
+ if (!newPseudoStyle || *newPseudoStyle != *pseudoStyleCache->at(i))
+ return true;
+ } else if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
else
newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
-
- if (*newPseudoStyle != *pseudoStyleCache[i]) {
+ if (!newPseudoStyle)
+ return true;
+ if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
if (pseudoId < FIRST_INTERNAL_PSEUDOID)
newStyle->setHasPseudoStyle(pseudoId);
newStyle->addCachedPseudoStyle(newPseudoStyle);
@@ -1288,13 +1344,8 @@ void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
frame->selection()->setSelection(newSelection);
frame->revealSelection();
}
- }
- // FIXME: I'm not sure all devices will want this off, but this is
- // currently turned off for Android.
-#if !ENABLE(DIRECTIONAL_PAD_NAVIGATION)
- else if (renderer() && !renderer()->isWidget())
+ } else if (renderer() && !renderer()->isWidget())
renderer()->enclosingLayer()->scrollRectToVisible(getRect());
-#endif
}
void Element::blur()
@@ -1347,10 +1398,13 @@ void Element::setMinimumSizeForResizing(const IntSize& size)
ensureRareData()->m_minimumSizeForResizing = size;
}
-RenderStyle* Element::computedStyle()
+RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
{
+ // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
+ // properties, which are only known by the renderer because it did the layout, will be correct and so that the
+ // values returned for the ":selection" pseudo-element will be correct.
if (RenderStyle* usedStyle = renderStyle())
- return usedStyle;
+ return pseudoElementSpecifier ? usedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : usedStyle;
if (!attached())
// FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
@@ -1360,7 +1414,7 @@ RenderStyle* Element::computedStyle()
ElementRareData* data = ensureRareData();
if (!data->m_computedStyle)
data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this);
- return data->m_computedStyle.get();
+ return pseudoElementSpecifier ? data->m_computedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : data->m_computedStyle.get();
}
void Element::cancelFocusAppearanceUpdate()
diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h
index a5c4e96..eefaeb1 100644
--- a/WebCore/dom/Element.h
+++ b/WebCore/dom/Element.h
@@ -98,6 +98,8 @@ public:
DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
#endif
+ virtual PassRefPtr<DocumentFragment> createContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
+
const AtomicString& getIDAttribute() const;
bool hasAttribute(const QualifiedName&) const;
const AtomicString& getAttribute(const QualifiedName&) const;
@@ -199,7 +201,7 @@ public:
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void recalcStyle(StyleChange = NoChange);
- virtual RenderStyle* computedStyle();
+ RenderStyle* computedStyle(PseudoId = NOPSEUDO);
void dispatchAttrRemovalEvent(Attribute*);
void dispatchAttrAdditionEvent(Attribute*);
@@ -263,6 +265,7 @@ public:
virtual const AtomicString& formControlName() const { return nullAtom; }
virtual const AtomicString& formControlType() const { return nullAtom; }
+ virtual bool shouldSaveAndRestoreFormControlState() const { return true; }
virtual bool saveFormControlState(String&) const { return false; }
virtual void restoreFormControlState(const String&) { }
@@ -309,6 +312,7 @@ private:
virtual const AtomicString& virtualPrefix() const { return prefix(); }
virtual const AtomicString& virtualLocalName() const { return localName(); }
virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
+ virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
// cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
// are used instead.
diff --git a/WebCore/dom/Element.idl b/WebCore/dom/Element.idl
index e565bc0..1368503 100644
--- a/WebCore/dom/Element.idl
+++ b/WebCore/dom/Element.idl
@@ -195,12 +195,10 @@ module core {
attribute [DontEnum] EventListener onreset;
attribute [DontEnum] EventListener onsearch;
attribute [DontEnum] EventListener onselectstart;
-#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS
- attribute [DontEnum] EventListener ontouchstart;
- attribute [DontEnum] EventListener ontouchmove;
- attribute [DontEnum] EventListener ontouchend;
- attribute [DontEnum] EventListener ontouchcancel;
-#endif
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchstart;
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchmove;
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchend;
+ attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchcancel;
#endif
};
diff --git a/WebCore/dom/Event.cpp b/WebCore/dom/Event.cpp
index b6abb2a..506d945 100644
--- a/WebCore/dom/Event.cpp
+++ b/WebCore/dom/Event.cpp
@@ -24,6 +24,7 @@
#include "Event.h"
#include "AtomicString.h"
+#include "UserGestureIndicator.h"
#include <wtf/CurrentTime.h>
namespace WebCore {
@@ -32,10 +33,10 @@ Event::Event()
: m_canBubble(false)
, m_cancelable(false)
, m_propagationStopped(false)
+ , m_immediatePropagationStopped(false)
, m_defaultPrevented(false)
, m_defaultHandled(false)
, m_cancelBubble(false)
- , m_createdByDOM(false)
, m_eventPhase(0)
, m_currentTarget(0)
, m_createTime(static_cast<DOMTimeStamp>(currentTime() * 1000.0))
@@ -47,10 +48,10 @@ Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableAr
, m_canBubble(canBubbleArg)
, m_cancelable(cancelableArg)
, m_propagationStopped(false)
+ , m_immediatePropagationStopped(false)
, m_defaultPrevented(false)
, m_defaultHandled(false)
, m_cancelBubble(false)
- , m_createdByDOM(false)
, m_eventPhase(0)
, m_currentTarget(0)
, m_createTime(static_cast<DOMTimeStamp>(currentTime() * 1000.0))
@@ -71,6 +72,11 @@ void Event::initEvent(const AtomicString& eventTypeArg, bool canBubbleArg, bool
m_cancelable = cancelableArg;
}
+bool Event::isCustomEvent() const
+{
+ return false;
+}
+
bool Event::isUIEvent() const
{
return false;
@@ -196,7 +202,7 @@ bool Event::isTouchEvent() const
bool Event::fromUserGesture()
{
- if (createdByDOM())
+ if (!UserGestureIndicator::processingUserGesture())
return false;
const AtomicString& type = this->type();
@@ -247,4 +253,25 @@ void Event::setUnderlyingEvent(PassRefPtr<Event> ue)
m_underlyingEvent = ue;
}
+const AtomicString& Event::aliasedType() const
+{
+ if (type() == eventNames().focusinEvent)
+ return eventNames().DOMFocusInEvent;
+ if (type() == eventNames().focusoutEvent)
+ return eventNames().DOMFocusOutEvent;
+ if (type() == eventNames().DOMFocusInEvent)
+ return eventNames().focusinEvent;
+ if (type() == eventNames().DOMFocusOutEvent)
+ return eventNames().focusoutEvent;
+
+ ASSERT_NOT_REACHED();
+ return type();
+}
+
+bool Event::hasAliasedType() const
+{
+ return type() == eventNames().focusinEvent || type() == eventNames().focusoutEvent ||
+ type() == eventNames().DOMFocusInEvent || type() == eventNames().DOMFocusOutEvent;
+}
+
} // namespace WebCore
diff --git a/WebCore/dom/Event.h b/WebCore/dom/Event.h
index 0a05863..00b3341 100644
--- a/WebCore/dom/Event.h
+++ b/WebCore/dom/Event.h
@@ -75,6 +75,9 @@ namespace WebCore {
void initEvent(const AtomicString& type, bool canBubble, bool cancelable);
const AtomicString& type() const { return m_type; }
+
+ const AtomicString& aliasedType() const;
+ bool hasAliasedType() const;
EventTarget* target() const { return m_target.get(); }
void setTarget(PassRefPtr<EventTarget>);
@@ -88,8 +91,10 @@ namespace WebCore {
bool bubbles() const { return m_canBubble; }
bool cancelable() const { return m_cancelable; }
DOMTimeStamp timeStamp() const { return m_createTime; }
- void stopPropagation() { m_propagationStopped = true; }
+ void stopPropagation() { m_propagationStopped = true; }
+ void stopImmediatePropagation() { m_immediatePropagationStopped = true; }
+
// IE Extensions
EventTarget* srcElement() const { return target(); } // MSIE extension - "the object that fired the event"
@@ -98,6 +103,7 @@ namespace WebCore {
Clipboard* clipboardData() const { return isClipboardEvent() ? clipboard() : 0; }
+ virtual bool isCustomEvent() const;
virtual bool isUIEvent() const;
virtual bool isMouseEvent() const;
virtual bool isMutationEvent() const;
@@ -131,7 +137,8 @@ namespace WebCore {
#endif
bool fromUserGesture();
- bool propagationStopped() const { return m_propagationStopped; }
+ bool propagationStopped() const { return m_propagationStopped || m_immediatePropagationStopped; }
+ bool immediatePropagationStopped() const { return m_immediatePropagationStopped; }
bool defaultPrevented() const { return m_defaultPrevented; }
void preventDefault() { if (m_cancelable) m_defaultPrevented = true; }
@@ -151,9 +158,6 @@ namespace WebCore {
virtual Clipboard* clipboard() const { return 0; }
- bool createdByDOM() const { return m_createdByDOM; }
- void setCreatedByDOM(bool createdByDOM) { m_createdByDOM = createdByDOM; }
-
protected:
Event();
Event(const AtomicString& type, bool canBubble, bool cancelable);
@@ -167,13 +171,11 @@ namespace WebCore {
bool m_cancelable;
bool m_propagationStopped;
+ bool m_immediatePropagationStopped;
bool m_defaultPrevented;
bool m_defaultHandled;
bool m_cancelBubble;
- // Whether this event was created by document.createEvent().
- bool m_createdByDOM;
-
unsigned short m_eventPhase;
EventTarget* m_currentTarget;
RefPtr<EventTarget> m_target;
diff --git a/WebCore/dom/Event.idl b/WebCore/dom/Event.idl
index d64d122..919fc90 100644
--- a/WebCore/dom/Event.idl
+++ b/WebCore/dom/Event.idl
@@ -66,6 +66,10 @@ module events {
in boolean canBubbleArg,
in boolean cancelableArg);
+ // DOM Level 3 Additions.
+ readonly attribute boolean defaultPrevented;
+ void stopImmediatePropagation();
+
// IE Extensions
readonly attribute EventTarget srcElement;
attribute boolean returnValue;
diff --git a/WebCore/dom/EventListener.h b/WebCore/dom/EventListener.h
index c0d045d..249d3eb 100644
--- a/WebCore/dom/EventListener.h
+++ b/WebCore/dom/EventListener.h
@@ -47,8 +47,6 @@ namespace WebCore {
virtual ~EventListener() { }
virtual bool operator==(const EventListener&) = 0;
virtual void handleEvent(ScriptExecutionContext*, Event*) = 0;
- // Return true to indicate that the error is handled.
- virtual bool reportError(ScriptExecutionContext*, const String& /*message*/, const String& /*url*/, int /*lineNumber*/) { return false; }
virtual bool wasCreatedFromMarkup() const { return false; }
#if USE(JSC)
diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h
index b20eaa8..c50cfb2 100644
--- a/WebCore/dom/EventNames.h
+++ b/WebCore/dom/EventNames.h
@@ -60,6 +60,8 @@ namespace WebCore {
macro(drop) \
macro(error) \
macro(focus) \
+ macro(focusin) \
+ macro(focusout) \
macro(hashchange) \
macro(input) \
macro(invalid) \
@@ -100,10 +102,10 @@ namespace WebCore {
macro(zoom) \
\
macro(DOMActivate) \
- macro(DOMAttrModified) \
- macro(DOMCharacterDataModified) \
macro(DOMFocusIn) \
macro(DOMFocusOut) \
+ macro(DOMAttrModified) \
+ macro(DOMCharacterDataModified) \
macro(DOMNodeInserted) \
macro(DOMNodeInsertedIntoDocument) \
macro(DOMNodeRemoved) \
diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp
index 65d751a..1598790 100644
--- a/WebCore/dom/EventTarget.cpp
+++ b/WebCore/dom/EventTarget.cpp
@@ -272,10 +272,22 @@ bool EventTarget::fireEventListeners(Event* event)
return true;
EventListenerMap::iterator result = d->eventListenerMap.find(event->type());
- if (result == d->eventListenerMap.end())
- return false;
- EventListenerVector& entry = *result->second;
-
+ if (result != d->eventListenerMap.end())
+ fireEventListeners(event, d, *result->second);
+
+ // Alias DOMFocusIn/DOMFocusOut to focusin/focusout (and vice versa). Just consider them to be the
+ // same event (triggering one another's handlers). This mechanism allows us to deprecate or change event
+ // names in the future and still make them be interoperable.
+ if (event->hasAliasedType() && !event->immediatePropagationStopped()) {
+ EventListenerMap::iterator result = d->eventListenerMap.find(event->aliasedType());
+ if (result != d->eventListenerMap.end())
+ fireEventListeners(event, d, *result->second);
+ }
+ return !event->defaultPrevented();
+}
+
+void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
+{
RefPtr<EventTarget> protect = this;
// Fire all listeners registered for this event. Don't fire listeners removed
@@ -292,13 +304,17 @@ bool EventTarget::fireEventListeners(Event* event)
continue;
if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
continue;
+
+ // If stopImmediatePropagation has been called, we just break out immediately, without
+ // handling any more events on this target.
+ if (event->immediatePropagationStopped())
+ break;
+
// To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
// event listeners, even though that violates some versions of the DOM spec.
registeredListener.listener->handleEvent(scriptExecutionContext(), event);
}
d->firingEventIterators.removeLast();
-
- return !event->defaultPrevented();
}
const EventListenerVector& EventTarget::getEventListeners(const AtomicString& eventType)
diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h
index ece0f34..da98d98 100644
--- a/WebCore/dom/EventTarget.h
+++ b/WebCore/dom/EventTarget.h
@@ -153,6 +153,8 @@ namespace WebCore {
private:
virtual void refEventTarget() = 0;
virtual void derefEventTarget() = 0;
+
+ void fireEventListeners(Event*, EventTargetData*, EventListenerVector&);
};
#define DEFINE_ATTRIBUTE_EVENT_LISTENER(attribute) \
diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp
index 13bb0b2..52812f9 100644
--- a/WebCore/dom/InputElement.cpp
+++ b/WebCore/dom/InputElement.cpp
@@ -151,7 +151,7 @@ String InputElement::sanitizeUserInputValue(const InputElement* inputElement, co
string.replace('\r', ' ');
string.replace('\n', ' ');
- unsigned newLength = string.numCharactersInGraphemeClusters(maxLength);
+ unsigned newLength = numCharactersInGraphemeClusters(string, maxLength);
for (unsigned i = 0; i < newLength; ++i) {
const UChar current = string[i];
if (current < ' ' && current != '\t') {
@@ -170,10 +170,10 @@ void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputEl
// We use RenderTextControlSingleLine::text() instead of InputElement::value()
// because they can be mismatched by sanitizeValue() in
// RenderTextControlSingleLine::subtreeHasChanged() in some cases.
- unsigned oldLength = toRenderTextControlSingleLine(element->renderer())->text().numGraphemeClusters();
+ unsigned oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text());
// selection() may be a pre-edit text.
- unsigned selectionLength = plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
+ unsigned selectionLength = numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()));
ASSERT(oldLength >= selectionLength);
// Selected characters will be removed by the next text event.
diff --git a/WebCore/dom/KeyboardEvent.cpp b/WebCore/dom/KeyboardEvent.cpp
index 99c9220..7b0f3af 100644
--- a/WebCore/dom/KeyboardEvent.cpp
+++ b/WebCore/dom/KeyboardEvent.cpp
@@ -131,7 +131,7 @@ int KeyboardEvent::charCode() const
// Firefox: 0 for keydown/keyup events, character code for keypress
// We match Firefox, unless in backward compatibility mode, where we always return the character code.
bool backwardCompatibilityMode = false;
- if (view())
+ if (view() && view()->frame())
backwardCompatibilityMode = view()->frame()->eventHandler()->needsKeyboardEventDisambiguationQuirks();
if (!m_keyEvent || (type() != eventNames().keypressEvent && !backwardCompatibilityMode))
diff --git a/WebCore/dom/MessagePort.idl b/WebCore/dom/MessagePort.idl
index 62cf63a..9312430 100644
--- a/WebCore/dom/MessagePort.idl
+++ b/WebCore/dom/MessagePort.idl
@@ -43,12 +43,12 @@ module events {
attribute EventListener onmessage;
// EventTarget interface
- [Custom] void addEventListener(in DOMString type,
- in EventListener listener,
- in boolean useCapture);
- [Custom] void removeEventListener(in DOMString type,
+ [JSCCustom] void addEventListener(in DOMString type,
in EventListener listener,
in boolean useCapture);
+ [JSCCustom] void removeEventListener(in DOMString type,
+ in EventListener listener,
+ in boolean useCapture);
boolean dispatchEvent(in Event evt)
raises(EventException);
#endif
diff --git a/WebCore/dom/NamedNodeMap.idl b/WebCore/dom/NamedNodeMap.idl
index 4d36577..7bfbf23 100644
--- a/WebCore/dom/NamedNodeMap.idl
+++ b/WebCore/dom/NamedNodeMap.idl
@@ -28,7 +28,7 @@ module core {
Node getNamedItem(in DOMString name);
- Node setNamedItem(in Node node)
+ [Custom] Node setNamedItem(in Node node)
raises(DOMException);
Node removeNamedItem(in DOMString name)
@@ -46,7 +46,7 @@ module core {
// FIXME: the implementation does take an exceptioncode parameter.
/*raises(DOMException)*/;
- Node setNamedItemNS(in Node node)
+ [Custom] Node setNamedItemNS(in Node node)
raises(DOMException);
[OldStyleObjC] Node removeNamedItemNS(in [ConvertNullToNullString] DOMString namespaceURI,
diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp
index 49006fc..a8ffc37 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, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
@@ -39,7 +39,6 @@
#include "CSSStyleRule.h"
#include "CSSStyleSelector.h"
#include "CSSStyleSheet.h"
-#include "CString.h"
#include "ChildNodeList.h"
#include "ClassNodeList.h"
#include "ContextMenuController.h"
@@ -85,6 +84,7 @@
#include "WheelEvent.h"
#include "XMLNames.h"
#include "htmlediting.h"
+#include <wtf/text/CString.h>
#include <wtf/HashSet.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefCountedLeakCounter.h>
@@ -1087,8 +1087,7 @@ bool Node::canReplaceChild(Node* newChild, Node*)
void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec)
{
- // Perform error checking as required by spec for adding a new child. Used by
- // appendChild(), replaceChild() and insertBefore()
+ // Perform error checking as required by spec for adding a new child. Used by replaceChild().
// Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
if (!newChild) {
@@ -1143,8 +1142,7 @@ void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec)
void Node::checkAddChild(Node *newChild, ExceptionCode& ec)
{
- // Perform error checking as required by spec for adding a new child. Used by
- // appendChild(), replaceChild() and insertBefore()
+ // Perform error checking as required by spec for adding a new child. Used by appendChild() and insertBefore().
// Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
if (!newChild) {
@@ -1441,9 +1439,9 @@ void Node::setRenderStyle(PassRefPtr<RenderStyle> s)
m_renderer->setAnimatableStyle(s);
}
-RenderStyle* Node::computedStyle()
+RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
{
- return parent() ? parent()->computedStyle() : 0;
+ return parent() ? parent()->computedStyle(pseudoElementSpecifier) : 0;
}
int Node::maxCharacterOffset() const
@@ -2688,10 +2686,13 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
}
#if ENABLE(INSPECTOR)
- InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent();
- bool timelineAgentIsActive = timelineAgent && eventHasListeners(event->type(), targetForWindowEvents, this, ancestors);
- if (timelineAgentIsActive)
- timelineAgent->willDispatchEvent(*event);
+ Page* inspectedPage = InspectorTimelineAgent::instanceCount() ? document()->page() : 0;
+ if (inspectedPage) {
+ if (InspectorTimelineAgent* timelineAgent = eventHasListeners(event->type(), targetForWindowEvents, this, ancestors) ? inspectedPage->inspectorTimelineAgent() : 0)
+ timelineAgent->willDispatchEvent(*event);
+ else
+ inspectedPage = 0;
+ }
#endif
// Give the target node a chance to do some work before DOM event handlers get a crack.
@@ -2775,12 +2776,11 @@ doneDispatching:
doneWithDefault:
#if ENABLE(INSPECTOR)
- if (timelineAgentIsActive && (timelineAgent = document()->inspectorTimelineAgent()))
- timelineAgent->didDispatchEvent();
+ if (inspectedPage)
+ if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent())
+ timelineAgent->didDispatchEvent();
#endif
- Document::updateStyleForAllDocuments();
-
return !event->defaultPrevented();
}
@@ -2801,7 +2801,8 @@ void Node::dispatchSubtreeModifiedEvent()
void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent)
{
ASSERT(!eventDispatchForbidden());
- ASSERT(eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent);
+ ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().focusoutEvent ||
+ eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent);
bool cancelable = eventType == eventNames().DOMActivateEvent;
@@ -2943,7 +2944,7 @@ bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int det
if (eventType == eventNames().clickEvent && detail == 2) {
RefPtr<Event> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
true, cancelable, document()->defaultView(),
- detail, screenX, screenY, pageX, pageY,
+ detail, screenX, screenY, adjustedPageX, adjustedPageY,
ctrlKey, altKey, shiftKey, metaKey, button,
relatedTarget, 0, isSimulated);
doubleClickEvent->setUnderlyingEvent(underlyingEvent.get());
@@ -2980,14 +2981,27 @@ void Node::dispatchWheelEvent(PlatformWheelEvent& e)
}
}
- RefPtr<WheelEvent> we = WheelEvent::create(e.wheelTicksX(), e.wheelTicksY(),
+ WheelEvent::Granularity granularity;
+ switch (e.granularity()) {
+ case ScrollByPageWheelEvent:
+ granularity = WheelEvent::Page;
+ break;
+ case ScrollByPixelWheelEvent:
+ default:
+ granularity = WheelEvent::Pixel;
+ break;
+ }
+
+ RefPtr<WheelEvent> we = WheelEvent::create(e.wheelTicksX(), e.wheelTicksY(), e.deltaX(), e.deltaY(), granularity,
document()->defaultView(), e.globalX(), e.globalY(), adjustedPageX, adjustedPageY,
e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey());
we->setAbsoluteLocation(IntPoint(pos.x(), pos.y()));
- if (!dispatchEvent(we.release()))
+ if (!dispatchEvent(we) || we->defaultHandled())
e.accept();
+
+ we.release();
}
void Node::dispatchFocusEvent()
@@ -3044,6 +3058,18 @@ void Node::defaultEventHandler(Event* event)
}
}
#endif
+ } else if (eventType == eventNames().mousewheelEvent && event->isWheelEvent()) {
+ WheelEvent* wheelEvent = static_cast<WheelEvent*>(event);
+
+ // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
+ // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
+ Node* startNode = this;
+ while (startNode && !startNode->renderer())
+ startNode = startNode->parent();
+
+ if (startNode && startNode->renderer())
+ if (Frame* frame = document()->frame())
+ frame->eventHandler()->defaultWheelEventHandler(startNode, wheelEvent);
}
}
diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h
index 495bca9..b2af8fc 100644
--- a/WebCore/dom/Node.h
+++ b/WebCore/dom/Node.h
@@ -27,6 +27,7 @@
#include "EventTarget.h"
#include "KURLHash.h"
+#include "RenderStyleConstants.h"
#include "ScriptWrappable.h"
#include "TreeShared.h"
#include <wtf/ListHashSet.h>
@@ -445,7 +446,7 @@ public:
RenderStyle* renderStyle() const;
virtual void setRenderStyle(PassRefPtr<RenderStyle>);
- virtual RenderStyle* computedStyle();
+ RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); }
// -----------------------------------------------------------------------------
// Notification of document structure changes
@@ -599,8 +600,6 @@ private:
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
- void removeAllEventListenersSlowCase();
-
virtual NodeRareData* createRareData();
Node* containerChildNode(unsigned index) const;
unsigned containerChildNodeCount() const;
@@ -613,6 +612,7 @@ private:
virtual const AtomicString& virtualPrefix() const;
virtual const AtomicString& virtualLocalName() const;
virtual const AtomicString& virtualNamespaceURI() const;
+ virtual RenderStyle* virtualComputedStyle(PseudoId = NOPSEUDO);
Element* ancestorElement() const;
diff --git a/WebCore/dom/Node.idl b/WebCore/dom/Node.idl
index c6cd4b9..c0f159c 100644
--- a/WebCore/dom/Node.idl
+++ b/WebCore/dom/Node.idl
@@ -21,6 +21,7 @@
module core {
interface [
+ CustomHeader,
CustomMarkFunction,
CustomPushEventHandlerScope,
CustomToJS,
@@ -50,7 +51,7 @@ module core {
readonly attribute [ConvertNullStringTo=Null] DOMString nodeName;
// FIXME: the spec says this can also raise on retrieval.
- attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString nodeValue
+ attribute [CustomSetter, ConvertNullStringTo=Null, ConvertNullToNullString] DOMString nodeValue
setter raises(DOMException);
readonly attribute unsigned short nodeType;
@@ -61,7 +62,9 @@ module core {
readonly attribute Node previousSibling;
readonly attribute Node nextSibling;
readonly attribute NamedNodeMap attributes;
+#if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT
readonly attribute Document ownerDocument;
+#endif
[OldStyleObjC, Custom] Node insertBefore(in [Return] Node newChild,
in Node refChild)
@@ -95,7 +98,7 @@ module core {
readonly attribute [ConvertNullStringTo=Null] DOMString baseURI;
// FIXME: the spec says this can also raise on retrieval.
- attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString textContent
+ attribute [CustomSetter, ConvertNullStringTo=Null, ConvertNullToNullString] DOMString textContent
setter raises(DOMException);
boolean isSameNode(in Node other);
@@ -132,15 +135,17 @@ module core {
#endif /* defined(LANGUAGE_OBJECTIVE_C) */
#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
- [Custom] void addEventListener(in DOMString type,
- in EventListener listener,
- in boolean useCapture);
- [Custom] void removeEventListener(in DOMString type,
+#if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT
+ [JSCCustom] void addEventListener(in DOMString type,
in EventListener listener,
in boolean useCapture);
+ [JSCCustom] 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/OptionElement.h b/WebCore/dom/OptionElement.h
index a765d53..232c3ee 100644
--- a/WebCore/dom/OptionElement.h
+++ b/WebCore/dom/OptionElement.h
@@ -34,6 +34,7 @@ class OptionElement {
public:
virtual ~OptionElement() { }
+ virtual bool disabled() const = 0;
virtual bool selected() const = 0;
virtual void setSelectedState(bool) = 0;
diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp
index c0f6fa3..fa994e3 100644
--- a/WebCore/dom/Position.cpp
+++ b/WebCore/dom/Position.cpp
@@ -27,7 +27,6 @@
#include "Position.h"
#include "CSSComputedStyleDeclaration.h"
-#include "CString.h"
#include "CharacterNames.h"
#include "Logging.h"
#include "PositionIterator.h"
@@ -38,6 +37,7 @@
#include "htmlediting.h"
#include "visible_units.h"
#include <stdio.h>
+#include <wtf/text/CString.h>
namespace WebCore {
@@ -946,14 +946,7 @@ Position Position::trailingWhitespacePosition(EAffinity, bool considerNonCollaps
void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
{
- TextDirection primaryDirection = LTR;
- for (RenderObject* r = node()->renderer(); r; r = r->parent()) {
- if (r->isBlockFlow()) {
- primaryDirection = r->style()->direction();
- break;
- }
- }
- getInlineBoxAndOffset(affinity, primaryDirection, inlineBox, caretOffset);
+ getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset);
}
static bool isNonTextLeafChild(RenderObject* object)
@@ -1018,7 +1011,7 @@ void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi
inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
return;
- } else if (node()->isContentEditable()) {
+ } else if (!node()->isLink() && node()->isContentEditable()) {
Position pos = positionInParentBeforeNode(node()).upstream();
pos.getInlineBoxAndOffset(DOWNSTREAM, primaryDirection, inlineBox, caretOffset);
return;
@@ -1041,7 +1034,8 @@ void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi
return;
}
- if ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
+ if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
+ || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM)))
break;
candidate = box;
@@ -1146,6 +1140,20 @@ void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi
}
}
+TextDirection Position::primaryDirection() const
+{
+ TextDirection primaryDirection = LTR;
+ for (const RenderObject* r = m_anchorNode->renderer(); r; r = r->parent()) {
+ if (r->isBlockFlow()) {
+ primaryDirection = r->style()->direction();
+ break;
+ }
+ }
+
+ return primaryDirection;
+}
+
+
void Position::debugPosition(const char* msg) const
{
if (isNull())
diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h
index fc5849f..591b0e6 100644
--- a/WebCore/dom/Position.h
+++ b/WebCore/dom/Position.h
@@ -158,6 +158,8 @@ public:
void getInlineBoxAndOffset(EAffinity, InlineBox*&, int& caretOffset) const;
void getInlineBoxAndOffset(EAffinity, TextDirection primaryDirection, InlineBox*&, int& caretOffset) const;
+ TextDirection primaryDirection() const;
+
static bool hasRenderedNonAnonymousDescendantsWithHeight(RenderObject*);
static bool nodeIsUserSelectNone(Node*);
diff --git a/WebCore/dom/ProcessingInstruction.cpp b/WebCore/dom/ProcessingInstruction.cpp
index 122a175..544882c 100644
--- a/WebCore/dom/ProcessingInstruction.cpp
+++ b/WebCore/dom/ProcessingInstruction.cpp
@@ -165,7 +165,7 @@ void ProcessingInstruction::checkStyleSheet()
{
String charset = attrs.get("charset");
if (charset.isEmpty())
- charset = document()->frame()->loader()->encoding();
+ charset = document()->frame()->loader()->writer()->encoding();
m_cachedSheet = document()->docLoader()->requestCSSStyleSheet(url, charset);
}
diff --git a/WebCore/dom/QualifiedName.cpp b/WebCore/dom/QualifiedName.cpp
index 795bdb6..6f5a74f 100644
--- a/WebCore/dom/QualifiedName.cpp
+++ b/WebCore/dom/QualifiedName.cpp
@@ -26,9 +26,9 @@
#endif
#include "QualifiedName.h"
-#include "StaticConstructors.h"
#include <wtf/Assertions.h>
#include <wtf/HashSet.h>
+#include <wtf/StaticConstructors.h>
namespace WebCore {
diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp
index 52d1785..c704262 100644
--- a/WebCore/dom/Range.cpp
+++ b/WebCore/dom/Range.cpp
@@ -25,7 +25,6 @@
#include "Range.h"
#include "RangeException.h"
-#include "CString.h"
#include "ClientRect.h"
#include "ClientRectList.h"
#include "DocumentFragment.h"
@@ -40,6 +39,7 @@
#include "markup.h"
#include "visible_units.h"
#include <stdio.h>
+#include <wtf/text/CString.h>
#include <wtf/RefCountedLeakCounter.h>
namespace WebCore {
@@ -1661,15 +1661,13 @@ void Range::formatForDebugger(char* buffer, unsigned length) const
#undef FormatBufferSize
#endif
-bool operator==(const Range& a, const Range& b)
+bool areRangesEqual(const Range* a, const Range* b)
{
- if (&a == &b)
+ if (a == b)
return true;
- // Not strictly legal C++, but in practice this can happen, and this check works
- // fine with GCC to detect such cases and return false rather than crashing.
- if (!&a || !&b)
+ if (!a || !b)
return false;
- return a.startPosition() == b.startPosition() && a.endPosition() == b.endPosition();
+ return a->startPosition() == b->startPosition() && a->endPosition() == b->endPosition();
}
PassRefPtr<Range> rangeOfContents(Node* node)
diff --git a/WebCore/dom/Range.h b/WebCore/dom/Range.h
index fd0f66a..b1ed786 100644
--- a/WebCore/dom/Range.h
+++ b/WebCore/dom/Range.h
@@ -153,8 +153,7 @@ private:
PassRefPtr<Range> rangeOfContents(Node*);
-bool operator==(const Range&, const Range&);
-inline bool operator!=(const Range& a, const Range& b) { return !(a == b); }
+bool areRangesEqual(const Range*, const Range*);
} // namespace
diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp
index 9a80e16..22d6981 100644
--- a/WebCore/dom/ScriptElement.cpp
+++ b/WebCore/dom/ScriptElement.cpp
@@ -177,7 +177,7 @@ void ScriptElementData::evaluateScript(const ScriptSourceCode& sourceCode)
return;
if (Frame* frame = m_element->document()->frame()) {
- if (!frame->script()->canExecuteScripts())
+ if (!frame->script()->canExecuteScripts(AboutToExecuteScript))
return;
m_evaluated = true;
@@ -246,7 +246,13 @@ bool ScriptElementData::shouldExecuteAsJavaScript() const
// and we support the for syntax in script tags, this check can be removed and we should just
// return 'true' here.
String forAttribute = m_scriptElement->forAttributeValue();
- return forAttribute.isEmpty();
+ String eventAttribute = m_scriptElement->eventAttributeValue();
+ if (forAttribute.isEmpty() || eventAttribute.isEmpty())
+ return true;
+
+ forAttribute = forAttribute.stripWhiteSpace();
+ eventAttribute = eventAttribute.stripWhiteSpace();
+ return equalIgnoringCase(forAttribute, "window") && (equalIgnoringCase(eventAttribute, "onload") || equalIgnoringCase(eventAttribute, "onload()"));
}
String ScriptElementData::scriptCharset() const
@@ -257,7 +263,7 @@ String ScriptElementData::scriptCharset() const
// If charset has not been declared in script tag, fall back to frame encoding.
if (charset.isEmpty()) {
if (Frame* frame = m_element->document()->frame())
- charset = frame->loader()->encoding();
+ charset = frame->loader()->writer()->encoding();
}
return charset;
diff --git a/WebCore/dom/ScriptElement.h b/WebCore/dom/ScriptElement.h
index 0aed5e8..fad6fe7 100644
--- a/WebCore/dom/ScriptElement.h
+++ b/WebCore/dom/ScriptElement.h
@@ -43,6 +43,7 @@ public:
virtual String typeAttributeValue() const = 0;
virtual String languageAttributeValue() const = 0;
virtual String forAttributeValue() const = 0;
+ virtual String eventAttributeValue() const = 0;
virtual void dispatchLoadEvent() = 0;
virtual void dispatchErrorEvent() = 0;
diff --git a/WebCore/dom/ScriptExecutionContext.cpp b/WebCore/dom/ScriptExecutionContext.cpp
index c2fe120..226aad8 100644
--- a/WebCore/dom/ScriptExecutionContext.cpp
+++ b/WebCore/dom/ScriptExecutionContext.cpp
@@ -31,6 +31,9 @@
#include "Database.h"
#include "DatabaseTask.h"
#include "DatabaseThread.h"
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+#include "FileThread.h"
+#endif
#include "MessagePort.h"
#include "SecurityOrigin.h"
#include "WorkerContext.h"
@@ -83,6 +86,12 @@ ScriptExecutionContext::~ScriptExecutionContext()
m_databaseThread = 0;
}
#endif
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+ if (m_fileThread) {
+ m_fileThread->stop();
+ m_fileThread = 0;
+ }
+#endif
}
#if ENABLE(DATABASE)
@@ -261,6 +270,18 @@ DOMTimer* ScriptExecutionContext::findTimeout(int timeoutId)
return m_timeouts.get(timeoutId);
}
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+FileThread* ScriptExecutionContext::fileThread()
+{
+ if (!m_fileThread) {
+ m_fileThread = FileThread::create();
+ if (!m_fileThread->start())
+ m_fileThread = 0;
+ }
+ return m_fileThread.get();
+}
+#endif
+
ScriptExecutionContext::Task::~Task()
{
}
diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h
index 709bc69..d0f2e26 100644
--- a/WebCore/dom/ScriptExecutionContext.h
+++ b/WebCore/dom/ScriptExecutionContext.h
@@ -45,17 +45,16 @@ namespace WebCore {
class DatabaseThread;
#endif
class DOMTimer;
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+ class FileThread;
+#endif
class MessagePort;
class SecurityOrigin;
class ScriptString;
class String;
-
- enum MessageDestination {
#if ENABLE(INSPECTOR)
- InspectorControllerDestination,
+ class InspectorController;
#endif
- ConsoleDestination,
- };
class ScriptExecutionContext {
public:
@@ -84,11 +83,12 @@ namespace WebCore {
virtual String userAgent(const KURL&) const = 0;
SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
+#if ENABLE(INSPECTOR)
+ virtual InspectorController* inspectorController() const { return 0; }
+#endif
virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL) = 0;
- virtual void addMessage(MessageDestination, MessageSource, MessageType, 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;
+ virtual void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL) = 0;
// Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked.
bool canSuspendActiveDOMObjects();
@@ -130,6 +130,11 @@ namespace WebCore {
JSC::JSGlobalData* globalData();
#endif
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+ FileThread* fileThread();
+ void stopFileThread();
+#endif
+
protected:
// Explicitly override the security origin for this script context.
// Note: It is dangerous to change the security origin of a script context
@@ -157,6 +162,10 @@ namespace WebCore {
typedef HashSet<Database* > DatabaseSet;
OwnPtr<DatabaseSet> m_openDatabaseSet;
#endif
+
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+ RefPtr<FileThread> m_fileThread;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp
index 866b6ca..4af90c9 100644
--- a/WebCore/dom/SelectElement.cpp
+++ b/WebCore/dom/SelectElement.cpp
@@ -150,7 +150,7 @@ void SelectElement::setActiveSelectionEndIndex(SelectElementData& data, int inde
void SelectElement::updateListBoxSelection(SelectElementData& data, Element* element, bool deselectOtherOptions)
{
- ASSERT(element->renderer() && element->renderer()->isListBox());
+ ASSERT(element->renderer() && (element->renderer()->isListBox() || data.multiple()));
ASSERT(data.activeSelectionAnchorIndex() >= 0);
unsigned start = min(data.activeSelectionAnchorIndex(), data.activeSelectionEndIndex());
@@ -176,7 +176,7 @@ void SelectElement::updateListBoxSelection(SelectElementData& data, Element* ele
void SelectElement::listBoxOnChange(SelectElementData& data, Element* element)
{
- ASSERT(!data.usesMenuList());
+ ASSERT(!data.usesMenuList() || data.multiple());
Vector<bool>& lastOnChangeSelection = data.lastOnChangeSelection();
const Vector<Element*>& items = data.listItems(element);
@@ -270,11 +270,11 @@ void SelectElement::recalcListItems(SelectElementData& data, const Element* elem
if (OptionElement* optionElement = toOptionElement(current)) {
listItems.append(current);
- if (updateSelectedStates) {
- if (!foundSelected && (data.usesMenuList() || (!data.multiple() && optionElement->selected()))) {
+ if (updateSelectedStates && !data.multiple()) {
+ if (!foundSelected && (data.size() <= 1 || optionElement->selected())) {
foundSelected = optionElement;
foundSelected->setSelectedState(true);
- } else if (foundSelected && !data.multiple() && optionElement->selected()) {
+ } else if (foundSelected && optionElement->selected()) {
foundSelected->setSelectedState(false);
foundSelected = optionElement;
}
@@ -464,27 +464,15 @@ bool SelectElement::appendFormData(SelectElementData& data, Element* element, Fo
for (unsigned i = 0; i < items.size(); ++i) {
OptionElement* optionElement = toOptionElement(items[i]);
- if (optionElement && optionElement->selected()) {
+ if (optionElement && optionElement->selected() && !optionElement->disabled()) {
list.appendData(name, optionElement->value());
successful = true;
}
}
- // FIXME: This case should not happen. Make sure that we select the first option
- // in any case, otherwise we have no consistency with the DOM interface.
- // We return the first one if it was a combobox select
- if (!successful && !data.multiple() && data.size() <= 1 && items.size()) {
- OptionElement* optionElement = toOptionElement(items[0]);
- if (optionElement) {
- const AtomicString& value = optionElement->value();
- if (value.isNull())
- list.appendData(name, optionElement->text().stripWhiteSpace());
- else
- list.appendData(name, value);
- successful = true;
- }
- }
-
+ // It's possible that this is a menulist with multiple options and nothing
+ // will be submitted (!successful). We won't send a unselected non-disabled
+ // option as fallback. This behavior matches to other browsers.
return successful;
}
@@ -511,7 +499,7 @@ void SelectElement::reset(SelectElementData& data, Element* element)
firstOption = optionElement;
}
- if (!selectedOption && firstOption && data.usesMenuList())
+ if (!selectedOption && firstOption && !data.multiple() && data.size() <= 1)
firstOption->setSelectedState(true);
setOptionsChangedOnRenderer(data, element);
@@ -659,6 +647,52 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element
}
}
+void SelectElement::updateSelectedState(SelectElementData& data, Element* element, int listIndex,
+ bool multi, bool shift)
+{
+ ASSERT(listIndex >= 0);
+
+ // Save the selection so it can be compared to the new selection when dispatching change events during mouseup, or after autoscroll finishes.
+ saveLastSelection(data, element);
+
+ data.setActiveSelectionState(true);
+
+ bool shiftSelect = data.multiple() && shift;
+ bool multiSelect = data.multiple() && multi && !shift;
+
+ Element* clickedElement = data.listItems(element)[listIndex];
+ OptionElement* option = toOptionElement(clickedElement);
+ if (option) {
+ // Keep track of whether an active selection (like during drag selection), should select or deselect
+ if (option->selected() && multi)
+ data.setActiveSelectionState(false);
+
+ if (!data.activeSelectionState())
+ option->setSelectedState(false);
+ }
+
+ // If we're not in any special multiple selection mode, then deselect all other items, excluding the clicked option.
+ // If no option was clicked, then this will deselect all items in the list.
+ if (!shiftSelect && !multiSelect)
+ deselectItems(data, element, clickedElement);
+
+ // If the anchor hasn't been set, and we're doing a single selection or a shift selection, then initialize the anchor to the first selected index.
+ if (data.activeSelectionAnchorIndex() < 0 && !multiSelect)
+ setActiveSelectionAnchorIndex(data, element, selectedIndex(data, element));
+
+ // Set the selection state of the clicked option
+ if (option && !clickedElement->disabled())
+ option->setSelectedState(true);
+
+ // If there was no selectedIndex() for the previous initialization, or
+ // If we're doing a single selection, or a multiple selection (using cmd or ctrl), then initialize the anchor index to the listIndex that just got clicked.
+ if (data.activeSelectionAnchorIndex() < 0 || !shiftSelect)
+ setActiveSelectionAnchorIndex(data, element, listIndex);
+
+ setActiveSelectionEndIndex(data, listIndex);
+ updateListBoxSelection(data, element, !multiSelect);
+}
+
void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm)
{
const Vector<Element*>& listItems = data.listItems(element);
@@ -671,53 +705,11 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element*
IntPoint localOffset = roundedIntPoint(element->renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
int listIndex = toRenderListBox(element->renderer())->listIndexAtOffset(localOffset.x(), localOffset.y());
if (listIndex >= 0) {
- // Save the selection so it can be compared to the new selection when dispatching change events during mouseup, or after autoscroll finishes.
- saveLastSelection(data, element);
-
- data.setActiveSelectionState(true);
-
- bool multiSelectKeyPressed = false;
#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
- multiSelectKeyPressed = mouseEvent->metaKey();
+ updateSelectedState(data, element, listIndex, mouseEvent->metaKey(), mouseEvent->shiftKey());
#else
- multiSelectKeyPressed = mouseEvent->ctrlKey();
+ updateSelectedState(data, element, listIndex, mouseEvent->ctrlKey(), mouseEvent->shiftKey());
#endif
-
- bool shiftSelect = data.multiple() && mouseEvent->shiftKey();
- bool multiSelect = data.multiple() && multiSelectKeyPressed && !mouseEvent->shiftKey();
-
- Element* clickedElement = listItems[listIndex];
- OptionElement* option = toOptionElement(clickedElement);
- if (option) {
- // Keep track of whether an active selection (like during drag selection), should select or deselect
- if (option->selected() && multiSelectKeyPressed)
- data.setActiveSelectionState(false);
-
- if (!data.activeSelectionState())
- option->setSelectedState(false);
- }
-
- // If we're not in any special multiple selection mode, then deselect all other items, excluding the clicked option.
- // If no option was clicked, then this will deselect all items in the list.
- if (!shiftSelect && !multiSelect)
- deselectItems(data, element, clickedElement);
-
- // If the anchor hasn't been set, and we're doing a single selection or a shift selection, then initialize the anchor to the first selected index.
- if (data.activeSelectionAnchorIndex() < 0 && !multiSelect)
- setActiveSelectionAnchorIndex(data, element, selectedIndex(data, element));
-
- // Set the selection state of the clicked option
- if (option && !clickedElement->disabled())
- option->setSelectedState(true);
-
- // If there was no selectedIndex() for the previous initialization, or
- // If we're doing a single selection, or a multiple selection (using cmd or ctrl), then initialize the anchor index to the listIndex that just got clicked.
- if (listIndex >= 0 && (data.activeSelectionAnchorIndex() < 0 || !shiftSelect))
- setActiveSelectionAnchorIndex(data, element, listIndex);
-
- setActiveSelectionEndIndex(data, listIndex);
- updateListBoxSelection(data, element, !multiSelect);
-
if (Frame* frame = element->document()->frame())
frame->eventHandler()->setMouseDownMayStartAutoscroll();
@@ -750,7 +742,7 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element*
// Save the selection so it can be compared to the new selection when dispatching change events immediately after making the new selection.
saveLastSelection(data, element);
- ASSERT(endIndex >= 0 && (unsigned) endIndex < listItems.size());
+ ASSERT_UNUSED(listItems, endIndex >= 0 && (unsigned) endIndex < listItems.size());
setActiveSelectionEndIndex(data, endIndex);
// If the anchor is unitialized, or if we're going to deselect all other options, then set the anchor index equal to the end index.
@@ -954,7 +946,7 @@ SelectElementData::SelectElementData()
void SelectElementData::checkListItems(const Element* element) const
{
#if !ASSERT_DISABLED
- const Vector<Element*>& items = m_listItems;
+ Vector<Element*> items = m_listItems;
SelectElement::recalcListItems(*const_cast<SelectElementData*>(this), element, false);
ASSERT(items == m_listItems);
#else
diff --git a/WebCore/dom/SelectElement.h b/WebCore/dom/SelectElement.h
index 6891c22..dcb6879 100644
--- a/WebCore/dom/SelectElement.h
+++ b/WebCore/dom/SelectElement.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http//www.torchmobile.com/)
*
* This library is free software; you can redistribute it and/or
@@ -60,6 +61,8 @@ public:
virtual void setSelectedIndex(int index, bool deselect = true) = 0;
virtual void setSelectedIndexByUser(int index, bool deselect = true, bool fireOnChangeNow = false) = 0;
+ virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) = 0;
+
protected:
virtual ~SelectElement() { }
@@ -95,6 +98,9 @@ protected:
static void insertedIntoTree(SelectElementData&, Element*);
static void accessKeySetSelectedIndex(SelectElementData&, Element*, int index);
static unsigned optionCount(const SelectElementData&, const Element*);
+
+ static void updateSelectedState(SelectElementData& data, Element* element, int listIndex,
+ bool multi, bool shift);
private:
static void menuListDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*);
@@ -114,7 +120,14 @@ public:
int size() const { return m_size; }
void setSize(int value) { m_size = value; }
- bool usesMenuList() const { return !m_multiple && m_size <= 1; }
+ bool usesMenuList() const
+ {
+#if ENABLE(NO_LISTBOX_RENDERING)
+ return true;
+#else
+ return !m_multiple && m_size <= 1;
+#endif
+ }
int lastOnChangeIndex() const { return m_lastOnChangeIndex; }
void setLastOnChangeIndex(int value) { m_lastOnChangeIndex = value; }
diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp
index 1ce074a..cf98817 100644
--- a/WebCore/dom/Text.cpp
+++ b/WebCore/dom/Text.cpp
@@ -22,10 +22,10 @@
#include "config.h"
#include "Text.h"
-#include "CString.h"
#include "ExceptionCode.h"
#include "RenderText.h"
#include "TextBreakIterator.h"
+#include <wtf/text/CString.h>
#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
diff --git a/WebCore/dom/UserGestureIndicator.cpp b/WebCore/dom/UserGestureIndicator.cpp
new file mode 100644
index 0000000..9fb30d3
--- /dev/null
+++ b/WebCore/dom/UserGestureIndicator.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "UserGestureIndicator.h"
+
+namespace WebCore {
+
+bool UserGestureIndicator::s_processingUserGesture = false;
+
+UserGestureIndicator::UserGestureIndicator(ProcessingUserGestureState state)
+ : m_previousValue(s_processingUserGesture)
+{
+ if (state == DefinitelyProcessingUserGesture)
+ s_processingUserGesture = true;
+}
+
+UserGestureIndicator::~UserGestureIndicator()
+{
+ s_processingUserGesture = m_previousValue;
+}
+
+} // namespace WebCore
diff --git a/WebCore/dom/UserGestureIndicator.h b/WebCore/dom/UserGestureIndicator.h
new file mode 100644
index 0000000..d83d968
--- /dev/null
+++ b/WebCore/dom/UserGestureIndicator.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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.
+ */
+
+#ifndef UserGestureIndicator_h
+#define UserGestureIndicator_h
+
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+enum ProcessingUserGestureState {
+ DefinitelyProcessingUserGesture,
+ PossiblyProcessingUserGesture
+};
+
+class UserGestureIndicator : public Noncopyable {
+public:
+ static bool processingUserGesture() { return s_processingUserGesture; }
+
+ explicit UserGestureIndicator(ProcessingUserGestureState);
+ ~UserGestureIndicator();
+
+private:
+ static bool s_processingUserGesture;
+ bool m_previousValue;
+};
+
+} // namespace WebCore
+
+#endif // UserGestureIndicator_h
diff --git a/WebCore/dom/ViewportArguments.cpp b/WebCore/dom/ViewportArguments.cpp
new file mode 100644
index 0000000..d585896
--- /dev/null
+++ b/WebCore/dom/ViewportArguments.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (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) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 "ViewportArguments.h"
+
+#include "Chrome.h"
+#include "Console.h"
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Frame.h"
+#include "Page.h"
+#include "PlatformString.h"
+#include "Tokenizer.h"
+
+namespace WebCore {
+
+void setViewportFeature(const String& keyString, const String& valueString, Document* document, void* data)
+{
+ ViewportArguments* arguments = static_cast<ViewportArguments*>(data);
+ float value = ViewportArguments::ValueUndefined;
+ bool didUseConstants = false;
+
+ if (equalIgnoringCase(valueString, "yes"))
+ value = 1;
+ else if (equalIgnoringCase(valueString, "device-width")) {
+ didUseConstants = true;
+ if (document->page())
+ value = document->page()->chrome()->windowRect().width();
+ } else if (equalIgnoringCase(valueString, "device-height")) {
+ didUseConstants = true;
+ if (document->page())
+ value = document->page()->chrome()->windowRect().height();
+ } else if (equalIgnoringCase(valueString, "default")) // This allows us to distinguish the omission of a key from asking for the default value.
+ value = -2;
+ else if (valueString.length()) // listing a key with no value is shorthand for key=default
+ value = valueString.toFloat();
+
+ if (keyString == "initial-scale")
+ arguments->initialScale = value;
+ else if (keyString == "minimum-scale")
+ arguments->minimumScale = value;
+ else if (keyString == "maximum-scale") {
+ arguments->maximumScale = value;
+ if (value > 10.0)
+ reportViewportWarning(document, MaximumScaleTooLargeError, keyString);
+ } else if (keyString == "user-scalable")
+ arguments->userScalable = value;
+ else if (keyString == "width") {
+ if (document->page() && value == document->page()->chrome()->windowRect().width() && !didUseConstants)
+ reportViewportWarning(document, DeviceWidthShouldBeUsedWarning, keyString);
+ else if (document->page() && value == document->page()->chrome()->windowRect().height() && !didUseConstants)
+ reportViewportWarning(document, DeviceHeightShouldBeUsedWarning, keyString);
+
+ arguments->width = value;
+ } else if (keyString == "height") {
+ if (document->page() && value == document->page()->chrome()->windowRect().width() && !didUseConstants)
+ reportViewportWarning(document, DeviceWidthShouldBeUsedWarning, keyString);
+ else if (document->page() && value == document->page()->chrome()->windowRect().height() && !didUseConstants)
+ reportViewportWarning(document, DeviceHeightShouldBeUsedWarning, keyString);
+
+ arguments->height = value;
+ } else
+ reportViewportWarning(document, UnrecognizedViewportArgumentError, keyString);
+}
+
+static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode)
+{
+ static const char* const errors[] = {
+ "Viewport width or height set to physical device width, try using \"device-width\" constant instead for future compatibility.",
+ "Viewport height or height set to physical device height, try using \"device-height\" constant instead for future compatibility.",
+ "Viewport argument \"%replacement\" not recognized. Content ignored.",
+ "Viewport maximum-scale cannot be larger than 10.0. The maximum-scale will be set to 10.0."
+ };
+
+ return errors[errorCode];
+}
+
+static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode)
+{
+ return errorCode == UnrecognizedViewportArgumentError || errorCode == MaximumScaleTooLargeError ? ErrorMessageLevel : TipMessageLevel;
+}
+
+void reportViewportWarning(Document* document, ViewportErrorCode errorCode, const String& replacement)
+{
+ Tokenizer* tokenizer = document->tokenizer();
+
+ Frame* frame = document->frame();
+ if (!frame)
+ return;
+
+ String message = viewportErrorMessageTemplate(errorCode);
+ message.replace("%replacement", replacement);
+
+ frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, viewportErrorMessageLevel(errorCode), message, tokenizer ? tokenizer->lineNumber() + 1 : 0, document->url().string());
+}
+
+} // namespace WebCore
diff --git a/WebCore/dom/ViewportArguments.h b/WebCore/dom/ViewportArguments.h
new file mode 100644
index 0000000..29eec8e
--- /dev/null
+++ b/WebCore/dom/ViewportArguments.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (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) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 ViewportArguments_h
+#define ViewportArguments_h
+
+namespace WebCore {
+
+class Document;
+class String;
+
+enum ViewportErrorCode {
+ DeviceWidthShouldBeUsedWarning,
+ DeviceHeightShouldBeUsedWarning,
+ UnrecognizedViewportArgumentError,
+ MaximumScaleTooLargeError
+};
+
+struct ViewportArguments {
+
+ enum { ValueUndefined = -1 };
+
+ ViewportArguments()
+ : initialScale(ValueUndefined)
+ , minimumScale(ValueUndefined)
+ , maximumScale(ValueUndefined)
+ , width(ValueUndefined)
+ , height(ValueUndefined)
+ , userScalable(ValueUndefined)
+ {
+ }
+
+ float initialScale;
+ float minimumScale;
+ float maximumScale;
+ float width;
+ float height;
+
+ float userScalable;
+
+ bool hasCustomArgument() const
+ {
+ return initialScale != ValueUndefined || minimumScale != ValueUndefined || maximumScale != ValueUndefined || width != ValueUndefined || height != ValueUndefined || userScalable != ValueUndefined;
+ }
+};
+
+void setViewportFeature(const String& keyString, const String& valueString, Document*, void* data);
+void reportViewportWarning(Document*, ViewportErrorCode, const String& replacement);
+
+} // namespace WebCore
+
+#endif // ViewportArguments_h
diff --git a/WebCore/dom/WheelEvent.cpp b/WebCore/dom/WheelEvent.cpp
index 2039541..0981a57 100644
--- a/WebCore/dom/WheelEvent.cpp
+++ b/WebCore/dom/WheelEvent.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
* Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2005, 2006, 2008, 2010 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
@@ -31,21 +31,28 @@ namespace WebCore {
WheelEvent::WheelEvent()
: m_wheelDeltaX(0)
, m_wheelDeltaY(0)
+ , m_rawDeltaX(0)
+ , m_rawDeltaY(0)
+ , m_granularity(Pixel)
{
}
-WheelEvent::WheelEvent(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView> view,
+WheelEvent::WheelEvent(float wheelTicksX, float wheelTicksY, float rawDeltaX, float rawDeltaY,
+ Granularity granularity, 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,
+ true, true, view, 0, screenX, screenY, pageX, pageY,
ctrlKey, altKey, shiftKey, metaKey)
, m_wheelDeltaX(lroundf(wheelTicksX * 120))
, m_wheelDeltaY(lroundf(wheelTicksY * 120)) // Normalize to the Windows 120 multiple
+ , m_rawDeltaX(rawDeltaX)
+ , m_rawDeltaY(rawDeltaY)
+ , m_granularity(granularity)
{
}
-void WheelEvent::initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<AbstractView> view,
+void WheelEvent::initWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView> view,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
{
@@ -60,12 +67,25 @@ void WheelEvent::initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<Abs
m_altKey = altKey;
m_shiftKey = shiftKey;
m_metaKey = metaKey;
- m_wheelDeltaX = wheelDeltaX;
- m_wheelDeltaY = wheelDeltaY;
+
+ // Normalize to the Windows 120 multiple
+ m_wheelDeltaX = rawDeltaX * 120;
+ m_wheelDeltaY = rawDeltaY * 120;
+
+ m_rawDeltaX = rawDeltaX;
+ m_rawDeltaY = rawDeltaY;
+ m_granularity = Pixel;
initCoordinates(pageX, pageY);
}
+void WheelEvent::initWebKitWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView> view,
+ int screenX, int screenY, int pageX, int pageY,
+ bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
+{
+ initWheelEvent(rawDeltaX, rawDeltaY, view, screenX, screenY, pageX, pageY,
+ ctrlKey, altKey, shiftKey, metaKey);
+}
bool WheelEvent::isWheelEvent() const
{
diff --git a/WebCore/dom/WheelEvent.h b/WebCore/dom/WheelEvent.h
index 04d5421..b085e86 100644
--- a/WebCore/dom/WheelEvent.h
+++ b/WebCore/dom/WheelEvent.h
@@ -2,7 +2,7 @@
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
* Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010 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
@@ -31,39 +31,55 @@ namespace WebCore {
// extension: mouse wheel event
class WheelEvent : public MouseRelatedEvent {
public:
+ enum Granularity { Pixel, Line, Page };
+
static PassRefPtr<WheelEvent> create()
{
return adoptRef(new WheelEvent);
}
- static PassRefPtr<WheelEvent> create(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView> view,
+ static PassRefPtr<WheelEvent> create(float wheelTicksX, float wheelTicksY,
+ float rawDeltaX, float rawDeltaY, Granularity granularity, PassRefPtr<AbstractView> view,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
{
- return adoptRef(new WheelEvent(wheelTicksX, wheelTicksY, view, screenX, screenY, pageX, pageY,
+ return adoptRef(new WheelEvent(wheelTicksX, wheelTicksY, rawDeltaX, rawDeltaY,
+ granularity, view, screenX, screenY, pageX, pageY,
ctrlKey, altKey, shiftKey, metaKey));
}
- void initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<AbstractView>,
+ void initWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView>,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
+ void initWebKitWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView>,
+ int screenX, int screenY, int pageX, int pageY,
+ bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
+
int wheelDelta() const { if (m_wheelDeltaY == 0) return m_wheelDeltaX; return m_wheelDeltaY; }
int wheelDeltaX() const { return m_wheelDeltaX; }
int wheelDeltaY() const { return m_wheelDeltaY; }
+ int rawDeltaX() const { return m_rawDeltaX; }
+ int rawDeltaY() const { return m_rawDeltaY; }
+ Granularity granularity() const { return m_granularity; }
// Needed for Objective-C legacy support
bool isHorizontal() const { return m_wheelDeltaX; }
private:
WheelEvent();
- WheelEvent(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView>,
+ WheelEvent(float wheelTicksX, float wheelTicksY, float rawDeltaX, float rawDeltaY,
+ Granularity granularity, PassRefPtr<AbstractView>,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);
virtual bool isWheelEvent() const;
-
+
int m_wheelDeltaX;
int m_wheelDeltaY;
+
+ int m_rawDeltaX;
+ int m_rawDeltaY;
+ Granularity m_granularity;
};
} // namespace WebCore
diff --git a/WebCore/dom/WheelEvent.idl b/WebCore/dom/WheelEvent.idl
index a8481a0..4c709ce 100644
--- a/WebCore/dom/WheelEvent.idl
+++ b/WebCore/dom/WheelEvent.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2010 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
@@ -57,6 +57,19 @@ module events {
in boolean shiftKey,
in boolean metaKey);
#endif /* !defined(LANGUAGE_JAVASCRIPT) */
- };
+#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
+ void initWebKitWheelEvent(in long wheelDeltaX,
+ in long wheelDeltaY,
+ in DOMWindow view,
+ in long screenX,
+ in long screenY,
+ in long clientX,
+ in long clientY,
+ in boolean ctrlKey,
+ in boolean altKey,
+ in boolean shiftKey,
+ in boolean metaKey);
+#endif /* defined(LANGUAGE_JAVASCRIPT) */
+ };
}
diff --git a/WebCore/dom/XMLTokenizer.cpp b/WebCore/dom/XMLTokenizer.cpp
index 1c43322..818dacd 100644
--- a/WebCore/dom/XMLTokenizer.cpp
+++ b/WebCore/dom/XMLTokenizer.cpp
@@ -27,7 +27,6 @@
#include "XMLTokenizer.h"
#include "CDATASection.h"
-#include "CString.h"
#include "CachedScript.h"
#include "Comment.h"
#include "DocLoader.h"
@@ -51,7 +50,7 @@
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "TextResourceDecoder.h"
-#include <wtf/Platform.h>
+#include <wtf/text/CString.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
#include <wtf/Vector.h>
@@ -68,6 +67,7 @@ namespace WebCore {
using namespace HTMLNames;
const int maxErrors = 25;
+const size_t maxNestingDepth = 4096;
#if ENABLE(WML)
bool XMLTokenizer::isWMLDocument() const
@@ -87,6 +87,8 @@ void XMLTokenizer::pushCurrentNode(Node* n)
n->ref();
m_currentNodeStack.append(m_currentNode);
m_currentNode = n;
+ if (m_currentNodeStack.size() > maxNestingDepth)
+ handleError(fatal, "Excessive node nesting.", lineNumber(), columnNumber());
}
void XMLTokenizer::popCurrentNode()
@@ -206,7 +208,11 @@ void XMLTokenizer::exitText()
void XMLTokenizer::end()
{
doEnd();
-
+
+ // doEnd() could process a script tag, thus pausing parsing.
+ if (m_parserPaused)
+ return;
+
if (m_sawError)
insertErrorMessageBlock();
else {
diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp
index fcb3718..c0976a9 100644
--- a/WebCore/dom/XMLTokenizerLibxml2.cpp
+++ b/WebCore/dom/XMLTokenizerLibxml2.cpp
@@ -27,7 +27,6 @@
#include "XMLTokenizer.h"
#include "CDATASection.h"
-#include "CString.h"
#include "CachedScript.h"
#include "Comment.h"
#include "DocLoader.h"
@@ -55,7 +54,7 @@
#include "XMLTokenizerScope.h"
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
-#include <wtf/Platform.h>
+#include <wtf/text/CString.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
#include <wtf/UnusedParam.h>
@@ -786,7 +785,7 @@ void XMLTokenizer::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xm
}
ScriptController* jsProxy = m_doc->frame() ? m_doc->frame()->script() : 0;
- if (jsProxy && m_doc->frame()->script()->canExecuteScripts())
+ if (jsProxy && m_doc->frame()->script()->canExecuteScripts(NotAboutToExecuteScript))
jsProxy->setEventHandlerLineNumber(lineNumber());
handleElementAttributes(newElement.get(), libxmlAttributes, nb_attributes, ec, m_scriptingPermission);
@@ -1059,13 +1058,7 @@ void XMLTokenizer::internalSubset(const xmlChar* name, const xmlChar* externalID
}
#endif
-#if ENABLE(XHTMLMP)
- m_doc->addChild(DocumentType::create(m_doc, dtdName, extId, toString(systemID)));
-#elif ENABLE(WML)
- m_doc->addChild(DocumentType::create(m_doc, toString(name), extId, toString(systemID)));
-#else
m_doc->addChild(DocumentType::create(m_doc, toString(name), toString(externalID), toString(systemID)));
-#endif
}
}
@@ -1252,7 +1245,7 @@ static void externalSubsetHandler(void* closure, const xmlChar*, const xmlChar*
|| (extId == "-//W3C//DTD XHTML Basic 1.0//EN")
|| (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN")
|| (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN")
-#if !ENABLE(XHTMLMP)
+#if ENABLE(XHTMLMP)
|| (extId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN")
#endif
)
@@ -1314,6 +1307,9 @@ void XMLTokenizer::doEnd()
}
#endif
+ if (m_parserStopped)
+ return;
+
if (m_context) {
// Tell libxml we're done.
{
diff --git a/WebCore/dom/XMLTokenizerQt.cpp b/WebCore/dom/XMLTokenizerQt.cpp
index 5335b07..2f76b28 100644
--- a/WebCore/dom/XMLTokenizerQt.cpp
+++ b/WebCore/dom/XMLTokenizerQt.cpp
@@ -27,7 +27,6 @@
#include "XMLTokenizer.h"
#include "CDATASection.h"
-#include "CString.h"
#include "CachedScript.h"
#include "Comment.h"
#include "DocLoader.h"
@@ -52,10 +51,10 @@
#include "TextResourceDecoder.h"
#include "TransformSource.h"
#include <QDebug>
-#include <wtf/Platform.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
#if ENABLE(XHTMLMP)
#include "HTMLNames.h"
@@ -329,7 +328,7 @@ static inline void handleElementNamespaces(Element* newElement, const QXmlStream
for (int i = 0; i < ns.count(); ++i) {
const QXmlStreamNamespaceDeclaration &decl = ns[i];
String namespaceURI = decl.namespaceUri();
- String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:") + decl.prefix();
+ String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:") + String(decl.prefix());
newElement->setAttributeNS("http://www.w3.org/2000/xmlns/", namespaceQName, namespaceURI, ec, scriptingPermission);
if (ec) // exception setting attributes
return;
diff --git a/WebCore/dom/make_names.pl b/WebCore/dom/make_names.pl
index 083e309..57006d2 100755
--- a/WebCore/dom/make_names.pl
+++ b/WebCore/dom/make_names.pl
@@ -47,7 +47,14 @@ my %tags = ();
my %attrs = ();
my %parameters = ();
my $extraDefines = 0;
-my $preprocessor = "/usr/bin/gcc -E -P -x c++";
+require Config;
+my $gccLocation = "";
+if (($Config::Config{'osname'}) =~ /solaris/i) {
+ $gccLocation = "/usr/sfw/bin/gcc";
+} else {
+ $gccLocation = "/usr/bin/gcc";
+}
+my $preprocessor = $gccLocation . " -E -P -x c++";
GetOptions(
'tags=s' => \$tagsFile,
@@ -280,8 +287,10 @@ sub printConstructorInterior
# Handle media elements.
if ($tags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
print F <<END
- if (!MediaPlayer::isAvailable())
+ Settings* settings = document->settings();
+ if (!MediaPlayer::isAvailable() || (settings && !settings->isMediaEnabled()))
return HTMLElement::create($constructorTagName, document);
+
END
;
}
@@ -491,7 +500,7 @@ print F "#endif\n\n";
print F "#include \"$parameters{namespace}Names.h\"\n\n";
-print F "#include \"StaticConstructors.h\"\n";
+print F "#include <wtf/StaticConstructors.h>\n";
print F "namespace WebCore {\n\n namespace $parameters{namespace}Names {
@@ -631,7 +640,7 @@ printElementIncludes($F);
print F <<END
#include <wtf/HashMap.h>
-#if ENABLE(DASHBOARD_SUPPORT)
+#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(VIDEO)
#include "Document.h"
#include "Settings.h"
#endif
@@ -832,7 +841,8 @@ sub printWrapperFunctions
print F <<END
static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
{
- if (!MediaPlayer::isAvailable())
+ Settings* settings = element->document()->settings();
+ if (!MediaPlayer::isAvailable() || (settings && !settings->isMediaEnabled()))
return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get());
return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get());
}
@@ -850,14 +860,29 @@ END
;
}
} elsif ($wrapperFactoryType eq "V8") {
+ if ($tags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
+ print F <<END
+static v8::Handle<v8::Value> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element)
+{
+ Settings* settings = element->document()->settings();
+ if (!MediaPlayer::isAvailable() || (settings && !settings->isMediaEnabled()))
+ return toV8(static_cast<$parameters{namespace}Element*>(element));
+ return toV8(static_cast<${JSInterfaceName}*>(element));
+}
+
+END
+;
+ } else {
print F <<END
static v8::Handle<v8::Value> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element)
{
return toV8(static_cast<${JSInterfaceName}*>(element));
}
+
END
;
+ }
}
if ($conditional) {
@@ -888,7 +913,16 @@ sub printWrapperFactoryCppFile
printElementIncludes($F);
- print F "\n#include <wtf/StdLibExtras.h>\n\n";
+ print F <<END
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(VIDEO)
+#include "Document.h"
+#include "Settings.h"
+#endif
+
+END
+;
if ($wrapperFactoryType eq "JS") {
print F <<END