diff options
Diffstat (limited to 'WebCore/dom')
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 |