diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/html | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/html')
648 files changed, 25858 insertions, 21668 deletions
diff --git a/chromium/third_party/WebKit/Source/core/html/ClassList.cpp b/chromium/third_party/WebKit/Source/core/html/ClassList.cpp index ba44f7b0b0d..a6c8156260a 100644 --- a/chromium/third_party/WebKit/Source/core/html/ClassList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/ClassList.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "core/html/ClassList.h" +#include "core/dom/Document.h" namespace WebCore { @@ -32,6 +33,7 @@ using namespace HTMLNames; ClassList::ClassList(Element* element) : m_element(element) { } +#if !ENABLE(OILPAN) void ClassList::ref() { m_element->ref(); @@ -41,6 +43,7 @@ void ClassList::deref() { m_element->deref(); } +#endif unsigned ClassList::length() const { @@ -70,4 +73,10 @@ const SpaceSplitString& ClassList::classNames() const return m_element->elementData()->classNames(); } +void ClassList::trace(Visitor* visitor) +{ + visitor->trace(m_element); + DOMTokenList::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/ClassList.h b/chromium/third_party/WebKit/Source/core/html/ClassList.h index cc2217fab5e..13444d97253 100644 --- a/chromium/third_party/WebKit/Source/core/html/ClassList.h +++ b/chromium/third_party/WebKit/Source/core/html/ClassList.h @@ -25,7 +25,7 @@ #ifndef ClassList_h #define ClassList_h -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/DOMTokenList.h" #include "core/dom/Element.h" #include "core/dom/SpaceSplitString.h" @@ -38,15 +38,17 @@ class Element; typedef int ExceptionCode; -class ClassList : public DOMTokenList { +class ClassList FINAL : public DOMTokenList { public: - static PassOwnPtr<ClassList> create(Element* element) + static PassOwnPtrWillBeRawPtr<ClassList> create(Element* element) { - return adoptPtr(new ClassList(element)); + return adoptPtrWillBeNoop(new ClassList(element)); } +#if !ENABLE(OILPAN) virtual void ref() OVERRIDE; virtual void deref() OVERRIDE; +#endif virtual unsigned length() const OVERRIDE; virtual const AtomicString item(unsigned index) const OVERRIDE; @@ -55,17 +57,19 @@ public: void clearValueForQuirksMode() { m_classNamesForQuirksMode = nullptr; } + virtual void trace(Visitor*) OVERRIDE; + private: - ClassList(Element*); + explicit ClassList(Element*); virtual bool containsInternal(const AtomicString&) const OVERRIDE; const SpaceSplitString& classNames() const; - virtual AtomicString value() const OVERRIDE { return m_element->getAttribute(HTMLNames::classAttr); } + virtual const AtomicString& value() const OVERRIDE { return m_element->getAttribute(HTMLNames::classAttr); } virtual void setValue(const AtomicString& value) OVERRIDE { m_element->setAttribute(HTMLNames::classAttr, value); } - Element* m_element; + RawPtrWillBeMember<Element> m_element; mutable OwnPtr<SpaceSplitString> m_classNamesForQuirksMode; }; diff --git a/chromium/third_party/WebKit/Source/core/html/CollectionIndexCache.h b/chromium/third_party/WebKit/Source/core/html/CollectionIndexCache.h new file mode 100644 index 00000000000..865104ba059 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/CollectionIndexCache.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CollectionIndexCache_h +#define CollectionIndexCache_h + +#include "core/dom/Element.h" + +namespace WebCore { + +template <typename Collection, typename NodeType> +class CollectionIndexCache { + DISALLOW_ALLOCATION(); +public: + CollectionIndexCache(); + + bool isEmpty(const Collection& collection) + { + if (isCachedNodeCountValid()) + return !cachedNodeCount(); + if (cachedNode()) + return false; + return !nodeAt(collection, 0); + } + bool hasExactlyOneNode(const Collection& collection) + { + if (isCachedNodeCountValid()) + return cachedNodeCount() == 1; + if (cachedNode()) + return !cachedNodeIndex() && !nodeAt(collection, 1); + return nodeAt(collection, 0) && !nodeAt(collection, 1); + } + + unsigned nodeCount(const Collection&); + NodeType* nodeAt(const Collection&, unsigned index); + + void invalidate(); + + void trace(Visitor* visitor) + { + visitor->trace(m_currentNode); + } + +private: + NodeType* nodeBeforeCachedNode(const Collection&, unsigned index); + NodeType* nodeAfterCachedNode(const Collection&, unsigned index); + + ALWAYS_INLINE NodeType* cachedNode() const { return m_currentNode; } + ALWAYS_INLINE unsigned cachedNodeIndex() const { ASSERT(cachedNode()); return m_cachedNodeIndex; } + ALWAYS_INLINE void setCachedNode(NodeType* node, unsigned index) + { + ASSERT(node); + m_currentNode = node; + m_cachedNodeIndex = index; + } + + ALWAYS_INLINE bool isCachedNodeCountValid() const { return m_isLengthCacheValid; } + ALWAYS_INLINE unsigned cachedNodeCount() const { return m_cachedNodeCount; } + ALWAYS_INLINE void setCachedNodeCount(unsigned length) + { + m_cachedNodeCount = length; + m_isLengthCacheValid = true; + } + + RawPtrWillBeMember<NodeType> m_currentNode; + unsigned m_cachedNodeCount; + unsigned m_cachedNodeIndex; + unsigned m_isLengthCacheValid : 1; +}; + +template <typename Collection, typename NodeType> +CollectionIndexCache<Collection, NodeType>::CollectionIndexCache() + : m_currentNode(nullptr) + , m_cachedNodeCount(0) + , m_cachedNodeIndex(0) + , m_isLengthCacheValid(false) +{ +} + +template <typename Collection, typename NodeType> +void CollectionIndexCache<Collection, NodeType>::invalidate() +{ + m_currentNode = nullptr; + m_isLengthCacheValid = false; +} + +template <typename Collection, typename NodeType> +inline unsigned CollectionIndexCache<Collection, NodeType>::nodeCount(const Collection& collection) +{ + if (isCachedNodeCountValid()) + return cachedNodeCount(); + + nodeAt(collection, UINT_MAX); + ASSERT(isCachedNodeCountValid()); + + return cachedNodeCount(); +} + +template <typename Collection, typename NodeType> +inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAt(const Collection& collection, unsigned index) +{ + if (isCachedNodeCountValid() && index >= cachedNodeCount()) + return 0; + + if (cachedNode()) { + if (index > cachedNodeIndex()) + return nodeAfterCachedNode(collection, index); + if (index < cachedNodeIndex()) + return nodeBeforeCachedNode(collection, index); + return cachedNode(); + } + + // No valid cache yet, let's find the first matching element. + ASSERT(!isCachedNodeCountValid()); + NodeType* firstNode = collection.traverseToFirstElement(); + if (!firstNode) { + // The collection is empty. + setCachedNodeCount(0); + return 0; + } + setCachedNode(firstNode, 0); + return index ? nodeAfterCachedNode(collection, index) : firstNode; +} + +template <typename Collection, typename NodeType> +inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeBeforeCachedNode(const Collection& collection, unsigned index) +{ + ASSERT(cachedNode()); // Cache should be valid. + unsigned currentIndex = cachedNodeIndex(); + ASSERT(currentIndex > index); + + // Determine if we should traverse from the beginning of the collection instead of the cached node. + bool firstIsCloser = index < currentIndex - index; + if (firstIsCloser || !collection.canTraverseBackward()) { + NodeType* firstNode = collection.traverseToFirstElement(); + ASSERT(firstNode); + setCachedNode(firstNode, 0); + return index ? nodeAfterCachedNode(collection, index) : firstNode; + } + + // Backward traversal from the cached node to the requested index. + ASSERT(collection.canTraverseBackward()); + NodeType* currentNode = collection.traverseBackwardToOffset(index, *cachedNode(), currentIndex); + ASSERT(currentNode); + setCachedNode(currentNode, currentIndex); + return currentNode; +} + +template <typename Collection, typename NodeType> +inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAfterCachedNode(const Collection& collection, unsigned index) +{ + ASSERT(cachedNode()); // Cache should be valid. + unsigned currentIndex = cachedNodeIndex(); + ASSERT(currentIndex < index); + + // Determine if we should traverse from the end of the collection instead of the cached node. + bool lastIsCloser = isCachedNodeCountValid() && cachedNodeCount() - index < index - currentIndex; + if (lastIsCloser && collection.canTraverseBackward()) { + NodeType* lastItem = collection.traverseToLastElement(); + ASSERT(lastItem); + setCachedNode(lastItem, cachedNodeCount() - 1); + if (index < cachedNodeCount() - 1) + return nodeBeforeCachedNode(collection, index); + return lastItem; + } + + // Forward traversal from the cached node to the requested index. + NodeType* currentNode = collection.traverseForwardToOffset(index, *cachedNode(), currentIndex); + if (!currentNode) { + // Did not find the node. On plus side, we now know the length. + setCachedNodeCount(currentIndex + 1); + return 0; + } + setCachedNode(currentNode, currentIndex); + return currentNode; +} + +} // namespace WebCore + +#endif // CollectionIndexCache_h diff --git a/chromium/third_party/WebKit/Source/core/html/CollectionType.h b/chromium/third_party/WebKit/Source/core/html/CollectionType.h index 9db25d42e2e..f57a0c223b9 100644 --- a/chromium/third_party/WebKit/Source/core/html/CollectionType.h +++ b/chromium/third_party/WebKit/Source/core/html/CollectionType.h @@ -36,10 +36,6 @@ enum CollectionType { DocScripts, // all <script> elements DocAll, // "all" elements (IE) - // Named collection types cached in the document. - WindowNamedItems, - DocumentNamedItems, - // Unnamed HTMLCollection types cached in elements. NodeChildren, // first-level children (ParentNode DOM interface) TableTBodies, // all <tbody> elements in this table @@ -52,21 +48,38 @@ enum CollectionType { MapAreas, FormControls, + // Named HTMLCollection types cached in the document. + WindowNamedItems, + DocumentNamedItems, + + // Named HTMLCollection types cached in elements. + ClassCollectionType, + TagCollectionType, + HTMLTagCollectionType, + // Live NodeList. - ChildNodeListType, - ClassNodeListType, NameNodeListType, - TagNodeListType, - HTMLTagNodeListType, RadioNodeListType, + RadioImgNodeListType, LabelsNodeListType, }; -static const CollectionType FirstNodeListType = ChildNodeListType; +static const CollectionType FirstNamedCollectionType = WindowNamedItems; +static const CollectionType FirstLiveNodeListType = NameNodeListType; + +inline bool isUnnamedHTMLCollectionType(CollectionType type) +{ + return type < FirstNamedCollectionType; +} + +inline bool isHTMLCollectionType(CollectionType type) +{ + return type < FirstLiveNodeListType; +} -inline bool isNodeList(CollectionType type) +inline bool isLiveNodeListType(CollectionType type) { - return type >= FirstNodeListType; + return type >= FirstLiveNodeListType; } } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/DOMFormData.h b/chromium/third_party/WebKit/Source/core/html/DOMFormData.h index c522b72a0c8..58ce890a29d 100644 --- a/chromium/third_party/WebKit/Source/core/html/DOMFormData.h +++ b/chromium/third_party/WebKit/Source/core/html/DOMFormData.h @@ -32,6 +32,7 @@ #define DOMFormData_h #include "core/html/FormDataList.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -45,10 +46,17 @@ namespace WebCore { class Blob; class HTMLFormElement; -class DOMFormData : public FormDataList, public ScriptWrappable, public RefCounted<DOMFormData> { +class DOMFormData : public RefCountedWillBeGarbageCollectedFinalized<DOMFormData>, public FormDataList, public ScriptWrappable { public: - static PassRefPtr<DOMFormData> create(HTMLFormElement* form) { return adoptRef(new DOMFormData(form)); } - static PassRefPtr<DOMFormData> create(const WTF::TextEncoding& encoding) { return adoptRef(new DOMFormData(encoding)); } + static PassRefPtrWillBeRawPtr<DOMFormData> create(HTMLFormElement* form = 0) + { + return adoptRefWillBeNoop(new DOMFormData(form)); + } + + static PassRefPtrWillBeRawPtr<DOMFormData> create(const WTF::TextEncoding& encoding) + { + return adoptRefWillBeNoop(new DOMFormData(encoding)); + } void append(const String& name, const String& value); void append(const String& name, Blob*, const String& filename = String()); diff --git a/chromium/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp b/chromium/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp new file mode 100644 index 00000000000..223f8a90cf8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/DocumentNameCollection.cpp @@ -0,0 +1,33 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/DocumentNameCollection.h" + +#include "core/html/HTMLEmbedElement.h" +#include "core/html/HTMLFormElement.h" +#include "core/html/HTMLObjectElement.h" + +namespace WebCore { + +DocumentNameCollection::DocumentNameCollection(ContainerNode& document, const AtomicString& name) + : HTMLNameCollection(document, DocumentNamedItems, name) +{ +} + +bool DocumentNameCollection::elementMatches(const Element& element) const +{ + // Match images, forms, applets, embeds, objects and iframes by name, + // applets and object by id, and images by id but only if they have + // a name attribute (this very strange rule matches IE) + if (isHTMLFormElement(element) || isHTMLIFrameElement(element) || (isHTMLEmbedElement(element) && toHTMLEmbedElement(element).isExposed())) + return element.getNameAttribute() == m_name; + if (isHTMLAppletElement(element) || (isHTMLObjectElement(element) && toHTMLObjectElement(element).isExposed())) + return element.getNameAttribute() == m_name || element.getIdAttribute() == m_name; + if (isHTMLImageElement(element)) + return element.getNameAttribute() == m_name || (element.getIdAttribute() == m_name && element.hasName()); + return false; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/DocumentNameCollection.h b/chromium/third_party/WebKit/Source/core/html/DocumentNameCollection.h new file mode 100644 index 00000000000..2789bacfb9b --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/DocumentNameCollection.h @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DocumentNameCollection_h +#define DocumentNameCollection_h + +#include "core/html/HTMLNameCollection.h" + +namespace WebCore { + +class DocumentNameCollection FINAL : public HTMLNameCollection { +public: + static PassRefPtrWillBeRawPtr<DocumentNameCollection> create(ContainerNode& document, CollectionType type, const AtomicString& name) + { + ASSERT_UNUSED(type, type == DocumentNamedItems); + return adoptRefWillBeNoop(new DocumentNameCollection(document, name)); + } + + bool elementMatches(const Element&) const; + +private: + DocumentNameCollection(ContainerNode& document, const AtomicString& name); +}; + +DEFINE_TYPE_CASTS(DocumentNameCollection, LiveNodeListBase, collection, collection->type() == DocumentNamedItems, collection.type() == DocumentNamedItems); + +} // namespace WebCore + +#endif // DocumentNameCollection_h diff --git a/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp b/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp index ce1f4b58ddb..41c49e81d43 100644 --- a/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "core/html/FormAssociatedElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/IdTargetObserver.h" #include "core/html/HTMLFormControlElement.h" #include "core/html/HTMLFormElement.h" @@ -36,20 +36,21 @@ namespace WebCore { using namespace HTMLNames; -class FormAttributeTargetObserver : IdTargetObserver { - WTF_MAKE_FAST_ALLOCATED; +class FormAttributeTargetObserver : public IdTargetObserver { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<FormAttributeTargetObserver> create(const AtomicString& id, FormAssociatedElement*); + static PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> create(const AtomicString& id, FormAssociatedElement*); + virtual void trace(Visitor*) OVERRIDE; virtual void idTargetChanged() OVERRIDE; private: FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement*); - FormAssociatedElement* m_element; + RawPtrWillBeMember<FormAssociatedElement> m_element; }; FormAssociatedElement::FormAssociatedElement() - : m_form(0) + : m_formWasSetByParser(false) { } @@ -58,6 +59,13 @@ FormAssociatedElement::~FormAssociatedElement() // We can't call setForm here because it contains virtual calls. } +void FormAssociatedElement::trace(Visitor* visitor) +{ + visitor->trace(m_formAttributeTargetObserver); + visitor->trace(m_form); + visitor->trace(m_validityState); +} + ValidityState* FormAssociatedElement::validity() { if (!m_validityState) @@ -70,15 +78,14 @@ void FormAssociatedElement::didMoveToNewDocument(Document& oldDocument) { HTMLElement* element = toHTMLElement(this); if (element->fastHasAttribute(formAttr)) - m_formAttributeTargetObserver = nullptr; + setFormAttributeTargetObserver(nullptr); } void FormAssociatedElement::insertedInto(ContainerNode* insertionPoint) { - if (m_form && insertionPoint->highestAncestor() != m_form->highestAncestor()) - setForm(0); + if (!m_formWasSetByParser || insertionPoint->highestAncestorOrSelf() != m_form->highestAncestorOrSelf()) + resetFormOwner(); - resetFormOwner(); if (!insertionPoint->inDocument()) return; @@ -91,52 +98,71 @@ void FormAssociatedElement::removedFrom(ContainerNode* insertionPoint) { HTMLElement* element = toHTMLElement(this); if (insertionPoint->inDocument() && element->fastHasAttribute(formAttr)) - m_formAttributeTargetObserver = nullptr; + setFormAttributeTargetObserver(nullptr); // If the form and element are both in the same tree, preserve the connection to the form. // Otherwise, null out our form and remove ourselves from the form's list of elements. - if (m_form && element->highestAncestor() != m_form->highestAncestor()) - setForm(0); + if (m_form && element->highestAncestorOrSelf() != m_form->highestAncestorOrSelf()) + resetFormOwner(); } -HTMLFormElement* FormAssociatedElement::findAssociatedForm(const HTMLElement* element, HTMLFormElement* currentAssociatedForm) +HTMLFormElement* FormAssociatedElement::findAssociatedForm(const HTMLElement* element) { const AtomicString& formId(element->fastGetAttribute(formAttr)); + // 3. If the element is reassociateable, has a form content attribute, and + // is itself in a Document, then run these substeps: if (!formId.isNull() && element->inDocument()) { - // The HTML5 spec says that the element should be associated with - // the first element in the document to have an ID that equal to - // the value of form attribute, so we put the result of - // treeScope()->getElementById() over the given element. - HTMLFormElement* newForm = 0; + // 3.1. If the first element in the Document to have an ID that is + // case-sensitively equal to the element's form content attribute's + // value is a form element, then associate the form-associated element + // with that form element. + // 3.2. Abort the "reset the form owner" steps. Element* newFormCandidate = element->treeScope().getElementById(formId); - if (newFormCandidate && newFormCandidate->hasTagName(formTag)) - newForm = toHTMLFormElement(newFormCandidate); - return newForm; + return isHTMLFormElement(newFormCandidate) ? toHTMLFormElement(newFormCandidate) : 0; } - - if (!currentAssociatedForm) - return element->findFormAncestor(); - - return currentAssociatedForm; + // 4. Otherwise, if the form-associated element in question has an ancestor + // form element, then associate the form-associated element with the nearest + // such ancestor form element. + return element->findFormAncestor(); } -void FormAssociatedElement::formRemovedFromTree(const Node* formRoot) +void FormAssociatedElement::formRemovedFromTree(const Node& formRoot) { ASSERT(m_form); - if (toHTMLElement(this)->highestAncestor() == formRoot) + if (toHTMLElement(this)->highestAncestorOrSelf() == formRoot) return; - setForm(0); + resetFormOwner(); +} + +void FormAssociatedElement::associateByParser(HTMLFormElement* form) +{ + if (form && form->inDocument()) { + m_formWasSetByParser = true; + setForm(form); + form->didAssociateByParser(); + } } void FormAssociatedElement::setForm(HTMLFormElement* newForm) { - if (m_form == newForm) + if (m_form.get() == newForm) return; willChangeForm(); if (m_form) - m_form->removeFormElement(this); - m_form = newForm; - if (m_form) - m_form->registerFormElement(*this); + m_form->disassociate(*this); + if (newForm) { +#if ENABLE(OILPAN) + m_form = newForm; +#else + m_form = newForm->createWeakPtr(); +#endif + m_form->associate(*this); + } else { +#if ENABLE(OILPAN) + m_form = nullptr; +#else + m_form = WeakPtr<HTMLFormElement>(); +#endif + } didChangeForm(); } @@ -148,41 +174,31 @@ void FormAssociatedElement::didChangeForm() { } -void FormAssociatedElement::formWillBeDestroyed() -{ - ASSERT(m_form); - if (!m_form) - return; - willChangeForm(); - m_form = 0; - didChangeForm(); -} - void FormAssociatedElement::resetFormOwner() { - HTMLFormElement* originalForm = m_form; - setForm(findAssociatedForm(toHTMLElement(this), m_form)); + m_formWasSetByParser = false; HTMLElement* element = toHTMLElement(this); - if (m_form && m_form != originalForm && m_form->inDocument()) + const AtomicString& formId(element->fastGetAttribute(formAttr)); + HTMLFormElement* nearestForm = element->findFormAncestor(); + // 1. If the element's form owner is not null, and either the element is not + // reassociateable or its form content attribute is not present, and the + // element's form owner is its nearest form element ancestor after the + // change to the ancestor chain, then do nothing, and abort these steps. + if (m_form && formId.isNull() && m_form.get() == nearestForm) + return; + + HTMLFormElement* originalForm = m_form.get(); + setForm(findAssociatedForm(element)); + // FIXME: Move didAssociateFormControl call to didChangeForm or + // HTMLFormElement::associate. + if (m_form && m_form.get() != originalForm && m_form->inDocument()) element->document().didAssociateFormControl(element); } void FormAssociatedElement::formAttributeChanged() { - HTMLElement* element = toHTMLElement(this); - if (!element->fastHasAttribute(formAttr)) { - // The form attribute removed. We need to reset form owner here. - HTMLFormElement* originalForm = m_form; - setForm(element->findFormAncestor()); - HTMLElement* element = toHTMLElement(this); - if (m_form && m_form != originalForm && m_form->inDocument()) - element->document().didAssociateFormControl(element); - m_formAttributeTargetObserver = nullptr; - } else { - resetFormOwner(); - if (element->inDocument()) - resetFormAttributeTargetObserver(); - } + resetFormOwner(); + resetFormAttributeTargetObserver(); } bool FormAssociatedElement::customError() const @@ -253,10 +269,21 @@ void FormAssociatedElement::setCustomValidity(const String& error) m_customValidationMessage = error; } +void FormAssociatedElement::setFormAttributeTargetObserver(PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> newObserver) +{ + if (m_formAttributeTargetObserver) + m_formAttributeTargetObserver->unregister(); + m_formAttributeTargetObserver = newObserver; +} + void FormAssociatedElement::resetFormAttributeTargetObserver() { - ASSERT(toHTMLElement(this)->inDocument()); - m_formAttributeTargetObserver = FormAttributeTargetObserver::create(toHTMLElement(this)->fastGetAttribute(formAttr), this); + HTMLElement* element = toHTMLElement(this); + const AtomicString& formId(element->fastGetAttribute(formAttr)); + if (!formId.isNull() && element->inDocument()) + setFormAttributeTargetObserver(FormAttributeTargetObserver::create(formId, this)); + else + setFormAttributeTargetObserver(nullptr); } void FormAssociatedElement::formAttributeTargetChanged() @@ -299,9 +326,9 @@ HTMLElement& toHTMLElement(FormAssociatedElement& associatedElement) return const_cast<HTMLElement&>(toHTMLElement(static_cast<const FormAssociatedElement&>(associatedElement))); } -PassOwnPtr<FormAttributeTargetObserver> FormAttributeTargetObserver::create(const AtomicString& id, FormAssociatedElement* element) +PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> FormAttributeTargetObserver::create(const AtomicString& id, FormAssociatedElement* element) { - return adoptPtr(new FormAttributeTargetObserver(id, element)); + return adoptPtrWillBeNoop(new FormAttributeTargetObserver(id, element)); } FormAttributeTargetObserver::FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement* element) @@ -310,6 +337,12 @@ FormAttributeTargetObserver::FormAttributeTargetObserver(const AtomicString& id, { } +void FormAttributeTargetObserver::trace(Visitor* visitor) +{ + visitor->trace(m_element); + IdTargetObserver::trace(visitor); +} + void FormAttributeTargetObserver::idTargetChanged() { m_element->formAttributeTargetChanged(); diff --git a/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.h b/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.h index 15f2fa1fbc8..e41483a55c0 100644 --- a/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.h +++ b/chromium/third_party/WebKit/Source/core/html/FormAssociatedElement.h @@ -24,6 +24,8 @@ #ifndef FormAssociatedElement_h #define FormAssociatedElement_h +#include "platform/heap/Handle.h" +#include "wtf/WeakPtr.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -39,15 +41,17 @@ class ValidationMessage; class ValidityState; class VisibleSelection; -class FormAssociatedElement { +class FormAssociatedElement : public WillBeGarbageCollectedMixin { public: virtual ~FormAssociatedElement(); +#if !ENABLE(OILPAN) void ref() { refFormAssociatedElement(); } void deref() { derefFormAssociatedElement(); } +#endif - static HTMLFormElement* findAssociatedForm(const HTMLElement*, HTMLFormElement*); - HTMLFormElement* form() const { return m_form; } + static HTMLFormElement* findAssociatedForm(const HTMLElement*); + HTMLFormElement* form() const { return m_form.get(); } ValidityState* validity(); virtual bool isFormControlElement() const = 0; @@ -63,11 +67,9 @@ public: // Return true for a successful control (see HTML4-17.13.2). virtual bool appendFormData(FormDataList&, bool) { return false; } - void formWillBeDestroyed(); - void resetFormOwner(); - void formRemovedFromTree(const Node* formRoot); + void formRemovedFromTree(const Node& formRoot); // ValidityState attribute implementations bool customError() const; @@ -88,14 +90,20 @@ public: void formAttributeTargetChanged(); + typedef WillBeHeapVector<RawPtrWillBeMember<FormAssociatedElement> > List; + protected: FormAssociatedElement(); + void trace(Visitor*); void insertedInto(ContainerNode*); void removedFrom(ContainerNode*); void didMoveToNewDocument(Document& oldDocument); + // FIXME: Remove usage of setForm. resetFormOwner should be enough, and + // setForm is confusing. void setForm(HTMLFormElement*); + void associateByParser(HTMLFormElement*); void formAttributeChanged(); // If you add an override of willChangeForm() or didChangeForm() to a class @@ -107,15 +115,23 @@ protected: String customValidationMessage() const; private: +#if !ENABLE(OILPAN) virtual void refFormAssociatedElement() = 0; virtual void derefFormAssociatedElement() = 0; +#endif + void setFormAttributeTargetObserver(PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver>); void resetFormAttributeTargetObserver(); - OwnPtr<FormAttributeTargetObserver> m_formAttributeTargetObserver; - HTMLFormElement* m_form; - OwnPtr<ValidityState> m_validityState; + OwnPtrWillBeMember<FormAttributeTargetObserver> m_formAttributeTargetObserver; +#if ENABLE(OILPAN) + Member<HTMLFormElement> m_form; +#else + WeakPtr<HTMLFormElement> m_form; +#endif + OwnPtrWillBeMember<ValidityState> m_validityState; String m_customValidationMessage; + bool m_formWasSetByParser; }; HTMLElement* toHTMLElement(FormAssociatedElement*); diff --git a/chromium/third_party/WebKit/Source/core/html/FormData.idl b/chromium/third_party/WebKit/Source/core/html/FormData.idl index 73dcbfb9479..49914a7b35c 100644 --- a/chromium/third_party/WebKit/Source/core/html/FormData.idl +++ b/chromium/third_party/WebKit/Source/core/html/FormData.idl @@ -28,14 +28,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#formdata + [ - Constructor([Default=Undefined] optional HTMLFormElement form), - ImplementedAs=DOMFormData + Constructor(optional HTMLFormElement form), + Exposed=Window&Worker, + ImplementedAs=DOMFormData, + WillBeGarbageCollected, ] interface FormData { - // void append(DOMString name, DOMString value); - // void append(DOMString name, Blob value, optional DOMString filename); - [Custom] void append([Default=Undefined] optional DOMString name, - [Default=Undefined] optional DOMString value, - [Default=Undefined] optional DOMString filename); + void append(DOMString name, Blob value, optional DOMString filename); + void append(DOMString name, DOMString value); }; - diff --git a/chromium/third_party/WebKit/Source/core/html/FormDataList.cpp b/chromium/third_party/WebKit/Source/core/html/FormDataList.cpp index b564d2cc102..39aa18ddaed 100644 --- a/chromium/third_party/WebKit/Source/core/html/FormDataList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/FormDataList.cpp @@ -43,22 +43,22 @@ void FormDataList::appendString(const CString& string) m_items.append(string); } -void FormDataList::appendBlob(PassRefPtr<Blob> blob, const String& filename) +void FormDataList::appendBlob(PassRefPtrWillBeRawPtr<Blob> blob, const String& filename) { m_items.append(Item(blob, filename)); } -PassRefPtr<FormData> FormDataList::createFormData(const WTF::TextEncoding& encoding, FormData::EncodingType encodingType) +PassRefPtr<FormData> FormDataList::createFormData(FormData::EncodingType encodingType) { RefPtr<FormData> result = FormData::create(); - appendKeyValuePairItemsTo(result.get(), encoding, false, encodingType); + appendKeyValuePairItemsTo(result.get(), m_encoding, false, encodingType); return result.release(); } -PassRefPtr<FormData> FormDataList::createMultiPartFormData(const WTF::TextEncoding& encoding) +PassRefPtr<FormData> FormDataList::createMultiPartFormData() { RefPtr<FormData> result = FormData::create(); - appendKeyValuePairItemsTo(result.get(), encoding, true); + appendKeyValuePairItemsTo(result.get(), m_encoding, true); return result.release(); } @@ -69,7 +69,7 @@ void FormDataList::appendKeyValuePairItemsTo(FormData* formData, const WTF::Text Vector<char> encodedData; - const Vector<FormDataList::Item>& items = this->items(); + const WillBeHeapVector<Item>& items = this->items(); size_t formDataListSize = items.size(); ASSERT(!(formDataListSize % 2)); for (size_t i = 0; i < formDataListSize; i += 2) { @@ -130,12 +130,7 @@ void FormDataList::appendKeyValuePairItemsTo(FormData* formData, const WTF::Text } formData->appendData("\r\n", 2); } else { - // Omit the name "isindex" if it's the first form data element. - // FIXME: Why is this a good rule? Is this obsolete now? - if (encodedData.isEmpty() && key.data() == "isindex") - FormDataBuilder::encodeStringAsFormData(encodedData, value.data()); - else - FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data(), encodingType); + FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data(), encodingType); } } @@ -145,4 +140,14 @@ void FormDataList::appendKeyValuePairItemsTo(FormData* formData, const WTF::Text formData->appendData(encodedData.data(), encodedData.size()); } +void FormDataList::trace(Visitor* visitor) +{ + visitor->trace(m_items); +} + +void FormDataList::Item::trace(Visitor* visitor) +{ + visitor->trace(m_blob); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/FormDataList.h b/chromium/third_party/WebKit/Source/core/html/FormDataList.h index 123e566f621..301365951d1 100644 --- a/chromium/third_party/WebKit/Source/core/html/FormDataList.h +++ b/chromium/third_party/WebKit/Source/core/html/FormDataList.h @@ -22,6 +22,7 @@ #define FormDataList_h #include "core/fileapi/Blob.h" +#include "platform/heap/Handle.h" #include "platform/network/FormData.h" #include "wtf/Forward.h" #include "wtf/text/CString.h" @@ -32,18 +33,21 @@ namespace WebCore { class FormDataList { public: class Item { + ALLOW_ONLY_INLINE_ALLOCATION(); public: Item() { } Item(const WTF::CString& data) : m_data(data) { } - Item(PassRefPtr<Blob> blob, const String& filename) : m_blob(blob), m_filename(filename) { } + Item(PassRefPtrWillBeRawPtr<Blob> blob, const String& filename) : m_blob(blob), m_filename(filename) { } const WTF::CString& data() const { return m_data; } Blob* blob() const { return m_blob.get(); } const String& filename() const { return m_filename; } + void trace(Visitor*); + private: WTF::CString m_data; - RefPtr<Blob> m_blob; + RefPtrWillBeMember<Blob> m_blob; String m_filename; }; @@ -64,29 +68,33 @@ public: appendString(key); appendString(String::number(value)); } - void appendBlob(const String& key, PassRefPtr<Blob> blob, const String& filename = String()) + void appendBlob(const String& key, PassRefPtrWillBeRawPtr<Blob> blob, const String& filename = String()) { appendString(key); appendBlob(blob, filename); } - const Vector<Item>& items() const { return m_items; } + const WillBeHeapVector<Item>& items() const { return m_items; } const WTF::TextEncoding& encoding() const { return m_encoding; } - PassRefPtr<FormData> createFormData(const WTF::TextEncoding&, FormData::EncodingType = FormData::FormURLEncoded); - PassRefPtr<FormData> createMultiPartFormData(const WTF::TextEncoding&); + PassRefPtr<FormData> createFormData(FormData::EncodingType = FormData::FormURLEncoded); + PassRefPtr<FormData> createMultiPartFormData(); + + void trace(Visitor*); private: void appendKeyValuePairItemsTo(FormData*, const WTF::TextEncoding&, bool isMultiPartForm, FormData::EncodingType = FormData::FormURLEncoded); void appendString(const CString&); void appendString(const String&); - void appendBlob(PassRefPtr<Blob>, const String& filename); + void appendBlob(PassRefPtrWillBeRawPtr<Blob>, const String& filename); WTF::TextEncoding m_encoding; - Vector<Item> m_items; + WillBeHeapVector<Item> m_items; }; } // namespace WebCore +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::FormDataList::Item); + #endif // FormDataList_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp index 5fc4b8bee57..38c620a350b 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.cpp @@ -31,13 +31,14 @@ namespace WebCore { -PassRefPtr<HTMLAllCollection> HTMLAllCollection::create(Node* node, CollectionType type) +PassRefPtrWillBeRawPtr<HTMLAllCollection> HTMLAllCollection::create(ContainerNode& node, CollectionType type) { - return adoptRef(new HTMLAllCollection(node, type)); + ASSERT_UNUSED(type, type == DocAll); + return adoptRefWillBeNoop(new HTMLAllCollection(node)); } -HTMLAllCollection::HTMLAllCollection(Node* node, CollectionType type) - : HTMLCollection(node, type, DoesNotOverrideItemAfter) +HTMLAllCollection::HTMLAllCollection(ContainerNode& node) + : HTMLCollection(node, DocAll, DoesNotOverrideItemAfter) { ScriptWrappable::init(this); } @@ -46,27 +47,28 @@ HTMLAllCollection::~HTMLAllCollection() { } -Node* HTMLAllCollection::namedItemWithIndex(const AtomicString& name, unsigned index) const +Element* HTMLAllCollection::namedItemWithIndex(const AtomicString& name, unsigned index) const { - updateNameCache(); + updateIdNameCache(); - if (Vector<Element*>* cache = idCache(name)) { - if (index < cache->size()) - return cache->at(index); - index -= cache->size(); + const NamedItemCache& cache = namedItemCache(); + if (WillBeHeapVector<RawPtrWillBeMember<Element> >* elements = cache.getElementsById(name)) { + if (index < elements->size()) + return elements->at(index); + index -= elements->size(); } - if (Vector<Element*>* cache = nameCache(name)) { - if (index < cache->size()) - return cache->at(index); + if (WillBeHeapVector<RawPtrWillBeMember<Element> >* elements = cache.getElementsByName(name)) { + if (index < elements->size()) + return elements->at(index); } return 0; } -void HTMLAllCollection::anonymousNamedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtr<Node>& returnValue1) +void HTMLAllCollection::namedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtrWillBeRawPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtrWillBeRawPtr<Element>& returnValue1) { - Vector<RefPtr<Node> > namedItems; + WillBeHeapVector<RefPtrWillBeMember<Element> > namedItems; this->namedItems(name, namedItems); if (!namedItems.size()) @@ -84,9 +86,4 @@ void HTMLAllCollection::anonymousNamedGetter(const AtomicString& name, bool& ret returnValue0 = NamedNodesCollection::create(namedItems); } -PassRefPtr<NodeList> HTMLAllCollection::tags(const String& name) -{ - return ownerNode()->getElementsByTagName(name); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.h b/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.h index d5f1106ac5d..458e3bc96ac 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.h @@ -32,17 +32,18 @@ namespace WebCore { class HTMLAllCollection FINAL : public HTMLCollection { public: - static PassRefPtr<HTMLAllCollection> create(Node*, CollectionType); + static PassRefPtrWillBeRawPtr<HTMLAllCollection> create(ContainerNode&, CollectionType); virtual ~HTMLAllCollection(); - Node* namedItemWithIndex(const AtomicString& name, unsigned index) const; - void anonymousNamedGetter(const AtomicString& name, bool&, RefPtr<NodeList>&, bool&, RefPtr<Node>&); - PassRefPtr<NodeList> tags(const String&); + Element* namedItemWithIndex(const AtomicString& name, unsigned index) const; + void namedGetter(const AtomicString& name, bool&, RefPtrWillBeRawPtr<NodeList>&, bool&, RefPtrWillBeRawPtr<Element>&); private: - HTMLAllCollection(Node*, CollectionType); + explicit HTMLAllCollection(ContainerNode&); }; +DEFINE_TYPE_CASTS(HTMLAllCollection, LiveNodeListBase, collection, collection->type() == DocAll, collection.type() == DocAll); + } // namespace WebCore #endif // HTMLAllCollection_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.idl b/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.idl index 3508f8bc731..d56b8b6dbf5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAllCollection.idl @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2014 Samsung Electronics. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,17 +24,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// FIXME: This interface should inherit HTMLCollection. [ Custom=LegacyCallAsFunction, DependentLifetime, - GenerateVisitDOMWrapper=ownerNode, + SetWrapperReferenceFrom=ownerNode, + WillBeGarbageCollected, ] interface HTMLAllCollection { readonly attribute unsigned long length; - [ImplementedAs=item] getter Node (unsigned long index); - [Custom] Node item([Default=Undefined] optional unsigned long index); - [ImplementedAs=anonymousNamedGetter, NotEnumerable] getter (NodeList or Node)(DOMString name); - [Custom] Node namedItem(DOMString name); - // FIXME: This should return an HTMLAllCollection. - [MeasureAs=DocumentAllTags] NodeList tags(DOMString name); + [ImplementedAs=item] getter Element (unsigned long index); + [Custom] Element item([Default=Undefined] optional unsigned long index); + // FIXME: This should return an (HTMLCollection or Element) union. + [ImplementedAs=namedGetter] getter (NodeList or Element) namedItem(DOMString name); }; - diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp index 8a0e9f372d8..7c955b5f483 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp @@ -28,8 +28,10 @@ #include "core/editing/FrameSelection.h" #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/Frame.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLImageElement.h" #include "core/html/parser/HTMLParserIdioms.h" @@ -40,10 +42,7 @@ #include "core/loader/PingLoader.h" #include "core/page/Chrome.h" #include "core/page/ChromeClient.h" -#include "core/page/Page.h" -#include "core/frame/Settings.h" #include "core/rendering/RenderImage.h" -#include "core/svg/graphics/SVGImage.h" #include "platform/PlatformMouseEvent.h" #include "platform/network/DNS.h" #include "platform/network/ResourceRequest.h" @@ -70,11 +69,11 @@ void preconnectToURL(const KURL& url, blink::WebPreconnectMotivation motivation) } -class HTMLAnchorElement::PrefetchEventHandler { +class HTMLAnchorElement::PrefetchEventHandler FINAL : public NoBaseWillBeGarbageCollected<HTMLAnchorElement::PrefetchEventHandler> { public: - static PassOwnPtr<PrefetchEventHandler> create(HTMLAnchorElement* anchorElement) + static PassOwnPtrWillBeRawPtr<PrefetchEventHandler> create(HTMLAnchorElement* anchorElement) { - return adoptPtr(new HTMLAnchorElement::PrefetchEventHandler(anchorElement)); + return adoptPtrWillBeNoop(new HTMLAnchorElement::PrefetchEventHandler(anchorElement)); } void reset(); @@ -83,6 +82,8 @@ public: void didChangeHREF() { m_hadHREFChanged = true; } bool hasIssuedPreconnect() const { return m_hasIssuedPreconnect; } + void trace(Visitor* visitor) { visitor->trace(m_anchorElement); } + private: explicit PrefetchEventHandler(HTMLAnchorElement*); @@ -96,7 +97,7 @@ private: bool shouldPrefetch(const KURL&); void prefetch(blink::WebPreconnectMotivation); - HTMLAnchorElement* m_anchorElement; + RawPtrWillBeMember<HTMLAnchorElement> m_anchorElement; double m_mouseOverTimestamp; double m_mouseDownTimestamp; double m_tapDownTimestamp; @@ -109,27 +110,19 @@ using namespace HTMLNames; HTMLAnchorElement::HTMLAnchorElement(const QualifiedName& tagName, Document& document) : HTMLElement(tagName, document) - , m_hasRootEditableElementForSelectionOnMouseDown(false) - , m_wasShiftKeyDownOnMouseDown(false) , m_linkRelations(0) , m_cachedVisitedLinkHash(0) { ScriptWrappable::init(this); } -PassRefPtr<HTMLAnchorElement> HTMLAnchorElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLAnchorElement> HTMLAnchorElement::create(Document& document) { - return adoptRef(new HTMLAnchorElement(aTag, document)); -} - -PassRefPtr<HTMLAnchorElement> HTMLAnchorElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLAnchorElement(tagName, document)); + return adoptRefWillBeNoop(new HTMLAnchorElement(aTag, document)); } HTMLAnchorElement::~HTMLAnchorElement() { - clearRootEditableElementForSelectionOnMouseDown(); } bool HTMLAnchorElement::supportsFocus() const @@ -152,16 +145,13 @@ bool HTMLAnchorElement::isMouseFocusable() const bool HTMLAnchorElement::isKeyboardFocusable() const { + ASSERT(document().isActive()); + if (isFocusable() && Element::supportsFocus()) return HTMLElement::isKeyboardFocusable(); - if (isLink()) { - Page* page = document().page(); - if (!page) - return false; - if (!page->chrome().client().tabsToLinks()) - return false; - } + if (isLink() && !document().frameHost()->chrome().client().tabsToLinks()) + return false; return HTMLElement::isKeyboardFocusable(); } @@ -173,16 +163,16 @@ static void appendServerMapMousePosition(StringBuilder& url, Event* event) ASSERT(event->target()); Node* target = event->target()->toNode(); ASSERT(target); - if (!target->hasTagName(imgTag)) + if (!isHTMLImageElement(*target)) return; - HTMLImageElement* imageElement = toHTMLImageElement(event->target()->toNode()); - if (!imageElement || !imageElement->isServerMap()) + HTMLImageElement& imageElement = toHTMLImageElement(*target); + if (!imageElement.isServerMap()) return; - if (!imageElement->renderer() || !imageElement->renderer()->isRenderImage()) + if (!imageElement.renderer() || !imageElement.renderer()->isRenderImage()) return; - RenderImage* renderer = toRenderImage(imageElement->renderer()); + RenderImage* renderer = toRenderImage(imageElement.renderer()); // FIXME: This should probably pass true for useTransforms. FloatPoint absolutePosition = renderer->absoluteToLocal(FloatPoint(toMouseEvent(event)->pageX(), toMouseEvent(event)->pageY())); @@ -197,7 +187,7 @@ static void appendServerMapMousePosition(StringBuilder& url, Event* event) void HTMLAnchorElement::defaultEventHandler(Event* event) { if (isLink()) { - if (focused() && isEnterKeyKeydownEvent(event) && treatLinkAsLiveForEventType(NonMouseEvent)) { + if (focused() && isEnterKeyKeydownEvent(event) && isLiveLink()) { event->setDefaultHandled(); dispatchSimulatedClick(event); return; @@ -205,25 +195,11 @@ void HTMLAnchorElement::defaultEventHandler(Event* event) prefetchEventHandler()->handleEvent(event); - if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event))) { + if (isLinkClick(event) && isLiveLink()) { handleClick(event); prefetchEventHandler()->reset(); return; } - - if (rendererIsEditable()) { - // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked - // for the LiveWhenNotFocused editable link behavior - if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() != RightButton && document().frame()) { - setRootEditableElementForSelectionOnMouseDown(document().frame()->selection().rootEditableElement()); - m_wasShiftKeyDownOnMouseDown = toMouseEvent(event)->shiftKey(); - } else if (event->type() == EventTypeNames::mouseover) { - // These are cleared on mouseover and not mouseout because their values are needed for drag events, - // but drag events happen after mouse out events. - clearRootEditableElementForSelectionOnMouseDown(); - m_wasShiftKeyDownOnMouseDown = false; - } - } } HTMLElement::defaultEventHandler(event); @@ -231,32 +207,8 @@ void HTMLAnchorElement::defaultEventHandler(Event* event) void HTMLAnchorElement::setActive(bool down) { - if (rendererIsEditable()) { - EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior; - if (Settings* settings = document().settings()) - editableLinkBehavior = settings->editableLinkBehavior(); - - switch (editableLinkBehavior) { - default: - case EditableLinkDefaultBehavior: - case EditableLinkAlwaysLive: - break; - - case EditableLinkNeverLive: - return; - - // Don't set the link to be active if the current selection is in the same editable block as - // this link - case EditableLinkLiveWhenNotFocused: - if (down && document().frame() && document().frame()->selection().rootEditableElement() == rootEditableElement()) - return; - break; - - case EditableLinkOnlyLiveWithShiftKey: - return; - } - - } + if (rendererIsEditable()) + return; ContainerNode::setActive(down); } @@ -303,9 +255,13 @@ bool HTMLAnchorElement::isURLAttribute(const Attribute& attribute) const return attribute.name().localName() == hrefAttr || HTMLElement::isURLAttribute(attribute); } +bool HTMLAnchorElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == hrefAttr || HTMLElement::hasLegalLinkAttribute(name); +} + bool HTMLAnchorElement::canStartSelection() const { - // FIXME: We probably want this same behavior in SVGAElement too if (!isLink()) return HTMLElement::canStartSelection(); return rendererIsEditable(); @@ -349,7 +305,7 @@ String HTMLAnchorElement::input() const void HTMLAnchorElement::setInput(const String& value) { - setHref(value); + setHref(AtomicString(value)); } bool HTMLAnchorElement::hasRel(uint32_t relation) const @@ -357,7 +313,7 @@ bool HTMLAnchorElement::hasRel(uint32_t relation) const return m_linkRelations & relation; } -void HTMLAnchorElement::setRel(const String& value) +void HTMLAnchorElement::setRel(const AtomicString& value) { m_linkRelations = 0; SpaceSplitString newLinkRelations(value, true); @@ -377,37 +333,34 @@ short HTMLAnchorElement::tabIndex() const return Element::tabIndex(); } -String HTMLAnchorElement::target() const +AtomicString HTMLAnchorElement::target() const { return getAttribute(targetAttr); } - -String HTMLAnchorElement::text() -{ - return innerText(); -} - bool HTMLAnchorElement::isLiveLink() const { - return isLink() && treatLinkAsLiveForEventType(m_wasShiftKeyDownOnMouseDown ? MouseEventWithShiftKey : MouseEventWithoutShiftKey); + return isLink() && !rendererIsEditable(); } void HTMLAnchorElement::sendPings(const KURL& destinationURL) { - if (!hasAttribute(pingAttr) || !document().settings() || !document().settings()->hyperlinkAuditingEnabled()) + const AtomicString& pingValue = getAttribute(pingAttr); + if (pingValue.isNull() || !document().settings() || !document().settings()->hyperlinkAuditingEnabled()) return; - SpaceSplitString pingURLs(getAttribute(pingAttr), false); + UseCounter::count(document(), UseCounter::HTMLAnchorElementPingAttribute); + + SpaceSplitString pingURLs(pingValue, false); for (unsigned i = 0; i < pingURLs.size(); i++) - PingLoader::sendPing(document().frame(), document().completeURL(pingURLs[i]), destinationURL); + PingLoader::sendLinkAuditPing(document().frame(), document().completeURL(pingURLs[i]), destinationURL); } void HTMLAnchorElement::handleClick(Event* event) { event->setDefaultHandled(); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) return; @@ -427,10 +380,13 @@ void HTMLAnchorElement::handleClick(Event* event) if (!hasRel(RelationNoReferrer)) { String referrer = SecurityPolicy::generateReferrerHeader(document().referrerPolicy(), completedURL, document().outgoingReferrer()); if (!referrer.isEmpty()) - request.setHTTPReferrer(referrer); + request.setHTTPReferrer(Referrer(referrer, document().referrerPolicy())); } - frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, fastGetAttribute(downloadAttr)); + bool isSameOrigin = completedURL.protocolIsData() || document().securityOrigin()->canRequest(completedURL); + const AtomicString& suggestedName = (isSameOrigin ? fastGetAttribute(downloadAttr) : nullAtom); + + frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, suggestedName); } else { FrameLoadRequest frameRequest(&document(), request, target()); frameRequest.setTriggeringEvent(event); @@ -440,43 +396,6 @@ void HTMLAnchorElement::handleClick(Event* event) } } -HTMLAnchorElement::EventType HTMLAnchorElement::eventType(Event* event) -{ - if (!event->isMouseEvent()) - return NonMouseEvent; - return toMouseEvent(event)->shiftKey() ? MouseEventWithShiftKey : MouseEventWithoutShiftKey; -} - -bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const -{ - if (!rendererIsEditable()) - return true; - - Settings* settings = document().settings(); - if (!settings) - return true; - - switch (settings->editableLinkBehavior()) { - case EditableLinkDefaultBehavior: - case EditableLinkAlwaysLive: - return true; - - case EditableLinkNeverLive: - return false; - - // If the selection prior to clicking on this link resided in the same editable block as this link, - // and the shift key isn't pressed, we don't want to follow the link. - case EditableLinkLiveWhenNotFocused: - return eventType == MouseEventWithShiftKey || (eventType == MouseEventWithoutShiftKey && rootEditableElementForSelectionOnMouseDown() != rootEditableElement()); - - case EditableLinkOnlyLiveWithShiftKey: - return eventType == MouseEventWithShiftKey; - } - - ASSERT_NOT_REACHED(); - return false; -} - bool isEnterKeyKeydownEvent(Event* event) { return event->type() == EventTypeNames::keydown && event->isKeyboardEvent() && toKeyboardEvent(event)->keyIdentifier() == "Enter"; @@ -492,40 +411,6 @@ bool HTMLAnchorElement::willRespondToMouseClickEvents() return isLink() || HTMLElement::willRespondToMouseClickEvents(); } -typedef HashMap<const HTMLAnchorElement*, RefPtr<Element> > RootEditableElementMap; - -static RootEditableElementMap& rootEditableElementMap() -{ - DEFINE_STATIC_LOCAL(RootEditableElementMap, map, ()); - return map; -} - -Element* HTMLAnchorElement::rootEditableElementForSelectionOnMouseDown() const -{ - if (!m_hasRootEditableElementForSelectionOnMouseDown) - return 0; - return rootEditableElementMap().get(this); -} - -void HTMLAnchorElement::clearRootEditableElementForSelectionOnMouseDown() -{ - if (!m_hasRootEditableElementForSelectionOnMouseDown) - return; - rootEditableElementMap().remove(this); - m_hasRootEditableElementForSelectionOnMouseDown = false; -} - -void HTMLAnchorElement::setRootEditableElementForSelectionOnMouseDown(Element* element) -{ - if (!element) { - clearRootEditableElementForSelectionOnMouseDown(); - return; - } - - rootEditableElementMap().set(this, element); - m_hasRootEditableElementForSelectionOnMouseDown = true; -} - HTMLAnchorElement::PrefetchEventHandler* HTMLAnchorElement::prefetchEventHandler() { if (!m_prefetchEventHandler) @@ -667,7 +552,7 @@ bool HTMLAnchorElement::PrefetchEventHandler::shouldPrefetch(const KURL& url) if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(document.url(), url)) return false; - Frame* frame = document.frame(); + LocalFrame* frame = document.frame(); if (!frame) return false; @@ -698,4 +583,10 @@ bool HTMLAnchorElement::isInteractiveContent() const return isLink(); } +void HTMLAnchorElement::trace(Visitor* visitor) +{ + visitor->trace(m_prefetchEventHandler); + HTMLElement::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.h index bfb0d634729..769c6d2a0ea 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.h @@ -24,8 +24,9 @@ #ifndef HTMLAnchorElement_h #define HTMLAnchorElement_h -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/DOMURLUtils.h" +#include "core/dom/Document.h" #include "core/html/HTMLElement.h" #include "platform/LinkHash.h" @@ -56,8 +57,7 @@ enum { class HTMLAnchorElement : public HTMLElement, public DOMURLUtils { public: - static PassRefPtr<HTMLAnchorElement> create(Document&); - static PassRefPtr<HTMLAnchorElement> create(const QualifiedName&, Document&); + static PassRefPtrWillBeRawPtr<HTMLAnchorElement> create(Document&); virtual ~HTMLAnchorElement(); @@ -66,66 +66,52 @@ public: const AtomicString& name() const; - virtual KURL url() const OVERRIDE; - virtual void setURL(const KURL&) OVERRIDE; + virtual KURL url() const OVERRIDE FINAL; + virtual void setURL(const KURL&) OVERRIDE FINAL; - virtual String input() const OVERRIDE; - virtual void setInput(const String&) OVERRIDE; - - String text(); + virtual String input() const OVERRIDE FINAL; + virtual void setInput(const String&) OVERRIDE FINAL; bool isLiveLink() const; - virtual bool willRespondToMouseClickEvents() OVERRIDE; + virtual bool willRespondToMouseClickEvents() OVERRIDE FINAL; bool hasRel(uint32_t relation) const; - void setRel(const String&); + void setRel(const AtomicString&); LinkHash visitedLinkHash() const; void invalidateCachedVisitedLinkHash() { m_cachedVisitedLinkHash = 0; } + virtual void trace(Visitor*) OVERRIDE; + protected: HTMLAnchorElement(const QualifiedName&, Document&); virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; + virtual bool supportsFocus() const OVERRIDE; private: - virtual bool supportsFocus() const; - virtual bool isMouseFocusable() const; + virtual bool isMouseFocusable() const OVERRIDE; virtual bool isKeyboardFocusable() const OVERRIDE; - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE FINAL; virtual void setActive(bool = true) OVERRIDE FINAL; - virtual void accessKeyAction(bool sendMouseEvents); - virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - virtual bool canStartSelection() const; - virtual String target() const; - virtual short tabIndex() const; - virtual bool draggable() const; - virtual bool isInteractiveContent() const OVERRIDE; + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE FINAL; + virtual bool isURLAttribute(const Attribute&) const OVERRIDE FINAL; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE FINAL; + virtual bool canStartSelection() const OVERRIDE FINAL; + virtual short tabIndex() const OVERRIDE FINAL; + virtual bool draggable() const OVERRIDE FINAL; + virtual bool isInteractiveContent() const OVERRIDE FINAL; void sendPings(const KURL& destinationURL); - + AtomicString target() const; void handleClick(Event*); - enum EventType { - MouseEventWithoutShiftKey, - MouseEventWithShiftKey, - NonMouseEvent, - }; - static EventType eventType(Event*); - bool treatLinkAsLiveForEventType(EventType) const; - - Element* rootEditableElementForSelectionOnMouseDown() const; - void setRootEditableElementForSelectionOnMouseDown(Element*); - void clearRootEditableElementForSelectionOnMouseDown(); - class PrefetchEventHandler; PrefetchEventHandler* prefetchEventHandler(); - bool m_hasRootEditableElementForSelectionOnMouseDown : 1; - bool m_wasShiftKeyDownOnMouseDown : 1; - uint32_t m_linkRelations : 30; - OwnPtr<PrefetchEventHandler> m_prefetchEventHandler; + uint32_t m_linkRelations; + OwnPtrWillBeMember<PrefetchEventHandler> m_prefetchEventHandler; mutable LinkHash m_cachedVisitedLinkHash; }; @@ -141,23 +127,6 @@ inline LinkHash HTMLAnchorElement::visitedLinkHash() const bool isEnterKeyKeydownEvent(Event*); bool isLinkClick(Event*); -inline bool isHTMLAnchorElement(const Node* node) -{ - return node->hasTagName(HTMLNames::aTag); -} - -inline bool isHTMLAnchorElement(const Element* element) -{ - return element->hasTagName(HTMLNames::aTag); -} - -inline bool isHTMLAnchorElement(const Element& element) -{ - return element.hasTagName(HTMLNames::aTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLAnchorElement, hasTagName(HTMLNames::aTag)); - } // namespace WebCore #endif // HTMLAnchorElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.idl index 525c307807f..63775c24b9b 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAnchorElement.idl @@ -31,8 +31,9 @@ interface HTMLAnchorElement : HTMLElement { [Reflect] attribute DOMString target; [Reflect] attribute DOMString type; - readonly attribute DOMString text; + [ImplementedAs=textContent] attribute DOMString text; + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; -// force rebuild: crbug.com/307023 HTMLAnchorElement implements URLUtils; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.cpp index 242e2ea2110..6dd43e9d911 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.cpp @@ -24,14 +24,14 @@ #include "config.h" #include "core/html/HTMLAppletElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLParamElement.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/rendering/RenderApplet.h" #include "platform/Widget.h" #include "platform/weborigin/KURL.h" @@ -49,9 +49,9 @@ HTMLAppletElement::HTMLAppletElement(Document& document, bool createdByParser) m_serviceType = "application/x-java-applet"; } -PassRefPtr<HTMLAppletElement> HTMLAppletElement::create(Document& document, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLAppletElement> HTMLAppletElement::create(Document& document, bool createdByParser) { - RefPtr<HTMLAppletElement> element = adoptRef(new HTMLAppletElement(document, createdByParser)); + RefPtrWillBeRawPtr<HTMLAppletElement> element = adoptRefWillBeNoop(new HTMLAppletElement(document, createdByParser)); element->ensureUserAgentShadowRoot(); return element.release(); } @@ -77,6 +77,11 @@ bool HTMLAppletElement::isURLAttribute(const Attribute& attribute) const || HTMLPlugInElement::isURLAttribute(attribute); } +bool HTMLAppletElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == codebaseAttr || HTMLPlugInElement::hasLegalLinkAttribute(name); +} + bool HTMLAppletElement::rendererIsNeeded(const RenderStyle& style) { if (!fastHasAttribute(codeAttr) && !hasAuthorShadowRoot()) @@ -114,14 +119,9 @@ void HTMLAppletElement::updateWidgetInternal() RenderEmbeddedObject* renderer = renderEmbeddedObject(); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); ASSERT(frame); - LayoutUnit contentWidth = renderer->style()->width().isFixed() ? LayoutUnit(renderer->style()->width().value()) : - renderer->width() - renderer->borderAndPaddingWidth(); - LayoutUnit contentHeight = renderer->style()->height().isFixed() ? LayoutUnit(renderer->style()->height().value()) : - renderer->height() - renderer->borderAndPaddingHeight(); - Vector<String> paramNames; Vector<String> paramValues; @@ -172,11 +172,7 @@ void HTMLAppletElement::updateWidgetInternal() paramValues.append(mayScript.string()); } - for (Node* child = firstChild(); child; child = child->nextSibling()) { - if (!child->hasTagName(paramTag)) - continue; - - HTMLParamElement* param = toHTMLParamElement(child); + for (HTMLParamElement* param = Traversal<HTMLParamElement>::firstChild(*this); param; param = Traversal<HTMLParamElement>::nextSibling(*param)) { if (param->name().isEmpty()) continue; @@ -186,7 +182,7 @@ void HTMLAppletElement::updateWidgetInternal() RefPtr<Widget> widget; if (frame->loader().allowPlugins(AboutToInstantiatePlugin)) - widget = frame->loader().client()->createJavaAppletWidget(roundedIntSize(LayoutSize(contentWidth, contentHeight)), this, baseURL, paramNames, paramValues); + widget = frame->loader().client()->createJavaAppletWidget(this, baseURL, paramNames, paramValues); if (!widget) { if (!renderer->showsUnavailablePluginIndicator()) @@ -194,7 +190,7 @@ void HTMLAppletElement::updateWidgetInternal() return; } document().setContainsPlugins(); - renderer->setWidget(widget); + setWidget(widget); } bool HTMLAppletElement::canEmbedJava() const diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.h index 41c5193a81e..fbba123f567 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAppletElement.h @@ -31,7 +31,7 @@ class KURL; class HTMLAppletElement FINAL : public HTMLPlugInElement { public: - static PassRefPtr<HTMLAppletElement> create(Document&, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLAppletElement> create(Document&, bool createdByParser); protected: virtual RenderWidget* renderWidgetForJSBindings() const OVERRIDE; @@ -41,6 +41,7 @@ private: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp index 73cd5fb7ac0..1606791ed62 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp @@ -22,17 +22,16 @@ #include "config.h" #include "core/html/HTMLAreaElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLMapElement.h" #include "core/rendering/HitTestResult.h" #include "core/rendering/RenderImage.h" #include "core/rendering/RenderView.h" +#include "platform/LengthFunctions.h" #include "platform/graphics/Path.h" #include "platform/transforms/AffineTransform.h" -using namespace std; - namespace WebCore { using namespace HTMLNames; @@ -45,10 +44,7 @@ inline HTMLAreaElement::HTMLAreaElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLAreaElement> HTMLAreaElement::create(Document& document) -{ - return adoptRef(new HTMLAreaElement(document)); -} +DEFINE_NODE_FACTORY(HTMLAreaElement) void HTMLAreaElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { @@ -102,7 +98,7 @@ Path HTMLAreaElement::computePath(RenderObject* obj) const // Default should default to the size of the containing object. LayoutSize size = m_lastSize; if (m_shape == Default) - size = obj->absoluteOutlineBounds().size(); + size = obj->absoluteClippedOverflowRect().size(); Path p = getRegion(size); float zoomFactor = obj->style()->effectiveZoom(); @@ -141,35 +137,34 @@ Path HTMLAreaElement::getRegion(const LayoutSize& size) const } Path path; - RenderView* renderView = document().renderView(); switch (shape) { case Poly: if (m_coords.size() >= 6) { int numPoints = m_coords.size() / 2; - path.moveTo(FloatPoint(minimumValueForLength(m_coords[0], width, renderView), minimumValueForLength(m_coords[1], height, renderView))); + path.moveTo(FloatPoint(minimumValueForLength(m_coords[0], width).toFloat(), minimumValueForLength(m_coords[1], height).toFloat())); for (int i = 1; i < numPoints; ++i) - path.addLineTo(FloatPoint(minimumValueForLength(m_coords[i * 2], width, renderView), minimumValueForLength(m_coords[i * 2 + 1], height, renderView))); + path.addLineTo(FloatPoint(minimumValueForLength(m_coords[i * 2], width).toFloat(), minimumValueForLength(m_coords[i * 2 + 1], height).toFloat())); path.closeSubpath(); } break; case Circle: if (m_coords.size() >= 3) { Length radius = m_coords[2]; - int r = min(minimumValueForLength(radius, width, renderView), minimumValueForLength(radius, height, renderView)); - path.addEllipse(FloatRect(minimumValueForLength(m_coords[0], width, renderView) - r, minimumValueForLength(m_coords[1], height, renderView) - r, 2 * r, 2 * r)); + float r = std::min(minimumValueForLength(radius, width).toFloat(), minimumValueForLength(radius, height).toFloat()); + path.addEllipse(FloatRect(minimumValueForLength(m_coords[0], width).toFloat() - r, minimumValueForLength(m_coords[1], height).toFloat() - r, 2 * r, 2 * r)); } break; case Rect: if (m_coords.size() >= 4) { - int x0 = minimumValueForLength(m_coords[0], width, renderView); - int y0 = minimumValueForLength(m_coords[1], height, renderView); - int x1 = minimumValueForLength(m_coords[2], width, renderView); - int y1 = minimumValueForLength(m_coords[3], height, renderView); + float x0 = minimumValueForLength(m_coords[0], width).toFloat(); + float y0 = minimumValueForLength(m_coords[1], height).toFloat(); + float x1 = minimumValueForLength(m_coords[2], width).toFloat(); + float y1 = minimumValueForLength(m_coords[3], height).toFloat(); path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0)); } break; case Default: - path.addRect(FloatRect(0, 0, width, height)); + path.addRect(FloatRect(0, 0, width.toFloat(), height.toFloat())); break; case Unknown: break; @@ -181,13 +176,13 @@ Path HTMLAreaElement::getRegion(const LayoutSize& size) const HTMLImageElement* HTMLAreaElement::imageElement() const { Element* mapElement = parentElement(); - while (mapElement && !mapElement->hasTagName(mapTag)) + while (mapElement && !isHTMLMapElement(*mapElement)) mapElement = mapElement->parentElement(); if (!mapElement) return 0; - return toHTMLMapElement(mapElement)->imageElement(); + return toHTMLMapElement(*mapElement).imageElement(); } bool HTMLAreaElement::isKeyboardFocusable() const @@ -239,16 +234,4 @@ void HTMLAreaElement::updateFocusAppearance(bool restorePreviousSelection) imageElement->updateFocusAppearance(restorePreviousSelection); } -bool HTMLAreaElement::supportsFocus() const -{ - // If the AREA element was a link, it should support focus. - // FIXME: This means that an AREA that is not a link cannot be made focusable through contenteditable or tabindex. Is it correct? - return isLink(); -} - -String HTMLAreaElement::target() const -{ - return getAttribute(targetAttr); -} - } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.h index 35f34387d52..b68450ef951 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.h @@ -34,7 +34,7 @@ class Path; class HTMLAreaElement FINAL : public HTMLAnchorElement { public: - static PassRefPtr<HTMLAreaElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLAreaElement); bool isDefault() const { return m_shape == Default; } @@ -50,12 +50,10 @@ private: explicit HTMLAreaElement(Document&); virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual bool supportsFocus() const; - virtual String target() const; virtual bool isKeyboardFocusable() const OVERRIDE; - virtual bool isMouseFocusable() const; + virtual bool isMouseFocusable() const OVERRIDE; virtual bool rendererIsFocusable() const OVERRIDE; - virtual void updateFocusAppearance(bool /*restorePreviousSelection*/); + virtual void updateFocusAppearance(bool /*restorePreviousSelection*/) OVERRIDE; virtual void setFocus(bool) OVERRIDE; enum Shape { Default, Poly, Rect, Circle, Unknown }; @@ -68,18 +66,6 @@ private: Shape m_shape; }; -inline bool isHTMLAreaElement(const Node* node) -{ - return node->hasTagName(HTMLNames::areaTag); -} - -inline bool isHTMLAreaElement(const Element* element) -{ - return element->hasTagName(HTMLNames::areaTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLAreaElement, hasTagName(HTMLNames::areaTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.idl index 1ad7233a1f9..471e5835a6f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAreaElement.idl @@ -27,5 +27,4 @@ interface HTMLAreaElement : HTMLElement { [Reflect] attribute DOMString target; }; -// force rebuild: crbug.com/307023 HTMLAreaElement implements URLUtils; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAttributeNames.in b/chromium/third_party/WebKit/Source/core/html/HTMLAttributeNames.in index 4ae7745ae45..9494fad2a03 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAttributeNames.in +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAttributeNames.in @@ -126,6 +126,7 @@ id incremental indeterminate inputmode +integrity is ismap itemid @@ -176,7 +177,6 @@ onautocomplete onautocompleteerror onbeforecopy onbeforecut -onbeforeload onbeforepaste onbeforeunload onblur @@ -211,6 +211,7 @@ oninvalid onkeydown onkeypress onkeyup +onlanguagechange onload onloadeddata onloadedmetadata @@ -252,6 +253,7 @@ onstorage onsuspend onsubmit ontimeupdate +ontoggle ontouchstart ontouchmove ontouchend @@ -282,7 +284,6 @@ pluginspage pluginurl ping poster -precision preload primary profile @@ -292,7 +293,6 @@ pseudo readonly rel required -reset-style-inheritance results rev reversed @@ -307,7 +307,6 @@ scoped scrollamount scrolldelay scrolling -seamless select selected shape @@ -316,8 +315,6 @@ sizes sortable sortdirection span -x-webkit-speech -x-webkit-grammar spellcheck src srcset diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.cpp index bdc0d9f3a04..07db2563fc3 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.cpp @@ -26,29 +26,32 @@ #include "config.h" #include "core/html/HTMLAudioElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/dom/shadow/ShadowRoot.h" namespace WebCore { using namespace HTMLNames; -HTMLAudioElement::HTMLAudioElement(Document& document, bool createdByParser) - : HTMLMediaElement(audioTag, document, createdByParser) +HTMLAudioElement::HTMLAudioElement(Document& document) + : HTMLMediaElement(audioTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLAudioElement> HTMLAudioElement::create(Document& document, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLAudioElement> HTMLAudioElement::create(Document& document) { - RefPtr<HTMLAudioElement> audioElement(adoptRef(new HTMLAudioElement(document, createdByParser))); - audioElement->suspendIfNeeded(); - return audioElement.release(); + RefPtrWillBeRawPtr<HTMLAudioElement> audio = adoptRefWillBeNoop(new HTMLAudioElement(document)); + audio->ensureUserAgentShadowRoot(); + audio->suspendIfNeeded(); + return audio.release(); } -PassRefPtr<HTMLAudioElement> HTMLAudioElement::createForJSConstructor(Document& document, const AtomicString& src) +PassRefPtrWillBeRawPtr<HTMLAudioElement> HTMLAudioElement::createForJSConstructor(Document& document, const AtomicString& src) { - RefPtr<HTMLAudioElement> audio = adoptRef(new HTMLAudioElement(document, false)); - audio->setPreload("auto"); + RefPtrWillBeRawPtr<HTMLAudioElement> audio = adoptRefWillBeNoop(new HTMLAudioElement(document)); + audio->ensureUserAgentShadowRoot(); + audio->setPreload(AtomicString("auto", AtomicString::ConstructFromLiteral)); if (!src.isNull()) audio->setSrc(src); audio->suspendIfNeeded(); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.h index c69a3057630..9969491d803 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.h @@ -35,13 +35,11 @@ class Document; class HTMLAudioElement FINAL : public HTMLMediaElement { public: - static PassRefPtr<HTMLAudioElement> create(Document&, bool); - static PassRefPtr<HTMLAudioElement> createForJSConstructor(Document&, const AtomicString& src); + static PassRefPtrWillBeRawPtr<HTMLAudioElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLAudioElement> createForJSConstructor(Document&, const AtomicString& src); private: - HTMLAudioElement(Document&, bool); - - virtual bool isVideo() const OVERRIDE { return false; } + HTMLAudioElement(Document&); }; } //namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.idl index ffb4769c23f..f1e3629d65e 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLAudioElement.idl @@ -25,6 +25,7 @@ [ RuntimeEnabled=Media, - NamedConstructor=Audio([Default=NullString] optional DOMString src) + NamedConstructor=Audio(optional DOMString src = null), + ConstructorCallWith=Document ] interface HTMLAudioElement : HTMLMediaElement { }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBDIElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLBDIElement.h index b5050a6ddee..52db54e9369 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBDIElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBDIElement.h @@ -27,13 +27,10 @@ namespace WebCore { class HTMLBDIElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLBDIElement> create(Document& document) - { - return adoptRef(new HTMLBDIElement(document)); - } + DECLARE_NODE_FACTORY(HTMLBDIElement); private: - explicit HTMLBDIElement(Document& document) + inline explicit HTMLBDIElement(Document& document) : HTMLElement(HTMLNames::bdiTag, document) { // FIXME: Rename setSelfOrAncestorHasDirAutoAttribute to reflect the fact bdi also uses this flag. @@ -41,6 +38,8 @@ private: } }; +DEFINE_NODE_FACTORY(HTMLBDIElement) + } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.cpp index 19b3aa9dab9..b04ba6edef5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.cpp @@ -23,25 +23,22 @@ #include "config.h" #include "core/html/HTMLBRElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/rendering/RenderBR.h" namespace WebCore { using namespace HTMLNames; -HTMLBRElement::HTMLBRElement(Document& document) +inline HTMLBRElement::HTMLBRElement(Document& document) : HTMLElement(brTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLBRElement> HTMLBRElement::create(Document& document) -{ - return adoptRef(new HTMLBRElement(document)); -} +DEFINE_NODE_FACTORY(HTMLBRElement) bool HTMLBRElement::isPresentationAttribute(const QualifiedName& name) const { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.h index 0188c71bd41..01af5657750 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBRElement.h @@ -30,9 +30,9 @@ namespace WebCore { class HTMLBRElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLBRElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLBRElement); - virtual bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE { return false; } private: explicit HTMLBRElement(Document&); @@ -40,7 +40,7 @@ private: virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp index 6ec6654c17f..de1075c7907 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp @@ -23,11 +23,11 @@ #include "config.h" #include "core/html/HTMLBaseElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" -#include "core/fetch/TextResourceDecoder.h" #include "core/html/parser/HTMLParserIdioms.h" +#include "core/html/parser/TextResourceDecoder.h" namespace WebCore { @@ -39,10 +39,7 @@ inline HTMLBaseElement::HTMLBaseElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLBaseElement> HTMLBaseElement::create(Document& document) -{ - return adoptRef(new HTMLBaseElement(document)); -} +DEFINE_NODE_FACTORY(HTMLBaseElement) void HTMLBaseElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { @@ -72,11 +69,6 @@ bool HTMLBaseElement::isURLAttribute(const Attribute& attribute) const return attribute.name().localName() == hrefAttr || HTMLElement::isURLAttribute(attribute); } -String HTMLBaseElement::target() const -{ - return fastGetAttribute(targetAttr); -} - KURL HTMLBaseElement::href() const { // This does not use the getURLAttribute function because that will resolve relative to the document's base URL; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.h index 39c8bfeadff..cefdc19f3f0 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBaseElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLBaseElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLBaseElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLBaseElement); KURL href() const; void setHref(const AtomicString&); @@ -37,7 +37,6 @@ public: private: explicit HTMLBaseElement(Document&); - virtual String target() const; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp index 44a1572fec5..624dec6126e 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp @@ -24,33 +24,30 @@ #include "config.h" #include "core/html/HTMLBodyElement.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/CSSImageValue.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/StylePropertySet.h" #include "core/dom/Attribute.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLFrameElementBase.h" #include "core/html/parser/HTMLParserIdioms.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" +#include "core/rendering/RenderBox.h" namespace WebCore { using namespace HTMLNames; -HTMLBodyElement::HTMLBodyElement(Document& document) +inline HTMLBodyElement::HTMLBodyElement(Document& document) : HTMLElement(bodyTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(Document& document) -{ - return adoptRef(new HTMLBodyElement(document)); -} +DEFINE_NODE_FACTORY(HTMLBodyElement) HTMLBodyElement::~HTMLBodyElement() { @@ -68,8 +65,9 @@ void HTMLBodyElement::collectStyleForPresentationAttribute(const QualifiedName& if (name == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(value); if (!url.isEmpty()) { - RefPtr<CSSImageValue> imageValue = CSSImageValue::create(document().completeURL(url).string()); + RefPtrWillBeRawPtr<CSSImageValue> imageValue = CSSImageValue::create(url, document().completeURL(url)); imageValue->setInitiator(localName()); + imageValue->setReferrer(Referrer(document().outgoingReferrer(), document().referrerPolicy())); style->setProperty(CSSProperty(CSSPropertyBackgroundImage, imageValue.release())); } } else if (name == marginwidthAttr || name == leftmarginAttr) { @@ -101,7 +99,7 @@ void HTMLBodyElement::parseAttribute(const QualifiedName& name, const AtomicStri document().textLinkColors().resetActiveLinkColor(); } else { RGBA32 color; - if (CSSParser::parseColor(color, value, !document().inQuirksMode())) { + if (BisonCSSParser::parseColor(color, value, !document().inQuirksMode())) { if (name == linkAttr) document().textLinkColors().setLinkColor(color); else if (name == vlinkAttr) @@ -111,45 +109,45 @@ void HTMLBodyElement::parseAttribute(const QualifiedName& name, const AtomicStri } } - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } else if (name == onloadAttr) - document().setWindowAttributeEventListener(EventTypeNames::load, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::load, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onbeforeunloadAttr) - document().setWindowAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onunloadAttr) - document().setWindowAttributeEventListener(EventTypeNames::unload, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::unload, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onpagehideAttr) - document().setWindowAttributeEventListener(EventTypeNames::pagehide, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::pagehide, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onpageshowAttr) - document().setWindowAttributeEventListener(EventTypeNames::pageshow, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::pageshow, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onpopstateAttr) - document().setWindowAttributeEventListener(EventTypeNames::popstate, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::popstate, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onblurAttr) - document().setWindowAttributeEventListener(EventTypeNames::blur, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::blur, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onerrorAttr) - document().setWindowAttributeEventListener(EventTypeNames::error, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::error, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onfocusAttr) - document().setWindowAttributeEventListener(EventTypeNames::focus, createAttributeEventListener(document().frame(), name, value)); -#if ENABLE(ORIENTATION_EVENTS) - else if (name == onorientationchangeAttr) - document().setWindowAttributeEventListener(EventTypeNames::orientationchange, createAttributeEventListener(document().frame(), name, value)); -#endif + document().setWindowAttributeEventListener(EventTypeNames::focus, createAttributeEventListener(document().frame(), name, value, eventParameterName())); + else if (RuntimeEnabledFeatures::orientationEventEnabled() && name == onorientationchangeAttr) + document().setWindowAttributeEventListener(EventTypeNames::orientationchange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onhashchangeAttr) - document().setWindowAttributeEventListener(EventTypeNames::hashchange, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::hashchange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onmessageAttr) - document().setWindowAttributeEventListener(EventTypeNames::message, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::message, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onresizeAttr) - document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onscrollAttr) - document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onselectionchangeAttr) - document().setAttributeEventListener(EventTypeNames::selectionchange, createAttributeEventListener(document().frame(), name, value)); + document().setAttributeEventListener(EventTypeNames::selectionchange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onstorageAttr) - document().setWindowAttributeEventListener(EventTypeNames::storage, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::storage, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == ononlineAttr) - document().setWindowAttributeEventListener(EventTypeNames::online, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::online, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onofflineAttr) - document().setWindowAttributeEventListener(EventTypeNames::offline, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::offline, createAttributeEventListener(document().frame(), name, value, eventParameterName())); + else if (name == onlanguagechangeAttr) + document().setWindowAttributeEventListener(EventTypeNames::languagechange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else HTMLElement::parseAttribute(name, value); } @@ -157,22 +155,24 @@ void HTMLBodyElement::parseAttribute(const QualifiedName& name, const AtomicStri Node::InsertionNotificationRequest HTMLBodyElement::insertedInto(ContainerNode* insertionPoint) { HTMLElement::insertedInto(insertionPoint); - if (insertionPoint->inDocument()) { - // FIXME: It's surprising this is web compatible since it means a marginwidth - // and marginheight attribute can magically appear on the <body> of all documents - // embedded through <iframe> or <frame>. - Element* ownerElement = document().ownerElement(); - if (ownerElement && ownerElement->isFrameElementBase()) { - HTMLFrameElementBase* ownerFrameElement = toHTMLFrameElementBase(ownerElement); - int marginWidth = ownerFrameElement->marginWidth(); - if (marginWidth != -1) - setIntegralAttribute(marginwidthAttr, marginWidth); - int marginHeight = ownerFrameElement->marginHeight(); - if (marginHeight != -1) - setIntegralAttribute(marginheightAttr, marginHeight); - } - } - return InsertionDone; + return InsertionShouldCallDidNotifySubtreeInsertions; +} + +void HTMLBodyElement::didNotifySubtreeInsertionsToDocument() +{ + // FIXME: It's surprising this is web compatible since it means a + // marginwidth and marginheight attribute can magically appear on the <body> + // of all documents embedded through <iframe> or <frame>. + Element* ownerElement = document().ownerElement(); + if (!isHTMLFrameElementBase(ownerElement)) + return; + HTMLFrameElementBase& ownerFrameElement = toHTMLFrameElementBase(*ownerElement); + int marginWidth = ownerFrameElement.marginWidth(); + int marginHeight = ownerFrameElement.marginHeight(); + if (marginWidth != -1) + setIntegralAttribute(marginwidthAttr, marginWidth); + if (marginHeight != -1) + setIntegralAttribute(marginheightAttr, marginHeight); } bool HTMLBodyElement::isURLAttribute(const Attribute& attribute) const @@ -180,6 +180,16 @@ bool HTMLBodyElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute); } +bool HTMLBodyElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == backgroundAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLBodyElement::subResourceAttributeName() const +{ + return backgroundAttr; +} + bool HTMLBodyElement::supportsFocus() const { // This override is needed because the inherited method bails if the parent is editable. @@ -189,7 +199,7 @@ bool HTMLBodyElement::supportsFocus() const static int adjustForZoom(int value, Document* document) { - Frame* frame = document->frame(); + LocalFrame* frame = document->frame(); float zoomFactor = frame->pageZoomFactor(); if (zoomFactor == 1) return value; @@ -199,17 +209,28 @@ static int adjustForZoom(int value, Document* document) return static_cast<int>(value / zoomFactor); } -// FIXME: There are cases where body.scrollLeft is allowed to return -// non-zero values in both quirks and strict mode. It happens when -// <body> has an overflow that is not the Frame overflow. -// http://dev.w3.org/csswg/cssom-view/#dom-element-scrollleft -// http://code.google.com/p/chromium/issues/detail?id=312435 +// Blink, Gecko and Presto's quirks mode implementations of overflow set to the +// body element differ from IE's: the formers can create a scrollable area for the +// body element that is not the same as the root elements's one. On IE's quirks mode +// though, as body is the root element, body's and the root element's scrollable areas, +// if any, are the same. +// In order words, a <body> will only have an overflow clip (that differs from +// documentElement's) if both html and body nodes have its overflow set to either hidden, +// auto or scroll. +// That said, Blink's {set}scroll{Top,Left} behaviors match Gecko's: even if there is a non-overflown +// scrollable area, scrolling should not get propagated to the viewport in neither strict +// or quirks modes. int HTMLBodyElement::scrollLeft() { Document& document = this->document(); document.updateLayoutIgnorePendingStylesheets(); if (RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) { + RenderBox* render = renderBox(); + if (!render) + return 0; + if (render->hasOverflowClip()) + return adjustForAbsoluteZoom(render->scrollLeft(), render); if (!document.inQuirksMode()) return 0; } @@ -224,11 +245,19 @@ void HTMLBodyElement::setScrollLeft(int scrollLeft) document.updateLayoutIgnorePendingStylesheets(); if (RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) { + RenderBox* render = renderBox(); + if (!render) + return; + if (render->hasOverflowClip()) { + // FIXME: Investigate how are other browsers casting to int (rounding, ceiling, ...). + render->setScrollLeft(static_cast<int>(scrollLeft * render->style()->effectiveZoom())); + return; + } if (!document.inQuirksMode()) return; } - Frame* frame = document.frame(); + LocalFrame* frame = document.frame(); if (!frame) return; FrameView* view = frame->view(); @@ -243,6 +272,11 @@ int HTMLBodyElement::scrollTop() document.updateLayoutIgnorePendingStylesheets(); if (RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) { + RenderBox* render = renderBox(); + if (!render) + return 0; + if (render->hasOverflowClip()) + return adjustForAbsoluteZoom(render->scrollTop(), render); if (!document.inQuirksMode()) return 0; } @@ -257,11 +291,19 @@ void HTMLBodyElement::setScrollTop(int scrollTop) document.updateLayoutIgnorePendingStylesheets(); if (RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) { + RenderBox* render = renderBox(); + if (!render) + return; + if (render->hasOverflowClip()) { + // FIXME: Investigate how are other browsers casting to int (rounding, ceiling, ...). + render->setScrollTop(static_cast<int>(scrollTop * render->style()->effectiveZoom())); + return; + } if (!document.inQuirksMode()) return; } - Frame* frame = document.frame(); + LocalFrame* frame = document.frame(); if (!frame) return; FrameView* view = frame->view(); @@ -288,11 +330,4 @@ int HTMLBodyElement::scrollWidth() return view ? adjustForZoom(view->contentsWidth(), &document) : 0; } -void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, document().completeURL(getAttribute(backgroundAttr))); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.h index d7a5c45da0a..7dd1f21c09b 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.h @@ -24,6 +24,7 @@ #ifndef HTMLBodyElement_h #define HTMLBodyElement_h +#include "core/dom/Document.h" #include "core/html/HTMLElement.h" namespace WebCore { @@ -32,18 +33,16 @@ class Document; class HTMLBodyElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLBodyElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLBodyElement); virtual ~HTMLBodyElement(); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(blur); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(focus); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(load); + DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(resize); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(scroll); - -#if ENABLE(ORIENTATION_EVENTS) DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(orientationchange); -#endif private: explicit HTMLBodyElement(Document&); @@ -53,25 +52,24 @@ private: virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; + virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; - virtual bool supportsFocus() const; + virtual bool supportsFocus() const OVERRIDE; - virtual int scrollLeft(); - virtual void setScrollLeft(int scrollLeft); + virtual int scrollLeft() OVERRIDE; + virtual void setScrollLeft(int) OVERRIDE; - virtual int scrollTop(); - virtual void setScrollTop(int scrollTop); + virtual int scrollTop() OVERRIDE; + virtual void setScrollTop(int) OVERRIDE; - virtual int scrollHeight(); - virtual int scrollWidth(); - - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; + virtual int scrollHeight() OVERRIDE; + virtual int scrollWidth() OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLBodyElement, hasTagName(HTMLNames::bodyTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.idl index 139b34a52a1..6f454c6aeef 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLBodyElement.idl @@ -26,13 +26,14 @@ interface HTMLBodyElement : HTMLElement { [Reflect, TreatNullAs=NullString] attribute DOMString text; [Reflect, TreatNullAs=NullString] attribute DOMString vLink; - [Conditional=ORIENTATION_EVENTS] attribute EventHandler onorientationchange; + [RuntimeEnabled=OrientationEvent] attribute EventHandler onorientationchange; // Overrides of GlobalEventHandler attributes attribute EventHandler onblur; attribute EventHandler onerror; attribute EventHandler onfocus; attribute EventHandler onload; + attribute EventHandler onresize; attribute EventHandler onscroll; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.cpp index 4b3c235fdab..55f7defa1a4 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.cpp @@ -26,10 +26,9 @@ #include "config.h" #include "core/html/HTMLButtonElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/events/KeyboardEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/html/FormDataList.h" #include "core/html/HTMLFormElement.h" #include "core/rendering/RenderButton.h" @@ -47,9 +46,9 @@ inline HTMLButtonElement::HTMLButtonElement(Document& document, HTMLFormElement* ScriptWrappable::init(this); } -PassRefPtr<HTMLButtonElement> HTMLButtonElement::create(Document& document, HTMLFormElement* form) +PassRefPtrWillBeRawPtr<HTMLButtonElement> HTMLButtonElement::create(Document& document, HTMLFormElement* form) { - return adoptRef(new HTMLButtonElement(document, form)); + return adoptRefWillBeNoop(new HTMLButtonElement(document, form)); } void HTMLButtonElement::setType(const AtomicString& type) @@ -209,4 +208,9 @@ bool HTMLButtonElement::isInteractiveContent() const return true; } +bool HTMLButtonElement::supportsAutofocus() const +{ + return true; +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.h index 5032c386975..110e411f480 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.h @@ -30,7 +30,7 @@ namespace WebCore { class HTMLButtonElement FINAL : public HTMLFormControlElement { public: - static PassRefPtr<HTMLButtonElement> create(Document&, HTMLFormElement*); + static PassRefPtrWillBeRawPtr<HTMLButtonElement> create(Document&, HTMLFormElement*); void setType(const AtomicString&); @@ -43,34 +43,35 @@ private: enum Type { SUBMIT, RESET, BUTTON }; - virtual const AtomicString& formControlType() const; + virtual const AtomicString& formControlType() const OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; // HTMLFormControlElement always creates one, but buttons don't need it. virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE { return false; } virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; - virtual bool appendFormData(FormDataList&, bool); + virtual bool appendFormData(FormDataList&, bool) OVERRIDE; - virtual bool isEnumeratable() const { return true; } + virtual bool isEnumeratable() const OVERRIDE { return true; } virtual bool supportLabels() const OVERRIDE { return true; } virtual bool isInteractiveContent() const OVERRIDE; + virtual bool supportsAutofocus() const OVERRIDE; virtual bool canBeSuccessfulSubmitButton() const OVERRIDE; - virtual bool isActivatedSubmit() const; - virtual void setActivatedSubmit(bool flag); + virtual bool isActivatedSubmit() const OVERRIDE; + virtual void setActivatedSubmit(bool flag) OVERRIDE; - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - virtual bool canStartSelection() const { return false; } + virtual bool canStartSelection() const OVERRIDE { return false; } - virtual bool isOptionalFormControl() const { return true; } - virtual bool recalcWillValidate() const; + virtual bool isOptionalFormControl() const OVERRIDE { return true; } + virtual bool recalcWillValidate() const OVERRIDE; Type m_type; bool m_isActivatedSubmit; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.idl index aa402325ce4..d92dcd166a6 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLButtonElement.idl @@ -22,7 +22,7 @@ interface HTMLButtonElement : HTMLElement { [Reflect] attribute boolean autofocus; [Reflect] attribute boolean disabled; [ImplementedAs=formOwner] readonly attribute HTMLFormElement form; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString formAction; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString formAction; attribute DOMString formEnctype; attribute DOMString formMethod; [Reflect] attribute boolean formNoValidate; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index ba778484dbc..4d6c77edb14 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp @@ -28,29 +28,32 @@ #include "config.h" #include "core/html/HTMLCanvasElement.h" -#include <math.h> -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScriptController.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" #include "core/html/ImageData.h" #include "core/html/canvas/Canvas2DContextAttributes.h" #include "core/html/canvas/CanvasRenderingContext2D.h" #include "core/html/canvas/WebGLContextAttributes.h" +#include "core/html/canvas/WebGLContextEvent.h" #include "core/html/canvas/WebGLRenderingContext.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/rendering/RenderHTMLCanvas.h" #include "platform/MIMETypeRegistry.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/Canvas2DImageBufferSurface.h" #include "platform/graphics/GraphicsContextStateSaver.h" #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/UnacceleratedImageBufferSurface.h" #include "platform/graphics/gpu/WebGLImageBufferSurface.h" +#include "platform/transforms/AffineTransform.h" #include "public/platform/Platform.h" +#include <math.h> +#include <v8.h> namespace WebCore { @@ -68,10 +71,12 @@ static const int MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pix //In Skia, we will also limit width/height to 32767. static const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels. -HTMLCanvasElement::HTMLCanvasElement(Document& document) +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CanvasObserver); + +inline HTMLCanvasElement::HTMLCanvasElement(Document& document) : HTMLElement(canvasTag, document) + , DocumentVisibilityObserver(document) , m_size(DefaultWidth, DefaultHeight) - , m_rendererIsCanvas(false) , m_ignoreReset(false) , m_accelerationDisabled(false) , m_externallyAllocatedMemory(0) @@ -82,19 +87,19 @@ HTMLCanvasElement::HTMLCanvasElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document) -{ - return adoptRef(new HTMLCanvasElement(document)); -} +DEFINE_NODE_FACTORY(HTMLCanvasElement) HTMLCanvasElement::~HTMLCanvasElement() { - setExternallyAllocatedMemory(0); - HashSet<CanvasObserver*>::iterator end = m_observers.end(); - for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory); +#if !ENABLE(OILPAN) + HashSet<RawPtr<CanvasObserver> >::iterator end = m_observers.end(); + for (HashSet<RawPtr<CanvasObserver> >::iterator it = m_observers.begin(); it != end; ++it) (*it)->canvasDestroyed(this); - - m_context.clear(); // Ensure this goes away before the ImageBuffer. + // Ensure these go away before the ImageBuffer. + m_contextStateSaver.clear(); + m_context.clear(); +#endif } void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicString& value) @@ -106,13 +111,9 @@ void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicSt RenderObject* HTMLCanvasElement::createRenderer(RenderStyle* style) { - Frame* frame = document().frame(); - if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript)) { - m_rendererIsCanvas = true; + LocalFrame* frame = document().frame(); + if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript)) return new RenderHTMLCanvas(this); - } - - m_rendererIsCanvas = false; return HTMLElement::createRenderer(style); } @@ -166,38 +167,33 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas if (!m_context) { blink::Platform::current()->histogramEnumeration("Canvas.ContextType", Context2d, ContextTypeCount); m_context = CanvasRenderingContext2D::create(this, static_cast<Canvas2DContextAttributes*>(attrs), document().inQuirksMode()); - if (m_context) - scheduleLayerUpdate(); + setNeedsCompositingUpdate(); } return m_context.get(); } - Settings* settings = document().settings(); - if (settings && settings->webGLEnabled()) { - // Accept the legacy "webkit-3d" name as well as the provisional "experimental-webgl" name. - // Now that WebGL is ratified, we will also accept "webgl" as the context name in Chrome. - ContextType contextType; - bool is3dContext = true; - if (type == "webkit-3d") - contextType = ContextWebkit3d; - else if (type == "experimental-webgl") - contextType = ContextExperimentalWebgl; - else if (type == "webgl") - contextType = ContextWebgl; - else - is3dContext = false; - - if (is3dContext) { - if (m_context && !m_context->is3d()) - return 0; - if (!m_context) { - blink::Platform::current()->histogramEnumeration("Canvas.ContextType", contextType, ContextTypeCount); - m_context = WebGLRenderingContext::create(this, static_cast<WebGLContextAttributes*>(attrs)); - if (m_context) - scheduleLayerUpdate(); - } - return m_context.get(); + // Accept the the provisional "experimental-webgl" or official "webgl" context ID. + ContextType contextType; + bool is3dContext = true; + if (type == "experimental-webgl") + contextType = ContextExperimentalWebgl; + else if (type == "webgl") + contextType = ContextWebgl; + else + is3dContext = false; + + if (is3dContext) { + if (m_context && !m_context->is3d()) { + dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Canvas has an existing, non-WebGL context")); + return 0; } + if (!m_context) { + blink::Platform::current()->histogramEnumeration("Canvas.ContextType", contextType, ContextTypeCount); + m_context = WebGLRenderingContext::create(this, static_cast<WebGLContextAttributes*>(attrs)); + setNeedsCompositingUpdate(); + updateExternallyAllocatedMemory(); + } + return m_context.get(); } return 0; } @@ -214,7 +210,7 @@ void HTMLCanvasElement::didDraw(const FloatRect& rect) return; m_dirtyRect.unite(r); - ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); + ro->invalidatePaintRectangle(enclosingIntRect(m_dirtyRect)); } notifyObserversCanvasChanged(rect); @@ -222,8 +218,8 @@ void HTMLCanvasElement::didDraw(const FloatRect& rect) void HTMLCanvasElement::notifyObserversCanvasChanged(const FloatRect& rect) { - HashSet<CanvasObserver*>::iterator end = m_observers.end(); - for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) + WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> >::iterator end = m_observers.end(); + for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> >::iterator it = m_observers.begin(); it != end; ++it) (*it)->canvasChanged(this, rect); } @@ -269,19 +265,19 @@ void HTMLCanvasElement::reset() toWebGLRenderingContext(m_context.get())->reshape(width(), height()); if (RenderObject* renderer = this->renderer()) { - if (m_rendererIsCanvas) { + if (renderer->isCanvas()) { if (oldSize != size()) { toRenderHTMLCanvas(renderer)->canvasSizeChanged(); if (renderBox() && renderBox()->hasAcceleratedCompositing()) renderBox()->contentChanged(CanvasChanged); } if (hadImageBuffer) - renderer->repaint(); + renderer->paintInvalidationForWholeRenderer(); } } - HashSet<CanvasObserver*>::iterator end = m_observers.end(); - for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) + WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> >::iterator end = m_observers.end(); + for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> >::iterator it = m_observers.begin(); it != end; ++it) (*it)->canvasResized(this); } @@ -299,7 +295,7 @@ bool HTMLCanvasElement::paintsIntoCanvasBuffer() const } -void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r, bool useLowQualityScale) +void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r) { // Clear the dirty rect m_dirtyRect = FloatRect(); @@ -318,10 +314,14 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r, boo if (imageBuffer) { CompositeOperator compositeOperator = !m_context || m_context->hasAlpha() ? CompositeSourceOver : CompositeCopy; if (m_presentedImage) - context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r), compositeOperator, DoNotRespectImageOrientation, useLowQualityScale); + context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r), compositeOperator, DoNotRespectImageOrientation); else - context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), compositeOperator, blink::WebBlendModeNormal, useLowQualityScale); + context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), 0, compositeOperator); } + } else { + // When alpha is false, we should draw to opaque black. + if (m_context && !m_context->hasAlpha()) + context->fillRect(FloatRect(r), Color(0, 0, 0)); } if (is3D()) @@ -338,22 +338,28 @@ void HTMLCanvasElement::makePresentationCopy() if (!m_presentedImage) { // The buffer contains the last presented data, so save a copy of it. m_presentedImage = buffer()->copyImage(CopyBackingStore, Unscaled); + updateExternallyAllocatedMemory(); } } void HTMLCanvasElement::clearPresentationCopy() { m_presentedImage.clear(); + updateExternallyAllocatedMemory(); } void HTMLCanvasElement::setSurfaceSize(const IntSize& size) { m_size = size; m_didFailToCreateImageBuffer = false; - m_contextStateSaver.clear(); - m_imageBuffer.clear(); - setExternallyAllocatedMemory(0); + discardImageBuffer(); clearCopiedImage(); + if (m_context && m_context->is2d()) { + CanvasRenderingContext2D* context2d = toCanvasRenderingContext2D(m_context.get()); + if (context2d->isContextLost()) { + context2d->restoreContext(); + } + } } String HTMLCanvasElement::toEncodingMimeType(const String& mimeType) @@ -367,34 +373,47 @@ String HTMLCanvasElement::toEncodingMimeType(const String& mimeType) return lowercaseMimeType; } -String HTMLCanvasElement::toDataURL(const String& mimeType, const double* quality, ExceptionState& exceptionState) +const AtomicString HTMLCanvasElement::imageSourceURL() const { - if (!m_originClean) { - exceptionState.throwSecurityError("Tainted canvases may not be exported."); - return String(); - } + return AtomicString(toDataURLInternal("image/png", 0, true)); +} +String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double* quality, bool isSaving) const +{ if (m_size.isEmpty() || !buffer()) return String("data:,"); String encodingMimeType = toEncodingMimeType(mimeType); // Try to get ImageData first, as that may avoid lossy conversions. - RefPtr<ImageData> imageData = getImageData(); + RefPtrWillBeRawPtr<ImageData> imageData = getImageData(); if (imageData) return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->data()), encodingMimeType, quality); - if (m_context) + if (m_context && m_context->is3d()) { + toWebGLRenderingContext(m_context.get())->setSavingImage(isSaving); m_context->paintRenderingResultsToCanvas(); + toWebGLRenderingContext(m_context.get())->setSavingImage(false); + } return buffer()->toDataURL(encodingMimeType, quality); } -PassRefPtr<ImageData> HTMLCanvasElement::getImageData() +String HTMLCanvasElement::toDataURL(const String& mimeType, const double* quality, ExceptionState& exceptionState) const +{ + if (!m_originClean) { + exceptionState.throwSecurityError("Tainted canvases may not be exported."); + return String(); + } + + return toDataURLInternal(mimeType, quality); +} + +PassRefPtrWillBeRawPtr<ImageData> HTMLCanvasElement::getImageData() const { if (!m_context || !m_context->is3d()) - return 0; + return nullptr; return toWebGLRenderingContext(m_context.get())->paintRenderingResultsToImageData(); } @@ -446,7 +465,15 @@ PassOwnPtr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface(const void HTMLCanvasElement::createImageBuffer() { + createImageBufferInternal(); + if (m_didFailToCreateImageBuffer && m_context && m_context->is2d()) + toCanvasRenderingContext2D(m_context.get())->loseContext(); +} + +void HTMLCanvasElement::createImageBufferInternal() +{ ASSERT(!m_imageBuffer); + ASSERT(!m_contextStateSaver); m_didFailToCreateImageBuffer = true; m_didClearImageBuffer = true; @@ -465,20 +492,23 @@ void HTMLCanvasElement::createImageBuffer() OwnPtr<ImageBufferSurface> surface = createImageBufferSurface(deviceSize, &msaaSampleCount); if (!surface->isValid()) return; + m_imageBuffer = ImageBuffer::create(surface.release()); + m_imageBuffer->setClient(this); m_didFailToCreateImageBuffer = false; - setExternallyAllocatedMemory(4 * width() * height()); + updateExternallyAllocatedMemory(); if (is3D()) { // Early out for WebGL canvases - m_contextStateSaver.clear(); return; } + m_imageBuffer->setClient(this); m_imageBuffer->context()->setShouldClampToSourceRect(false); - m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality); + m_imageBuffer->context()->disableAntialiasingOptimizationForHairlineImages(); + m_imageBuffer->context()->setImageInterpolationQuality(CanvasDefaultInterpolationQuality); // Enabling MSAA overrides a request to disable antialiasing. This is true regardless of whether the // rendering mode is accelerated or not. For consistency, we don't want to apply AA in accelerated // canvases but not in unaccelerated canvases. @@ -488,15 +518,51 @@ void HTMLCanvasElement::createImageBuffer() // See CanvasRenderingContext2D::State::State() for more information. m_imageBuffer->context()->setMiterLimit(10); m_imageBuffer->context()->setStrokeThickness(1); +#if ASSERT_ENABLED + m_imageBuffer->context()->disableDestructionChecks(); // 2D canvas is allowed to leave context in an unfinalized state. +#endif m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer->context())); - // Recalculate compositing requirements if acceleration state changed. if (m_context) - scheduleLayerUpdate(); + setNeedsCompositingUpdate(); +} + +void HTMLCanvasElement::notifySurfaceInvalid() +{ + if (m_context && m_context->is2d()) { + CanvasRenderingContext2D* context2d = toCanvasRenderingContext2D(m_context.get()); + context2d->loseContext(); + } +} + +void HTMLCanvasElement::trace(Visitor* visitor) +{ + visitor->trace(m_observers); + visitor->trace(m_context); + DocumentVisibilityObserver::trace(visitor); + HTMLElement::trace(visitor); } -void HTMLCanvasElement::setExternallyAllocatedMemory(intptr_t externallyAllocatedMemory) +void HTMLCanvasElement::updateExternallyAllocatedMemory() const { + int bufferCount = 0; + if (m_imageBuffer) + bufferCount++; + if (is3D()) + bufferCount += 2; + if (m_copiedImage) + bufferCount++; + if (m_presentedImage) + bufferCount++; + + Checked<intptr_t, RecordOverflow> checkedExternallyAllocatedMemory = 4 * bufferCount; + checkedExternallyAllocatedMemory *= width(); + checkedExternallyAllocatedMemory *= height(); + intptr_t externallyAllocatedMemory; + if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == CheckedState::DidOverflow) + externallyAllocatedMemory = std::numeric_limits<intptr_t>::max(); + + // Subtracting two intptr_t that are known to be positive will never underflow. v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyAllocatedMemory - m_externallyAllocatedMemory); m_externallyAllocatedMemory = externallyAllocatedMemory; } @@ -508,10 +574,8 @@ GraphicsContext* HTMLCanvasElement::drawingContext() const GraphicsContext* HTMLCanvasElement::existingDrawingContext() const { - if (m_didFailToCreateImageBuffer) { - ASSERT(!hasImageBuffer()); + if (!hasImageBuffer()) return 0; - } return drawingContext(); } @@ -527,7 +591,7 @@ void HTMLCanvasElement::ensureUnacceleratedImageBuffer() { if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCreateImageBuffer) return; - m_imageBuffer.clear(); + discardImageBuffer(); OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque; m_imageBuffer = ImageBuffer::create(size(), opacityMode); m_didFailToCreateImageBuffer = !m_imageBuffer; @@ -539,6 +603,7 @@ Image* HTMLCanvasElement::copiedImage() const if (m_context) m_context->paintRenderingResultsToCanvas(); m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); + updateExternallyAllocatedMemory(); } return m_copiedImage.get(); } @@ -558,10 +623,23 @@ void HTMLCanvasElement::clearImageBuffer() } } +void HTMLCanvasElement::discardImageBuffer() +{ + m_contextStateSaver.clear(); // uses context owned by m_imageBuffer + m_imageBuffer.clear(); + updateExternallyAllocatedMemory(); +} + +bool HTMLCanvasElement::hasValidImageBuffer() const +{ + return m_imageBuffer && m_imageBuffer->isSurfaceValid(); +} + void HTMLCanvasElement::clearCopiedImage() { m_copiedImage.clear(); m_didClearImageBuffer = false; + updateExternallyAllocatedMemory(); } AffineTransform HTMLCanvasElement::baseTransform() const @@ -570,4 +648,62 @@ AffineTransform HTMLCanvasElement::baseTransform() const return m_imageBuffer->baseTransform(); } +void HTMLCanvasElement::didChangeVisibilityState(PageVisibilityState visibility) +{ + if (hasImageBuffer()) { + bool hidden = visibility != PageVisibilityStateVisible; + if (hidden) { + clearCopiedImage(); + if (is3D()) { + discardImageBuffer(); + } + } + if (hasImageBuffer()) { + m_imageBuffer->setIsHidden(hidden); + } + } +} + +void HTMLCanvasElement::didMoveToNewDocument(Document& oldDocument) +{ + setObservedDocument(document()); + HTMLElement::didMoveToNewDocument(oldDocument); +} + +PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageMode mode, SourceImageStatus* status) const +{ + if (!width() || !height()) { + *status = ZeroSizeCanvasSourceImageStatus; + return nullptr; + } + + if (!buffer()) { + *status = InvalidSourceImageStatus; + return nullptr; + } + + if (mode == CopySourceImageIfVolatile) { + *status = NormalSourceImageStatus; + return copiedImage(); + } + + if (m_context && m_context->is3d()) { + m_context->paintRenderingResultsToCanvas(); + *status = ExternalSourceImageStatus; + } else { + *status = NormalSourceImageStatus; + } + return m_imageBuffer->copyImage(DontCopyBackingStore, Unscaled); +} + +bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const +{ + return !originClean(); +} + +FloatSize HTMLCanvasElement::sourceSize() const +{ + return FloatSize(width(), height()); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.h index 8db8a6d70a0..175bd4e11d9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.h @@ -28,15 +28,22 @@ #ifndef HTMLCanvasElement_h #define HTMLCanvasElement_h +#include "core/dom/Document.h" #include "core/html/HTMLElement.h" +#include "core/html/canvas/CanvasImageSource.h" #include "platform/geometry/FloatRect.h" #include "platform/geometry/IntSize.h" +#include "platform/graphics/Canvas2DLayerBridge.h" +#include "platform/graphics/GraphicsTypes.h" +#include "platform/graphics/ImageBufferClient.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" -#define DefaultInterpolationQuality InterpolationMedium +#define CanvasDefaultInterpolationQuality InterpolationLow namespace WebCore { +class AffineTransform; class CanvasContextAttributes; class CanvasRenderingContext; class GraphicsContext; @@ -48,18 +55,22 @@ class ImageBuffer; class ImageBufferSurface; class IntSize; -class CanvasObserver { +class CanvasObserver : public WillBeGarbageCollectedMixin { + DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(CanvasObserver); public: - virtual ~CanvasObserver() { } - virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect) = 0; virtual void canvasResized(HTMLCanvasElement*) = 0; +#if !ENABLE(OILPAN) virtual void canvasDestroyed(HTMLCanvasElement*) = 0; +#endif + + virtual void trace(Visitor*) { } }; -class HTMLCanvasElement FINAL : public HTMLElement { +class HTMLCanvasElement FINAL : public HTMLElement, public DocumentVisibilityObserver, public CanvasImageSource, public ImageBufferClient { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLCanvasElement); public: - static PassRefPtr<HTMLCanvasElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLCanvasElement); virtual ~HTMLCanvasElement(); void addObserver(CanvasObserver*); @@ -90,14 +101,14 @@ public: CanvasRenderingContext* getContext(const String&, CanvasContextAttributes* attributes = 0); static String toEncodingMimeType(const String& mimeType); - String toDataURL(const String& mimeType, const double* quality, ExceptionState&); - String toDataURL(const String& mimeType, ExceptionState& exceptionState) { return toDataURL(mimeType, 0, exceptionState); } + String toDataURL(const String& mimeType, const double* quality, ExceptionState&) const; + String toDataURL(const String& mimeType, ExceptionState& exceptionState) const { return toDataURL(mimeType, 0, exceptionState); } // Used for rendering void didDraw(const FloatRect&); void notifyObserversCanvasChanged(const FloatRect&); - void paint(GraphicsContext*, const LayoutRect&, bool useLowQualityScale = false); + void paint(GraphicsContext*, const LayoutRect&); GraphicsContext* drawingContext() const; GraphicsContext* existingDrawingContext() const; @@ -108,56 +119,77 @@ public: ImageBuffer* buffer() const; Image* copiedImage() const; void clearCopiedImage(); - PassRefPtr<ImageData> getImageData(); + PassRefPtrWillBeRawPtr<ImageData> getImageData() const; void makePresentationCopy(); void clearPresentationCopy(); SecurityOrigin* securityOrigin() const; - void setOriginTainted() { m_originClean = false; } bool originClean() const { return m_originClean; } + void setOriginTainted() { m_originClean = false; } AffineTransform baseTransform() const; bool is3D() const; - bool hasImageBuffer() const { return m_imageBuffer.get(); } + bool hasImageBuffer() const { return m_imageBuffer; } + bool hasValidImageBuffer() const; + void discardImageBuffer(); bool shouldAccelerate(const IntSize&) const; - InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; + virtual const AtomicString imageSourceURL() const OVERRIDE; + + virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; + + // DocumentVisibilityObserver implementation + virtual void didChangeVisibilityState(PageVisibilityState) OVERRIDE; + + // CanvasImageSource implementation + virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus*) const OVERRIDE; + virtual bool wouldTaintOrigin(SecurityOrigin*) const OVERRIDE; + virtual FloatSize sourceSize() const OVERRIDE; + + // ImageBufferClient implementation + virtual void notifySurfaceInvalid() OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; + +protected: + virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; private: explicit HTMLCanvasElement(Document&); virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; } void reset(); PassOwnPtr<ImageBufferSurface> createImageBufferSurface(const IntSize& deviceSize, int* msaaSampleCount); void createImageBuffer(); + void createImageBufferInternal(); void clearImageBuffer(); void setSurfaceSize(const IntSize&); bool paintsIntoCanvasBuffer() const; - void setExternallyAllocatedMemory(intptr_t); + void updateExternallyAllocatedMemory() const; - HashSet<CanvasObserver*> m_observers; + String toDataURLInternal(const String& mimeType, const double* quality, bool isSaving = false) const; - IntSize m_size; + WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> > m_observers; - OwnPtr<CanvasRenderingContext> m_context; + IntSize m_size; - bool m_rendererIsCanvas; + OwnPtrWillBeMember<CanvasRenderingContext> m_context; bool m_ignoreReset; bool m_accelerationDisabled; FloatRect m_dirtyRect; - intptr_t m_externallyAllocatedMemory; + mutable intptr_t m_externallyAllocatedMemory; bool m_originClean; @@ -172,8 +204,6 @@ private: mutable RefPtr<Image> m_copiedImage; // FIXME: This is temporary for platforms that have to copy the image buffer to render (and for CSSCanvasValue). }; -DEFINE_NODE_TYPE_CASTS(HTMLCanvasElement, hasTagName(HTMLNames::canvasTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.idl index 0bee59fe085..e900490949d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLCanvasElement.idl @@ -32,6 +32,5 @@ interface HTMLCanvasElement : HTMLElement { [Custom, RaisesException] DOMString toDataURL([TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString type); // The custom binding is needed to handle context creation attributes. - [Custom, PerWorldBindings, ActivityLogging=ForIsolatedWorlds] any getContext([Default=Undefined] optional DOMString contextId); + [Custom, LogActivity] any getContext([Default=Undefined] optional DOMString contextId); }; - diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLCollection.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLCollection.cpp index a0edbbc2f20..7f7d597f521 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLCollection.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLCollection.cpp @@ -2,6 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2014 Samsung Electronics. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,23 +24,27 @@ #include "config.h" #include "core/html/HTMLCollection.h" -#include "HTMLNames.h" -#include "core/dom/ClassNodeList.h" +#include "core/HTMLNames.h" +#include "core/dom/ClassCollection.h" #include "core/dom/ElementTraversal.h" -#include "core/dom/NodeList.h" #include "core/dom/NodeRareData.h" -#include "core/dom/NodeTraversal.h" +#include "core/html/DocumentNameCollection.h" #include "core/html/HTMLElement.h" #include "core/html/HTMLObjectElement.h" #include "core/html/HTMLOptionElement.h" +#include "core/html/WindowNameCollection.h" +#include "wtf/HashSet.h" namespace WebCore { using namespace HTMLNames; -static bool shouldOnlyIncludeDirectChildren(CollectionType type) +static bool shouldTypeOnlyIncludeDirectChildren(CollectionType type) { switch (type) { + case ClassCollectionType: + case TagCollectionType: + case HTMLTagCollectionType: case DocAll: case DocAnchors: case DocApplets: @@ -62,12 +67,9 @@ static bool shouldOnlyIncludeDirectChildren(CollectionType type) case TSectionRows: case TableTBodies: return true; - case ChildNodeListType: - case ClassNodeListType: case NameNodeListType: - case TagNodeListType: - case HTMLTagNodeListType: case RadioNodeListType: + case RadioImgNodeListType: case LabelsNodeListType: break; } @@ -90,6 +92,9 @@ static NodeListRootType rootTypeFromCollectionType(CollectionType type) case DocumentNamedItems: case FormControls: return NodeListIsRootedAtDocument; + case ClassCollectionType: + case TagCollectionType: + case HTMLTagCollectionType: case NodeChildren: case TableTBodies: case TSectionRows: @@ -100,12 +105,9 @@ static NodeListRootType rootTypeFromCollectionType(CollectionType type) case DataListOptions: case MapAreas: return NodeListIsRootedAtNode; - case ChildNodeListType: - case ClassNodeListType: case NameNodeListType: - case TagNodeListType: - case HTMLTagNodeListType: case RadioNodeListType: + case RadioImgNodeListType: case LabelsNodeListType: break; } @@ -116,6 +118,8 @@ static NodeListRootType rootTypeFromCollectionType(CollectionType type) static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(CollectionType type) { switch (type) { + case TagCollectionType: + case HTMLTagCollectionType: case DocImages: case DocEmbeds: case DocForms: @@ -144,12 +148,11 @@ static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col return InvalidateOnIdNameAttrChange; case FormControls: return InvalidateForFormControls; - case ChildNodeListType: - case ClassNodeListType: + case ClassCollectionType: + return InvalidateOnClassAttrChange; case NameNodeListType: - case TagNodeListType: - case HTMLTagNodeListType: case RadioNodeListType: + case RadioImgNodeListType: case LabelsNodeListType: break; } @@ -157,536 +160,367 @@ static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col return DoNotInvalidateOnAttributeChanges; } -HTMLCollection::HTMLCollection(Node* ownerNode, CollectionType type, ItemAfterOverrideType itemAfterOverrideType) - : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type), - WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideType) +HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, ItemAfterOverrideType itemAfterOverrideType) + : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type), type) + , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter) + , m_shouldOnlyIncludeDirectChildren(shouldTypeOnlyIncludeDirectChildren(type)) { ScriptWrappable::init(this); } -PassRefPtr<HTMLCollection> HTMLCollection::create(Node* base, CollectionType type) +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLCollection::create(ContainerNode& base, CollectionType type) { - return adoptRef(new HTMLCollection(base, type, DoesNotOverrideItemAfter)); + return adoptRefWillBeNoop(new HTMLCollection(base, type, DoesNotOverrideItemAfter)); } HTMLCollection::~HTMLCollection() { - // HTMLNameCollection removes cache by itself. - if (type() != WindowNamedItems && type() != DocumentNamedItems) - ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type()); +#if !ENABLE(OILPAN) + if (hasValidIdNameCache()) + unregisterIdNameCacheFromDocument(document()); + // Named HTMLCollection types remove cache by themselves. + if (isUnnamedHTMLCollectionType(type())) + ownerNode().nodeLists()->removeCache(this, type()); +#endif +} + +void HTMLCollection::invalidateCache(Document* oldDocument) const +{ + m_collectionIndexCache.invalidate(); + invalidateIdNameCacheMaps(oldDocument); } template <class NodeListType> -inline bool isMatchingElement(const NodeListType*, Element*); +inline bool isMatchingElement(const NodeListType&, const Element&); -template <> inline bool isMatchingElement(const HTMLCollection* htmlCollection, Element* element) +template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) { - CollectionType type = htmlCollection->type(); - if (!element->isHTMLElement() && !(type == DocAll || type == NodeChildren || type == WindowNamedItems)) + CollectionType type = htmlCollection.type(); + + // These collections apply to any kind of Elements, not just HTMLElements. + switch (type) { + case DocAll: + case NodeChildren: + return true; + case ClassCollectionType: + return toClassCollection(htmlCollection).elementMatches(element); + case TagCollectionType: + return toTagCollection(htmlCollection).elementMatches(element); + case HTMLTagCollectionType: + return toHTMLTagCollection(htmlCollection).elementMatches(element); + case DocumentNamedItems: + return toDocumentNameCollection(htmlCollection).elementMatches(element); + case WindowNamedItems: + return toWindowNameCollection(htmlCollection).elementMatches(element); + default: + break; + } + + // The following only applies to HTMLElements. + if (!element.isHTMLElement()) return false; switch (type) { case DocImages: - return element->hasLocalName(imgTag); + return element.hasLocalName(imgTag); case DocScripts: - return element->hasLocalName(scriptTag); + return element.hasLocalName(scriptTag); case DocForms: - return element->hasLocalName(formTag); + return element.hasLocalName(formTag); case TableTBodies: - return element->hasLocalName(tbodyTag); + return element.hasLocalName(tbodyTag); case TRCells: - return element->hasLocalName(tdTag) || element->hasLocalName(thTag); + return element.hasLocalName(tdTag) || element.hasLocalName(thTag); case TSectionRows: - return element->hasLocalName(trTag); + return element.hasLocalName(trTag); case SelectOptions: - return element->hasLocalName(optionTag); + return element.hasLocalName(optionTag); case SelectedOptions: - return element->hasLocalName(optionTag) && toHTMLOptionElement(element)->selected(); + return element.hasLocalName(optionTag) && toHTMLOptionElement(element).selected(); case DataListOptions: - if (element->hasLocalName(optionTag)) { - HTMLOptionElement* option = toHTMLOptionElement(element); - if (!option->isDisabledFormControl() && !option->value().isEmpty()) + if (element.hasLocalName(optionTag)) { + const HTMLOptionElement& option = toHTMLOptionElement(element); + if (!option.isDisabledFormControl() && !option.value().isEmpty()) return true; } return false; case MapAreas: - return element->hasLocalName(areaTag); + return element.hasLocalName(areaTag); case DocApplets: - return element->hasLocalName(appletTag) || (element->hasLocalName(objectTag) && toHTMLObjectElement(element)->containsJavaApplet()); + return element.hasLocalName(appletTag) || (element.hasLocalName(objectTag) && toHTMLObjectElement(element).containsJavaApplet()); case DocEmbeds: - return element->hasLocalName(embedTag); + return element.hasLocalName(embedTag); case DocLinks: - return (element->hasLocalName(aTag) || element->hasLocalName(areaTag)) && element->fastHasAttribute(hrefAttr); + return (element.hasLocalName(aTag) || element.hasLocalName(areaTag)) && element.fastHasAttribute(hrefAttr); case DocAnchors: - return element->hasLocalName(aTag) && element->fastHasAttribute(nameAttr); + return element.hasLocalName(aTag) && element.fastHasAttribute(nameAttr); + case ClassCollectionType: + case TagCollectionType: + case HTMLTagCollectionType: case DocAll: case NodeChildren: - return true; case FormControls: case DocumentNamedItems: case TableRows: case WindowNamedItems: - case ChildNodeListType: - case ClassNodeListType: case NameNodeListType: - case TagNodeListType: - case HTMLTagNodeListType: case RadioNodeListType: + case RadioImgNodeListType: case LabelsNodeListType: ASSERT_NOT_REACHED(); } return false; } -template <> inline bool isMatchingElement(const LiveNodeList* nodeList, Element* element) -{ - return nodeList->nodeMatches(element); -} - -template <> inline bool isMatchingElement(const HTMLTagNodeList* nodeList, Element* element) -{ - return nodeList->nodeMatchesInlined(element); -} - -template <> inline bool isMatchingElement(const ClassNodeList* nodeList, Element* element) +template <> inline bool isMatchingElement(const ClassCollection& collection, const Element& element) { - return nodeList->nodeMatchesInlined(element); + return collection.elementMatches(element); } -static Node* previousNode(Node& base, Node& previous, bool onlyIncludeDirectChildren) +template <> inline bool isMatchingElement(const HTMLTagCollection& collection, const Element& element) { - return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversal::previous(previous, &base); + return collection.elementMatches(element); } -static inline Node* lastDescendent(Node& node) +Element* HTMLCollection::virtualItemAfter(Element*) const { - Node* descendent = node.lastChild(); - for (Node* current = descendent; current; current = current->lastChild()) - descendent = current; - return descendent; -} - -static Node* lastNode(Node& rootNode, bool onlyIncludeDirectChildren) -{ - return onlyIncludeDirectChildren ? rootNode.lastChild() : lastDescendent(rootNode); -} - -ALWAYS_INLINE Node* LiveNodeListBase::iterateForPreviousNode(Node* current) const -{ - bool onlyIncludeDirectChildren = shouldOnlyIncludeDirectChildren(); - CollectionType collectionType = type(); - Node& rootNode = this->rootNode(); - for (; current; current = previousNode(rootNode, *current, onlyIncludeDirectChildren)) { - if (isNodeList(collectionType)) { - if (current->isElementNode() && isMatchingElement(static_cast<const LiveNodeList*>(this), toElement(current))) - return toElement(current); - } else { - if (current->isElementNode() && isMatchingElement(static_cast<const HTMLCollection*>(this), toElement(current))) - return toElement(current); - } - } + ASSERT_NOT_REACHED(); return 0; } -ALWAYS_INLINE Node* LiveNodeListBase::itemBefore(Node* previous) const +static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) { - Node* current; - if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 10% slower. - current = previousNode(rootNode(), *previous, shouldOnlyIncludeDirectChildren()); - else - current = lastNode(rootNode(), shouldOnlyIncludeDirectChildren()); - - if (type() == ChildNodeListType) - return current; - return iterateForPreviousNode(current); + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#dom-htmlallcollection-nameditem: + // The document.all collection returns only certain types of elements by name, + // although it returns any type of element by id. + return element.hasLocalName(aTag) + || element.hasLocalName(appletTag) + || element.hasLocalName(areaTag) + || element.hasLocalName(embedTag) + || element.hasLocalName(formTag) + || element.hasLocalName(frameTag) + || element.hasLocalName(framesetTag) + || element.hasLocalName(iframeTag) + || element.hasLocalName(imgTag) + || element.hasLocalName(inputTag) + || element.hasLocalName(objectTag) + || element.hasLocalName(selectTag); +} + +inline Element* firstMatchingChildElement(const HTMLCollection& nodeList) +{ + Element* element = ElementTraversal::firstChild(nodeList.rootNode()); + while (element && !isMatchingElement(nodeList, *element)) + element = ElementTraversal::nextSibling(*element); + return element; } -template <class NodeListType> -inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode& root) +inline Element* lastMatchingChildElement(const HTMLCollection& nodeList) { - Element* element = ElementTraversal::firstWithin(root); - while (element && !isMatchingElement(nodeList, element)) - element = ElementTraversal::next(*element, &root); + Element* element = ElementTraversal::lastChild(nodeList.rootNode()); + while (element && !isMatchingElement(nodeList, *element)) + element = ElementTraversal::previousSibling(*element); return element; } -template <class NodeListType> -inline Element* nextMatchingElement(const NodeListType* nodeList, Element& current, ContainerNode* root) +inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element& current) { Element* next = ¤t; do { - next = ElementTraversal::next(*next, root); - } while (next && !isMatchingElement(nodeList, next)); + next = ElementTraversal::nextSibling(*next); + } while (next && !isMatchingElement(nodeList, *next)); return next; } -template <class NodeListType> -inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* nodeList, unsigned offset, Element& currentElement, unsigned& currentOffset, ContainerNode* root) -{ - ASSERT(currentOffset < offset); - Element* next = ¤tElement; - while ((next = nextMatchingElement(nodeList, *next, root))) { - if (++currentOffset == offset) - return next; - } - return 0; -} - -// FIXME: This should be in ChildNodeList -inline Node* LiveNodeListBase::traverseChildNodeListForwardToOffset(unsigned offset, Node* currentNode, unsigned& currentOffset) const +inline Element* previousMatchingChildElement(const HTMLCollection& nodeList, Element& current) { - ASSERT(type() == ChildNodeListType); - ASSERT(currentOffset < offset); - while ((currentNode = currentNode->nextSibling())) { - if (++currentOffset == offset) - return currentNode; + Element* previous = ¤t; + do { + previous = ElementTraversal::previousSibling(*previous); + } while (previous && !isMatchingElement(nodeList, *previous)); + return previous; +} + +Element* HTMLCollection::traverseToFirstElement() const +{ + switch (type()) { + case HTMLTagCollectionType: + return firstMatchingElement(toHTMLTagCollection(*this)); + case ClassCollectionType: + return firstMatchingElement(toClassCollection(*this)); + default: + if (overridesItemAfter()) + return virtualItemAfter(0); + if (shouldOnlyIncludeDirectChildren()) + return firstMatchingChildElement(*this); + return firstMatchingElement(*this); } - return 0; -} - -// FIXME: This should be in LiveNodeList -inline Element* LiveNodeListBase::traverseLiveNodeListFirstElement(ContainerNode& root) const -{ - ASSERT(isNodeList(type())); - ASSERT(type() != ChildNodeListType); - if (type() == HTMLTagNodeListType) - return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), root); - if (type() == ClassNodeListType) - return firstMatchingElement(static_cast<const ClassNodeList*>(this), root); - return firstMatchingElement(static_cast<const LiveNodeList*>(this), root); -} - -// FIXME: This should be in LiveNodeList -inline Element* LiveNodeListBase::traverseLiveNodeListForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset, ContainerNode* root) const -{ - ASSERT(isNodeList(type())); - ASSERT(type() != ChildNodeListType); - if (type() == HTMLTagNodeListType) - return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTagNodeList*>(this), offset, currentElement, currentOffset, root); - if (type() == ClassNodeListType) - return traverseMatchingElementsForwardToOffset(static_cast<const ClassNodeList*>(this), offset, currentElement, currentOffset, root); - return traverseMatchingElementsForwardToOffset(static_cast<const LiveNodeList*>(this), offset, currentElement, currentOffset, root); -} - -bool ALWAYS_INLINE LiveNodeListBase::isLastItemCloserThanLastOrCachedItem(unsigned offset) const -{ - ASSERT(isLengthCacheValid()); - unsigned distanceFromLastItem = cachedLength() - offset; - if (!isItemCacheValid()) - return distanceFromLastItem < offset; - - return cachedItemOffset() < offset && distanceFromLastItem < offset - cachedItemOffset(); -} - -bool ALWAYS_INLINE LiveNodeListBase::isFirstItemCloserThanCachedItem(unsigned offset) const -{ - ASSERT(isItemCacheValid()); - if (cachedItemOffset() < offset) - return false; - - unsigned distanceFromCachedItem = cachedItemOffset() - offset; - return offset < distanceFromCachedItem; } -ALWAYS_INLINE void LiveNodeListBase::setItemCache(Node* item, unsigned offset, unsigned elementsArrayOffset) const +Element* HTMLCollection::traverseToLastElement() const { - setItemCache(item, offset); - if (overridesItemAfter()) { - ASSERT_WITH_SECURITY_IMPLICATION(item->isElementNode()); - static_cast<const HTMLCollection*>(this)->m_cachedElementsArrayOffset = elementsArrayOffset; - } else - ASSERT(!elementsArrayOffset); -} - -unsigned LiveNodeListBase::length() const -{ - if (isLengthCacheValid()) - return cachedLength(); - - item(UINT_MAX); - ASSERT(isLengthCacheValid()); - - return cachedLength(); + ASSERT(canTraverseBackward()); + if (shouldOnlyIncludeDirectChildren()) + return lastMatchingChildElement(*this); + return lastMatchingElement(*this); } -// FIXME: It is silly that these functions are in HTMLCollection.cpp. -Node* LiveNodeListBase::item(unsigned offset) const +Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const { - if (isItemCacheValid() && cachedItemOffset() == offset) - return cachedItem(); - - if (isLengthCacheValid() && cachedLength() <= offset) - return 0; - - ContainerNode* root = rootContainerNode(); - if (!root) { - // FIMXE: In someTextNode.childNodes case the root is Text. We shouldn't even make a LiveNodeList for that. - setLengthCache(0); - return 0; - } - - if (isLengthCacheValid() && !overridesItemAfter() && isLastItemCloserThanLastOrCachedItem(offset)) { - Node* lastItem = itemBefore(0); - ASSERT(lastItem); - setItemCache(lastItem, cachedLength() - 1, 0); - } else if (!isItemCacheValid() || isFirstItemCloserThanCachedItem(offset) || (overridesItemAfter() && offset < cachedItemOffset())) { - unsigned offsetInArray = 0; - Node* firstItem; - if (type() == ChildNodeListType) - firstItem = root->firstChild(); - else if (isNodeList(type())) - firstItem = traverseLiveNodeListFirstElement(*root); - else - firstItem = static_cast<const HTMLCollection*>(this)->traverseFirstElement(offsetInArray, *root); - - if (!firstItem) { - setLengthCache(0); + ASSERT(currentOffset < offset); + switch (type()) { + case HTMLTagCollectionType: + return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this), offset, currentElement, currentOffset); + case ClassCollectionType: + return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset); + default: + if (overridesItemAfter()) { + Element* next = ¤tElement; + while ((next = virtualItemAfter(next))) { + if (++currentOffset == offset) + return next; + } return 0; } - setItemCache(firstItem, 0, offsetInArray); - ASSERT(!cachedItemOffset()); + if (shouldOnlyIncludeDirectChildren()) { + Element* next = ¤tElement; + while ((next = nextMatchingChildElement(*this, *next))) { + if (++currentOffset == offset) + return next; + } + return 0; + } + return traverseMatchingElementsForwardToOffset(*this, offset, currentElement, currentOffset); } - - if (cachedItemOffset() == offset) - return cachedItem(); - - return itemBeforeOrAfterCachedItem(offset, root); } -inline Node* LiveNodeListBase::itemBeforeOrAfterCachedItem(unsigned offset, ContainerNode* root) const +Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const { - unsigned currentOffset = cachedItemOffset(); - Node* currentItem = cachedItem(); - ASSERT(currentItem); - ASSERT(currentOffset != offset); - - if (offset < cachedItemOffset()) { - ASSERT(!overridesItemAfter()); - while ((currentItem = itemBefore(currentItem))) { - ASSERT(currentOffset); - currentOffset--; - if (currentOffset == offset) { - setItemCache(currentItem, currentOffset, 0); - return currentItem; - } + ASSERT(currentOffset > offset); + ASSERT(canTraverseBackward()); + if (shouldOnlyIncludeDirectChildren()) { + Element* previous = ¤tElement; + while ((previous = previousMatchingChildElement(*this, *previous))) { + if (--currentOffset == offset) + return previous; } - ASSERT_NOT_REACHED(); - return 0; - } - - unsigned offsetInArray = 0; - if (type() == ChildNodeListType) - currentItem = traverseChildNodeListForwardToOffset(offset, currentItem, currentOffset); - else if (isNodeList(type())) - currentItem = traverseLiveNodeListForwardToOffset(offset, toElement(*currentItem), currentOffset, root); - else - currentItem = static_cast<const HTMLCollection*>(this)->traverseForwardToOffset(offset, toElement(*currentItem), currentOffset, offsetInArray, root); - - if (!currentItem) { - // Did not find the item. On plus side, we now know the length. - setLengthCache(currentOffset + 1); return 0; } - setItemCache(currentItem, currentOffset, offsetInArray); - return currentItem; -} - -Element* HTMLCollection::virtualItemAfter(unsigned&, Element*) const -{ - ASSERT_NOT_REACHED(); - return 0; -} - -static inline bool nameShouldBeVisibleInDocumentAll(HTMLElement* element) -{ - // The document.all collection returns only certain types of elements by name, - // although it returns any type of element by id. - return element->hasLocalName(appletTag) - || element->hasLocalName(embedTag) - || element->hasLocalName(formTag) - || element->hasLocalName(imgTag) - || element->hasLocalName(inputTag) - || element->hasLocalName(objectTag) - || element->hasLocalName(selectTag); + return traverseMatchingElementsBackwardToOffset(*this, offset, currentElement, currentOffset); } -bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const AtomicString& name) const +Element* HTMLCollection::namedItem(const AtomicString& name) const { - if (!element->isHTMLElement()) - return false; - - HTMLElement* e = toHTMLElement(element); - if (!checkName) - return e->getIdAttribute() == name; - - if (type() == DocAll && !nameShouldBeVisibleInDocumentAll(e)) - return false; + // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp + // This method first searches for an object with a matching id + // attribute. If a match is not found, the method then searches for an + // object with a matching name attribute, but only on those elements + // that are allowed a name attribute. + updateIdNameCache(); - return e->getNameAttribute() == name && e->getIdAttribute() != name; -} + const NamedItemCache& cache = namedItemCache(); + WillBeHeapVector<RawPtrWillBeMember<Element> >* idResults = cache.getElementsById(name); + if (idResults && !idResults->isEmpty()) + return idResults->first(); -inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, ContainerNode& root) -{ - Element* element = ElementTraversal::firstWithin(root); - while (element && !isMatchingElement(nodeList, element)) - element = ElementTraversal::nextSkippingChildren(*element, &root); - return element; -} + WillBeHeapVector<RawPtrWillBeMember<Element> >* nameResults = cache.getElementsByName(name); + if (nameResults && !nameResults->isEmpty()) + return nameResults->first(); -inline Element* nextMatchingChildElement(const HTMLCollection* nodeList, Element& current, ContainerNode* root) -{ - Element* next = ¤t; - do { - next = ElementTraversal::nextSkippingChildren(*next, root); - } while (next && !isMatchingElement(nodeList, next)); - return next; -} - -inline Element* HTMLCollection::traverseFirstElement(unsigned& offsetInArray, ContainerNode& root) const -{ - if (overridesItemAfter()) - return virtualItemAfter(offsetInArray, 0); - ASSERT(!offsetInArray); - if (shouldOnlyIncludeDirectChildren()) - return firstMatchingChildElement(static_cast<const HTMLCollection*>(this), root); - return firstMatchingElement(static_cast<const HTMLCollection*>(this), root); + return 0; } -inline Element* HTMLCollection::traverseNextElement(unsigned& offsetInArray, Element& previous, ContainerNode* root) const +bool HTMLCollection::namedPropertyQuery(const AtomicString& name, ExceptionState&) { - if (overridesItemAfter()) - return virtualItemAfter(offsetInArray, &previous); - ASSERT(!offsetInArray); - if (shouldOnlyIncludeDirectChildren()) - return nextMatchingChildElement(this, previous, root); - return nextMatchingElement(this, previous, root); + return namedItem(name); } -inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset, unsigned& offsetInArray, ContainerNode* root) const +void HTMLCollection::supportedPropertyNames(Vector<String>& names) { - ASSERT(currentOffset < offset); - if (overridesItemAfter()) { - offsetInArray = m_cachedElementsArrayOffset; - Element* next = ¤tElement; - while ((next = virtualItemAfter(offsetInArray, next))) { - if (++currentOffset == offset) - return next; + // As per the specification (http://dom.spec.whatwg.org/#htmlcollection): + // The supported property names are the values from the list returned by these steps: + // 1. Let result be an empty list. + // 2. For each element represented by the collection, in tree order, run these substeps: + // 1. If element has an ID which is neither the empty string nor is in result, append element's ID to result. + // 2. If element is in the HTML namespace and has a name attribute whose value is neither the empty string + // nor is in result, append element's name attribute value to result. + // 3. Return result. + HashSet<AtomicString> existingNames; + unsigned length = this->length(); + for (unsigned i = 0; i < length; ++i) { + Element* element = item(i); + const AtomicString& idAttribute = element->getIdAttribute(); + if (!idAttribute.isEmpty()) { + HashSet<AtomicString>::AddResult addResult = existingNames.add(idAttribute); + if (addResult.isNewEntry) + names.append(idAttribute); } - return 0; - } - if (shouldOnlyIncludeDirectChildren()) { - Element* next = ¤tElement; - while ((next = nextMatchingChildElement(this, *next, root))) { - if (++currentOffset == offset) - return next; + if (!element->isHTMLElement()) + continue; + const AtomicString& nameAttribute = element->getNameAttribute(); + if (!nameAttribute.isEmpty() && (type() != DocAll || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) { + HashSet<AtomicString>::AddResult addResult = existingNames.add(nameAttribute); + if (addResult.isNewEntry) + names.append(nameAttribute); } - return 0; } - return traverseMatchingElementsForwardToOffset(this, offset, currentElement, currentOffset, root); } -Node* HTMLCollection::namedItem(const AtomicString& name) const +void HTMLCollection::namedPropertyEnumerator(Vector<String>& names, ExceptionState&) { - // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp - // This method first searches for an object with a matching id - // attribute. If a match is not found, the method then searches for an - // object with a matching name attribute, but only on those elements - // that are allowed a name attribute. - - ContainerNode* root = rootContainerNode(); - if (!root) - return 0; - - unsigned arrayOffset = 0; - unsigned i = 0; - for (Element* element = traverseFirstElement(arrayOffset, *root); element; element = traverseNextElement(arrayOffset, *element, root)) { - if (checkForNameMatch(element, /* checkName */ false, name)) { - setItemCache(element, i, arrayOffset); - return element; - } - i++; - } - - i = 0; - for (Element* element = traverseFirstElement(arrayOffset, *root); element; element = traverseNextElement(arrayOffset, *element, root)) { - if (checkForNameMatch(element, /* checkName */ true, name)) { - setItemCache(element, i, arrayOffset); - return element; - } - i++; - } - - return 0; + supportedPropertyNames(names); } -void HTMLCollection::updateNameCache() const +void HTMLCollection::updateIdNameCache() const { - if (hasNameCache()) - return; - - ContainerNode* root = rootContainerNode(); - if (!root) + if (hasValidIdNameCache()) return; - unsigned arrayOffset = 0; - for (Element* element = traverseFirstElement(arrayOffset, *root); element; element = traverseNextElement(arrayOffset, *element, root)) { + OwnPtrWillBeRawPtr<NamedItemCache> cache = NamedItemCache::create(); + unsigned length = this->length(); + for (unsigned i = 0; i < length; ++i) { + Element* element = item(i); const AtomicString& idAttrVal = element->getIdAttribute(); if (!idAttrVal.isEmpty()) - appendIdCache(idAttrVal, element); + cache->addElementWithId(idAttrVal, element); if (!element->isHTMLElement()) continue; const AtomicString& nameAttrVal = element->getNameAttribute(); - if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != DocAll || nameShouldBeVisibleInDocumentAll(toHTMLElement(element)))) - appendNameCache(nameAttrVal, element); + if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != DocAll || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) + cache->addElementWithName(nameAttrVal, element); } - - setHasNameCache(); + // Set the named item cache last as traversing the tree may cause cache invalidation. + setNamedItemCache(cache.release()); } -bool HTMLCollection::hasNamedItem(const AtomicString& name) const +void HTMLCollection::namedItems(const AtomicString& name, WillBeHeapVector<RefPtrWillBeMember<Element> >& result) const { + ASSERT(result.isEmpty()); if (name.isEmpty()) - return false; + return; - updateNameCache(); + updateIdNameCache(); - if (Vector<Element*>* cache = idCache(name)) { - if (!cache->isEmpty()) - return true; + const NamedItemCache& cache = namedItemCache(); + if (WillBeHeapVector<RawPtrWillBeMember<Element> >* idResults = cache.getElementsById(name)) { + for (unsigned i = 0; i < idResults->size(); ++i) + result.append(idResults->at(i)); } - - if (Vector<Element*>* cache = nameCache(name)) { - if (!cache->isEmpty()) - return true; + if (WillBeHeapVector<RawPtrWillBeMember<Element> >* nameResults = cache.getElementsByName(name)) { + for (unsigned i = 0; i < nameResults->size(); ++i) + result.append(nameResults->at(i)); } - - return false; } -void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Node> >& result) const +HTMLCollection::NamedItemCache::NamedItemCache() { - ASSERT(result.isEmpty()); - if (name.isEmpty()) - return; - - updateNameCache(); - - Vector<Element*>* idResults = idCache(name); - Vector<Element*>* nameResults = nameCache(name); - - for (unsigned i = 0; idResults && i < idResults->size(); ++i) - result.append(idResults->at(i)); - - for (unsigned i = 0; nameResults && i < nameResults->size(); ++i) - result.append(nameResults->at(i)); } -void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element) +void HTMLCollection::trace(Visitor* visitor) { - OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->value; - if (!vector) - vector = adoptPtr(new Vector<Element*>); - vector->append(element); + visitor->trace(m_namedItemCache); + visitor->trace(m_collectionIndexCache); + LiveNodeListBase::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLCollection.h b/chromium/third_party/WebKit/Source/core/html/HTMLCollection.h index 967b247db4d..97416341978 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLCollection.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLCollection.h @@ -2,6 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2014 Samsung Electronics. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,7 +24,8 @@ #ifndef HTMLCollection_h #define HTMLCollection_h -#include "core/dom/LiveNodeList.h" +#include "core/dom/LiveNodeListBase.h" +#include "core/html/CollectionIndexCache.h" #include "core/html/CollectionType.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" @@ -31,65 +33,133 @@ namespace WebCore { -class HTMLCollection : public LiveNodeListBase { +class HTMLCollection : public RefCountedWillBeGarbageCollectedFinalized<HTMLCollection>, public ScriptWrappable, public LiveNodeListBase { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLCollection); public: - static PassRefPtr<HTMLCollection> create(Node* base, CollectionType); + enum ItemAfterOverrideType { + OverridesItemAfter, + DoesNotOverrideItemAfter, + }; + + static PassRefPtrWillBeRawPtr<HTMLCollection> create(ContainerNode& base, CollectionType); virtual ~HTMLCollection(); + virtual void invalidateCache(Document* oldDocument = 0) const OVERRIDE; + void invalidateCacheForAttribute(const QualifiedName*) const; // DOM API - virtual Node* namedItem(const AtomicString& name) const; + unsigned length() const { return m_collectionIndexCache.nodeCount(*this); } + Element* item(unsigned offset) const { return m_collectionIndexCache.nodeAt(*this, offset); } + virtual Element* namedItem(const AtomicString& name) const; + bool namedPropertyQuery(const AtomicString&, ExceptionState&); + void namedPropertyEnumerator(Vector<String>& names, ExceptionState&); // Non-DOM API - virtual bool hasNamedItem(const AtomicString& name) const; - void namedItems(const AtomicString& name, Vector<RefPtr<Node> >&) const; - bool isEmpty() const - { - if (isLengthCacheValid()) - return !cachedLength(); - if (isItemCacheValid()) - return !cachedItem(); - return !item(0); - } - bool hasExactlyOneItem() const - { - if (isLengthCacheValid()) - return cachedLength() == 1; - if (isItemCacheValid()) - return cachedItem() && !cachedItemOffset() && !item(1); - return item(0) && !item(1); - } + void namedItems(const AtomicString& name, WillBeHeapVector<RefPtrWillBeMember<Element> >&) const; + bool isEmpty() const { return m_collectionIndexCache.isEmpty(*this); } + bool hasExactlyOneItem() const { return m_collectionIndexCache.hasExactlyOneNode(*this); } - virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const; + // CollectionIndexCache API. + bool canTraverseBackward() const { return !overridesItemAfter(); } + Element* traverseToFirstElement() const; + Element* traverseToLastElement() const; + Element* traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const; + Element* traverseBackwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const; - Element* traverseFirstElement(unsigned& offsetInArray, ContainerNode& root) const; - Element* traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset, unsigned& offsetInArray, ContainerNode* root) const; + virtual void trace(Visitor*); protected: - HTMLCollection(Node* base, CollectionType, ItemAfterOverrideType); - - virtual void updateNameCache() const; + HTMLCollection(ContainerNode& base, CollectionType, ItemAfterOverrideType); + + class NamedItemCache FINAL : public NoBaseWillBeGarbageCollected<NamedItemCache> { + public: + static PassOwnPtrWillBeRawPtr<NamedItemCache> create() + { + return adoptPtrWillBeNoop(new NamedItemCache); + } + + WillBeHeapVector<RawPtrWillBeMember<Element> >* getElementsById(const AtomicString& id) const { return m_idCache.get(id.impl()); } + WillBeHeapVector<RawPtrWillBeMember<Element> >* getElementsByName(const AtomicString& name) const { return m_nameCache.get(name.impl()); } + void addElementWithId(const AtomicString& id, Element* element) { addElementToMap(m_idCache, id, element); } + void addElementWithName(const AtomicString& name, Element* element) { addElementToMap(m_nameCache, name, element); } + + void trace(Visitor* visitor) + { + visitor->trace(m_idCache); + visitor->trace(m_nameCache); + } + + private: + NamedItemCache(); + typedef WillBeHeapHashMap<StringImpl*, OwnPtrWillBeMember<WillBeHeapVector<RawPtrWillBeMember<Element> > > > StringToElementsMap; + static void addElementToMap(StringToElementsMap& map, const AtomicString& key, Element* element) + { + OwnPtrWillBeMember<WillBeHeapVector<RawPtrWillBeMember<Element> > >& vector = map.add(key.impl(), nullptr).storedValue->value; + if (!vector) + vector = adoptPtrWillBeNoop(new WillBeHeapVector<RawPtrWillBeMember<Element> >); + vector->append(element); + } + + StringToElementsMap m_idCache; + StringToElementsMap m_nameCache; + }; + + bool overridesItemAfter() const { return m_overridesItemAfter; } + virtual Element* virtualItemAfter(Element*) const; + bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; } + virtual void supportedPropertyNames(Vector<String>& names); + + virtual void updateIdNameCache() const; + bool hasValidIdNameCache() const { return m_namedItemCache; } + + void setNamedItemCache(PassOwnPtrWillBeRawPtr<NamedItemCache> cache) const + { + ASSERT(!m_namedItemCache); + document().registerNodeListWithIdNameCache(this); + m_namedItemCache = cache; + } - typedef HashMap<StringImpl*, OwnPtr<Vector<Element*> > > NodeCacheMap; - Vector<Element*>* idCache(const AtomicString& name) const { return m_idCache.get(name.impl()); } - Vector<Element*>* nameCache(const AtomicString& name) const { return m_nameCache.get(name.impl()); } - void appendIdCache(const AtomicString& name, Element* element) const { append(m_idCache, name, element); } - void appendNameCache(const AtomicString& name, Element* element) const { append(m_nameCache, name, element); } + NamedItemCache& namedItemCache() const + { + ASSERT(m_namedItemCache); + return *m_namedItemCache; + } private: - bool checkForNameMatch(Element*, bool checkName, const AtomicString& name) const; - Element* traverseNextElement(unsigned& offsetInArray, Element& previous, ContainerNode* root) const; + void invalidateIdNameCacheMaps(Document* oldDocument = 0) const + { + if (!hasValidIdNameCache()) + return; - virtual bool isLiveNodeList() const OVERRIDE { ASSERT_NOT_REACHED(); return true; } + // Make sure we decrement the NodeListWithIdNameCache count from + // the old document instead of the new one in the case the collection + // is moved to a new document. + unregisterIdNameCacheFromDocument(oldDocument ? *oldDocument : document()); - static void append(NodeCacheMap&, const AtomicString&, Element*); + m_namedItemCache.clear(); + } - mutable NodeCacheMap m_idCache; - mutable NodeCacheMap m_nameCache; - mutable unsigned m_cachedElementsArrayOffset; + void unregisterIdNameCacheFromDocument(Document& document) const + { + ASSERT(hasValidIdNameCache()); + document.unregisterNodeListWithIdNameCache(this); + } - friend class LiveNodeListBase; + const unsigned m_overridesItemAfter : 1; + const unsigned m_shouldOnlyIncludeDirectChildren : 1; + mutable OwnPtrWillBeMember<NamedItemCache> m_namedItemCache; + mutable CollectionIndexCache<HTMLCollection, Element> m_collectionIndexCache; }; +DEFINE_TYPE_CASTS(HTMLCollection, LiveNodeListBase, collection, isHTMLCollectionType(collection->type()), isHTMLCollectionType(collection.type())); + +inline void HTMLCollection::invalidateCacheForAttribute(const QualifiedName* attrName) const +{ + if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName)) + invalidateCache(); + else if (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr) + invalidateIdNameCacheMaps(); +} + } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLCollection.idl b/chromium/third_party/WebKit/Source/core/html/HTMLCollection.idl index 0198742a6cb..cab83cd6177 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLCollection.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLCollection.idl @@ -1,6 +1,7 @@ /* * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2014 Samsung Electronics. 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 @@ -21,11 +22,11 @@ [ Custom=Wrap, DependentLifetime, - GenerateVisitDOMWrapper=ownerNode, + SetWrapperReferenceFrom=ownerNode, + WillBeGarbageCollected, ] interface HTMLCollection { readonly attribute unsigned long length; - getter Node item([Default=Undefined] optional unsigned long index); - Node namedItem([Default=Undefined] optional DOMString name); - [NotEnumerable, ImplementedAs=namedItem] getter Node ([Default=Undefined] optional DOMString name); + getter Element item([Default=Undefined] optional unsigned long index); + getter Element namedItem(DOMString name); }; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.cpp index 81691295e85..e47e91002d5 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.cpp @@ -25,26 +25,22 @@ */ #include "config.h" -#include "core/html/shadow/HTMLContentElement.h" +#include "core/html/HTMLContentElement.h" -#include "HTMLNames.h" -#include "core/css/CSSParser.h" +#include "core/HTMLNames.h" #include "core/css/SelectorChecker.h" #include "core/css/SiblingTraversalStrategies.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/dom/QualifiedName.h" #include "core/dom/shadow/ElementShadow.h" #include "core/dom/shadow/ShadowRoot.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { using namespace HTMLNames; -PassRefPtr<HTMLContentElement> HTMLContentElement::create(Document& document) -{ - return adoptRef(new HTMLContentElement(document)); -} - -HTMLContentElement::HTMLContentElement(Document& document) +inline HTMLContentElement::HTMLContentElement(Document& document) : InsertionPoint(contentTag, document) , m_shouldParseSelect(false) , m_isValidSelector(true) @@ -52,6 +48,8 @@ HTMLContentElement::HTMLContentElement(Document& document) ScriptWrappable::init(this); } +DEFINE_NODE_FACTORY(HTMLContentElement) + HTMLContentElement::~HTMLContentElement() { } @@ -60,7 +58,7 @@ void HTMLContentElement::parseSelect() { ASSERT(m_shouldParseSelect); - CSSParser parser(document()); + BisonCSSParser parser(CSSParserContext(document(), 0)); parser.parseSelector(m_select, m_selectorList); m_shouldParseSelect = false; m_isValidSelector = validateSelect(); @@ -77,8 +75,14 @@ void HTMLContentElement::parseAttribute(const QualifiedName& name, const AtomicS root->owner()->willAffectSelector(); m_shouldParseSelect = true; m_select = value; - } else + } else { InsertionPoint::parseAttribute(name, value); + } +} + +static inline bool includesDisallowedPseudoClass(const CSSSelector& selector) +{ + return selector.match() == CSSSelector::PseudoClass && selector.pseudoType() != CSSSelector::PseudoNot; } bool HTMLContentElement::validateSelect() const @@ -91,15 +95,22 @@ bool HTMLContentElement::validateSelect() const if (!m_selectorList.isValid()) return false; - for (const CSSSelector* selector = m_selectorList.first(); selector; selector = m_selectorList.next(selector)) { + bool allowAnyPseudoClasses = RuntimeEnabledFeatures::pseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled() || (containingShadowRoot() && containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot); + + for (const CSSSelector* selector = m_selectorList.first(); selector; selector = m_selectorList.next(*selector)) { if (!selector->isCompound()) return false; + if (allowAnyPseudoClasses) + continue; + for (const CSSSelector* subSelector = selector; subSelector; subSelector = subSelector->tagHistory()) { + if (includesDisallowedPseudoClass(*subSelector)) + return false; + } } - return true; } -static inline bool checkOneSelector(const CSSSelector* selector, const Vector<Node*, 32>& siblings, int nth) +static inline bool checkOneSelector(const CSSSelector& selector, const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) { Element* element = toElement(siblings[nth]); SelectorChecker selectorChecker(element->document(), SelectorChecker::CollectingCSSRules); @@ -108,10 +119,10 @@ static inline bool checkOneSelector(const CSSSelector* selector, const Vector<No return selectorChecker.match(context, strategy) == SelectorChecker::SelectorMatches; } -bool HTMLContentElement::matchSelector(const Vector<Node*, 32>& siblings, int nth) const +bool HTMLContentElement::matchSelector(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) const { - for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(selector)) { - if (checkOneSelector(selector, siblings, nth)) + for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(*selector)) { + if (checkOneSelector(*selector, siblings, nth)) return true; } return false; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.h index 9d14a277dc7..775813415d1 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.h @@ -1,2 +1,94 @@ -// FIXME: Move HTMLContentElement.h here. -#include "core/html/shadow/HTMLContentElement.h" +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLContentElement_h +#define HTMLContentElement_h + +#include "core/css/CSSSelectorList.h" +#include "core/dom/shadow/InsertionPoint.h" + +namespace WebCore { + +class HTMLContentElement FINAL : public InsertionPoint { +public: + DECLARE_NODE_FACTORY(HTMLContentElement); + virtual ~HTMLContentElement(); + + virtual bool canAffectSelector() const OVERRIDE { return true; } + + bool canSelectNode(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) const; + + const CSSSelectorList& selectorList() const; + bool isSelectValid() const; + +private: + explicit HTMLContentElement(Document&); + + virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; + + bool validateSelect() const; + void parseSelect(); + + bool matchSelector(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) const; + + bool m_shouldParseSelect; + bool m_isValidSelector; + AtomicString m_select; + CSSSelectorList m_selectorList; +}; + +inline const CSSSelectorList& HTMLContentElement::selectorList() const +{ + if (m_shouldParseSelect) + const_cast<HTMLContentElement*>(this)->parseSelect(); + return m_selectorList; +} + +inline bool HTMLContentElement::isSelectValid() const +{ + if (m_shouldParseSelect) + const_cast<HTMLContentElement*>(this)->parseSelect(); + return m_isValidSelector; +} + +inline bool HTMLContentElement::canSelectNode(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) const +{ + if (m_select.isNull() || m_select.isEmpty()) + return true; + if (!isSelectValid()) + return false; + if (!siblings[nth]->isElementNode()) + return false; + return matchSelector(siblings, nth); +} + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.idl index ab593425152..15d63d6681a 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLContentElement.idl @@ -27,6 +27,5 @@ [ ] interface HTMLContentElement : HTMLElement { [Reflect, TreatNullAs=NullString] attribute DOMString select; - attribute boolean resetStyleInheritance; NodeList getDistributedNodes(); }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.cpp index 7196698f622..59f54a6e039 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "core/html/HTMLDListElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -35,9 +35,6 @@ inline HTMLDListElement::HTMLDListElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLDListElement> HTMLDListElement::create(Document& document) -{ - return adoptRef(new HTMLDListElement(document)); -} +DEFINE_NODE_FACTORY(HTMLDListElement) } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.h index 24aeb814c09..8942e5e29ff 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDListElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLDListElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLDListElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLDListElement); private: explicit HTMLDListElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.cpp index d8666e88e91..99f268c9395 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.cpp @@ -32,7 +32,7 @@ #include "config.h" #include "core/html/HTMLDataListElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/IdTargetObserverRegistry.h" #include "core/frame/UseCounter.h" @@ -44,13 +44,13 @@ inline HTMLDataListElement::HTMLDataListElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLDataListElement> HTMLDataListElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLDataListElement> HTMLDataListElement::create(Document& document) { UseCounter::count(document, UseCounter::DataListElement); - return adoptRef(new HTMLDataListElement(document)); + return adoptRefWillBeNoop(new HTMLDataListElement(document)); } -PassRefPtr<HTMLCollection> HTMLDataListElement::options() +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLDataListElement::options() { return ensureCachedHTMLCollection(DataListOptions); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.h index e19686bfa5c..7d79c7720f3 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.h @@ -39,9 +39,9 @@ namespace WebCore { class HTMLDataListElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLDataListElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLDataListElement> create(Document&); - PassRefPtr<HTMLCollection> options(); + PassRefPtrWillBeRawPtr<HTMLCollection> options(); void optionElementChildrenChanged(); @@ -51,8 +51,6 @@ private: virtual void finishParsingChildren() OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLDataListElement, hasTagName(HTMLNames::datalistTag)); - } // namespace WebCore #endif // HTMLDataListElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.idl index 93c8663c2bb..4dd3654e759 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDataListElement.idl @@ -28,8 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -[ - RuntimeEnabled=DataListElement -] interface HTMLDataListElement : HTMLElement { +interface HTMLDataListElement : HTMLElement { readonly attribute HTMLCollection options; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp index 28c6bbeae6c..b2973cf2e51 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp @@ -21,12 +21,17 @@ #include "config.h" #include "core/html/HTMLDetailsElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/dom/Text.h" #include "core/dom/shadow/ShadowRoot.h" +#include "core/events/EventSender.h" +#include "core/html/HTMLContentElement.h" +#include "core/html/HTMLDivElement.h" #include "core/html/HTMLSummaryElement.h" -#include "core/html/shadow/HTMLContentElement.h" +#include "core/html/shadow/ShadowElementNames.h" #include "core/rendering/RenderBlockFlow.h" #include "platform/text/PlatformLocale.h" @@ -34,9 +39,15 @@ namespace WebCore { using namespace HTMLNames; -PassRefPtr<HTMLDetailsElement> HTMLDetailsElement::create(Document& document) +static DetailsEventSender& detailsToggleEventSender() { - RefPtr<HTMLDetailsElement> details = adoptRef(new HTMLDetailsElement(document)); + DEFINE_STATIC_LOCAL(DetailsEventSender, sharedToggleEventSender, (EventTypeNames::toggle)); + return sharedToggleEventSender; +} + +PassRefPtrWillBeRawPtr<HTMLDetailsElement> HTMLDetailsElement::create(Document& document) +{ + RefPtrWillBeRawPtr<HTMLDetailsElement> details = adoptRefWillBeNoop(new HTMLDetailsElement(document)); details->ensureUserAgentShadowRoot(); return details.release(); } @@ -48,6 +59,18 @@ HTMLDetailsElement::HTMLDetailsElement(Document& document) ScriptWrappable::init(this); } +HTMLDetailsElement::~HTMLDetailsElement() +{ + detailsToggleEventSender().cancelEvent(this); +} + +void HTMLDetailsElement::dispatchPendingEvent(DetailsEventSender* eventSender) +{ + ASSERT_UNUSED(eventSender, eventSender == &detailsToggleEventSender()); + dispatchEvent(Event::create(EventTypeNames::toggle)); +} + + RenderObject* HTMLDetailsElement::createRenderer(RenderStyle*) { return new RenderBlockFlow(this); @@ -57,26 +80,29 @@ void HTMLDetailsElement::didAddUserAgentShadowRoot(ShadowRoot& root) { DEFINE_STATIC_LOCAL(const AtomicString, summarySelector, ("summary:first-of-type", AtomicString::ConstructFromLiteral)); - RefPtr<HTMLSummaryElement> defaultSummary = HTMLSummaryElement::create(document()); + RefPtrWillBeRawPtr<HTMLSummaryElement> defaultSummary = HTMLSummaryElement::create(document()); defaultSummary->appendChild(Text::create(document(), locale().queryString(blink::WebLocalizedString::DetailsLabel))); - RefPtr<HTMLContentElement> content = HTMLContentElement::create(document()); - content->setAttribute(selectAttr, summarySelector); - content->appendChild(defaultSummary); - - root.appendChild(content); - root.appendChild(HTMLContentElement::create(document())); + RefPtrWillBeRawPtr<HTMLContentElement> summary = HTMLContentElement::create(document()); + summary->setIdAttribute(ShadowElementNames::detailsSummary()); + summary->setAttribute(selectAttr, summarySelector); + summary->appendChild(defaultSummary); + root.appendChild(summary.release()); + + RefPtrWillBeRawPtr<HTMLDivElement> content = HTMLDivElement::create(document()); + content->setIdAttribute(ShadowElementNames::detailsContent()); + content->appendChild(HTMLContentElement::create(document())); + content->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); + root.appendChild(content.release()); } Element* HTMLDetailsElement::findMainSummary() const { - for (Node* child = firstChild(); child; child = child->nextSibling()) { - if (child->hasTagName(summaryTag)) - return toElement(child); - } + if (HTMLSummaryElement* summary = Traversal<HTMLSummaryElement>::firstChild(*this)) + return summary; HTMLContentElement* content = toHTMLContentElement(userAgentShadowRoot()->firstChild()); - ASSERT(content->firstChild() && content->firstChild()->hasTagName(summaryTag)); + ASSERT(content->firstChild() && isHTMLSummaryElement(*content->firstChild())); return toElement(content->firstChild()); } @@ -85,20 +111,28 @@ void HTMLDetailsElement::parseAttribute(const QualifiedName& name, const AtomicS if (name == openAttr) { bool oldValue = m_isOpen; m_isOpen = !value.isNull(); - if (oldValue != m_isOpen) - lazyReattachIfAttached(); - } else - HTMLElement::parseAttribute(name, value); -} - -bool HTMLDetailsElement::childShouldCreateRenderer(const Node& child) const -{ - // FIXME: These checks do not look correct, we should just use insertion points instead. - if (m_isOpen) - return HTMLElement::childShouldCreateRenderer(child); - if (!child.hasTagName(summaryTag)) - return false; - return child == findMainSummary() && HTMLElement::childShouldCreateRenderer(child); + if (m_isOpen == oldValue) + return; + + // Dispatch toggle event asynchronously. + detailsToggleEventSender().cancelEvent(this); + detailsToggleEventSender().dispatchEventSoon(this); + + Element* content = ensureUserAgentShadowRoot().getElementById(ShadowElementNames::detailsContent()); + ASSERT(content); + if (m_isOpen) + content->removeInlineStyleProperty(CSSPropertyDisplay); + else + content->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); + Element* summary = ensureUserAgentShadowRoot().getElementById(ShadowElementNames::detailsSummary()); + ASSERT(summary); + // FIXME: DetailsMarkerControl's RenderDetailsMarker has no concept of being updated + // without recreating it causing a repaint. Instead we should change it so we can tell + // it to toggle the open/closed triangle state and avoid reattaching the entire summary. + summary->lazyReattachIfAttached(); + return; + } + HTMLElement::parseAttribute(name, value); } void HTMLDetailsElement::toggleOpen() diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.h index d5a6b4a6169..2e9d762d980 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDetailsElement.h @@ -25,18 +25,23 @@ namespace WebCore { +template<typename T> class EventSender; +typedef EventSender<HTMLDetailsElement> DetailsEventSender; + class HTMLDetailsElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLDetailsElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLDetailsElement> create(Document&); void toggleOpen(); + virtual ~HTMLDetailsElement(); + + void dispatchPendingEvent(DetailsEventSender*); Element* findMainSummary() const; private: explicit HTMLDetailsElement(Document&); - virtual RenderObject* createRenderer(RenderStyle*); - virtual bool childShouldCreateRenderer(const Node& child) const OVERRIDE; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE; virtual bool isInteractiveContent() const OVERRIDE; @@ -44,18 +49,6 @@ private: bool m_isOpen; }; -inline bool isHTMLDetailsElement(const Node* node) -{ - return node->hasTagName(HTMLNames::detailsTag); -} - -inline bool isHTMLDetailsElement(const Element* element) -{ - return element->hasTagName(HTMLNames::detailsTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLDetailsElement, hasTagName(HTMLNames::detailsTag)); - } // namespace WebCore #endif // HTMLDetailsElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp index 59d5bc04a5e..5eb8125e534 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp @@ -45,7 +45,7 @@ static void setFocusForModalDialog(HTMLDialogElement* dialog) Element* focusableDescendant = 0; Node* next = 0; for (Node* node = dialog->firstChild(); node; node = next) { - if (node->hasTagName(dialogTag)) + if (isHTMLDialogElement(*node)) next = NodeTraversal::nextSkippingChildren(*node, dialog); else next = NodeTraversal::next(*node, dialog); @@ -57,7 +57,6 @@ static void setFocusForModalDialog(HTMLDialogElement* dialog) HTMLFormControlElement* control = toHTMLFormControlElement(node); if (control->isAutofocusable()) { control->focus(); - control->setAutofocused(); return; } } @@ -75,7 +74,7 @@ static void setFocusForModalDialog(HTMLDialogElement* dialog) return; } - dialog->document().setFocusedElement(0); + dialog->document().setFocusedElement(nullptr); } static void inertSubtreesChanged(Document& document) @@ -84,25 +83,22 @@ static void inertSubtreesChanged(Document& document) // tree can change inertness which means they must be added or removed from // the tree. The most foolproof way is to clear the entire tree and rebuild // it, though a more clever way is probably possible. - Document* topDocument = document.topDocument(); - topDocument->clearAXObjectCache(); - if (AXObjectCache* cache = topDocument->axObjectCache()) - cache->childrenChanged(cache->getOrCreate(topDocument)); + Document& topDocument = document.topDocument(); + topDocument.clearAXObjectCache(); + if (AXObjectCache* cache = topDocument.axObjectCache()) + cache->childrenChanged(cache->getOrCreate(&topDocument)); } -HTMLDialogElement::HTMLDialogElement(Document& document) +inline HTMLDialogElement::HTMLDialogElement(Document& document) : HTMLElement(dialogTag, document) - , m_centeringMode(Uninitialized) + , m_centeringMode(NotCentered) , m_centeredPosition(0) , m_returnValue("") { ScriptWrappable::init(this); } -PassRefPtr<HTMLDialogElement> HTMLDialogElement::create(Document& document) -{ - return adoptRef(new HTMLDialogElement(document)); -} +DEFINE_NODE_FACTORY(HTMLDialogElement) void HTMLDialogElement::close(const String& returnValue, ExceptionState& exceptionState) { @@ -132,10 +128,10 @@ void HTMLDialogElement::closeDialog(const String& returnValue) void HTMLDialogElement::forceLayoutForCentering() { - m_centeringMode = Uninitialized; + m_centeringMode = NeedsCentering; document().updateLayoutIgnorePendingStylesheets(); - if (m_centeringMode == Uninitialized) - m_centeringMode = NotCentered; + if (m_centeringMode == NeedsCentering) + setNotCentered(); } void HTMLDialogElement::show() @@ -143,7 +139,6 @@ void HTMLDialogElement::show() if (fastHasAttribute(openAttr)) return; setBooleanAttribute(openAttr, true); - forceLayoutForCentering(); } void HTMLDialogElement::showModal(ExceptionState& exceptionState) @@ -168,16 +163,22 @@ void HTMLDialogElement::showModal(ExceptionState& exceptionState) setFocusForModalDialog(this); } +void HTMLDialogElement::removedFrom(ContainerNode* insertionPoint) +{ + HTMLElement::removedFrom(insertionPoint); + setNotCentered(); + // FIXME: We should call inertSubtreesChanged() here. +} + void HTMLDialogElement::setCentered(LayoutUnit centeredPosition) { - ASSERT(m_centeringMode == Uninitialized); + ASSERT(m_centeringMode == NeedsCentering); m_centeredPosition = centeredPosition; m_centeringMode = Centered; } void HTMLDialogElement::setNotCentered() { - ASSERT(m_centeringMode == Uninitialized); m_centeringMode = NotCentered; } @@ -201,11 +202,4 @@ void HTMLDialogElement::defaultEventHandler(Event* event) HTMLElement::defaultEventHandler(event); } -bool HTMLDialogElement::shouldBeReparentedUnderRenderView(const RenderStyle* style) const -{ - if (style && style->position() == AbsolutePosition) - return true; - return Element::shouldBeReparentedUnderRenderView(style); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.h index 248044e98f8..2f003c9dc95 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.h @@ -26,7 +26,6 @@ #ifndef HTMLDialogElement_h #define HTMLDialogElement_h -#include "RuntimeEnabledFeatures.h" #include "core/html/HTMLElement.h" namespace WebCore { @@ -37,14 +36,18 @@ class QualifiedName; class HTMLDialogElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLDialogElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLDialogElement); void close(const String& returnValue, ExceptionState&); void closeDialog(const String& returnValue = String()); void show(); void showModal(ExceptionState&); + virtual void removedFrom(ContainerNode*) OVERRIDE; - enum CenteringMode { Uninitialized, Centered, NotCentered }; + // NotCentered means do not center the dialog. Centered means the dialog has + // been centered and centeredPosition() is set. NeedsCentering means attempt + // to center on the next layout, then set to Centered or NotCentered. + enum CenteringMode { NotCentered, Centered, NeedsCentering }; CenteringMode centeringMode() const { return m_centeringMode; } LayoutUnit centeredPosition() const { @@ -62,7 +65,6 @@ private: virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; - virtual bool shouldBeReparentedUnderRenderView(const RenderStyle*) const OVERRIDE; void forceLayoutForCentering(); @@ -71,13 +73,6 @@ private: String m_returnValue; }; -inline HTMLDialogElement* toHTMLDialogElement(Node* node) -{ - ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(HTMLNames::dialogTag)); - ASSERT_WITH_SECURITY_IMPLICATION(RuntimeEnabledFeatures::dialogElementEnabled()); - return static_cast<HTMLDialogElement*>(node); -} - } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.idl index 6c2d0c8c0fe..c26e3941dce 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDialogElement.idl @@ -28,7 +28,7 @@ ] interface HTMLDialogElement : HTMLElement { [Reflect] attribute boolean open; attribute DOMString returnValue; - [RaisesException] void close([Default=NullString] optional DOMString returnValue); + [RaisesException] void close(optional DOMString returnValue = null); void show(); [RaisesException] void showModal(); }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.cpp index 2010c5a5178..8d739dc3d7e 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "core/html/HTMLDirectoryElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -35,9 +35,6 @@ inline HTMLDirectoryElement::HTMLDirectoryElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLDirectoryElement> HTMLDirectoryElement::create(Document& document) -{ - return adoptRef(new HTMLDirectoryElement(document)); -} +DEFINE_NODE_FACTORY(HTMLDirectoryElement) } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.h index 7c0dcaa7951..fc2a0792ef9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDirectoryElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLDirectoryElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLDirectoryElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLDirectoryElement); private: explicit HTMLDirectoryElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.cpp index af3d8938783..29d4ce2f7e5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.cpp @@ -23,9 +23,9 @@ #include "config.h" #include "core/html/HTMLDivElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -37,17 +37,7 @@ HTMLDivElement::HTMLDivElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLDivElement> HTMLDivElement::create(Document& document) -{ - return adoptRef(new HTMLDivElement(document)); -} - -bool HTMLDivElement::isPresentationAttribute(const QualifiedName& name) const -{ - if (name == alignAttr) - return true; - return HTMLElement::isPresentationAttribute(name); -} +DEFINE_NODE_FACTORY(HTMLDivElement) void HTMLDivElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.h index 12e230088b2..37279ed111d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDivElement.h @@ -29,18 +29,15 @@ namespace WebCore { class HTMLDivElement : public HTMLElement { public: - static PassRefPtr<HTMLDivElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLDivElement); protected: explicit HTMLDivElement(Document&); private: - virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLDivElement, hasTagName(HTMLNames::divTag)); - } // namespace WebCore #endif // HTMLDivElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDocument.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLDocument.cpp index 761a6e3093a..298f8b6e91d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDocument.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDocument.cpp @@ -53,11 +53,11 @@ #include "config.h" #include "core/html/HTMLDocument.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptController.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/HTMLNames.h" +#include "core/frame/LocalDOMWindow.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLBodyElement.h" #include "core/page/FocusController.h" #include "core/page/FrameTree.h" @@ -73,69 +73,20 @@ HTMLDocument::HTMLDocument(const DocumentInit& initializer, DocumentClassFlags e { ScriptWrappable::init(this); clearXMLVersion(); + if (isSrcdocDocument() || initializer.importsController()) { + ASSERT(inNoQuirksMode()); + lockCompatibilityMode(); + } } HTMLDocument::~HTMLDocument() { } -const AtomicString& HTMLDocument::dir() -{ - HTMLElement* b = body(); - if (!b) - return nullAtom; - return b->getAttribute(dirAttr); -} - -void HTMLDocument::setDir(const AtomicString& value) -{ - HTMLElement* b = body(); - if (b) - b->setAttribute(dirAttr, value); -} - -String HTMLDocument::designMode() const -{ - return inDesignMode() ? "on" : "off"; -} - -void HTMLDocument::setDesignMode(const String& value) -{ - InheritedBool mode; - if (equalIgnoringCase(value, "on")) - mode = on; - else if (equalIgnoringCase(value, "off")) - mode = off; - else - mode = inherit; - Document::setDesignMode(mode); -} - -Element* HTMLDocument::activeElement() -{ - if (Element* element = treeScope().adjustedFocusedElement()) - return element; - return body(); -} - -bool HTMLDocument::hasFocus() -{ - Page* page = this->page(); - if (!page) - return false; - if (!page->focusController().isActive() || !page->focusController().isFocused()) - return false; - if (Frame* focusedFrame = page->focusController().focusedFrame()) { - if (focusedFrame->tree().isDescendantOf(frame())) - return true; - } - return false; -} - HTMLBodyElement* HTMLDocument::htmlBodyElement() const { HTMLElement* body = this->body(); - return (body && body->hasTagName(bodyTag)) ? toHTMLBodyElement(body) : 0; + return isHTMLBodyElement(body) ? toHTMLBodyElement(body) : 0; } const AtomicString& HTMLDocument::bodyAttributeValue(const QualifiedName& name) const @@ -207,7 +158,7 @@ void HTMLDocument::setVlinkColor(const AtomicString& value) setBodyAttribute(vlinkAttr, value); } -PassRefPtr<Document> HTMLDocument::cloneDocumentWithoutChildren() +PassRefPtrWillBeRawPtr<Document> HTMLDocument::cloneDocumentWithoutChildren() { return create(DocumentInit(url()).withRegistrationContext(registrationContext())); } @@ -221,7 +172,7 @@ void HTMLDocument::addItemToMap(HashCountedSet<AtomicString>& map, const AtomicS if (name.isEmpty()) return; map.add(name); - if (Frame* f = frame()) + if (LocalFrame* f = frame()) f->script().namedItemAdded(this, name); } @@ -230,7 +181,7 @@ void HTMLDocument::removeItemFromMap(HashCountedSet<AtomicString>& map, const At if (name.isEmpty()) return; map.remove(name); - if (Frame* f = frame()) + if (LocalFrame* f = frame()) f->script().namedItemRemoved(this, name); } @@ -321,29 +272,22 @@ bool HTMLDocument::isCaseSensitiveAttribute(const QualifiedName& attributeName) return !isPossibleHTMLAttr || !htmlCaseInsensitiveAttributesSet->contains(attributeName.localName().impl()); } -void HTMLDocument::clear() -{ - // FIXME: This does nothing, and that seems unlikely to be correct. - // We've long had a comment saying that IE doesn't support this. - // But I do see it in the documentation for Mozilla. -} - -void HTMLDocument::write(DOMWindow* activeWindow, const Vector<String>& text) +void HTMLDocument::write(LocalDOMWindow* callingWindow, const Vector<String>& text, ExceptionState& exceptionState) { - ASSERT(activeWindow); + ASSERT(callingWindow); StringBuilder builder; for (size_t i = 0; i < text.size(); ++i) builder.append(text[i]); - write(builder.toString(), activeWindow->document()); + write(builder.toString(), callingWindow->document(), exceptionState); } -void HTMLDocument::writeln(DOMWindow* activeWindow, const Vector<String>& text) +void HTMLDocument::writeln(LocalDOMWindow* callingWindow, const Vector<String>& text, ExceptionState& exceptionState) { - ASSERT(activeWindow); + ASSERT(callingWindow); StringBuilder builder; for (size_t i = 0; i < text.size(); ++i) builder.append(text[i]); - writeln(builder.toString(), activeWindow->document()); + writeln(builder.toString(), callingWindow->document(), exceptionState); } } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDocument.h b/chromium/third_party/WebKit/Source/core/html/HTMLDocument.h index aa52f77ac85..f89c1b7639f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDocument.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDocument.h @@ -35,21 +35,12 @@ class HTMLElement; class HTMLDocument : public Document, public ResourceClient { public: - static PassRefPtr<HTMLDocument> create(const DocumentInit& initializer = DocumentInit()) + static PassRefPtrWillBeRawPtr<HTMLDocument> create(const DocumentInit& initializer = DocumentInit()) { - return adoptRef(new HTMLDocument(initializer)); + return adoptRefWillBeNoop(new HTMLDocument(initializer)); } virtual ~HTMLDocument(); - const AtomicString& dir(); - void setDir(const AtomicString&); - - String designMode() const; - void setDesignMode(const String&); - - Element* activeElement(); - bool hasFocus(); - const AtomicString& bgColor() const; void setBgColor(const AtomicString&); const AtomicString& fgColor() const; @@ -61,7 +52,7 @@ public: const AtomicString& vlinkColor() const; void setVlinkColor(const AtomicString&); - void clear(); + void clear() { } void captureEvents() { } void releaseEvents() { } @@ -76,12 +67,12 @@ public: using Document::write; using Document::writeln; - void write(DOMWindow*, const Vector<String>& text); - void writeln(DOMWindow*, const Vector<String>& text); + void write(LocalDOMWindow*, const Vector<String>& text, ExceptionState&); + void writeln(LocalDOMWindow*, const Vector<String>& text, ExceptionState&); static bool isCaseSensitiveAttribute(const QualifiedName&); - virtual PassRefPtr<Document> cloneDocumentWithoutChildren() OVERRIDE FINAL; + virtual PassRefPtrWillBeRawPtr<Document> cloneDocumentWithoutChildren() OVERRIDE FINAL; protected: HTMLDocument(const DocumentInit&, DocumentClassFlags extendedDocumentClasses = DefaultDocumentClass); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLDocument.idl b/chromium/third_party/WebKit/Source/core/html/HTMLDocument.idl index 84328c8565f..04ba97f3187 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLDocument.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLDocument.idl @@ -18,36 +18,30 @@ * Boston, MA 02110-1301, USA. */ -interface HTMLDocument : Document { +[ + // FIXME: Oilpan: remove this once Node specifies WillBeGarbageCollected. + WillBeGarbageCollected +] interface HTMLDocument : Document { [Custom, CustomElementCallbacks] void open(); - void close(); + [RaisesException] void close(); // We support multiple DOMString arguments to match FF / IE, e.g.: // document.write("a", "b", "c") --> document.write("abc") // document.write() --> document.write("") - [CallWith=ActiveWindow, PerWorldBindings, ActivityLogging=ForIsolatedWorlds, CustomElementCallbacks] void write(DOMString... text); - [CallWith=ActiveWindow, PerWorldBindings, ActivityLogging=ForIsolatedWorlds, CustomElementCallbacks] void writeln(DOMString... text); - - readonly attribute HTMLCollection embeds; - [ImplementedAs=embeds] readonly attribute HTMLCollection plugins; - readonly attribute HTMLCollection scripts; + [CallWith=ActiveWindow,LogActivity, CustomElementCallbacks, RaisesException] void write(DOMString... text); + [CallWith=ActiveWindow, LogActivity, CustomElementCallbacks, RaisesException] void writeln(DOMString... text); // Extensions [Replaceable, ImplementedAs=allForBinding] readonly attribute HTMLAllCollection all; - [DeprecateAs=DocumentClear] void clear(); + [MeasureAs=DocumentClear] void clear(); - [DeprecateAs=CaptureEvents] void captureEvents(); - [DeprecateAs=ReleaseEvents] void releaseEvents(); + [MeasureAs=DocumentCaptureEvents] void captureEvents(); + [MeasureAs=DocumentReleaseEvents] void releaseEvents(); - [TreatNullAs=NullString, CustomElementCallbacks] attribute DOMString dir; - [TreatNullAs=NullString, CustomElementCallbacks] attribute DOMString designMode; readonly attribute DOMString compatMode; - readonly attribute Element activeElement; - boolean hasFocus(); - // Deprecated attributes [TreatNullAs=NullString, CustomElementCallbacks] attribute DOMString bgColor; [TreatNullAs=NullString, CustomElementCallbacks] attribute DOMString fgColor; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLElement.cpp index 8fcff5b5bfb..6a64bc4b5b5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLElement.cpp @@ -25,35 +25,34 @@ #include "config.h" #include "core/html/HTMLElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" -#include "XMLNames.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptEventListener.h" -#include "core/css/CSSParser.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" +#include "core/XMLNames.h" +#include "core/css/CSSMarkup.h" #include "core/css/CSSValuePool.h" #include "core/css/StylePropertySet.h" #include "core/dom/DocumentFragment.h" #include "core/dom/ExceptionCode.h" #include "core/dom/NodeTraversal.h" #include "core/dom/Text.h" +#include "core/dom/shadow/ElementShadow.h" +#include "core/dom/shadow/ShadowRoot.h" #include "core/editing/markup.h" #include "core/events/EventListener.h" #include "core/events/KeyboardEvent.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/Settings.h" #include "core/html/HTMLBRElement.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLInputElement.h" #include "core/html/HTMLTemplateElement.h" #include "core/html/HTMLTextFormControlElement.h" #include "core/html/parser/HTMLParserIdioms.h" -#include "core/loader/FrameLoader.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" -#include "core/rendering/RenderWordBreak.h" +#include "core/rendering/RenderObject.h" #include "platform/text/BidiResolver.h" +#include "platform/text/BidiTextRun.h" #include "platform/text/TextRunIterator.h" #include "wtf/StdLibExtras.h" #include "wtf/text/CString.h" @@ -66,18 +65,18 @@ using namespace WTF; using std::min; using std::max; -PassRefPtr<HTMLElement> HTMLElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLElement); String HTMLElement::nodeName() const { // FIXME: Would be nice to have an atomicstring lookup based off uppercase // chars that does not have to copy the string on a hit in the hash. // FIXME: We should have a way to detect XHTML elements and replace the hasPrefix() check with it. - if (document().isHTMLDocument() && !tagQName().hasPrefix()) - return tagQName().localNameUpper(); + if (document().isHTMLDocument()) { + if (!tagQName().hasPrefix()) + return tagQName().localNameUpper(); + return Element::nodeName().upper(); + } return Element::nodeName(); } @@ -101,7 +100,6 @@ bool HTMLElement::ieForbidsInsertHTML() const || hasLocalName(imageTag) || hasLocalName(imgTag) || hasLocalName(inputTag) - || hasLocalName(isindexTag) || hasLocalName(linkTag) || hasLocalName(metaTag) || hasLocalName(paramTag) @@ -204,95 +202,102 @@ void HTMLElement::collectStyleForPresentationAttribute(const QualifiedName& name Element::collectStyleForPresentationAttribute(name, value, style); } -const AtomicString& HTMLElement::eventNameForAttributeName(const QualifiedName& attrName) const +const AtomicString& HTMLElement::eventNameForAttributeName(const QualifiedName& attrName) { if (!attrName.namespaceURI().isNull()) return nullAtom; + if (!attrName.localName().startsWith("on", false)) + return nullAtom; + typedef HashMap<AtomicString, AtomicString> StringToStringMap; DEFINE_STATIC_LOCAL(StringToStringMap, attributeNameToEventNameMap, ()); if (!attributeNameToEventNameMap.size()) { - attributeNameToEventNameMap.set(onanimationstartAttr.localName(), EventTypeNames::animationstart); - attributeNameToEventNameMap.set(onanimationiterationAttr.localName(), EventTypeNames::animationiteration); + attributeNameToEventNameMap.set(onabortAttr.localName(), EventTypeNames::abort); attributeNameToEventNameMap.set(onanimationendAttr.localName(), EventTypeNames::animationend); + attributeNameToEventNameMap.set(onanimationiterationAttr.localName(), EventTypeNames::animationiteration); + attributeNameToEventNameMap.set(onanimationstartAttr.localName(), EventTypeNames::animationstart); + attributeNameToEventNameMap.set(onautocompleteAttr.localName(), EventTypeNames::autocomplete); + attributeNameToEventNameMap.set(onautocompleteerrorAttr.localName(), EventTypeNames::autocompleteerror); + attributeNameToEventNameMap.set(onbeforecopyAttr.localName(), EventTypeNames::beforecopy); + attributeNameToEventNameMap.set(onbeforecutAttr.localName(), EventTypeNames::beforecut); + attributeNameToEventNameMap.set(onbeforepasteAttr.localName(), EventTypeNames::beforepaste); + attributeNameToEventNameMap.set(onblurAttr.localName(), EventTypeNames::blur); attributeNameToEventNameMap.set(oncancelAttr.localName(), EventTypeNames::cancel); + attributeNameToEventNameMap.set(oncanplayAttr.localName(), EventTypeNames::canplay); + attributeNameToEventNameMap.set(oncanplaythroughAttr.localName(), EventTypeNames::canplaythrough); + attributeNameToEventNameMap.set(onchangeAttr.localName(), EventTypeNames::change); attributeNameToEventNameMap.set(onclickAttr.localName(), EventTypeNames::click); attributeNameToEventNameMap.set(oncloseAttr.localName(), EventTypeNames::close); attributeNameToEventNameMap.set(oncontextmenuAttr.localName(), EventTypeNames::contextmenu); - attributeNameToEventNameMap.set(ondblclickAttr.localName(), EventTypeNames::dblclick); - attributeNameToEventNameMap.set(onmousedownAttr.localName(), EventTypeNames::mousedown); - attributeNameToEventNameMap.set(onmouseenterAttr.localName(), EventTypeNames::mouseenter); - attributeNameToEventNameMap.set(onmouseleaveAttr.localName(), EventTypeNames::mouseleave); - attributeNameToEventNameMap.set(onmousemoveAttr.localName(), EventTypeNames::mousemove); - attributeNameToEventNameMap.set(onmouseoutAttr.localName(), EventTypeNames::mouseout); - attributeNameToEventNameMap.set(onmouseoverAttr.localName(), EventTypeNames::mouseover); - attributeNameToEventNameMap.set(onmouseupAttr.localName(), EventTypeNames::mouseup); - attributeNameToEventNameMap.set(onmousewheelAttr.localName(), EventTypeNames::mousewheel); - attributeNameToEventNameMap.set(onwheelAttr.localName(), EventTypeNames::wheel); - attributeNameToEventNameMap.set(onfocusAttr.localName(), EventTypeNames::focus); - attributeNameToEventNameMap.set(onfocusinAttr.localName(), EventTypeNames::focusin); - attributeNameToEventNameMap.set(onfocusoutAttr.localName(), EventTypeNames::focusout); - attributeNameToEventNameMap.set(onblurAttr.localName(), EventTypeNames::blur); - attributeNameToEventNameMap.set(onkeydownAttr.localName(), EventTypeNames::keydown); - attributeNameToEventNameMap.set(onkeypressAttr.localName(), EventTypeNames::keypress); - attributeNameToEventNameMap.set(onkeyupAttr.localName(), EventTypeNames::keyup); - attributeNameToEventNameMap.set(onscrollAttr.localName(), EventTypeNames::scroll); - attributeNameToEventNameMap.set(onbeforecutAttr.localName(), EventTypeNames::beforecut); - attributeNameToEventNameMap.set(oncutAttr.localName(), EventTypeNames::cut); - attributeNameToEventNameMap.set(onbeforecopyAttr.localName(), EventTypeNames::beforecopy); attributeNameToEventNameMap.set(oncopyAttr.localName(), EventTypeNames::copy); - attributeNameToEventNameMap.set(onbeforepasteAttr.localName(), EventTypeNames::beforepaste); - attributeNameToEventNameMap.set(onpasteAttr.localName(), EventTypeNames::paste); + attributeNameToEventNameMap.set(oncuechangeAttr.localName(), EventTypeNames::cuechange); + attributeNameToEventNameMap.set(oncutAttr.localName(), EventTypeNames::cut); + attributeNameToEventNameMap.set(ondblclickAttr.localName(), EventTypeNames::dblclick); + attributeNameToEventNameMap.set(ondragAttr.localName(), EventTypeNames::drag); + attributeNameToEventNameMap.set(ondragendAttr.localName(), EventTypeNames::dragend); attributeNameToEventNameMap.set(ondragenterAttr.localName(), EventTypeNames::dragenter); - attributeNameToEventNameMap.set(ondragoverAttr.localName(), EventTypeNames::dragover); attributeNameToEventNameMap.set(ondragleaveAttr.localName(), EventTypeNames::dragleave); - attributeNameToEventNameMap.set(ondropAttr.localName(), EventTypeNames::drop); + attributeNameToEventNameMap.set(ondragoverAttr.localName(), EventTypeNames::dragover); attributeNameToEventNameMap.set(ondragstartAttr.localName(), EventTypeNames::dragstart); - attributeNameToEventNameMap.set(ondragAttr.localName(), EventTypeNames::drag); - attributeNameToEventNameMap.set(ondragendAttr.localName(), EventTypeNames::dragend); - attributeNameToEventNameMap.set(onselectstartAttr.localName(), EventTypeNames::selectstart); - attributeNameToEventNameMap.set(onsubmitAttr.localName(), EventTypeNames::submit); - attributeNameToEventNameMap.set(onerrorAttr.localName(), EventTypeNames::error); - attributeNameToEventNameMap.set(onwebkitanimationstartAttr.localName(), EventTypeNames::webkitAnimationStart); - attributeNameToEventNameMap.set(onwebkitanimationiterationAttr.localName(), EventTypeNames::webkitAnimationIteration); - attributeNameToEventNameMap.set(onwebkitanimationendAttr.localName(), EventTypeNames::webkitAnimationEnd); - attributeNameToEventNameMap.set(onwebkittransitionendAttr.localName(), EventTypeNames::webkitTransitionEnd); - attributeNameToEventNameMap.set(ontransitionendAttr.localName(), EventTypeNames::webkitTransitionEnd); - attributeNameToEventNameMap.set(oninputAttr.localName(), EventTypeNames::input); - attributeNameToEventNameMap.set(oninvalidAttr.localName(), EventTypeNames::invalid); - attributeNameToEventNameMap.set(ontouchstartAttr.localName(), EventTypeNames::touchstart); - attributeNameToEventNameMap.set(ontouchmoveAttr.localName(), EventTypeNames::touchmove); - attributeNameToEventNameMap.set(ontouchendAttr.localName(), EventTypeNames::touchend); - attributeNameToEventNameMap.set(ontouchcancelAttr.localName(), EventTypeNames::touchcancel); - attributeNameToEventNameMap.set(onwebkitfullscreenchangeAttr.localName(), EventTypeNames::webkitfullscreenchange); - attributeNameToEventNameMap.set(onwebkitfullscreenerrorAttr.localName(), EventTypeNames::webkitfullscreenerror); - attributeNameToEventNameMap.set(onabortAttr.localName(), EventTypeNames::abort); - attributeNameToEventNameMap.set(oncanplayAttr.localName(), EventTypeNames::canplay); - attributeNameToEventNameMap.set(oncanplaythroughAttr.localName(), EventTypeNames::canplaythrough); - attributeNameToEventNameMap.set(onchangeAttr.localName(), EventTypeNames::change); - attributeNameToEventNameMap.set(oncuechangeAttr.localName(), EventTypeNames::cuechange); + attributeNameToEventNameMap.set(ondropAttr.localName(), EventTypeNames::drop); attributeNameToEventNameMap.set(ondurationchangeAttr.localName(), EventTypeNames::durationchange); attributeNameToEventNameMap.set(onemptiedAttr.localName(), EventTypeNames::emptied); attributeNameToEventNameMap.set(onendedAttr.localName(), EventTypeNames::ended); + attributeNameToEventNameMap.set(onerrorAttr.localName(), EventTypeNames::error); + attributeNameToEventNameMap.set(onfocusAttr.localName(), EventTypeNames::focus); + attributeNameToEventNameMap.set(onfocusinAttr.localName(), EventTypeNames::focusin); + attributeNameToEventNameMap.set(onfocusoutAttr.localName(), EventTypeNames::focusout); + attributeNameToEventNameMap.set(oninputAttr.localName(), EventTypeNames::input); + attributeNameToEventNameMap.set(oninvalidAttr.localName(), EventTypeNames::invalid); + attributeNameToEventNameMap.set(onkeydownAttr.localName(), EventTypeNames::keydown); + attributeNameToEventNameMap.set(onkeypressAttr.localName(), EventTypeNames::keypress); + attributeNameToEventNameMap.set(onkeyupAttr.localName(), EventTypeNames::keyup); + attributeNameToEventNameMap.set(onloadAttr.localName(), EventTypeNames::load); attributeNameToEventNameMap.set(onloadeddataAttr.localName(), EventTypeNames::loadeddata); attributeNameToEventNameMap.set(onloadedmetadataAttr.localName(), EventTypeNames::loadedmetadata); attributeNameToEventNameMap.set(onloadstartAttr.localName(), EventTypeNames::loadstart); + attributeNameToEventNameMap.set(onmousedownAttr.localName(), EventTypeNames::mousedown); + attributeNameToEventNameMap.set(onmouseenterAttr.localName(), EventTypeNames::mouseenter); + attributeNameToEventNameMap.set(onmouseleaveAttr.localName(), EventTypeNames::mouseleave); + attributeNameToEventNameMap.set(onmousemoveAttr.localName(), EventTypeNames::mousemove); + attributeNameToEventNameMap.set(onmouseoutAttr.localName(), EventTypeNames::mouseout); + attributeNameToEventNameMap.set(onmouseoverAttr.localName(), EventTypeNames::mouseover); + attributeNameToEventNameMap.set(onmouseupAttr.localName(), EventTypeNames::mouseup); + attributeNameToEventNameMap.set(onmousewheelAttr.localName(), EventTypeNames::mousewheel); + attributeNameToEventNameMap.set(onpasteAttr.localName(), EventTypeNames::paste); attributeNameToEventNameMap.set(onpauseAttr.localName(), EventTypeNames::pause); attributeNameToEventNameMap.set(onplayAttr.localName(), EventTypeNames::play); attributeNameToEventNameMap.set(onplayingAttr.localName(), EventTypeNames::playing); attributeNameToEventNameMap.set(onprogressAttr.localName(), EventTypeNames::progress); attributeNameToEventNameMap.set(onratechangeAttr.localName(), EventTypeNames::ratechange); attributeNameToEventNameMap.set(onresetAttr.localName(), EventTypeNames::reset); + attributeNameToEventNameMap.set(onresizeAttr.localName(), EventTypeNames::resize); + attributeNameToEventNameMap.set(onscrollAttr.localName(), EventTypeNames::scroll); attributeNameToEventNameMap.set(onseekedAttr.localName(), EventTypeNames::seeked); attributeNameToEventNameMap.set(onseekingAttr.localName(), EventTypeNames::seeking); attributeNameToEventNameMap.set(onselectAttr.localName(), EventTypeNames::select); + attributeNameToEventNameMap.set(onselectstartAttr.localName(), EventTypeNames::selectstart); attributeNameToEventNameMap.set(onshowAttr.localName(), EventTypeNames::show); attributeNameToEventNameMap.set(onstalledAttr.localName(), EventTypeNames::stalled); + attributeNameToEventNameMap.set(onsubmitAttr.localName(), EventTypeNames::submit); attributeNameToEventNameMap.set(onsuspendAttr.localName(), EventTypeNames::suspend); attributeNameToEventNameMap.set(ontimeupdateAttr.localName(), EventTypeNames::timeupdate); + attributeNameToEventNameMap.set(ontoggleAttr.localName(), EventTypeNames::toggle); + attributeNameToEventNameMap.set(ontouchcancelAttr.localName(), EventTypeNames::touchcancel); + attributeNameToEventNameMap.set(ontouchendAttr.localName(), EventTypeNames::touchend); + attributeNameToEventNameMap.set(ontouchmoveAttr.localName(), EventTypeNames::touchmove); + attributeNameToEventNameMap.set(ontouchstartAttr.localName(), EventTypeNames::touchstart); + attributeNameToEventNameMap.set(ontransitionendAttr.localName(), EventTypeNames::webkitTransitionEnd); attributeNameToEventNameMap.set(onvolumechangeAttr.localName(), EventTypeNames::volumechange); attributeNameToEventNameMap.set(onwaitingAttr.localName(), EventTypeNames::waiting); - attributeNameToEventNameMap.set(onloadAttr.localName(), EventTypeNames::load); + attributeNameToEventNameMap.set(onwebkitanimationendAttr.localName(), EventTypeNames::webkitAnimationEnd); + attributeNameToEventNameMap.set(onwebkitanimationiterationAttr.localName(), EventTypeNames::webkitAnimationIteration); + attributeNameToEventNameMap.set(onwebkitanimationstartAttr.localName(), EventTypeNames::webkitAnimationStart); + attributeNameToEventNameMap.set(onwebkitfullscreenchangeAttr.localName(), EventTypeNames::webkitfullscreenchange); + attributeNameToEventNameMap.set(onwebkitfullscreenerrorAttr.localName(), EventTypeNames::webkitfullscreenerror); + attributeNameToEventNameMap.set(onwebkittransitionendAttr.localName(), EventTypeNames::webkitTransitionEnd); + attributeNameToEventNameMap.set(onwheelAttr.localName(), EventTypeNames::wheel); } return attributeNameToEventNameMap.get(attrName.localName()); @@ -300,37 +305,24 @@ const AtomicString& HTMLElement::eventNameForAttributeName(const QualifiedName& void HTMLElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { - if (isIdAttributeName(name) || name == classAttr || name == styleAttr) + if (name == tabindexAttr) return Element::parseAttribute(name, value); - if (name == dirAttr) + if (name == dirAttr) { dirAttributeChanged(value); - else if (name == tabindexAttr) { - int tabindex = 0; - if (value.isEmpty()) { - clearTabIndexExplicitlyIfNeeded(); - if (treeScope().adjustedFocusedElement() == this) { - // We might want to call blur(), but it's dangerous to dispatch - // events here. - document().setNeedsFocusedElementCheck(); - } - } else if (parseHTMLInteger(value, tabindex)) { - // Clamp tabindex to the range of 'short' to match Firefox's behavior. - setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); - } } else { const AtomicString& eventName = eventNameForAttributeName(name); if (!eventName.isNull()) - setAttributeEventListener(eventName, createAttributeEventListener(this, name, value)); + setAttributeEventListener(eventName, createAttributeEventListener(this, name, value, eventParameterName())); } } -PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionState& exceptionState) { - RefPtr<DocumentFragment> fragment = DocumentFragment::create(document()); - unsigned int i, length = text.length(); + RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(document()); + unsigned i, length = text.length(); UChar c = 0; - for (unsigned int start = 0; start < length; ) { + for (unsigned start = 0; start < length; ) { // Find next line break. for (i = start; i < length; i++) { @@ -341,12 +333,12 @@ PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, Exc fragment->appendChild(Text::create(document(), text.substring(start, i - start)), exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; if (c == '\r' || c == '\n') { fragment->appendChild(HTMLBRElement::create(document()), exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; // Make sure \r\n doesn't result in two line breaks. if (c == '\r' && i + 1 < length && text[i + 1] == '\n') i++; @@ -400,7 +392,7 @@ void HTMLElement::setInnerText(const String& text, ExceptionState& exceptionStat } // Add text nodes and <br> elements. - RefPtr<DocumentFragment> fragment = textToFragment(text, exceptionState); + RefPtrWillBeRawPtr<DocumentFragment> fragment = textToFragment(text, exceptionState); if (!exceptionState.hadException()) replaceChildrenWithFragment(this, fragment.release(), exceptionState); } @@ -425,9 +417,9 @@ void HTMLElement::setOuterText(const String &text, ExceptionState& exceptionStat return; } - RefPtr<Node> prev = previousSibling(); - RefPtr<Node> next = nextSibling(); - RefPtr<Node> newChild; + RefPtrWillBeRawPtr<Node> prev = previousSibling(); + RefPtrWillBeRawPtr<Node> next = nextSibling(); + RefPtrWillBeRawPtr<Node> newChild = nullptr; // Convert text to fragment with <br> tags instead of linebreaks if needed. if (text.contains('\r') || text.contains('\n')) @@ -436,7 +428,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionState& exceptionStat newChild = Text::create(document(), text); // textToFragment might cause mutation events. - if (!this || !parentNode()) + if (!parentNode()) exceptionState.throwDOMException(HierarchyRequestError, "The element has no parent."); if (exceptionState.hadException()) @@ -444,7 +436,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionState& exceptionStat parent->replaceChild(newChild.release(), this, exceptionState); - RefPtr<Node> node = next ? next->previousSibling() : 0; + RefPtrWillBeRawPtr<Node> node = next ? next->previousSibling() : nullptr; if (!exceptionState.hadException() && node && node->isTextNode()) mergeWithNextTextNode(node.release(), exceptionState); @@ -452,24 +444,6 @@ void HTMLElement::setOuterText(const String &text, ExceptionState& exceptionStat mergeWithNextTextNode(prev.release(), exceptionState); } -Element* HTMLElement::insertAdjacentElement(const String& where, Element* newChild, ExceptionState& exceptionState) -{ - if (!newChild) { - // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative. - exceptionState.throwTypeError("The node provided is null."); - return 0; - } - - Node* returnValue = insertAdjacent(where, newChild, exceptionState); - return toElement(returnValue); -} - -void HTMLElement::insertAdjacentText(const String& where, const String& text, ExceptionState& exceptionState) -{ - RefPtr<Text> textNode = document().createTextNode(text); - insertAdjacent(where, textNode.get(), exceptionState); -} - void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStylePropertySet* style) { // Vertical alignment with respect to the current baseline of the text @@ -510,33 +484,6 @@ bool HTMLElement::hasCustomFocusLogic() const return false; } -bool HTMLElement::supportsSpatialNavigationFocus() const -{ - // This function checks whether the element satisfies the extended criteria - // for the element to be focusable, introduced by spatial navigation feature, - // i.e. checks if click or keyboard event handler is specified. - // This is the way to make it possible to navigate to (focus) elements - // which web designer meant for being active (made them respond to click events). - - if (!document().settings() || !document().settings()->spatialNavigationEnabled()) - return false; - return hasEventListeners(EventTypeNames::click) - || hasEventListeners(EventTypeNames::keydown) - || hasEventListeners(EventTypeNames::keypress) - || hasEventListeners(EventTypeNames::keyup); -} - -bool HTMLElement::supportsFocus() const -{ - // FIXME: supportsFocus() can be called when layout is not up to date. - // Logic that deals with the renderer should be moved to rendererIsFocusable(). - // But supportsFocus must return true when the element is editable, or else - // it won't be focusable. Furthermore, supportsFocus cannot just return true - // always or else tabIndex() will change for all HTML elements. - return Element::supportsFocus() || (rendererIsEditable() && parentNode() && !parentNode()->rendererIsEditable()) - || supportsSpatialNavigationFocus(); -} - String HTMLElement::contentEditable() const { const AtomicString& value = fastGetAttribute(contenteditableAttr); @@ -600,7 +547,7 @@ void HTMLElement::accessKeyAction(bool sendMouseEvents) String HTMLElement::title() const { - return getAttribute(titleAttr); + return fastGetAttribute(titleAttr); } short HTMLElement::tabIndex() const @@ -610,11 +557,6 @@ short HTMLElement::tabIndex() const return -1; } -void HTMLElement::setTabIndex(int value) -{ - setIntegralAttribute(tabindexAttr, value); -} - TranslateAttributeMode HTMLElement::translateAttributeMode() const { const AtomicString& value = getAttribute(translateAttr); @@ -631,13 +573,11 @@ TranslateAttributeMode HTMLElement::translateAttributeMode() const bool HTMLElement::translate() const { - for (const Node* n = this; n; n = n->parentNode()) { - if (n->isHTMLElement()) { - TranslateAttributeMode mode = toHTMLElement(n)->translateAttributeMode(); - if (mode != TranslateAttributeInherit) { - ASSERT(mode == TranslateAttributeYes || mode == TranslateAttributeNo); - return mode == TranslateAttributeYes; - } + for (const HTMLElement* element = this; element; element = Traversal<HTMLElement>::firstAncestor(*element)) { + TranslateAttributeMode mode = element->translateAttributeMode(); + if (mode != TranslateAttributeInherit) { + ASSERT(mode == TranslateAttributeYes || mode == TranslateAttributeNo); + return mode == TranslateAttributeYes; } } @@ -650,39 +590,43 @@ void HTMLElement::setTranslate(bool enable) setAttribute(translateAttr, enable ? "yes" : "no"); } -bool HTMLElement::rendererIsNeeded(const RenderStyle& style) +// Returns the conforming 'dir' value associated with the state the attribute is in (in its canonical case), if any, +// or the empty string if the attribute is in a state that has no associated keyword value or if the attribute is +// not in a defined state (e.g. the attribute is missing and there is no missing value default). +// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#limited-to-only-known-values +static inline const AtomicString& toValidDirValue(const AtomicString& value) { - if (hasLocalName(noscriptTag)) { - Frame* frame = document().frame(); - if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript)) - return false; - } else if (hasLocalName(noembedTag)) { - Frame* frame = document().frame(); - if (frame && frame->loader().allowPlugins(NotAboutToInstantiatePlugin)) - return false; - } - return Element::rendererIsNeeded(style); + DEFINE_STATIC_LOCAL(const AtomicString, ltrValue, ("ltr", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, rtlValue, ("rtl", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, autoValue, ("auto", AtomicString::ConstructFromLiteral)); + + if (equalIgnoringCase(value, ltrValue)) + return ltrValue; + if (equalIgnoringCase(value, rtlValue)) + return rtlValue; + if (equalIgnoringCase(value, autoValue)) + return autoValue; + return nullAtom; +} + +const AtomicString& HTMLElement::dir() +{ + return toValidDirValue(fastGetAttribute(dirAttr)); } -RenderObject* HTMLElement::createRenderer(RenderStyle* style) +void HTMLElement::setDir(const AtomicString& value) { - if (hasLocalName(wbrTag)) - return new RenderWordBreak(this); - return RenderObject::createObject(this, style); + setAttribute(dirAttr, value); } HTMLFormElement* HTMLElement::findFormAncestor() const { - for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) { - if (ancestor->hasTagName(formTag)) - return toHTMLFormElement(ancestor); - } - return 0; + return Traversal<HTMLFormElement>::firstAncestor(*this); } static inline bool elementAffectsDirectionality(const Node* node) { - return node->isHTMLElement() && (node->hasTagName(bdiTag) || toHTMLElement(node)->hasAttribute(dirAttr)); + return node->isHTMLElement() && (isHTMLBDIElement(*node) || toHTMLElement(node)->hasAttribute(dirAttr)); } static void setHasDirAutoFlagRecursively(Node* firstNode, bool flag, Node* lastNode = 0) @@ -692,9 +636,6 @@ static void setHasDirAutoFlagRecursively(Node* firstNode, bool flag, Node* lastN Node* node = firstNode->firstChild(); while (node) { - if (node->selfOrAncestorHasDirAutoAttribute() == flag) - return; - if (elementAffectsDirectionality(node)) { if (node == lastNode) return; @@ -717,7 +658,7 @@ void HTMLElement::childrenChanged(bool changedByParser, Node* beforeChange, Node bool HTMLElement::hasDirectionAuto() const { const AtomicString& direction = fastGetAttribute(dirAttr); - return (hasTagName(bdiTag) && direction == nullAtom) || equalIgnoringCase(direction, "auto"); + return (isHTMLBDIElement(*this) && direction == nullAtom) || equalIgnoringCase(direction, "auto"); } TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) const @@ -731,18 +672,9 @@ TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) con return directionality(); } -static TextDirection determineDirectionality(const String& value, bool& hasStrongDirectionality) -{ - TextRun run(value); - BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; - bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride())); - bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0)); - return bidiResolver.determineParagraphDirectionality(&hasStrongDirectionality); -} - TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) const { - if (hasTagName(inputTag)) { + if (isHTMLInputElement(*this)) { HTMLInputElement* inputElement = toHTMLInputElement(const_cast<HTMLElement*>(this)); bool hasStrongDirectionality; TextDirection textDirection = determineDirectionality(inputElement->value(), hasStrongDirectionality); @@ -754,7 +686,7 @@ TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) c Node* node = firstChild(); while (node) { // Skip bdi, script, style and text form controls. - if (equalIgnoringCase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag) + if (equalIgnoringCase(node->nodeName(), "bdi") || isHTMLScriptElement(*node) || isHTMLStyleElement(*node) || (node->isElementNode() && toElement(node)->isTextFormControl())) { node = NodeTraversal::nextSkippingChildren(*node, this); continue; @@ -806,7 +738,7 @@ void HTMLElement::adjustDirectionalityIfNeededAfterChildAttributeChanged(Element Element* elementToAdjust = this; for (; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) { if (elementAffectsDirectionality(elementToAdjust)) { - elementToAdjust->setNeedsStyleRecalc(); + elementToAdjust->setNeedsStyleRecalc(SubtreeStyleChange); return; } } @@ -817,14 +749,16 @@ void HTMLElement::calculateAndAdjustDirectionality() { Node* strongDirectionalityTextNode; TextDirection textDirection = directionality(&strongDirectionalityTextNode); - setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode); + setHasDirAutoFlagRecursively(this, hasDirectionAuto(), strongDirectionalityTextNode); + for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) + setHasDirAutoFlagRecursively(root, hasDirectionAuto()); if (renderer() && renderer()->style() && renderer()->style()->direction() != textDirection) - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeChange, int childCountDelta) { - if (document().renderer() && childCountDelta < 0) { + if (document().renderView() && childCountDelta < 0) { Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(*beforeChange) : 0; for (int counter = 0; node && counter < childCountDelta; counter++, node = NodeTraversal::nextSkippingChildren(*node)) { if (elementAffectsDirectionality(node)) @@ -859,25 +793,25 @@ void HTMLElement::addHTMLLengthToStyle(MutableStylePropertySet* style, CSSProper // strip attribute garbage.. StringImpl* v = value.impl(); if (v) { - unsigned int l = 0; + unsigned length = 0; - while (l < v->length() && (*v)[l] <= ' ') - l++; + while (length < v->length() && (*v)[length] <= ' ') + length++; - for (; l < v->length(); l++) { - UChar cc = (*v)[l]; + for (; length < v->length(); length++) { + UChar cc = (*v)[length]; if (cc > '9') break; if (cc < '0') { if (cc == '%' || cc == '*') - l++; + length++; if (cc != '.') break; } } - if (l != v->length()) { - addPropertyToPresentationAttributeStyle(style, propertyID, v->substring(0, l)); + if (length != v->length()) { + addPropertyToPresentationAttributeStyle(style, propertyID, v->substring(0, length)); return; } } @@ -955,8 +889,8 @@ void HTMLElement::addHTMLColorToStyle(MutableStylePropertySet* style, CSSPropert return; // If the string is a named CSS color or a 3/6-digit hex color, use that. - Color parsedColor(colorString); - if (!parsedColor.isValid()) + Color parsedColor; + if (!parsedColor.setFromString(colorString)) parsedColor.setRGB(parseColorStringWithCrazyLegacyRules(colorString)); style->setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb())); @@ -978,6 +912,26 @@ void HTMLElement::defaultEventHandler(Event* event) Element::defaultEventHandler(event); } +bool HTMLElement::matchesReadOnlyPseudoClass() const +{ + return !matchesReadWritePseudoClass(); +} + +bool HTMLElement::matchesReadWritePseudoClass() const +{ + if (fastHasAttribute(contenteditableAttr)) { + const AtomicString& value = fastGetAttribute(contenteditableAttr); + + if (value.isEmpty() || equalIgnoringCase(value, "true") || equalIgnoringCase(value, "plaintext-only")) + return true; + if (equalIgnoringCase(value, "false")) + return false; + // All other values should be treated as "inherit". + } + + return parentElement() && parentElement()->rendererIsEditable(); +} + void HTMLElement::handleKeypressEvent(KeyboardEvent* event) { if (!document().settings() || !document().settings()->spatialNavigationEnabled() || !supportsFocus()) @@ -994,6 +948,12 @@ void HTMLElement::handleKeypressEvent(KeyboardEvent* event) } } +const AtomicString& HTMLElement::eventParameterName() +{ + DEFINE_STATIC_LOCAL(const AtomicString, eventString, ("event", AtomicString::ConstructFromLiteral)); + return eventString; +} + } // namespace WebCore #ifndef NDEBUG diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLElement.h index ef4736aa9bc..492555175a6 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLElement.h @@ -40,21 +40,15 @@ enum TranslateAttributeMode { class HTMLElement : public Element { public: - static PassRefPtr<HTMLElement> create(const QualifiedName& tagName, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLElement); virtual String title() const OVERRIDE FINAL; - - virtual short tabIndex() const; - void setTabIndex(int); + virtual short tabIndex() const OVERRIDE; void setInnerText(const String&, ExceptionState&); void setOuterText(const String&, ExceptionState&); - Element* insertAdjacentElement(const String& where, Element* newChild, ExceptionState&); - void insertAdjacentText(const String& where, const String& text, ExceptionState&); - virtual bool hasCustomFocusLogic() const; - virtual bool supportsFocus() const; String contentEditable() const; void setContentEditable(const String&, ExceptionState&); @@ -68,15 +62,15 @@ public: bool translate() const; void setTranslate(bool); + const AtomicString& dir(); + void setDir(const AtomicString&); + void click(); - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; bool ieForbidsInsertHTML() const; - virtual bool rendererIsNeeded(const RenderStyle&); - virtual RenderObject* createRenderer(RenderStyle*); - virtual HTMLFormElement* formOwner() const { return 0; } HTMLFormElement* findFormAncestor() const; @@ -85,12 +79,20 @@ public: TextDirection directionalityIfhasDirAutoAttribute(bool& isAuto) const; virtual bool isHTMLUnknownElement() const { return false; } + virtual bool isPluginElement() const { return false; } virtual bool isLabelable() const { return false; } // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#interactive-content virtual bool isInteractiveContent() const; virtual void defaultEventHandler(Event*) OVERRIDE; + static const AtomicString& eventNameForAttributeName(const QualifiedName& attrName); + + virtual bool matchesReadOnlyPseudoClass() const OVERRIDE; + virtual bool matchesReadWritePseudoClass() const OVERRIDE; + + static const AtomicString& eventParameterName(); + protected: HTMLElement(const QualifiedName& tagName, Document&, ConstructionType); @@ -105,7 +107,7 @@ protected: virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; unsigned parseBorderWidthAttribute(const AtomicString&) const; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; void calculateAndAdjustDirectionality(); private: @@ -113,7 +115,7 @@ private: void mapLanguageAttributeToLocale(const AtomicString&, MutableStylePropertySet*); - PassRefPtr<DocumentFragment> textToFragment(const String&, ExceptionState&); + PassRefPtrWillBeRawPtr<DocumentFragment> textToFragment(const String&, ExceptionState&); void dirAttributeChanged(const AtomicString&); void adjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child); @@ -122,13 +124,14 @@ private: TranslateAttributeMode translateAttributeMode() const; - const AtomicString& eventNameForAttributeName(const QualifiedName& attrName) const; - void handleKeypressEvent(KeyboardEvent*); - bool supportsSpatialNavigationFocus() const; }; -DEFINE_NODE_TYPE_CASTS(HTMLElement, isHTMLElement()); +DEFINE_ELEMENT_TYPE_CASTS(HTMLElement, isHTMLElement()); + +template <> inline bool isElementOfType<const HTMLElement>(const Node& node) { return node.isHTMLElement(); } +template <typename T> bool isElementOfType(const HTMLElement&); +template <> inline bool isElementOfType<const HTMLElement>(const HTMLElement&) { return true; } inline HTMLElement::HTMLElement(const QualifiedName& tagName, Document& document, ConstructionType type = CreateHTMLElement) : Element(tagName, &document, type) @@ -137,6 +140,22 @@ inline HTMLElement::HTMLElement(const QualifiedName& tagName, Document& document ScriptWrappable::init(this); } +// This requires isHTML*Element(const Element&) and isHTML*Element(const HTMLElement&). +// When the input element is an HTMLElement, we don't need to check the namespace URI, just the local name. +#define DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) \ + inline bool is##thisType(const thisType* element); \ + inline bool is##thisType(const thisType& element); \ + inline bool is##thisType(const HTMLElement* element) { return element && is##thisType(*element); } \ + inline bool is##thisType(const Element* element) { return element && is##thisType(*element); } \ + inline bool is##thisType(const Node& node) { return node.isElementNode() ? is##thisType(toElement(node)) : false; } \ + inline bool is##thisType(const Node* node) { return node && node->isElementNode() ? is##thisType(*toElement(node)) : false; } \ + template<typename T> inline bool is##thisType(const PassRefPtr<T>& node) { return is##thisType(node.get()); } \ + template<typename T> inline bool is##thisType(const RefPtr<T>& node) { return is##thisType(node.get()); } \ + template <> inline bool isElementOfType<const thisType>(const HTMLElement& element) { return is##thisType(element); } \ + DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) + } // namespace WebCore +#include "core/HTMLElementTypeHelpers.h" + #endif // HTMLElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLElement.idl index 5d065681ee8..65e7cb26ae9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLElement.idl @@ -24,7 +24,7 @@ [Reflect] attribute DOMString title; [Reflect] attribute DOMString lang; attribute boolean translate; - [Reflect] attribute DOMString dir; + attribute DOMString dir; [CustomElementCallbacks] attribute long tabIndex; [CustomElementCallbacks] attribute boolean draggable; @@ -36,11 +36,6 @@ [TreatNullAs=NullString, CustomElementCallbacks, RaisesException=Setter, MeasureAs=HTMLElementInnerText] attribute DOMString innerText; [TreatNullAs=NullString, CustomElementCallbacks, RaisesException=Setter, MeasureAs=HTMLElementOuterText] attribute DOMString outerText; - [RaisesException, CustomElementCallbacks, MeasureAs=InsertAdjacentElement] Element insertAdjacentElement([Default=Undefined] optional DOMString where, - [Default=Undefined] optional Element element); - [RaisesException, MeasureAs=InsertAdjacentText] void insertAdjacentText([Default=Undefined] optional DOMString where, - [Default=Undefined] optional DOMString text); - [RuntimeEnabled=IMEAPI] readonly attribute InputMethodContext inputMethodContext; [CustomElementCallbacks, RaisesException=Setter] attribute DOMString contentEditable; @@ -52,3 +47,4 @@ }; HTMLElement implements GlobalEventHandlers; + diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp index c6bde0181e1..99e3467a03f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp @@ -24,8 +24,8 @@ #include "config.h" #include "core/html/HTMLEmbedElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLImageLoader.h" @@ -45,9 +45,9 @@ inline HTMLEmbedElement::HTMLEmbedElement(Document& document, bool createdByPars ScriptWrappable::init(this); } -PassRefPtr<HTMLEmbedElement> HTMLEmbedElement::create(Document& document, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLEmbedElement> HTMLEmbedElement::create(Document& document, bool createdByParser) { - RefPtr<HTMLEmbedElement> element = adoptRef(new HTMLEmbedElement(document, createdByParser)); + RefPtrWillBeRawPtr<HTMLEmbedElement> element = adoptRefWillBeNoop(new HTMLEmbedElement(document, createdByParser)); element->ensureUserAgentShadowRoot(); return element.release(); } @@ -55,9 +55,7 @@ PassRefPtr<HTMLEmbedElement> HTMLEmbedElement::create(Document& document, bool c static inline RenderWidget* findWidgetRenderer(const Node* n) { if (!n->renderer()) - do - n = n->parentNode(); - while (n && !n->hasTagName(objectTag)); + n = Traversal<HTMLObjectElement>::firstAncestor(*n); if (n && n->renderer() && n->renderer()->isWidget()) return toRenderWidget(n->renderer()); @@ -96,13 +94,15 @@ void HTMLEmbedElement::parseAttribute(const QualifiedName& name, const AtomicStr size_t pos = m_serviceType.find(";"); if (pos != kNotFound) m_serviceType = m_serviceType.left(pos); + if (!renderer()) + requestPluginCreationWithoutRendererIfPossible(); } else if (name == codeAttr) { m_url = stripLeadingAndTrailingHTMLSpaces(value); } else if (name == srcAttr) { m_url = stripLeadingAndTrailingHTMLSpaces(value); if (renderer() && isImageType()) { if (!m_imageLoader) - m_imageLoader = adoptPtr(new HTMLImageLoader(this)); + m_imageLoader = HTMLImageLoader::create(this); m_imageLoader->updateFromElementIgnoringPreviousError(); } } else { @@ -115,10 +115,11 @@ void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<St if (!hasAttributes()) return; - for (unsigned i = 0; i < attributeCount(); ++i) { - const Attribute* attribute = attributeItem(i); - paramNames.append(attribute->localName().string()); - paramValues.append(attribute->value().string()); + AttributeCollection attributes = this->attributes(); + AttributeCollection::const_iterator end = attributes.end(); + for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { + paramNames.append(it->localName().string()); + paramValues.append(it->value().string()); } } @@ -143,21 +144,12 @@ void HTMLEmbedElement::updateWidgetInternal() Vector<String> paramValues; parametersForPlugin(paramNames, paramValues); - RefPtr<HTMLEmbedElement> protect(this); // Loading the plugin might remove us from the document. - bool beforeLoadAllowedLoad = dispatchBeforeLoadEvent(m_url); - if (!beforeLoadAllowedLoad) { - if (document().isPluginDocument()) { - // Plugins inside plugin documents load differently than other plugins. By the time - // we are here in a plugin document, the load of the plugin (which is the plugin document's - // main resource) has already started. We need to explicitly cancel the main resource load here. - toPluginDocument(document()).cancelManualPluginLoad(); - } - return; - } - if (!renderer()) // Do not load the plugin if beforeload removed this element or its renderer. + RefPtrWillBeRawPtr<HTMLEmbedElement> protect(this); // Loading the plugin might remove us from the document. + + // FIXME: Can we not have renderer here now that beforeload events are gone? + if (!renderer()) return; - // FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above. requestObject(m_url, m_serviceType, paramNames, paramValues); } @@ -166,14 +158,14 @@ bool HTMLEmbedElement::rendererIsNeeded(const RenderStyle& style) if (isImageType()) return HTMLPlugInElement::rendererIsNeeded(style); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) return false; // If my parent is an <object> and is not set to use fallback content, I // should be ignored and not get a renderer. ContainerNode* p = parentNode(); - if (p && p->hasTagName(objectTag)) { + if (isHTMLObjectElement(p)) { ASSERT(p->renderer()); if (!toHTMLObjectElement(p)->useFallbackContent()) { ASSERT(!p->renderer()->isEmbeddedObject()); @@ -188,16 +180,14 @@ bool HTMLEmbedElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == srcAttr || HTMLPlugInElement::isURLAttribute(attribute); } -const AtomicString HTMLEmbedElement::imageSourceURL() const +const QualifiedName& HTMLEmbedElement::subResourceAttributeName() const { - return getAttribute(srcAttr); + return srcAttr; } -void HTMLEmbedElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const +const AtomicString HTMLEmbedElement::imageSourceURL() const { - HTMLPlugInElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, document().completeURL(getAttribute(srcAttr))); + return getAttribute(srcAttr); } bool HTMLEmbedElement::isInteractiveContent() const @@ -208,8 +198,8 @@ bool HTMLEmbedElement::isInteractiveContent() const bool HTMLEmbedElement::isExposed() const { // http://www.whatwg.org/specs/web-apps/current-work/#exposed - for (Node* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) { - if (ancestor->hasTagName(objectTag) && toHTMLObjectElement(ancestor)->isExposed()) + for (HTMLObjectElement* object = Traversal<HTMLObjectElement>::firstAncestor(*this); object; object = Traversal<HTMLObjectElement>::firstAncestor(*object)) { + if (object->isExposed()) return false; } return true; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.h index 8107fd188f2..becba85d94c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLEmbedElement FINAL : public HTMLPlugInElement { public: - static PassRefPtr<HTMLEmbedElement> create(Document&, bool createdByParser = false); + static PassRefPtrWillBeRawPtr<HTMLEmbedElement> create(Document&, bool createdByParser = false); bool isExposed() const; @@ -40,25 +40,22 @@ private: virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; virtual const AtomicString imageSourceURL() const OVERRIDE; virtual RenderWidget* existingRenderWidget() const OVERRIDE; virtual void updateWidgetInternal() OVERRIDE; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; - void parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues); virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; } virtual bool isInteractiveContent() const OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLEmbedElement, hasTagName(HTMLNames::embedTag)); - } #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl index 74524f3ec05..399417d8c00 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLEmbedElement.idl @@ -24,7 +24,7 @@ [Reflect] attribute DOMString align; [Reflect] attribute DOMString height; [Reflect] attribute DOMString name; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly, LogPreviousValue] attribute DOMString src; [Reflect] attribute DOMString type; [Reflect] attribute DOMString width; [Custom, NotEnumerable] getter boolean (unsigned long index); @@ -32,5 +32,7 @@ [Custom, NotEnumerable] getter Node (DOMString name); [Custom] setter Node (DOMString name, Node value); - [CheckSecurity=Node, RaisesException] SVGDocument getSVGDocument(); + [CheckSecurity=Node, RaisesException] Document getSVGDocument(); + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.cpp index bf568d1417c..54f6d7bbb93 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.cpp @@ -25,9 +25,10 @@ #include "config.h" #include "core/html/HTMLFieldSetElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/ElementTraversal.h" #include "core/html/HTMLCollection.h" +#include "core/html/HTMLFormControlsCollection.h" #include "core/html/HTMLLegendElement.h" #include "core/html/HTMLObjectElement.h" #include "core/rendering/RenderFieldset.h" @@ -44,9 +45,17 @@ inline HTMLFieldSetElement::HTMLFieldSetElement(Document& document, HTMLFormElem ScriptWrappable::init(this); } -PassRefPtr<HTMLFieldSetElement> HTMLFieldSetElement::create(Document& document, HTMLFormElement* form) +PassRefPtrWillBeRawPtr<HTMLFieldSetElement> HTMLFieldSetElement::create(Document& document, HTMLFormElement* form) { - return adoptRef(new HTMLFieldSetElement(document, form)); + return adoptRefWillBeNoop(new HTMLFieldSetElement(document, form)); +} + +void HTMLFieldSetElement::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_associatedElements); +#endif + HTMLFormControlElement::trace(visitor); } void HTMLFieldSetElement::invalidateDisabledStateUnder(Element& base) @@ -67,10 +76,8 @@ void HTMLFieldSetElement::disabledAttributeChanged() void HTMLFieldSetElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - for (Element* element = ElementTraversal::firstWithin(*this); element; element = ElementTraversal::nextSkippingChildren(*element, this)) { - if (element->hasTagName(legendTag)) - invalidateDisabledStateUnder(*element); - } + for (HTMLLegendElement* legend = Traversal<HTMLLegendElement>::firstChild(*this); legend; legend = Traversal<HTMLLegendElement>::nextSibling(*legend)) + invalidateDisabledStateUnder(*legend); } bool HTMLFieldSetElement::supportsFocus() const @@ -91,16 +98,12 @@ RenderObject* HTMLFieldSetElement::createRenderer(RenderStyle*) HTMLLegendElement* HTMLFieldSetElement::legend() const { - for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSkippingChildren(*child, this)) { - if (child->hasTagName(legendTag)) - return toHTMLLegendElement(child); - } - return 0; + return Traversal<HTMLLegendElement>::firstChild(*this); } -PassRefPtr<HTMLCollection> HTMLFieldSetElement::elements() +PassRefPtrWillBeRawPtr<HTMLFormControlsCollection> HTMLFieldSetElement::elements() { - return ensureCachedHTMLCollection(FormControls); + return toHTMLFormControlsCollection(ensureCachedHTMLCollection(FormControls).get()); } void HTMLFieldSetElement::refreshElementsIfNeeded() const @@ -113,8 +116,8 @@ void HTMLFieldSetElement::refreshElementsIfNeeded() const m_associatedElements.clear(); - for (Element* element = ElementTraversal::firstWithin(*this); element; element = ElementTraversal::next(*element, this)) { - if (element->hasTagName(objectTag)) { + for (HTMLElement* element = Traversal<HTMLElement>::firstWithin(*this); element; element = Traversal<HTMLElement>::next(*element, this)) { + if (isHTMLObjectElement(*element)) { m_associatedElements.append(toHTMLObjectElement(element)); continue; } @@ -126,20 +129,10 @@ void HTMLFieldSetElement::refreshElementsIfNeeded() const } } -const Vector<FormAssociatedElement*>& HTMLFieldSetElement::associatedElements() const +const FormAssociatedElement::List& HTMLFieldSetElement::associatedElements() const { refreshElementsIfNeeded(); return m_associatedElements; } -unsigned HTMLFieldSetElement::length() const -{ - refreshElementsIfNeeded(); - unsigned len = 0; - for (unsigned i = 0; i < m_associatedElements.size(); ++i) - if (m_associatedElements[i]->isEnumeratable()) - ++len; - return len; -} - } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.h index e0835449cdf..bb6da9e2bc1 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFieldSetElement.h @@ -30,16 +30,17 @@ namespace WebCore { class FormAssociatedElement; class HTMLCollection; +class HTMLFormControlsCollection; class HTMLFieldSetElement FINAL : public HTMLFormControlElement { public: - static PassRefPtr<HTMLFieldSetElement> create(Document&, HTMLFormElement*); + static PassRefPtrWillBeRawPtr<HTMLFieldSetElement> create(Document&, HTMLFormElement*); + virtual void trace(Visitor*) OVERRIDE; HTMLLegendElement* legend() const; - PassRefPtr<HTMLCollection> elements(); + PassRefPtrWillBeRawPtr<HTMLFormControlsCollection> elements(); - const Vector<FormAssociatedElement*>& associatedElements() const; - unsigned length() const; + const FormAssociatedElement::List& associatedElements() const; protected: virtual void disabledAttributeChanged() OVERRIDE; @@ -47,24 +48,22 @@ protected: private: HTMLFieldSetElement(Document&, HTMLFormElement*); - virtual bool isEnumeratable() const { return true; } - virtual bool supportsFocus() const; - virtual RenderObject* createRenderer(RenderStyle*); - virtual const AtomicString& formControlType() const; - virtual bool recalcWillValidate() const { return false; } + virtual bool isEnumeratable() const OVERRIDE { return true; } + virtual bool supportsFocus() const OVERRIDE; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual const AtomicString& formControlType() const OVERRIDE; + virtual bool recalcWillValidate() const OVERRIDE { return false; } virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE; virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; } static void invalidateDisabledStateUnder(Element&); void refreshElementsIfNeeded() const; - mutable Vector<FormAssociatedElement*> m_associatedElements; + mutable FormAssociatedElement::List m_associatedElements; // When dom tree is modified, we have to refresh the m_associatedElements array. mutable uint64_t m_documentVersion; }; -DEFINE_NODE_TYPE_CASTS(HTMLFieldSetElement, hasTagName(HTMLNames::fieldsetTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.cpp index 853eae4a786..3f808f855d1 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.cpp @@ -23,9 +23,9 @@ #include "config.h" #include "core/html/HTMLFontElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/CSSValueList.h" #include "core/css/CSSValuePool.h" #include "core/css/StylePropertySet.h" @@ -38,16 +38,13 @@ namespace WebCore { using namespace HTMLNames; -HTMLFontElement::HTMLFontElement(Document& document) +inline HTMLFontElement::HTMLFontElement(Document& document) : HTMLElement(fontTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLFontElement> HTMLFontElement::create(Document& document) -{ - return adoptRef(new HTMLFontElement(document)); -} +DEFINE_NODE_FACTORY(HTMLFontElement) // http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#fonts-and-colors template <typename CharacterType> @@ -193,7 +190,7 @@ void HTMLFontElement::collectStyleForPresentationAttribute(const QualifiedName& } else if (name == colorAttr) addHTMLColorToStyle(style, CSSPropertyColor, value); else if (name == faceAttr) { - if (RefPtr<CSSValueList> fontFaceValue = cssValuePool().createFontFaceValue(value)) + if (RefPtrWillBeRawPtr<CSSValueList> fontFaceValue = cssValuePool().createFontFaceValue(value)) style->setProperty(CSSProperty(CSSPropertyFontFamily, fontFaceValue.release())); } else HTMLElement::collectStyleForPresentationAttribute(name, value, style); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.h index 229c5c94896..e0f542cfb76 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFontElement.h @@ -30,7 +30,7 @@ namespace WebCore { class HTMLFontElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLFontElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLFontElement); static bool cssValueFromFontSizeNumber(const String&, CSSValueID&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp index 4c68907eaf4..d3d3b22cbcb 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp @@ -25,14 +25,12 @@ #include "config.h" #include "core/html/HTMLFormControlElement.h" -#include "core/dom/PostAttachCallbacks.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/html/HTMLDataListElement.h" #include "core/html/HTMLFieldSetElement.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLInputElement.h" #include "core/html/HTMLLegendElement.h" -#include "core/html/HTMLTextAreaElement.h" #include "core/html/ValidityState.h" #include "core/html/forms/ValidationMessage.h" #include "core/frame/UseCounter.h" @@ -43,7 +41,6 @@ namespace WebCore { using namespace HTMLNames; -using namespace std; HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form) : LabelableElement(tagName, document) @@ -51,7 +48,6 @@ HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Doc , m_isAutofilled(false) , m_isReadOnly(false) , m_isRequired(false) - , m_valueMatchesRenderer(false) , m_ancestorDisabledState(AncestorDisabledStateUnknown) , m_dataListAncestorState(Unknown) , m_willValidateInitialized(false) @@ -59,15 +55,22 @@ HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Doc , m_isValid(true) , m_wasChangedSinceLastFormControlChangeEvent(false) , m_wasFocusedByMouse(false) - , m_hasAutofocused(false) { - setForm(form ? form : findFormAncestor()); setHasCustomStyleCallbacks(); + associateByParser(form); } HTMLFormControlElement::~HTMLFormControlElement() { +#if !ENABLE(OILPAN) setForm(0); +#endif +} + +void HTMLFormControlElement::trace(Visitor* visitor) +{ + FormAssociatedElement::trace(visitor); + LabelableElement::trace(visitor); } String HTMLFormControlElement::formEnctype() const @@ -105,10 +108,10 @@ void HTMLFormControlElement::updateAncestorDisabledState() const { HTMLFieldSetElement* fieldSetAncestor = 0; ContainerNode* legendAncestor = 0; - for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) { - if (!legendAncestor && ancestor->hasTagName(legendTag)) + for (HTMLElement* ancestor = Traversal<HTMLElement>::firstAncestor(*this); ancestor; ancestor = Traversal<HTMLElement>::firstAncestor(*ancestor)) { + if (!legendAncestor && isHTMLLegendElement(*ancestor)) legendAncestor = ancestor; - if (ancestor->hasTagName(fieldsetTag)) { + if (isHTMLFieldSetElement(*ancestor)) { fieldSetAncestor = toHTMLFieldSetElement(ancestor); break; } @@ -143,9 +146,9 @@ void HTMLFormControlElement::parseAttribute(const QualifiedName& name, const Ato m_isReadOnly = !value.isNull(); if (wasReadOnly != m_isReadOnly) { setNeedsWillValidateCheck(); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); if (renderer() && renderer()->style()->hasAppearance()) - RenderTheme::theme().stateChanged(renderer(), ReadOnlyState); + RenderTheme::theme().stateChanged(renderer(), ReadOnlyControlState); } } else if (name == requiredAttr) { bool wasRequired = m_isRequired; @@ -165,7 +168,7 @@ void HTMLFormControlElement::disabledAttributeChanged() setNeedsWillValidateCheck(); didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); if (renderer() && renderer()->style()->hasAppearance()) - RenderTheme::theme().stateChanged(renderer(), EnabledState); + RenderTheme::theme().stateChanged(renderer(), EnabledControlState); if (isDisabledFormControl() && treeScope().adjustedFocusedElement() == this) { // We might want to call blur(), but it's dangerous to dispatch events // here. @@ -178,33 +181,17 @@ void HTMLFormControlElement::requiredAttributeChanged() setNeedsValidityCheck(); // Style recalculation is needed because style selectors may include // :required and :optional pseudo-classes. - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } -static void focusPostAttach(Node* element) +bool HTMLFormControlElement::supportsAutofocus() const { - toElement(element)->focus(); - element->deref(); + return false; } bool HTMLFormControlElement::isAutofocusable() const { - if (!fastHasAttribute(autofocusAttr)) - return false; - - // FIXME: Should this set of hasTagName checks be replaced by a - // virtual member function? - if (hasTagName(inputTag)) - return !toHTMLInputElement(this)->isInputTypeHidden(); - if (hasTagName(selectTag)) - return true; - if (hasTagName(keygenTag)) - return true; - if (hasTagName(buttonTag)) - return true; - if (isHTMLTextAreaElement(this)) - return true; - return false; + return fastHasAttribute(autofocusAttr) && supportsAutofocus(); } void HTMLFormControlElement::setAutofilled(bool autofilled) @@ -213,15 +200,13 @@ void HTMLFormControlElement::setAutofilled(bool autofilled) return; m_isAutofilled = autofilled; - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } static bool shouldAutofocusOnAttach(const HTMLFormControlElement* element) { if (!element->isAutofocusable()) return false; - if (element->hasAutofocused()) - return false; if (element->document().isSandboxed(SandboxAutomaticFeatures)) { // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists. element->document().addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked autofocusing on a form control because the form's frame is sandboxed and the 'allow-scripts' permission is not set."); @@ -243,11 +228,10 @@ void HTMLFormControlElement::attach(const AttachContext& context) // on the renderer. renderer()->updateFromElement(); - if (shouldAutofocusOnAttach(this)) { - setAutofocused(); - ref(); - PostAttachCallbacks::queueCallback(focusPostAttach, this); - } + // FIXME: Autofocus handling should be moved to insertedInto according to + // the standard. + if (shouldAutofocusOnAttach(this)) + document().setAutofocusElement(this); } void HTMLFormControlElement::didMoveToNewDocument(Document& oldDocument) @@ -268,6 +252,7 @@ Node::InsertionNotificationRequest HTMLFormControlElement::insertedInto(Containe void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint) { + hideVisibleValidationMessage(); m_validationMessage = nullptr; m_ancestorDisabledState = AncestorDisabledStateUnknown; m_dataListAncestorState = Unknown; @@ -275,19 +260,19 @@ void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint) FormAssociatedElement::removedFrom(insertionPoint); } -bool HTMLFormControlElement::wasChangedSinceLastFormControlChangeEvent() const +void HTMLFormControlElement::setChangedSinceLastFormControlChangeEvent(bool changed) { - return m_wasChangedSinceLastFormControlChangeEvent; + m_wasChangedSinceLastFormControlChangeEvent = changed; } -void HTMLFormControlElement::setChangedSinceLastFormControlChangeEvent(bool changed) +void HTMLFormControlElement::dispatchChangeEvent() { - m_wasChangedSinceLastFormControlChangeEvent = changed; + dispatchScopedEvent(Event::createBubble(EventTypeNames::change)); } void HTMLFormControlElement::dispatchFormControlChangeEvent() { - HTMLElement::dispatchChangeEvent(); + dispatchChangeEvent(); setChangedSinceLastFormControlChangeEvent(false); } @@ -322,20 +307,10 @@ String HTMLFormControlElement::resultForDialogSubmit() return fastGetAttribute(valueAttr); } -static void updateFromElementCallback(Node* node) -{ - ASSERT_ARG(node, node->isElementNode()); - ASSERT_ARG(node, toElement(node)->isFormControlElement()); - if (RenderObject* renderer = node->renderer()) - renderer->updateFromElement(); -} - void HTMLFormControlElement::didRecalcStyle(StyleRecalcChange) { - // updateFromElement() can cause the selection to change, and in turn - // trigger synchronous layout, so it must not be called during style recalc. - if (renderer()) - PostAttachCallbacks::queueCallback(updateFromElementCallback, this); + if (RenderObject* renderer = this->renderer()) + renderer->updateFromElement(); } bool HTMLFormControlElement::supportsFocus() const @@ -354,11 +329,11 @@ bool HTMLFormControlElement::shouldShowFocusRingOnMouseFocus() const return false; } -void HTMLFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction) +void HTMLFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType type) { - if (direction != FocusDirectionPage) - m_wasFocusedByMouse = direction == FocusDirectionMouse; - HTMLElement::dispatchFocusEvent(oldFocusedElement, direction); + if (type != FocusTypePage) + m_wasFocusedByMouse = type == FocusTypeMouse; + HTMLElement::dispatchFocusEvent(oldFocusedElement, type); } bool HTMLFormControlElement::shouldHaveFocusAppearance() const @@ -375,7 +350,7 @@ void HTMLFormControlElement::willCallDefaultEventHandler(const Event& event) return; m_wasFocusedByMouse = false; if (renderer()) - renderer()->repaint(); + renderer()->paintInvalidationForWholeRenderer(); } @@ -388,13 +363,9 @@ short HTMLFormControlElement::tabIndex() const bool HTMLFormControlElement::recalcWillValidate() const { if (m_dataListAncestorState == Unknown) { - for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) { - if (ancestor->hasTagName(datalistTag)) { - m_dataListAncestorState = InsideDataList; - break; - } - } - if (m_dataListAncestorState == Unknown) + if (Traversal<HTMLDataListElement>::firstAncestor(*this)) + m_dataListAncestorState = InsideDataList; + else m_dataListAncestorState = NotInsideDataList; } return m_dataListAncestorState == NotInsideDataList && !isDisabledOrReadOnly(); @@ -427,7 +398,7 @@ void HTMLFormControlElement::setNeedsWillValidateCheck() m_willValidateInitialized = true; m_willValidate = newWillValidate; setNeedsValidityCheck(); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); if (!m_willValidate) hideVisibleValidationMessage(); } @@ -451,15 +422,13 @@ void HTMLFormControlElement::hideVisibleValidationMessage() m_validationMessage->requestToHideMessage(); } -bool HTMLFormControlElement::checkValidity(Vector<RefPtr<FormAssociatedElement> >* unhandledInvalidControls, CheckValidityDispatchEvents dispatchEvents) +bool HTMLFormControlElement::checkValidity(WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> >* unhandledInvalidControls) { if (!willValidate() || isValidFormControlElement()) return true; - if (dispatchEvents == CheckValidityDispatchEventsNone) - return false; // An event handler can deref this object. - RefPtr<HTMLFormControlElement> protector(this); - RefPtr<Document> originalDocument(document()); + RefPtrWillBeRawPtr<HTMLFormControlElement> protector(this); + RefPtrWillBeRawPtr<Document> originalDocument(document()); bool needsDefaultAction = dispatchEvent(Event::createCancelable(EventTypeNames::invalid)); if (needsDefaultAction && unhandledInvalidControls && inDocument() && originalDocument == document()) unhandledInvalidControls->append(this); @@ -479,11 +448,11 @@ void HTMLFormControlElement::setNeedsValidityCheck() bool newIsValid = valid(); if (willValidate() && newIsValid != m_isValid) { // Update style for pseudo classes such as :valid :invalid. - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } m_isValid = newIsValid; - // Updates only if this control already has a validtion message. + // Updates only if this control already has a validation message. if (m_validationMessage && m_validationMessage->isVisible()) { // Calls updateVisibleValidationMessage() even if m_isValid is not // changed because a validation message can be chagned. @@ -515,11 +484,9 @@ bool HTMLFormControlElement::isDefaultButtonForForm() const HTMLFormControlElement* HTMLFormControlElement::enclosingFormControlElement(Node* node) { - for (; node; node = node->parentNode()) { - if (node->isElementNode() && toElement(node)->isFormControlElement()) - return toHTMLFormControlElement(node); - } - return 0; + if (!node) + return 0; + return Traversal<HTMLFormControlElement>::firstAncestorOrSelf(*node); } String HTMLFormControlElement::nameForAutofill() const @@ -533,4 +500,12 @@ String HTMLFormControlElement::nameForAutofill() const return trimmedName; } +void HTMLFormControlElement::setFocus(bool flag) +{ + LabelableElement::setFocus(flag); + + if (!flag && wasChangedSinceLastFormControlChangeEvent()) + dispatchFormControlChangeEvent(); +} + } // namespace Webcore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.h index bb5cdd8c8a2..eae67074b0b 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElement.h @@ -40,8 +40,11 @@ class ValidityState; // and form-associated element implementations should use HTMLFormControlElement // unless there is a special reason. class HTMLFormControlElement : public LabelableElement, public FormAssociatedElement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLFormControlElement); + public: virtual ~HTMLFormControlElement(); + virtual void trace(Visitor*) OVERRIDE; String formEnctype() const; void setFormEnctype(const AtomicString&); @@ -53,32 +56,30 @@ public: void reset(); - virtual bool formControlValueMatchesRenderer() const { return m_valueMatchesRenderer; } - virtual void setFormControlValueMatchesRenderer(bool b) { m_valueMatchesRenderer = b; } - - virtual bool wasChangedSinceLastFormControlChangeEvent() const; - virtual void setChangedSinceLastFormControlChangeEvent(bool); + bool wasChangedSinceLastFormControlChangeEvent() const { return m_wasChangedSinceLastFormControlChangeEvent; } + void setChangedSinceLastFormControlChangeEvent(bool); virtual void dispatchFormControlChangeEvent(); - virtual void dispatchFormControlInputEvent(); + void dispatchChangeEvent(); + void dispatchFormControlInputEvent(); - virtual HTMLFormElement* formOwner() const OVERRIDE; + virtual HTMLFormElement* formOwner() const OVERRIDE FINAL; virtual bool isDisabledFormControl() const OVERRIDE; - virtual bool isEnumeratable() const { return false; } + virtual bool isEnumeratable() const OVERRIDE { return false; } bool isRequired() const; const AtomicString& type() const { return formControlType(); } - virtual const AtomicString& formControlType() const OVERRIDE = 0; + virtual const AtomicString& formControlType() const = 0; virtual bool canTriggerImplicitSubmission() const { return false; } // Override in derived classes to get the encoded name=value pair for submitting. // Return true for a successful control (see HTML4-17.13.2). - virtual bool appendFormData(FormDataList&, bool) { return false; } + virtual bool appendFormData(FormDataList&, bool) OVERRIDE { return false; } virtual String resultForDialogSubmit(); virtual bool canBeSuccessfulSubmitButton() const { return false; } @@ -86,21 +87,17 @@ public: virtual bool isActivatedSubmit() const { return false; } virtual void setActivatedSubmit(bool) { } - enum CheckValidityDispatchEvents { CheckValidityDispatchEventsAllowed, CheckValidityDispatchEventsNone }; - - virtual bool willValidate() const; + virtual bool willValidate() const OVERRIDE; void updateVisibleValidationMessage(); void hideVisibleValidationMessage(); - bool checkValidity(Vector<RefPtr<FormAssociatedElement> >* unhandledInvalidControls = 0, CheckValidityDispatchEvents = CheckValidityDispatchEventsAllowed); + bool checkValidity(WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> >* unhandledInvalidControls = 0); // This must be called when a validation constraint or control value is changed. void setNeedsValidityCheck(); - virtual void setCustomValidity(const String&) OVERRIDE; + virtual void setCustomValidity(const String&) OVERRIDE FINAL; bool isReadOnly() const { return m_isReadOnly; } bool isDisabledOrReadOnly() const { return isDisabledFormControl() || m_isReadOnly; } - bool hasAutofocused() const { return m_hasAutofocused; } - void setAutofocused() { m_hasAutofocused = true; } bool isAutofocusable() const; bool isAutofilled() const { return m_isAutofilled; } @@ -110,8 +107,12 @@ public: String nameForAutofill() const; + virtual void setFocus(bool flag) OVERRIDE; + +#if !ENABLE(OILPAN) using Node::ref; using Node::deref; +#endif protected: HTMLFormControlElement(const QualifiedName& tagName, Document&, HTMLFormElement*); @@ -127,30 +128,33 @@ protected: virtual bool supportsFocus() const OVERRIDE; virtual bool isKeyboardFocusable() const OVERRIDE; virtual bool shouldShowFocusRingOnMouseFocus() const; - virtual bool shouldHaveFocusAppearance() const OVERRIDE; - virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE; + virtual bool shouldHaveFocusAppearance() const OVERRIDE FINAL; + virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusType) OVERRIDE; virtual void dispatchBlurEvent(Element* newFocusedElement) OVERRIDE; - virtual void willCallDefaultEventHandler(const Event&) OVERRIDE; + virtual void willCallDefaultEventHandler(const Event&) OVERRIDE FINAL; - virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE; + virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE FINAL; // This must be called any time the result of willValidate() has changed. void setNeedsWillValidateCheck(); virtual bool recalcWillValidate() const; virtual void resetImpl() { } + virtual bool supportsAutofocus() const; private: - virtual void refFormAssociatedElement() { ref(); } - virtual void derefFormAssociatedElement() { deref(); } +#if !ENABLE(OILPAN) + virtual void refFormAssociatedElement() OVERRIDE FINAL { ref(); } + virtual void derefFormAssociatedElement() OVERRIDE FINAL { deref(); } +#endif - virtual bool isFormControlElement() const { return true; } + virtual bool isFormControlElement() const OVERRIDE FINAL { return true; } virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE { return true; } - virtual short tabIndex() const; + virtual short tabIndex() const OVERRIDE FINAL; - virtual bool isDefaultButtonForForm() const; - virtual bool isValidFormControlElement(); + virtual bool isDefaultButtonForForm() const OVERRIDE FINAL; + virtual bool isValidFormControlElement() OVERRIDE FINAL; void updateAncestorDisabledState() const; OwnPtr<ValidationMessage> m_validationMessage; @@ -158,7 +162,6 @@ private: bool m_isAutofilled : 1; bool m_isReadOnly : 1; bool m_isRequired : 1; - bool m_valueMatchesRenderer : 1; enum AncestorDisabledState { AncestorDisabledStateUnknown, AncestorDisabledStateEnabled, AncestorDisabledStateDisabled }; mutable AncestorDisabledState m_ancestorDisabledState; @@ -177,15 +180,14 @@ private: bool m_wasChangedSinceLastFormControlChangeEvent : 1; bool m_wasFocusedByMouse : 1; - bool m_hasAutofocused : 1; }; -inline bool isHTMLFormControlElement(const Node& node) +inline bool isHTMLFormControlElement(const Element& element) { - return node.isElementNode() && toElement(node).isFormControlElement(); + return element.isFormControlElement(); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLFormControlElement); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLFormControlElement); DEFINE_TYPE_CASTS(HTMLFormControlElement, FormAssociatedElement, control, control->isFormControlElement(), control.isFormControlElement()); } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp index 1508d798f18..23375e1dd90 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp @@ -25,12 +25,13 @@ #include "config.h" #include "core/html/HTMLFormControlElementWithState.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLFormElement.h" #include "core/html/forms/FormController.h" +#include "core/loader/FrameLoaderClient.h" #include "core/page/Chrome.h" #include "core/page/ChromeClient.h" -#include "core/frame/Frame.h" -#include "core/page/Page.h" namespace WebCore { @@ -46,14 +47,14 @@ HTMLFormControlElementWithState::~HTMLFormControlElementWithState() Node::InsertionNotificationRequest HTMLFormControlElementWithState::insertedInto(ContainerNode* insertionPoint) { if (insertionPoint->inDocument() && !containingShadowRoot()) - document().formController()->registerFormElementWithState(this); + document().formController().registerStatefulFormControl(*this); return HTMLFormControlElement::insertedInto(insertionPoint); } void HTMLFormControlElementWithState::removedFrom(ContainerNode* insertionPoint) { if (insertionPoint->inDocument() && !containingShadowRoot() && !insertionPoint->containingShadowRoot()) - document().formController()->unregisterFormElementWithState(this); + document().formController().unregisterStatefulFormControl(*this); HTMLFormControlElement::removedFrom(insertionPoint); } @@ -66,18 +67,17 @@ bool HTMLFormControlElementWithState::shouldAutocomplete() const void HTMLFormControlElementWithState::notifyFormStateChanged() { - Frame* frame = document().frame(); - if (!frame) + // This can be called during fragment parsing as a result of option + // selection before the document is active (or even in a frame). + if (!document().isActive()) return; - - if (Page* page = frame->page()) - page->chrome().client().formStateDidChange(this); + document().frame()->loader().client()->didUpdateCurrentHistoryItem(); } bool HTMLFormControlElementWithState::shouldSaveAndRestoreFormControlState() const { // We don't save/restore control state in a form with autocomplete=off. - return inActiveDocument() && shouldAutocomplete(); + return inDocument() && shouldAutocomplete(); } FormControlState HTMLFormControlElementWithState::saveFormControlState() const @@ -88,7 +88,7 @@ FormControlState HTMLFormControlElementWithState::saveFormControlState() const void HTMLFormControlElementWithState::finishParsingChildren() { HTMLFormControlElement::finishParsingChildren(); - document().formController()->restoreControlStateFor(*this); + document().formController().restoreControlStateFor(*this); } bool HTMLFormControlElementWithState::isFormControlElementWithState() const diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h index 0328920e53a..d81fd207d69 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h @@ -34,8 +34,9 @@ class HTMLFormControlElementWithState : public HTMLFormControlElement { public: virtual ~HTMLFormControlElementWithState(); - virtual bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE FINAL { return false; } + virtual bool shouldAutocomplete() const; virtual bool shouldSaveAndRestoreFormControlState() const; virtual FormControlState saveFormControlState() const; // The specified FormControlState must have at least one string value. @@ -45,11 +46,10 @@ public: protected: HTMLFormControlElementWithState(const QualifiedName& tagName, Document&, HTMLFormElement*); - virtual bool shouldAutocomplete() const; - virtual void finishParsingChildren(); + virtual void finishParsingChildren() OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual bool isFormControlElementWithState() const OVERRIDE; + virtual bool isFormControlElementWithState() const OVERRIDE FINAL; }; DEFINE_TYPE_CASTS(HTMLFormControlElementWithState, FormAssociatedElement, control, control->isFormControlElementWithState(), control.isFormControlElementWithState()); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp index 972bb757c54..a7c4a9fecb9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.cpp @@ -2,6 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2014 Samsung Electronics. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,10 +24,12 @@ #include "config.h" #include "core/html/HTMLFormControlsCollection.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLFieldSetElement.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLImageElement.h" +#include "wtf/HashSet.h" namespace WebCore { @@ -35,53 +38,80 @@ using namespace HTMLNames; // Since the collections are to be "live", we have to do the // calculation every time if anything has changed. -HTMLFormControlsCollection::HTMLFormControlsCollection(Node* ownerNode) +HTMLFormControlsCollection::HTMLFormControlsCollection(ContainerNode& ownerNode) : HTMLCollection(ownerNode, FormControls, OverridesItemAfter) + , m_cachedElement(nullptr) + , m_cachedElementOffsetInArray(0) { - ASSERT(ownerNode->hasTagName(formTag) || ownerNode->hasTagName(fieldsetTag)); + ASSERT(isHTMLFormElement(ownerNode) || isHTMLFieldSetElement(ownerNode)); ScriptWrappable::init(this); } -PassRefPtr<HTMLFormControlsCollection> HTMLFormControlsCollection::create(Node* ownerNode, CollectionType) +PassRefPtrWillBeRawPtr<HTMLFormControlsCollection> HTMLFormControlsCollection::create(ContainerNode& ownerNode, CollectionType type) { - return adoptRef(new HTMLFormControlsCollection(ownerNode)); + ASSERT_UNUSED(type, type == FormControls); + return adoptRefWillBeNoop(new HTMLFormControlsCollection(ownerNode)); } HTMLFormControlsCollection::~HTMLFormControlsCollection() { } -const Vector<FormAssociatedElement*>& HTMLFormControlsCollection::formControlElements() const +const FormAssociatedElement::List& HTMLFormControlsCollection::formControlElements() const { - ASSERT(ownerNode()); - ASSERT(ownerNode()->hasTagName(formTag) || ownerNode()->hasTagName(fieldsetTag)); - if (ownerNode()->hasTagName(formTag)) - return toHTMLFormElement(ownerNode())->associatedElements(); - return toHTMLFieldSetElement(ownerNode())->associatedElements(); + ASSERT(isHTMLFormElement(ownerNode()) || isHTMLFieldSetElement(ownerNode())); + if (isHTMLFormElement(ownerNode())) + return toHTMLFormElement(ownerNode()).associatedElements(); + return toHTMLFieldSetElement(ownerNode()).associatedElements(); } -const Vector<HTMLImageElement*>& HTMLFormControlsCollection::formImageElements() const +const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >& HTMLFormControlsCollection::formImageElements() const { - ASSERT(ownerNode()); - return toHTMLFormElement(ownerNode())->imageElements(); + return toHTMLFormElement(ownerNode()).imageElements(); } -Element* HTMLFormControlsCollection::virtualItemAfter(unsigned& offset, Element* previousItem) const +static unsigned findFormAssociatedElement(const FormAssociatedElement::List& associatedElements, Element* element) { - const Vector<FormAssociatedElement*>& elementsArray = formControlElements(); - if (previousItem) - offset++; - while (offset < elementsArray.size()) { - FormAssociatedElement* element = elementsArray[offset]; - if (element->isEnumeratable()) - return toHTMLElement(element); - offset++; + unsigned i = 0; + for (; i < associatedElements.size(); ++i) { + FormAssociatedElement* associatedElement = associatedElements[i]; + if (associatedElement->isEnumeratable() && toHTMLElement(associatedElement) == element) + break; + } + return i; +} + +Element* HTMLFormControlsCollection::virtualItemAfter(Element* previous) const +{ + const FormAssociatedElement::List& associatedElements = formControlElements(); + unsigned offset; + if (!previous) + offset = 0; + else if (m_cachedElement == previous) + offset = m_cachedElementOffsetInArray + 1; + else + offset = findFormAssociatedElement(associatedElements, previous) + 1; + + for (unsigned i = offset; i < associatedElements.size(); ++i) { + FormAssociatedElement* associatedElement = associatedElements[i]; + if (associatedElement->isEnumeratable()) { + m_cachedElement = toHTMLElement(associatedElement); + m_cachedElementOffsetInArray = i; + return m_cachedElement; + } } return 0; } -static HTMLElement* firstNamedItem(const Vector<FormAssociatedElement*>& elementsArray, - const Vector<HTMLImageElement*>* imageElementsArray, const QualifiedName& attrName, const String& name) +void HTMLFormControlsCollection::invalidateCache(Document* oldDocument) const +{ + HTMLCollection::invalidateCache(oldDocument); + m_cachedElement = nullptr; + m_cachedElementOffsetInArray = 0; +} + +static HTMLElement* firstNamedItem(const FormAssociatedElement::List& elementsArray, + const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >* imageElementsArray, const QualifiedName& attrName, const String& name) { ASSERT(attrName == idAttr || attrName == nameAttr); @@ -96,35 +126,38 @@ static HTMLElement* firstNamedItem(const Vector<FormAssociatedElement*>& element for (unsigned i = 0; i < imageElementsArray->size(); ++i) { HTMLImageElement* element = (*imageElementsArray)[i]; - if (element->fastGetAttribute(attrName) == name) + if (element->fastGetAttribute(attrName) == name) { + UseCounter::count(element->document(), UseCounter::FormNameAccessForImageElement); return element; + } } return 0; } -Node* HTMLFormControlsCollection::namedItem(const AtomicString& name) const +Element* HTMLFormControlsCollection::namedItem(const AtomicString& name) const { // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp // This method first searches for an object with a matching id // attribute. If a match is not found, the method then searches for an // object with a matching name attribute, but only on those elements // that are allowed a name attribute. - const Vector<HTMLImageElement*>* imagesElements = ownerNode()->hasTagName(fieldsetTag) ? 0 : &formImageElements(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >* imagesElements = isHTMLFieldSetElement(ownerNode()) ? 0 : &formImageElements(); if (HTMLElement* item = firstNamedItem(formControlElements(), imagesElements, idAttr, name)) return item; return firstNamedItem(formControlElements(), imagesElements, nameAttr, name); } -void HTMLFormControlsCollection::updateNameCache() const +void HTMLFormControlsCollection::updateIdNameCache() const { - if (hasNameCache()) + if (hasValidIdNameCache()) return; + OwnPtrWillBeRawPtr<NamedItemCache> cache = NamedItemCache::create(); HashSet<StringImpl*> foundInputElements; - const Vector<FormAssociatedElement*>& elementsArray = formControlElements(); + const FormAssociatedElement::List& elementsArray = formControlElements(); for (unsigned i = 0; i < elementsArray.size(); ++i) { FormAssociatedElement* associatedElement = elementsArray[i]; @@ -133,48 +166,82 @@ void HTMLFormControlsCollection::updateNameCache() const const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty()) { - appendIdCache(idAttrVal, element); + cache->addElementWithId(idAttrVal, element); foundInputElements.add(idAttrVal.impl()); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { - appendNameCache(nameAttrVal, element); + cache->addElementWithName(nameAttrVal, element); foundInputElements.add(nameAttrVal.impl()); } } } - if (ownerNode()->hasTagName(formTag)) { - const Vector<HTMLImageElement*>& imageElementsArray = formImageElements(); + if (isHTMLFormElement(ownerNode())) { + const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >& imageElementsArray = formImageElements(); for (unsigned i = 0; i < imageElementsArray.size(); ++i) { HTMLImageElement* element = imageElementsArray[i]; const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) - appendIdCache(idAttrVal, element); + cache->addElementWithId(idAttrVal, element); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) - appendNameCache(nameAttrVal, element); + cache->addElementWithName(nameAttrVal, element); } } - setHasNameCache(); + // Set the named item cache last as traversing the tree may cause cache invalidation. + setNamedItemCache(cache.release()); } -void HTMLFormControlsCollection::namedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtr<RadioNodeList>& returnValue0, bool& returnValue1Enabled, RefPtr<Node>& returnValue1) +void HTMLFormControlsCollection::namedGetter(const AtomicString& name, bool& radioNodeListEnabled, RefPtrWillBeRawPtr<RadioNodeList>& radioNodeList, bool& elementEnabled, RefPtrWillBeRawPtr<Element>& element) { - Vector<RefPtr<Node> > namedItems; + WillBeHeapVector<RefPtrWillBeMember<Element> > namedItems; this->namedItems(name, namedItems); - if (!namedItems.size()) + if (namedItems.isEmpty()) return; if (namedItems.size() == 1) { - returnValue1Enabled = true; - returnValue1 = namedItems.at(0); + elementEnabled = true; + element = namedItems.at(0); return; } - returnValue0Enabled = true; - returnValue0 = this->ownerNode()->radioNodeList(name); + radioNodeListEnabled = true; + radioNodeList = ownerNode().radioNodeList(name); +} + +void HTMLFormControlsCollection::supportedPropertyNames(Vector<String>& names) +{ + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlformcontrolscollection-0: + // The supported property names consist of the non-empty values of all the id and name attributes + // of all the elements represented by the collection, in tree order, ignoring later duplicates, + // with the id of an element preceding its name if it contributes both, they differ from each + // other, and neither is the duplicate of an earlier entry. + HashSet<AtomicString> existingNames; + unsigned length = this->length(); + for (unsigned i = 0; i < length; ++i) { + Element* element = item(i); + ASSERT(element); + const AtomicString& idAttribute = element->getIdAttribute(); + if (!idAttribute.isEmpty()) { + HashSet<AtomicString>::AddResult addResult = existingNames.add(idAttribute); + if (addResult.isNewEntry) + names.append(idAttribute); + } + const AtomicString& nameAttribute = element->getNameAttribute(); + if (!nameAttribute.isEmpty()) { + HashSet<AtomicString>::AddResult addResult = existingNames.add(nameAttribute); + if (addResult.isNewEntry) + names.append(nameAttribute); + } + } +} + +void HTMLFormControlsCollection::trace(Visitor* visitor) +{ + visitor->trace(m_cachedElement); + HTMLCollection::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.h b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.h index 45b286ccb78..df90351776a 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.h @@ -2,6 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2014 Samsung Electronics. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,12 +24,12 @@ #ifndef HTMLFormControlsCollection_h #define HTMLFormControlsCollection_h +#include "core/html/FormAssociatedElement.h" #include "core/html/HTMLCollection.h" #include "core/html/RadioNodeList.h" namespace WebCore { -class FormAssociatedElement; class HTMLElement; class HTMLImageElement; class QualifiedName; @@ -38,22 +39,30 @@ class QualifiedName; class HTMLFormControlsCollection FINAL : public HTMLCollection { public: - static PassRefPtr<HTMLFormControlsCollection> create(Node*, CollectionType); + static PassRefPtrWillBeRawPtr<HTMLFormControlsCollection> create(ContainerNode&, CollectionType); virtual ~HTMLFormControlsCollection(); - virtual Node* namedItem(const AtomicString& name) const; - void namedGetter(const AtomicString& name, bool&, RefPtr<RadioNodeList>&, bool&, RefPtr<Node>&); + virtual Element* namedItem(const AtomicString& name) const OVERRIDE; + void namedGetter(const AtomicString& name, bool& radioNodeListEnabled, RefPtrWillBeRawPtr<RadioNodeList>&, bool& elementEnabled, RefPtrWillBeRawPtr<Element>&); + + virtual void trace(Visitor*) OVERRIDE; private: - explicit HTMLFormControlsCollection(Node*); + explicit HTMLFormControlsCollection(ContainerNode&); + + virtual void updateIdNameCache() const OVERRIDE; + virtual void supportedPropertyNames(Vector<String>& names) OVERRIDE; - virtual void updateNameCache() const OVERRIDE; + const FormAssociatedElement::List& formControlElements() const; + const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >& formImageElements() const; + virtual Element* virtualItemAfter(Element*) const OVERRIDE; + virtual void invalidateCache(Document* oldDocument = 0) const OVERRIDE; - const Vector<FormAssociatedElement*>& formControlElements() const; - const Vector<HTMLImageElement*>& formImageElements() const; - virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE; + mutable RawPtrWillBeMember<Element> m_cachedElement; + mutable unsigned m_cachedElementOffsetInArray; }; +DEFINE_TYPE_CASTS(HTMLFormControlsCollection, LiveNodeListBase, collection, collection->type() == FormControls, collection.type() == FormControls); } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.idl b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.idl index f483a675a31..5ed779f2dfa 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormControlsCollection.idl @@ -1,6 +1,7 @@ /* * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2014 Samsung Electronics. 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 @@ -20,9 +21,8 @@ [ DependentLifetime, - GenerateVisitDOMWrapper=ownerNode, + SetWrapperReferenceFrom=ownerNode, ] interface HTMLFormControlsCollection : HTMLCollection { - [ImplementedAs=item] getter Node(unsigned long index); - [Custom] Node namedItem([Default=Undefined] optional DOMString name); - [ImplementedAs=namedGetter, NotEnumerable] getter (RadioNodeList or Node)(DOMString name); + [ImplementedAs=item] getter Node (unsigned long index); + [ImplementedAs=namedGetter] getter (RadioNodeList or Element) namedItem(DOMString name); // shadows inherited namedItem() }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.cpp index 0e5cc98d302..18ef044388a 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.cpp @@ -26,34 +26,35 @@ #include "core/html/HTMLFormElement.h" #include <limits> -#include "HTMLNames.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" #include "core/dom/ElementTraversal.h" -#include "core/dom/NamedNodesCollection.h" +#include "core/dom/IdTargetObserverRegistry.h" #include "core/events/AutocompleteErrorEvent.h" #include "core/events/Event.h" +#include "core/events/GenericEventQueue.h" #include "core/events/ScopedEventQueue.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLDialogElement.h" +#include "core/html/HTMLFormControlsCollection.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLInputElement.h" #include "core/html/HTMLObjectElement.h" -#include "core/html/HTMLTableElement.h" +#include "core/html/RadioNodeList.h" #include "core/html/forms/FormController.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "core/frame/UseCounter.h" +#include "core/loader/MixedContentChecker.h" #include "core/rendering/RenderTextControl.h" #include "platform/UserGestureIndicator.h" - -using namespace std; +#include "wtf/text/AtomicString.h" namespace WebCore { @@ -61,37 +62,47 @@ using namespace HTMLNames; HTMLFormElement::HTMLFormElement(Document& document) : HTMLElement(formTag, document) - , m_associatedElementsBeforeIndex(0) - , m_associatedElementsAfterIndex(0) +#if !ENABLE(OILPAN) + , m_weakPtrFactory(this) +#endif + , m_associatedElementsAreDirty(false) + , m_imageElementsAreDirty(false) + , m_hasElementsAssociatedByParser(false) + , m_didFinishParsingChildren(false) , m_wasUserSubmitted(false) - , m_isSubmittingOrPreparingForSubmission(false) - , m_shouldSubmit(false) , m_isInResetFunction(false) , m_wasDemoted(false) - , m_requestAutocompleteTimer(this, &HTMLFormElement::requestAutocompleteTimerFired) + , m_pendingAutocompleteEventsQueue(GenericEventQueue::create(this)) { ScriptWrappable::init(this); } -PassRefPtr<HTMLFormElement> HTMLFormElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLFormElement> HTMLFormElement::create(Document& document) { UseCounter::count(document, UseCounter::FormElement); - return adoptRef(new HTMLFormElement(document)); + return adoptRefWillBeNoop(new HTMLFormElement(document)); } HTMLFormElement::~HTMLFormElement() { - document().formController()->willDeleteForm(this); - - for (unsigned i = 0; i < m_associatedElements.size(); ++i) - m_associatedElements[i]->formWillBeDestroyed(); - for (unsigned i = 0; i < m_imageElements.size(); ++i) - m_imageElements[i]->m_form = 0; +#if !ENABLE(OILPAN) + // With Oilpan, either removedFrom is called or the document and + // form controller are dead as well and there is no need to remove + // this form element from it. + document().formController().willDeleteForm(this); +#endif } -bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url) +void HTMLFormElement::trace(Visitor* visitor) { - return document().completeURL(url).protocolIs("https"); +#if ENABLE(OILPAN) + visitor->trace(m_pastNamesMap); + visitor->trace(m_radioButtonGroupScope); + visitor->trace(m_associatedElements); + visitor->trace(m_imageElements); + visitor->trace(m_pendingAutocompleteEventsQueue); +#endif + HTMLElement::trace(visitor); } bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style) @@ -100,14 +111,16 @@ bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style) return HTMLElement::rendererIsNeeded(style); ContainerNode* node = parentNode(); + if (!node || !node->renderer()) + return HTMLElement::rendererIsNeeded(style); RenderObject* parentRenderer = node->renderer(); // FIXME: Shouldn't we also check for table caption (see |formIsTablePart| below). // FIXME: This check is not correct for Shadow DOM. - bool parentIsTableElementPart = (parentRenderer->isTable() && isHTMLTableElement(node)) - || (parentRenderer->isTableRow() && node->hasTagName(trTag)) + bool parentIsTableElementPart = (parentRenderer->isTable() && isHTMLTableElement(*node)) + || (parentRenderer->isTableRow() && isHTMLTableRowElement(*node)) || (parentRenderer->isTableSection() && node->hasTagName(tbodyTag)) || (parentRenderer->isRenderTableCol() && node->hasTagName(colTag)) - || (parentRenderer->isTableCell() && node->hasTagName(trTag)); + || (parentRenderer->isTableCell() && isHTMLTableRowElement(*node)); if (!parentIsTableElementPart) return true; @@ -129,20 +142,46 @@ Node::InsertionNotificationRequest HTMLFormElement::insertedInto(ContainerNode* return InsertionDone; } -static inline Node* findRoot(Node* n) +template<class T> +void notifyFormRemovedFromTree(const T& elements, Node& root) { - Node* root = n; - for (; n; n = n->parentNode()) - root = n; - return root; + size_t size = elements.size(); + for (size_t i = 0; i < size; ++i) + elements[i]->formRemovedFromTree(root); + ASSERT(elements.size() == size); } void HTMLFormElement::removedFrom(ContainerNode* insertionPoint) { - Node* root = findRoot(this); - Vector<FormAssociatedElement*> associatedElements(m_associatedElements); - for (unsigned i = 0; i < associatedElements.size(); ++i) - associatedElements[i]->formRemovedFromTree(root); + // We don't need to take care of form association by 'form' content + // attribute becuse IdTargetObserver handles it. + if (m_hasElementsAssociatedByParser) { + Node& root = highestAncestorOrSelf(); + if (!m_associatedElementsAreDirty) { + FormAssociatedElement::List elements(associatedElements()); + notifyFormRemovedFromTree(elements, root); + } else { + FormAssociatedElement::List elements; + collectAssociatedElements(insertionPoint->highestAncestorOrSelf(), elements); + notifyFormRemovedFromTree(elements, root); + collectAssociatedElements(root, elements); + notifyFormRemovedFromTree(elements, root); + } + + if (!m_imageElementsAreDirty) { + WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> > images(imageElements()); + notifyFormRemovedFromTree(images, root); + } else { + WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> > images; + collectImageElements(insertionPoint->highestAncestorOrSelf(), images); + notifyFormRemovedFromTree(images, root); + collectImageElements(root, images); + notifyFormRemovedFromTree(images, root); + } + } +#if ENABLE(OILPAN) + document().formController().willDeleteForm(this); +#endif HTMLElement::removedFrom(insertionPoint); } @@ -158,14 +197,16 @@ void HTMLFormElement::handleLocalEvents(Event* event) unsigned HTMLFormElement::length() const { + const FormAssociatedElement::List& elements = associatedElements(); unsigned len = 0; - for (unsigned i = 0; i < m_associatedElements.size(); ++i) - if (m_associatedElements[i]->isEnumeratable()) + for (unsigned i = 0; i < elements.size(); ++i) { + if (elements[i]->isEnumeratable()) ++len; + } return len; } -Node* HTMLFormElement::item(unsigned index) +Element* HTMLFormElement::item(unsigned index) { return elements()->item(index); } @@ -174,8 +215,9 @@ void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmission { int submissionTriggerCount = 0; bool seenDefaultButton = false; - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - FormAssociatedElement* formAssociatedElement = m_associatedElements[i]; + const FormAssociatedElement::List& elements = associatedElements(); + for (unsigned i = 0; i < elements.size(); ++i) { + FormAssociatedElement* formAssociatedElement = elements[i]; if (!formAssociatedElement->isFormControlElement()) continue; HTMLFormControlElement* control = toHTMLFormControlElement(formAssociatedElement); @@ -183,10 +225,8 @@ void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmission if (fromImplicitSubmissionTrigger) seenDefaultButton = true; if (control->isSuccessfulSubmitButton()) { - if (control->renderer()) { - control->dispatchSimulatedClick(event); - return; - } + control->dispatchSimulatedClick(event); + return; } else if (fromImplicitSubmissionTrigger) { // Default (submit) button is not activated; no implicit submission. return; @@ -219,12 +259,13 @@ bool HTMLFormElement::validateInteractively(Event* event) if (submitElement && submitElement->formNoValidate()) return true; - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - if (m_associatedElements[i]->isFormControlElement()) - toHTMLFormControlElement(m_associatedElements[i])->hideVisibleValidationMessage(); + const FormAssociatedElement::List& elements = associatedElements(); + for (unsigned i = 0; i < elements.size(); ++i) { + if (elements[i]->isFormControlElement()) + toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(); } - Vector<RefPtr<FormAssociatedElement> > unhandledInvalidControls; + WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > unhandledInvalidControls; if (!checkInvalidControlsAndCollectUnhandled(&unhandledInvalidControls)) return true; // Because the form has invalid controls, we abort the form submission and @@ -234,7 +275,7 @@ bool HTMLFormElement::validateInteractively(Event* event) // has !renderer()->needsLayout() assertion. document().updateLayoutIgnorePendingStylesheets(); - RefPtr<HTMLFormElement> protector(this); + RefPtrWillBeRawPtr<HTMLFormElement> protector(this); // Focus on the first focusable control and show a validation message. for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidControls[i].get(); @@ -262,36 +303,21 @@ bool HTMLFormElement::validateInteractively(Event* event) return false; } -bool HTMLFormElement::prepareForSubmission(Event* event) +void HTMLFormElement::prepareForSubmission(Event* event) { - RefPtr<HTMLFormElement> protector(this); - Frame* frame = document().frame(); - if (m_isSubmittingOrPreparingForSubmission || !frame) - return m_isSubmittingOrPreparingForSubmission; - - m_isSubmittingOrPreparingForSubmission = true; - m_shouldSubmit = false; + RefPtrWillBeRawPtr<HTMLFormElement> protector(this); + LocalFrame* frame = document().frame(); + if (!frame) + return; // Interactive validation must be done before dispatching the submit event. - if (!validateInteractively(event)) { - m_isSubmittingOrPreparingForSubmission = false; - return false; - } + if (!validateInteractively(event)) + return; - StringPairVector controlNamesAndValues; - getTextFieldValues(controlNamesAndValues); - RefPtr<FormState> formState = FormState::create(this, controlNamesAndValues, &document(), NotSubmittedByJavaScript); - frame->loader().client()->dispatchWillSendSubmitEvent(formState.release()); + frame->loader().client()->dispatchWillSendSubmitEvent(this); if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) - m_shouldSubmit = true; - - m_isSubmittingOrPreparingForSubmission = false; - - if (m_shouldSubmit) submit(event, true, true, NotSubmittedByJavaScript); - - return m_shouldSubmit; } void HTMLFormElement::submit() @@ -304,30 +330,11 @@ void HTMLFormElement::submitFromJavaScript() submit(0, false, UserGestureIndicator::processingUserGesture(), SubmittedByJavaScript); } -void HTMLFormElement::getTextFieldValues(StringPairVector& fieldNamesAndValues) const -{ - ASSERT_ARG(fieldNamesAndValues, fieldNamesAndValues.isEmpty()); - - fieldNamesAndValues.reserveCapacity(m_associatedElements.size()); - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - FormAssociatedElement* control = m_associatedElements[i]; - HTMLElement* element = toHTMLElement(control); - if (!element->hasTagName(inputTag)) - continue; - - HTMLInputElement* input = toHTMLInputElement(element); - if (!input->isTextField()) - continue; - - fieldNamesAndValues.append(make_pair(input->name().string(), input->value())); - } -} - -void HTMLFormElement::submitDialog(PassRefPtr<FormSubmission> formSubmission) +void HTMLFormElement::submitDialog(PassRefPtrWillBeRawPtr<FormSubmission> formSubmission) { for (Node* node = this; node; node = node->parentOrShadowHostNode()) { - if (node->hasTagName(dialogTag)) { - toHTMLDialogElement(node)->closeDialog(formSubmission->result()); + if (isHTMLDialogElement(*node)) { + toHTMLDialogElement(*node).closeDialog(formSubmission->result()); return; } } @@ -336,23 +343,18 @@ void HTMLFormElement::submitDialog(PassRefPtr<FormSubmission> formSubmission) void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool processingUserGesture, FormSubmissionTrigger formSubmissionTrigger) { FrameView* view = document().view(); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!view || !frame || !frame->page()) return; - if (m_isSubmittingOrPreparingForSubmission) { - m_shouldSubmit = true; - return; - } - - m_isSubmittingOrPreparingForSubmission = true; m_wasUserSubmitted = processingUserGesture; - RefPtr<HTMLFormControlElement> firstSuccessfulSubmitButton; + RefPtrWillBeRawPtr<HTMLFormControlElement> firstSuccessfulSubmitButton = nullptr; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - FormAssociatedElement* associatedElement = m_associatedElements[i]; + const FormAssociatedElement::List& elements = associatedElements(); + for (unsigned i = 0; i < elements.size(); ++i) { + FormAssociatedElement* associatedElement = elements[i]; if (!associatedElement->isFormControlElement()) continue; if (needButtonActivation) { @@ -367,7 +369,7 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool proce if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); - RefPtr<FormSubmission> formSubmission = FormSubmission::create(this, m_attributes, event, formSubmissionTrigger); + RefPtrWillBeRawPtr<FormSubmission> formSubmission = FormSubmission::create(this, m_attributes, event, formSubmissionTrigger); EventQueueScope scopeForDialogClose; // Delay dispatching 'close' to dialog until done submitting. if (formSubmission->method() == FormSubmission::DialogMethod) submitDialog(formSubmission.release()); @@ -376,12 +378,9 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool proce if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(false); - - m_shouldSubmit = false; - m_isSubmittingOrPreparingForSubmission = false; } -void HTMLFormElement::scheduleFormSubmission(PassRefPtr<FormSubmission> submission) +void HTMLFormElement::scheduleFormSubmission(PassRefPtrWillBeRawPtr<FormSubmission> submission) { ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod); ASSERT(submission->data()); @@ -395,15 +394,15 @@ void HTMLFormElement::scheduleFormSubmission(PassRefPtr<FormSubmission> submissi } if (protocolIsJavaScript(submission->action())) { - if (!document().contentSecurityPolicy()->allowFormAction(KURL(submission->action()))) + if (!document().contentSecurityPolicy()->allowFormAction(submission->action())) return; document().frame()->script().executeScriptIfJavaScriptURL(submission->action()); return; } - Frame* targetFrame = document().frame()->loader().findFrameForNavigation(submission->target(), submission->state()->sourceDocument()); + LocalFrame* targetFrame = document().frame()->loader().findFrameForNavigation(submission->target(), submission->state()->sourceDocument()); if (!targetFrame) { - if (!DOMWindow::allowPopUp(document().frame()) && !UserGestureIndicator::processingUserGesture()) + if (!LocalDOMWindow::allowPopUp(*document().frame()) && !UserGestureIndicator::processingUserGesture()) return; targetFrame = document().frame(); } else { @@ -412,7 +411,15 @@ void HTMLFormElement::scheduleFormSubmission(PassRefPtr<FormSubmission> submissi if (!targetFrame->page()) return; - submission->setReferrer(document().outgoingReferrer()); + if (MixedContentChecker::isMixedContent(document().securityOrigin(), submission->action())) { + UseCounter::count(document(), UseCounter::MixedContentFormsSubmitted); + if (!document().frame()->loader().mixedContentChecker()->canSubmitToInsecureForm(document().securityOrigin(), submission->action())) + return; + } else { + UseCounter::count(document(), UseCounter::FormsSubmitted); + } + + submission->setReferrer(Referrer(document().outgoingReferrer(), document().referrerPolicy())); submission->setOrigin(document().outgoingOrigin()); targetFrame->navigationScheduler().scheduleFormSubmission(submission); @@ -420,7 +427,7 @@ void HTMLFormElement::scheduleFormSubmission(PassRefPtr<FormSubmission> submissi void HTMLFormElement::reset() { - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (m_isInResetFunction || !frame) return; @@ -431,9 +438,10 @@ void HTMLFormElement::reset() return; } - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - if (m_associatedElements[i]->isFormControlElement()) - toHTMLFormControlElement(m_associatedElements[i])->reset(); + const FormAssociatedElement::List& elements = associatedElements(); + for (unsigned i = 0; i < elements.size(); ++i) { + if (elements[i]->isFormControlElement()) + toHTMLFormControlElement(elements[i])->reset(); } m_isInResetFunction = false; @@ -441,54 +449,51 @@ void HTMLFormElement::reset() void HTMLFormElement::requestAutocomplete() { - Frame* frame = document().frame(); - if (!frame) - return; + String errorMessage; + + if (!document().frame()) + errorMessage = "requestAutocomplete: form is not owned by a displayed document."; + else if (!shouldAutocomplete()) + errorMessage = "requestAutocomplete: form autocomplete attribute is set to off."; + else if (!UserGestureIndicator::processingUserGesture()) + errorMessage = "requestAutocomplete: must be called in response to a user gesture."; - if (!shouldAutocomplete() || !UserGestureIndicator::processingUserGesture()) { + if (!errorMessage.isEmpty()) { + document().addConsoleMessage(RenderingMessageSource, LogMessageLevel, errorMessage); finishRequestAutocomplete(AutocompleteResultErrorDisabled); - return; + } else { + document().frame()->loader().client()->didRequestAutocomplete(this); } - - StringPairVector controlNamesAndValues; - getTextFieldValues(controlNamesAndValues); - RefPtr<FormState> formState = FormState::create(this, controlNamesAndValues, &document(), SubmittedByJavaScript); - frame->loader().client()->didRequestAutocomplete(formState.release()); } void HTMLFormElement::finishRequestAutocomplete(AutocompleteResult result) { - RefPtr<Event> event; + RefPtrWillBeRawPtr<Event> event = nullptr; if (result == AutocompleteResultSuccess) - event = Event::create(EventTypeNames::autocomplete); + event = Event::createBubble(EventTypeNames::autocomplete); else if (result == AutocompleteResultErrorDisabled) event = AutocompleteErrorEvent::create("disabled"); else if (result == AutocompleteResultErrorCancel) event = AutocompleteErrorEvent::create("cancel"); else if (result == AutocompleteResultErrorInvalid) event = AutocompleteErrorEvent::create("invalid"); + else + ASSERT_NOT_REACHED(); event->setTarget(this); - m_pendingAutocompleteEvents.append(event.release()); - - // Dispatch events later as this API is meant to work asynchronously in all situations and implementations. - if (!m_requestAutocompleteTimer.isActive()) - m_requestAutocompleteTimer.startOneShot(0); -} - -void HTMLFormElement::requestAutocompleteTimerFired(Timer<HTMLFormElement>*) -{ - Vector<RefPtr<Event> > pendingEvents; - m_pendingAutocompleteEvents.swap(pendingEvents); - for (size_t i = 0; i < pendingEvents.size(); ++i) - dispatchEvent(pendingEvents[i].release()); + m_pendingAutocompleteEventsQueue->enqueueEvent(event.release()); } void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { - if (name == actionAttr) + if (name == actionAttr) { m_attributes.parseAction(value); - else if (name == targetAttr) + // If the new action attribute is pointing to insecure "action" location from a secure page + // it is marked as "passive" mixed content. + KURL actionURL = document().completeURL(m_attributes.action().isEmpty() ? document().url().string() : m_attributes.action()); + if (MixedContentChecker::isMixedContent(document().securityOrigin(), actionURL)) + document().frame()->loader().mixedContentChecker()->canSubmitToInsecureForm(document().securityOrigin(), actionURL); + } else if (name == targetAttr) m_attributes.setTarget(value); else if (name == methodAttr) m_attributes.updateMethodType(value); @@ -497,135 +502,119 @@ void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicStri else if (name == accept_charsetAttr) m_attributes.setAcceptCharset(value); else if (name == onautocompleteAttr) - setAttributeEventListener(EventTypeNames::autocomplete, createAttributeEventListener(this, name, value)); + setAttributeEventListener(EventTypeNames::autocomplete, createAttributeEventListener(this, name, value, eventParameterName())); else if (name == onautocompleteerrorAttr) - setAttributeEventListener(EventTypeNames::autocompleteerror, createAttributeEventListener(this, name, value)); + setAttributeEventListener(EventTypeNames::autocompleteerror, createAttributeEventListener(this, name, value, eventParameterName())); else HTMLElement::parseAttribute(name, value); } -template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* item) +void HTMLFormElement::associate(FormAssociatedElement& e) { - size_t size = vec.size(); - for (size_t i = 0; i != size; ++i) - if (vec[i] == item) { - vec.remove(i); - break; - } + m_associatedElementsAreDirty = true; + m_associatedElements.clear(); } -unsigned HTMLFormElement::formElementIndexWithFormAttribute(Element* element, unsigned rangeStart, unsigned rangeEnd) +void HTMLFormElement::disassociate(FormAssociatedElement& e) { - if (m_associatedElements.isEmpty()) - return 0; - - ASSERT(rangeStart <= rangeEnd); - - if (rangeStart == rangeEnd) - return rangeStart; + m_associatedElementsAreDirty = true; + m_associatedElements.clear(); + removeFromPastNamesMap(toHTMLElement(e)); +} - unsigned left = rangeStart; - unsigned right = rangeEnd - 1; - unsigned short position; +bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const +{ + return attribute.name() == actionAttr || HTMLElement::isURLAttribute(attribute); +} - // Does binary search on m_associatedElements in order to find the index - // to be inserted. - while (left != right) { - unsigned middle = left + ((right - left) / 2); - ASSERT(middle < m_associatedElementsBeforeIndex || middle >= m_associatedElementsAfterIndex); - position = element->compareDocumentPosition(toHTMLElement(m_associatedElements[middle])); - if (position & DOCUMENT_POSITION_FOLLOWING) - right = middle; - else - left = middle + 1; - } +bool HTMLFormElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == actionAttr || HTMLElement::hasLegalLinkAttribute(name); +} - ASSERT(left < m_associatedElementsBeforeIndex || left >= m_associatedElementsAfterIndex); - position = element->compareDocumentPosition(toHTMLElement(m_associatedElements[left])); - if (position & DOCUMENT_POSITION_FOLLOWING) - return left; - return left + 1; +void HTMLFormElement::associate(HTMLImageElement& e) +{ + m_imageElementsAreDirty = true; + m_imageElements.clear(); } -unsigned HTMLFormElement::formElementIndex(FormAssociatedElement& associatedElement) +void HTMLFormElement::disassociate(HTMLImageElement& e) { - HTMLElement& associatedHTMLElement = toHTMLElement(associatedElement); - // Treats separately the case where this element has the form attribute - // for performance consideration. - if (associatedHTMLElement.fastHasAttribute(formAttr)) { - unsigned short position = compareDocumentPosition(&associatedHTMLElement); - if (position & DOCUMENT_POSITION_PRECEDING) { - ++m_associatedElementsBeforeIndex; - ++m_associatedElementsAfterIndex; - return HTMLFormElement::formElementIndexWithFormAttribute(&associatedHTMLElement, 0, m_associatedElementsBeforeIndex - 1); - } - if (position & DOCUMENT_POSITION_FOLLOWING && !(position & DOCUMENT_POSITION_CONTAINED_BY)) - return HTMLFormElement::formElementIndexWithFormAttribute(&associatedHTMLElement, m_associatedElementsAfterIndex, m_associatedElements.size()); - } + m_imageElementsAreDirty = true; + m_imageElements.clear(); + removeFromPastNamesMap(e); +} - // Check for the special case where this element is the very last thing in - // the form's tree of children; we don't want to walk the entire tree in that - // common case that occurs during parsing; instead we'll just return a value - // that says "add this form element to the end of the array". - if (ElementTraversal::next(associatedHTMLElement, this)) { - unsigned i = m_associatedElementsBeforeIndex; - for (Element* element = this; element; element = ElementTraversal::next(*element, this)) { - if (element == associatedHTMLElement) { - ++m_associatedElementsAfterIndex; - return i; - } - if (!element->isFormControlElement() && !element->hasTagName(objectTag)) - continue; - if (!element->isHTMLElement() || toHTMLElement(element)->formOwner() != this) - continue; - ++i; - } - } - return m_associatedElementsAfterIndex++; +#if !ENABLE(OILPAN) +WeakPtr<HTMLFormElement> HTMLFormElement::createWeakPtr() +{ + return m_weakPtrFactory.createWeakPtr(); } +#endif -void HTMLFormElement::registerFormElement(FormAssociatedElement& e) +void HTMLFormElement::didAssociateByParser() { - m_associatedElements.insert(formElementIndex(e), &e); + if (!m_didFinishParsingChildren) + return; + m_hasElementsAssociatedByParser = true; + UseCounter::count(document(), UseCounter::FormAssociationByParser); } -void HTMLFormElement::removeFormElement(FormAssociatedElement* e) +PassRefPtrWillBeRawPtr<HTMLFormControlsCollection> HTMLFormElement::elements() { - unsigned index; - for (index = 0; index < m_associatedElements.size(); ++index) { - if (m_associatedElements[index] == e) - break; - } - ASSERT_WITH_SECURITY_IMPLICATION(index < m_associatedElements.size()); - if (index < m_associatedElementsBeforeIndex) - --m_associatedElementsBeforeIndex; - if (index < m_associatedElementsAfterIndex) - --m_associatedElementsAfterIndex; - removeFromPastNamesMap(*toHTMLElement(e)); - removeFromVector(m_associatedElements, e); + return toHTMLFormControlsCollection(ensureCachedHTMLCollection(FormControls).get()); } -bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const +void HTMLFormElement::collectAssociatedElements(Node& root, FormAssociatedElement::List& elements) const { - return attribute.name() == actionAttr || HTMLElement::isURLAttribute(attribute); + elements.clear(); + for (HTMLElement* element = Traversal<HTMLElement>::firstWithin(root); element; element = Traversal<HTMLElement>::next(*element)) { + FormAssociatedElement* associatedElement = 0; + if (element->isFormControlElement()) + associatedElement = toHTMLFormControlElement(element); + else if (isHTMLObjectElement(*element)) + associatedElement = toHTMLObjectElement(element); + else + continue; + if (associatedElement->form()== this) + elements.append(associatedElement); + } } -void HTMLFormElement::registerImgElement(HTMLImageElement* e) +// This function should be const conceptually. However we update some fields +// because of lazy evaluation. +const FormAssociatedElement::List& HTMLFormElement::associatedElements() const { - ASSERT(m_imageElements.find(e) == kNotFound); - m_imageElements.append(e); + if (!m_associatedElementsAreDirty) + return m_associatedElements; + HTMLFormElement* mutableThis = const_cast<HTMLFormElement*>(this); + Node* scope = mutableThis; + if (m_hasElementsAssociatedByParser) + scope = &highestAncestorOrSelf(); + if (inDocument() && treeScope().idTargetObserverRegistry().hasObservers(fastGetAttribute(idAttr))) + scope = &treeScope().rootNode(); + ASSERT(scope); + collectAssociatedElements(*scope, mutableThis->m_associatedElements); + mutableThis->m_associatedElementsAreDirty = false; + return m_associatedElements; } -void HTMLFormElement::removeImgElement(HTMLImageElement* e) +void HTMLFormElement::collectImageElements(Node& root, WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >& elements) { - ASSERT(m_imageElements.find(e) != kNotFound); - removeFromPastNamesMap(*e); - removeFromVector(m_imageElements, e); + elements.clear(); + for (HTMLImageElement* image = Traversal<HTMLImageElement>::firstWithin(root); image; image = Traversal<HTMLImageElement>::next(*image)) { + if (image->formOwner() == this) + elements.append(image); + } } -PassRefPtr<HTMLCollection> HTMLFormElement::elements() +const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >& HTMLFormElement::imageElements() { - return ensureCachedHTMLCollection(FormControls); + if (!m_imageElementsAreDirty) + return m_imageElements; + collectImageElements(m_hasElementsAssociatedByParser ? highestAncestorOrSelf() : *this, m_imageElements); + m_imageElementsAreDirty = false; + return m_imageElements; } String HTMLFormElement::name() const @@ -646,11 +635,6 @@ const AtomicString& HTMLFormElement::action() const return getAttribute(actionAttr); } -void HTMLFormElement::setAction(const AtomicString& value) -{ - setAttribute(actionAttr, value); -} - void HTMLFormElement::setEnctype(const AtomicString& value) { setAttribute(enctypeAttr, value); @@ -666,11 +650,6 @@ void HTMLFormElement::setMethod(const AtomicString& value) setAttribute(methodAttr, value); } -String HTMLFormElement::target() const -{ - return getAttribute(targetAttr); -} - bool HTMLFormElement::wasUserSubmitted() const { return m_wasUserSubmitted; @@ -678,10 +657,11 @@ bool HTMLFormElement::wasUserSubmitted() const HTMLFormControlElement* HTMLFormElement::defaultButton() const { - for (unsigned i = 0; i < m_associatedElements.size(); ++i) { - if (!m_associatedElements[i]->isFormControlElement()) + const FormAssociatedElement::List& elements = associatedElements(); + for (unsigned i = 0; i < elements.size(); ++i) { + if (!elements[i]->isFormControlElement()) continue; - HTMLFormControlElement* control = toHTMLFormControlElement(m_associatedElements[i]); + HTMLFormControlElement* control = toHTMLFormControlElement(elements[i]); if (control->isSuccessfulSubmitButton()) return control; } @@ -691,61 +671,56 @@ HTMLFormControlElement* HTMLFormElement::defaultButton() const bool HTMLFormElement::checkValidity() { - Vector<RefPtr<FormAssociatedElement> > controls; - return !checkInvalidControlsAndCollectUnhandled(&controls); -} - -bool HTMLFormElement::checkValidityWithoutDispatchingEvents() -{ - return !checkInvalidControlsAndCollectUnhandled(0, HTMLFormControlElement::CheckValidityDispatchEventsNone); + return !checkInvalidControlsAndCollectUnhandled(0); } -bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(Vector<RefPtr<FormAssociatedElement> >* unhandledInvalidControls, HTMLFormControlElement::CheckValidityDispatchEvents dispatchEvents) +bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> >* unhandledInvalidControls) { - RefPtr<HTMLFormElement> protector(this); - // Copy m_associatedElements because event handlers called from - // HTMLFormControlElement::checkValidity() might change m_associatedElements. - Vector<RefPtr<FormAssociatedElement> > elements; - elements.reserveCapacity(m_associatedElements.size()); - for (unsigned i = 0; i < m_associatedElements.size(); ++i) - elements.append(m_associatedElements[i]); + RefPtrWillBeRawPtr<HTMLFormElement> protector(this); + // Copy associatedElements because event handlers called from + // HTMLFormControlElement::checkValidity() might change associatedElements. + const FormAssociatedElement::List& associatedElements = this->associatedElements(); + WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; + elements.reserveCapacity(associatedElements.size()); + for (unsigned i = 0; i < associatedElements.size(); ++i) + elements.append(associatedElements[i]); bool hasInvalidControls = false; for (unsigned i = 0; i < elements.size(); ++i) { if (elements[i]->form() == this && elements[i]->isFormControlElement()) { HTMLFormControlElement* control = toHTMLFormControlElement(elements[i].get()); - if (!control->checkValidity(unhandledInvalidControls, dispatchEvents) && control->formOwner() == this) + if (!control->checkValidity(unhandledInvalidControls) && control->formOwner() == this) hasInvalidControls = true; } } return hasInvalidControls; } -Node* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) const +Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) { if (pastName.isEmpty() || !m_pastNamesMap) return 0; - Node* node = m_pastNamesMap->get(pastName); -#if !ASSERT_DISABLED - if (!node) + Element* element = m_pastNamesMap->get(pastName); +#if ASSERT_ENABLED + if (!element) return 0; - ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(node)->formOwner() == this); - if (node->hasTagName(imgTag)) { - ASSERT_WITH_SECURITY_IMPLICATION(m_imageElements.find(node) != kNotFound); - } else if (node->hasTagName(objectTag)) { - ASSERT_WITH_SECURITY_IMPLICATION(m_associatedElements.find(toHTMLObjectElement(node)) != kNotFound); + ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this); + if (isHTMLImageElement(*element)) { + ASSERT_WITH_SECURITY_IMPLICATION(imageElements().find(element) != kNotFound); + } else if (isHTMLObjectElement(*element)) { + ASSERT_WITH_SECURITY_IMPLICATION(associatedElements().find(toHTMLObjectElement(element)) != kNotFound); } else { - ASSERT_WITH_SECURITY_IMPLICATION(m_associatedElements.find(toHTMLFormControlElement(node)) != kNotFound); + ASSERT_WITH_SECURITY_IMPLICATION(associatedElements().find(toHTMLFormControlElement(element)) != kNotFound); } #endif - return node; + return element; } -void HTMLFormElement::addToPastNamesMap(Node* element, const AtomicString& pastName) +void HTMLFormElement::addToPastNamesMap(Element* element, const AtomicString& pastName) { if (pastName.isEmpty()) return; if (!m_pastNamesMap) - m_pastNamesMap = adoptPtr(new PastNamesMap); + m_pastNamesMap = adoptPtrWillBeNoop(new PastNamesMap); m_pastNamesMap->set(pastName, element); } @@ -756,22 +731,24 @@ void HTMLFormElement::removeFromPastNamesMap(HTMLElement& element) PastNamesMap::iterator end = m_pastNamesMap->end(); for (PastNamesMap::iterator it = m_pastNamesMap->begin(); it != end; ++it) { if (it->value == &element) { - it->value = 0; + it->value = nullptr; // Keep looping. Single element can have multiple names. } } } -void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<Node> >& namedItems) +void HTMLFormElement::getNamedElements(const AtomicString& name, WillBeHeapVector<RefPtrWillBeMember<Element> >& namedItems) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#dom-form-nameditem elements()->namedItems(name, namedItems); - Node* elementFromPast = elementFromPastNamesMap(name); - if (namedItems.size() && namedItems.first() != elementFromPast) + Element* elementFromPast = elementFromPastNamesMap(name); + if (namedItems.size() && namedItems.first() != elementFromPast) { addToPastNamesMap(namedItems.first().get(), name); - else if (elementFromPast && namedItems.isEmpty()) + } else if (elementFromPast && namedItems.isEmpty()) { namedItems.append(elementFromPast); + UseCounter::count(document(), UseCounter::FormNameAccessForPastNamesMap); + } } bool HTMLFormElement::shouldAutocomplete() const @@ -782,7 +759,8 @@ bool HTMLFormElement::shouldAutocomplete() const void HTMLFormElement::finishParsingChildren() { HTMLElement::finishParsingChildren(); - document().formController()->restoreControlStateIn(*this); + document().formController().restoreControlStateIn(*this); + m_didFinishParsingChildren = true; } void HTMLFormElement::copyNonAttributePropertiesFromElement(const Element& source) @@ -791,13 +769,13 @@ void HTMLFormElement::copyNonAttributePropertiesFromElement(const Element& sourc HTMLElement::copyNonAttributePropertiesFromElement(source); } -void HTMLFormElement::anonymousNamedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtr<Node>& returnValue1) +void HTMLFormElement::anonymousNamedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtrWillBeRawPtr<RadioNodeList>& returnValue0, bool& returnValue1Enabled, RefPtrWillBeRawPtr<Element>& returnValue1) { // Call getNamedElements twice, first time check if it has a value // and let HTMLFormElement update its cache. // See issue: 867404 { - Vector<RefPtr<Node> > elements; + WillBeHeapVector<RefPtrWillBeMember<Element> > elements; getNamedElements(name, elements); if (elements.isEmpty()) return; @@ -805,7 +783,7 @@ void HTMLFormElement::anonymousNamedGetter(const AtomicString& name, bool& retur // Second call may return different results from the first call, // but if the first the size cannot be zero. - Vector<RefPtr<Node> > elements; + WillBeHeapVector<RefPtrWillBeMember<Element> > elements; getNamedElements(name, elements); ASSERT(!elements.isEmpty()); @@ -815,8 +793,9 @@ void HTMLFormElement::anonymousNamedGetter(const AtomicString& name, bool& retur return; } + bool onlyMatchImg = !elements.isEmpty() && isHTMLImageElement(*elements.first()); returnValue0Enabled = true; - returnValue0 = NamedNodesCollection::create(elements); + returnValue0 = radioNodeList(name, onlyMatchImg); } void HTMLFormElement::setDemoted(bool demoted) diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.h index d2f118e08c3..b4fb4793566 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.h @@ -26,10 +26,10 @@ #include "core/html/HTMLElement.h" #include "core/html/HTMLFormControlElement.h" -#include "core/html/forms/CheckedRadioButtons.h" -#include "core/loader/FormState.h" +#include "core/html/forms/RadioButtonGroupScope.h" #include "core/loader/FormSubmission.h" #include "wtf/OwnPtr.h" +#include "wtf/WeakPtr.h" namespace WTF{ class TextEncoding; @@ -40,20 +40,23 @@ namespace WebCore { class Event; class FormAssociatedElement; class FormData; +class GenericEventQueue; class HTMLFormControlElement; +class HTMLFormControlsCollection; class HTMLImageElement; class HTMLInputElement; class HTMLFormElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLFormElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLFormElement> create(Document&); virtual ~HTMLFormElement(); + virtual void trace(Visitor*) OVERRIDE; - PassRefPtr<HTMLCollection> elements(); - void getNamedElements(const AtomicString&, Vector<RefPtr<Node> >&); + PassRefPtrWillBeRawPtr<HTMLFormControlsCollection> elements(); + void getNamedElements(const AtomicString&, WillBeHeapVector<RefPtrWillBeMember<Element> >&); unsigned length() const; - Node* item(unsigned index); + Element* item(unsigned index); String enctype() const { return m_attributes.encodingType(); } void setEnctype(const AtomicString&); @@ -63,14 +66,16 @@ public: bool shouldAutocomplete() const; - // FIXME: Should rename these two functions to say "form control" or "form-associated element" instead of "form element". - void registerFormElement(FormAssociatedElement&); - void removeFormElement(FormAssociatedElement*); + void associate(FormAssociatedElement&); + void disassociate(FormAssociatedElement&); + void associate(HTMLImageElement&); + void disassociate(HTMLImageElement&); +#if !ENABLE(OILPAN) + WeakPtr<HTMLFormElement> createWeakPtr(); +#endif + void didAssociateByParser(); - void registerImgElement(HTMLImageElement*); - void removeImgElement(HTMLImageElement*); - - bool prepareForSubmission(Event*); + void prepareForSubmission(Event*); void submit(); void submitFromJavaScript(); void reset(); @@ -78,26 +83,21 @@ public: void setDemoted(bool); void submitImplicitly(Event*, bool fromImplicitSubmissionTrigger); - bool formWouldHaveSecureSubmission(const String& url); String name() const; bool noValidate() const; const AtomicString& action() const; - void setAction(const AtomicString&); String method() const; void setMethod(const AtomicString&); - virtual String target() const; - bool wasUserSubmitted() const; HTMLFormControlElement* defaultButton() const; bool checkValidity(); - bool checkValidityWithoutDispatchingEvents(); enum AutocompleteResult { AutocompleteResultSuccess, @@ -112,38 +112,38 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(autocomplete); DEFINE_ATTRIBUTE_EVENT_LISTENER(autocompleteerror); - CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; } + RadioButtonGroupScope& radioButtonGroupScope() { return m_radioButtonGroupScope; } - const Vector<FormAssociatedElement*>& associatedElements() const { return m_associatedElements; } - const Vector<HTMLImageElement*>& imageElements() const { return m_imageElements; } + const FormAssociatedElement::List& associatedElements() const; + const WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >& imageElements(); - void getTextFieldValues(StringPairVector& fieldNamesAndValues) const; - void anonymousNamedGetter(const AtomicString& name, bool&, RefPtr<NodeList>&, bool&, RefPtr<Node>&); + void anonymousNamedGetter(const AtomicString& name, bool&, RefPtrWillBeRawPtr<RadioNodeList>&, bool&, RefPtrWillBeRawPtr<Element>&); private: explicit HTMLFormElement(Document&); - virtual bool rendererIsNeeded(const RenderStyle&); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; virtual void finishParsingChildren() OVERRIDE; - virtual void handleLocalEvents(Event*); + virtual void handleLocalEvents(Event*) OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; } virtual void copyNonAttributePropertiesFromElement(const Element&) OVERRIDE; - void submitDialog(PassRefPtr<FormSubmission>); + void submitDialog(PassRefPtrWillBeRawPtr<FormSubmission>); void submit(Event*, bool activateSubmitButton, bool processingUserGesture, FormSubmissionTrigger); - void scheduleFormSubmission(PassRefPtr<FormSubmission>); + void scheduleFormSubmission(PassRefPtrWillBeRawPtr<FormSubmission>); - unsigned formElementIndexWithFormAttribute(Element*, unsigned rangeStart, unsigned rangeEnd); - unsigned formElementIndex(FormAssociatedElement&); + void collectAssociatedElements(Node& root, FormAssociatedElement::List&) const; + void collectImageElements(Node& root, WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> >&); // Returns true if the submission should proceed. bool validateInteractively(Event*); @@ -151,40 +151,40 @@ private: // Validates each of the controls, and stores controls of which 'invalid' // event was not canceled to the specified vector. Returns true if there // are any invalid controls in this form. - bool checkInvalidControlsAndCollectUnhandled(Vector<RefPtr<FormAssociatedElement> >*, HTMLFormControlElement::CheckValidityDispatchEvents = HTMLFormControlElement::CheckValidityDispatchEventsAllowed); + bool checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> >*); - Node* elementFromPastNamesMap(const AtomicString&) const; - void addToPastNamesMap(Node*, const AtomicString& pastName); + Element* elementFromPastNamesMap(const AtomicString&); + void addToPastNamesMap(Element*, const AtomicString& pastName); void removeFromPastNamesMap(HTMLElement&); - typedef HashMap<AtomicString, Node*> PastNamesMap; + typedef WillBeHeapHashMap<AtomicString, RawPtrWillBeMember<Element> > PastNamesMap; FormSubmission::Attributes m_attributes; - OwnPtr<PastNamesMap> m_pastNamesMap; - - CheckedRadioButtons m_checkedRadioButtons; - - unsigned m_associatedElementsBeforeIndex; - unsigned m_associatedElementsAfterIndex; - Vector<FormAssociatedElement*> m_associatedElements; - Vector<HTMLImageElement*> m_imageElements; + OwnPtrWillBeMember<PastNamesMap> m_pastNamesMap; + + RadioButtonGroupScope m_radioButtonGroupScope; + + // Do not access m_associatedElements directly. Use associatedElements() instead. + FormAssociatedElement::List m_associatedElements; + // Do not access m_imageElements directly. Use imageElements() instead. + WillBeHeapVector<RawPtrWillBeMember<HTMLImageElement> > m_imageElements; +#if !ENABLE(OILPAN) + WeakPtrFactory<HTMLFormElement> m_weakPtrFactory; +#endif + bool m_associatedElementsAreDirty; + bool m_imageElementsAreDirty; + bool m_hasElementsAssociatedByParser; + bool m_didFinishParsingChildren; bool m_wasUserSubmitted; - bool m_isSubmittingOrPreparingForSubmission; - bool m_shouldSubmit; bool m_isInResetFunction; bool m_wasDemoted; - void requestAutocompleteTimerFired(Timer<HTMLFormElement>*); - - Vector<RefPtr<Event> > m_pendingAutocompleteEvents; - Timer<HTMLFormElement> m_requestAutocompleteTimer; + OwnPtrWillBeMember<GenericEventQueue> m_pendingAutocompleteEventsQueue; }; -DEFINE_NODE_TYPE_CASTS(HTMLFormElement, hasTagName(HTMLNames::formTag)); - } // namespace WebCore #endif // HTMLFormElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.idl index 6ba5f418c01..68283fc8058 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFormElement.idl @@ -18,10 +18,12 @@ * Boston, MA 02110-1301, USA. */ -interface HTMLFormElement : HTMLElement { +[ + OverrideBuiltins, +] interface HTMLFormElement : HTMLElement { [Reflect=accept_charset] attribute DOMString acceptCharset; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString action; - [Reflect] attribute DOMString autocomplete; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString action; + [Reflect, ReflectOnly="on"|"off", ReflectMissing="on", ReflectInvalid="on"] attribute DOMString autocomplete; [CustomElementCallbacks] attribute DOMString enctype; [CustomElementCallbacks] attribute DOMString encoding; [CustomElementCallbacks] attribute DOMString method; @@ -31,14 +33,12 @@ interface HTMLFormElement : HTMLElement { readonly attribute HTMLCollection elements; readonly attribute long length; - [ImplementedAs=item] getter Node(unsigned long index); - [ImplementedAs=anonymousNamedGetter, OverrideBuiltins, NotEnumerable] getter (NodeList or Node)(DOMString name); + [ImplementedAs=item] getter Element (unsigned long index); + [NotEnumerable] getter (RadioNodeList or Element) (DOMString name); - [ImplementedAs=submitFromJavaScript, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] void submit(); + [ImplementedAs=submitFromJavaScript, LogActivity] void submit(); [CustomElementCallbacks] void reset(); boolean checkValidity(); [RuntimeEnabled=RequestAutocomplete] void requestAutocomplete(); - [RuntimeEnabled=RequestAutocomplete] attribute EventHandler onautocomplete; - [RuntimeEnabled=RequestAutocomplete] attribute EventHandler onautocompleteerror; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.cpp index 218a2216167..7f5a19fbf82 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.cpp @@ -24,7 +24,7 @@ #include "config.h" #include "core/html/HTMLFrameElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLFrameSetElement.h" #include "core/rendering/RenderFrame.h" @@ -40,10 +40,7 @@ inline HTMLFrameElement::HTMLFrameElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLFrameElement> HTMLFrameElement::create(Document& document) -{ - return adoptRef(new HTMLFrameElement(document)); -} +DEFINE_NODE_FACTORY(HTMLFrameElement) bool HTMLFrameElement::rendererIsNeeded(const RenderStyle&) { @@ -56,15 +53,6 @@ RenderObject* HTMLFrameElement::createRenderer(RenderStyle*) return new RenderFrame(this); } -static inline HTMLFrameSetElement* containingFrameSetElement(Node* node) -{ - while ((node = node->parentNode())) { - if (node->hasTagName(framesetTag)) - return toHTMLFrameSetElement(node); - } - return 0; -} - bool HTMLFrameElement::noResize() const { return hasAttribute(noresizeAttr); @@ -74,7 +62,7 @@ void HTMLFrameElement::attach(const AttachContext& context) { HTMLFrameElementBase::attach(context); - if (HTMLFrameSetElement* frameSetElement = containingFrameSetElement(this)) { + if (HTMLFrameSetElement* frameSetElement = Traversal<HTMLFrameSetElement>::firstAncestor(*this)) { if (!m_frameBorderSet) m_frameBorder = frameSetElement->hasFrameBorder(); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.h index 72ca10399ab..20ba93597bc 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.h @@ -30,7 +30,7 @@ namespace WebCore { class HTMLFrameElement FINAL : public HTMLFrameElementBase { public: - static PassRefPtr<HTMLFrameElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLFrameElement); bool hasFrameBorder() const { return m_frameBorder; } @@ -41,19 +41,15 @@ private: virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&); - virtual RenderObject* createRenderer(RenderStyle*); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual bool allowFullScreen() const { return false; } - bool m_frameBorder; bool m_frameBorderSet; }; -DEFINE_NODE_TYPE_CASTS(HTMLFrameElement, hasTagName(HTMLNames::frameTag)); - } // namespace WebCore #endif // HTMLFrameElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.idl index 1ab494ce552..ed43c3c69e4 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElement.idl @@ -27,7 +27,7 @@ interface HTMLFrameElement : HTMLElement { [Reflect] attribute DOMString name; [Reflect] attribute boolean noResize; [Reflect] attribute DOMString scrolling; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; // Introduced in DOM Level 2: [CheckSecurity=Node] readonly attribute Document contentDocument; @@ -35,10 +35,8 @@ interface HTMLFrameElement : HTMLElement { // Extensions readonly attribute Window contentWindow; - [CheckSecurity=Node, RaisesException] SVGDocument getSVGDocument(); + [CheckSecurity=Node, RaisesException] Document getSVGDocument(); - [TreatNullAs=NullString, Custom=Setter, MeasureAs=HTMLFrameElementLocation] attribute DOMString location; - - readonly attribute long width; - readonly attribute long height; + [MeasureAs=HTMLFrameElementWidth] readonly attribute long width; + [MeasureAs=HTMLFrameElementHeight] readonly attribute long height; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp index fc6bfb98c35..182189a86e5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp @@ -24,17 +24,17 @@ #include "config.h" #include "core/html/HTMLFrameElementBase.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/loader/FrameLoader.h" +#include "core/page/ChromeClient.h" #include "core/page/FocusController.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" #include "core/page/Page.h" #include "core/rendering/RenderPart.h" @@ -63,7 +63,7 @@ bool HTMLFrameElementBase::isURLAllowed() const return false; } - Frame* parentFrame = document().frame(); + LocalFrame* parentFrame = document().frame(); if (parentFrame) return parentFrame->isURLAllowed(completeURL); @@ -76,9 +76,9 @@ void HTMLFrameElementBase::openURL(bool lockBackForwardList) return; if (m_URL.isEmpty()) - m_URL = blankURL().string(); + m_URL = AtomicString(blankURL().string()); - Frame* parentFrame = document().frame(); + LocalFrame* parentFrame = document().frame(); if (!parentFrame) return; @@ -92,9 +92,9 @@ void HTMLFrameElementBase::openURL(bool lockBackForwardList) if (!loadOrRedirectSubframe(url, m_frameName, lockBackForwardList)) return; - if (!contentFrame() || scriptURL.isEmpty()) + if (!contentFrame() || scriptURL.isEmpty() || !contentFrame()->isLocalFrame()) return; - contentFrame()->script().executeScriptIfJavaScriptURL(scriptURL); + toLocalFrame(contentFrame())->script().executeScriptIfJavaScriptURL(scriptURL); } void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomicString& value) @@ -125,11 +125,9 @@ void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const Atomi else if (equalIgnoringCase(value, "no")) m_scrolling = ScrollbarAlwaysOff; // FIXME: If we are already attached, this has no effect. - } else if (name == onbeforeloadAttr) - setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value)); - else if (name == onbeforeunloadAttr) { + } else if (name == onbeforeunloadAttr) { // FIXME: should <frame> elements have beforeunload handlers? - setAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(this, name, value)); + setAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(this, name, value, eventParameterName())); } else HTMLFrameOwnerElement::parseAttribute(name, value); } @@ -137,8 +135,6 @@ void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const Atomi void HTMLFrameElementBase::setNameAndOpenURL() { m_frameName = getNameAttribute(); - if (m_frameName.isNull()) - m_frameName = getIdAttribute(); openURL(); } @@ -163,19 +159,14 @@ void HTMLFrameElementBase::attach(const AttachContext& context) { HTMLFrameOwnerElement::attach(context); - if (RenderPart* part = renderPart()) { - if (Frame* frame = contentFrame()) - part->setWidget(frame->view()); + if (renderPart()) { + if (Frame* frame = contentFrame()) { + if (frame->isLocalFrame()) + setWidget(toLocalFrame(frame)->view()); + } } } -KURL HTMLFrameElementBase::location() const -{ - if (fastHasAttribute(srcdocAttr)) - return KURL(ParsedURLString, "about:srcdoc"); - return document().completeURL(getAttribute(srcAttr)); -} - void HTMLFrameElementBase::setLocation(const String& str) { m_URL = AtomicString(str); @@ -196,7 +187,7 @@ void HTMLFrameElementBase::setFocus(bool received) if (received) page->focusController().setFocusedFrame(contentFrame()); else if (page->focusController().focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away. - page->focusController().setFocusedFrame(0); + page->focusController().setFocusedFrame(nullptr); } } @@ -206,6 +197,11 @@ bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const || HTMLFrameOwnerElement::isURLAttribute(attribute); } +bool HTMLFrameElementBase::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == srcAttr || HTMLFrameOwnerElement::hasLegalLinkAttribute(name); +} + bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const { return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute); @@ -227,4 +223,15 @@ int HTMLFrameElementBase::height() return renderBox()->height(); } +// FIXME: Remove this code once we have input routing in the browser +// process. See http://crbug.com/339659. +void HTMLFrameElementBase::defaultEventHandler(Event* event) +{ + if (contentFrame() && contentFrame()->isRemoteFrameTemporary()) { + contentFrame()->chromeClient().forwardInputEvent(contentFrame(), event); + return; + } + HTMLFrameOwnerElement::defaultEventHandler(event); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h index 9352e4e7056..dc6d9204385 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameElementBase.h @@ -31,10 +31,7 @@ namespace WebCore { class HTMLFrameElementBase : public HTMLFrameOwnerElement { public: - KURL location() const; - void setLocation(const String&); - - virtual ScrollbarMode scrollingMode() const { return m_scrolling; } + virtual ScrollbarMode scrollingMode() const OVERRIDE FINAL { return m_scrolling; } int marginWidth() const { return m_marginWidth; } int marginHeight() const { return m_marginHeight; } @@ -42,7 +39,7 @@ public: int width(); int height(); - virtual bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE FINAL { return false; } protected: HTMLFrameElementBase(const QualifiedName&, Document&); @@ -51,20 +48,24 @@ protected: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; - virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE; + virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE FINAL; virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; -private: - virtual bool supportsFocus() const; - virtual void setFocus(bool) OVERRIDE; + // FIXME: Remove this method once we have input routing in the browser + // process. See http://crbug.com/339659. + virtual void defaultEventHandler(Event*) OVERRIDE; - virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - virtual bool isHTMLContentAttribute(const Attribute&) const OVERRIDE; +private: + virtual bool supportsFocus() const OVERRIDE FINAL; + virtual void setFocus(bool) OVERRIDE FINAL; - virtual bool isFrameElementBase() const { return true; } + virtual bool isURLAttribute(const Attribute&) const OVERRIDE FINAL; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE FINAL; + virtual bool isHTMLContentAttribute(const Attribute&) const OVERRIDE FINAL; - virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; } + virtual bool areAuthorShadowsAllowed() const OVERRIDE FINAL { return false; } + void setLocation(const String&); void setNameAndOpenURL(); void openURL(bool lockBackForwardList = true); @@ -77,12 +78,17 @@ private: int m_marginHeight; }; -inline bool isHTMLFrameElementBase(const Node& node) +inline bool isHTMLFrameElementBase(const Element& element) +{ + return isHTMLFrameElement(element) || isHTMLIFrameElement(element); +} + +inline bool isHTMLFrameElementBase(const HTMLElement& element) { - return node.isElementNode() && toElement(node).isFrameElementBase(); + return isHTMLFrameElement(element) || isHTMLIFrameElement(element); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLFrameElementBase); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLFrameElementBase); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp index aaa73ff224c..3a5fea5d421 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp @@ -23,21 +23,77 @@ #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" +#include "core/accessibility/AXObjectCache.h" #include "core/dom/ExceptionCode.h" +#include "core/events/Event.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" +#include "core/rendering/RenderLayer.h" #include "core/rendering/RenderPart.h" -#include "core/svg/SVGDocument.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" #include "platform/weborigin/SecurityOrigin.h" #include "platform/weborigin/SecurityPolicy.h" namespace WebCore { +typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap; +static WidgetToParentMap& widgetNewParentMap() +{ + DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ()); + return map; +} + +static unsigned s_updateSuspendCount = 0; + +HTMLFrameOwnerElement::UpdateSuspendScope::UpdateSuspendScope() +{ + ++s_updateSuspendCount; +} + +void HTMLFrameOwnerElement::UpdateSuspendScope::performDeferredWidgetTreeOperations() +{ + WidgetToParentMap map; + widgetNewParentMap().swap(map); + WidgetToParentMap::iterator end = map.end(); + for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) { + Widget* child = it->key.get(); + ScrollView* currentParent = toScrollView(child->parent()); + FrameView* newParent = it->value; + if (newParent != currentParent) { + if (currentParent) + currentParent->removeChild(child); + if (newParent) + newParent->addChild(child); + } + } +} + +HTMLFrameOwnerElement::UpdateSuspendScope::~UpdateSuspendScope() +{ + ASSERT(s_updateSuspendCount > 0); + if (s_updateSuspendCount == 1) + performDeferredWidgetTreeOperations(); + --s_updateSuspendCount; +} + +static void moveWidgetToParentSoon(Widget* child, FrameView* parent) +{ + if (!s_updateSuspendCount) { + if (parent) + parent->addChild(child); + else if (toScrollView(child->parent())) + toScrollView(child->parent())->removeChild(child); + return; + } + widgetNewParentMap().set(child, parent); +} + HTMLFrameOwnerElement::HTMLFrameOwnerElement(const QualifiedName& tagName, Document& document) : HTMLElement(tagName, document) , m_contentFrame(0) + , m_widget(nullptr) , m_sandboxFlags(SandboxNone) { } @@ -54,7 +110,7 @@ RenderPart* HTMLFrameOwnerElement::renderPart() const void HTMLFrameOwnerElement::setContentFrame(Frame& frame) { // Make sure we will not end up with two frames referencing the same owner element. - ASSERT(!m_contentFrame || m_contentFrame->ownerElement() != this); + ASSERT(!m_contentFrame || m_contentFrame->owner() != this); // Disconnected frames should not be allowed to load. ASSERT(inDocument()); m_contentFrame = &frame; @@ -82,7 +138,8 @@ void HTMLFrameOwnerElement::disconnectContentFrame() // see if this behavior is really needed as Gecko does not allow this. if (Frame* frame = contentFrame()) { RefPtr<Frame> protect(frame); - frame->loader().frameDetached(); + if (frame->isLocalFrame()) + toLocalFrame(frame)->loader().frameDetached(); frame->disconnectOwnerElement(); } } @@ -95,10 +152,10 @@ HTMLFrameOwnerElement::~HTMLFrameOwnerElement() Document* HTMLFrameOwnerElement::contentDocument() const { - return m_contentFrame ? m_contentFrame->document() : 0; + return (m_contentFrame && m_contentFrame->isLocalFrame()) ? toLocalFrame(m_contentFrame)->document() : 0; } -DOMWindow* HTMLFrameOwnerElement::contentWindow() const +LocalDOMWindow* HTMLFrameOwnerElement::contentWindow() const { return m_contentFrame ? m_contentFrame->domWindow() : 0; } @@ -113,19 +170,59 @@ bool HTMLFrameOwnerElement::isKeyboardFocusable() const return m_contentFrame && HTMLElement::isKeyboardFocusable(); } -SVGDocument* HTMLFrameOwnerElement::getSVGDocument(ExceptionState& exceptionState) const +void HTMLFrameOwnerElement::dispatchLoad() +{ + dispatchEvent(Event::create(EventTypeNames::load)); +} + +Document* HTMLFrameOwnerElement::getSVGDocument(ExceptionState& exceptionState) const { Document* doc = contentDocument(); if (doc && doc->isSVGDocument()) - return toSVGDocument(doc); + return doc; return 0; } +void HTMLFrameOwnerElement::setWidget(PassRefPtr<Widget> widget) +{ + if (widget == m_widget) + return; + + if (m_widget) { + if (m_widget->parent()) + moveWidgetToParentSoon(m_widget.get(), 0); + m_widget = nullptr; + } + + m_widget = widget; + + RenderWidget* renderWidget = toRenderWidget(renderer()); + if (!renderWidget) + return; + + if (m_widget) { + renderWidget->updateOnWidgetChange(); + + ASSERT(document().view() == renderWidget->frameView()); + ASSERT(renderWidget->frameView()); + moveWidgetToParentSoon(m_widget.get(), renderWidget->frameView()); + } + + if (AXObjectCache* cache = document().existingAXObjectCache()) + cache->childrenChanged(renderWidget); +} + +Widget* HTMLFrameOwnerElement::ownedWidget() const +{ + return m_widget.get(); +} + bool HTMLFrameOwnerElement::loadOrRedirectSubframe(const KURL& url, const AtomicString& frameName, bool lockBackForwardList) { - RefPtr<Frame> parentFrame = document().frame(); - if (contentFrame()) { - contentFrame()->navigationScheduler().scheduleLocationChange(&document(), url.string(), document().outgoingReferrer(), lockBackForwardList); + RefPtr<LocalFrame> parentFrame = document().frame(); + // FIXME(kenrb): The necessary semantics for RemoteFrames have not been worked out yet, but this will likely need some logic to handle them. + if (contentFrame() && contentFrame()->isLocalFrame()) { + toLocalFrame(contentFrame())->navigationScheduler().scheduleLocationChange(&document(), url.string(), Referrer(document().outgoingReferrer(), document().referrerPolicy()), lockBackForwardList); return true; } @@ -138,7 +235,7 @@ bool HTMLFrameOwnerElement::loadOrRedirectSubframe(const KURL& url, const Atomic return false; String referrer = SecurityPolicy::generateReferrerHeader(document().referrerPolicy(), url, document().outgoingReferrer()); - RefPtr<Frame> childFrame = parentFrame->loader().client()->createFrame(url, frameName, referrer, this); + RefPtr<LocalFrame> childFrame = parentFrame->loader().client()->createFrame(url, frameName, Referrer(referrer, document().referrerPolicy()), this); if (!childFrame) { parentFrame->loader().checkCompleted(); @@ -153,10 +250,12 @@ bool HTMLFrameOwnerElement::loadOrRedirectSubframe(const KURL& url, const Atomic // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed. childFrame->loader().started(); - RenderObject* renderObject = renderer(); FrameView* view = childFrame->view(); + RenderObject* renderObject = renderer(); + // We need to test the existence of renderObject and its widget-ness, as + // failing to do so causes problems. if (renderObject && renderObject->isWidget() && view) - toRenderWidget(renderObject)->setWidget(view); + setWidget(view); // Some loads are performed synchronously (e.g., about:blank and loads // cancelled by returning a null ResourceRequest from requestFromDelegate). @@ -164,7 +263,7 @@ bool HTMLFrameOwnerElement::loadOrRedirectSubframe(const KURL& url, const Atomic // before we could connect the signals, so make sure to send the // completed() signal for the child by hand and mark the load as being // complete. - // FIXME: In this case the Frame will have finished loading before + // FIXME: In this case the LocalFrame will have finished loading before // it's being added to the child list. It would be a good idea to // create the child first, then invoke the loader separately. if (childFrame->loader().state() == FrameStateComplete && !childFrame->loader().policyDocumentLoader()) diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h index 834ac123c70..b9f4a7bbfe8 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h @@ -21,23 +21,25 @@ #ifndef HTMLFrameOwnerElement_h #define HTMLFrameOwnerElement_h +#include "core/dom/Document.h" +#include "core/frame/FrameOwner.h" #include "core/html/HTMLElement.h" #include "wtf/HashCountedSet.h" namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class ExceptionState; class Frame; class RenderPart; -class SVGDocument; +class Widget; -class HTMLFrameOwnerElement : public HTMLElement { +class HTMLFrameOwnerElement : public HTMLElement, public FrameOwner { public: virtual ~HTMLFrameOwnerElement(); Frame* contentFrame() const { return m_contentFrame; } - DOMWindow* contentWindow() const; + LocalDOMWindow* contentWindow() const; Document* contentDocument() const; void setContentFrame(Frame&); @@ -50,18 +52,27 @@ public: // RenderObject when using fallback content. RenderPart* renderPart() const; - SVGDocument* getSVGDocument(ExceptionState&) const; + Document* getSVGDocument(ExceptionState&) const; virtual ScrollbarMode scrollingMode() const { return ScrollbarAuto; } - SandboxFlags sandboxFlags() const { return m_sandboxFlags; } - virtual bool loadedNonEmptyDocument() const { return false; } virtual void didLoadNonEmptyDocument() { } virtual void renderFallbackContent() { } virtual bool isObjectElement() const { return false; } + void setWidget(PassRefPtr<Widget>); + Widget* ownedWidget() const; + + class UpdateSuspendScope { + public: + UpdateSuspendScope(); + ~UpdateSuspendScope(); + + private: + void performDeferredWidgetTreeOperations(); + }; protected: HTMLFrameOwnerElement(const QualifiedName& tagName, Document&); @@ -71,13 +82,19 @@ protected: private: virtual bool isKeyboardFocusable() const OVERRIDE; - virtual bool isFrameOwnerElement() const OVERRIDE { return true; } + virtual bool isFrameOwnerElement() const OVERRIDE FINAL { return true; } + + // FrameOwner overrides: + virtual bool isLocal() const { return true; } + virtual SandboxFlags sandboxFlags() const OVERRIDE { return m_sandboxFlags; } + virtual void dispatchLoad() OVERRIDE; Frame* m_contentFrame; + RefPtr<Widget> m_widget; SandboxFlags m_sandboxFlags; }; -DEFINE_NODE_TYPE_CASTS(HTMLFrameOwnerElement, isFrameOwnerElement()); +DEFINE_ELEMENT_TYPE_CASTS(HTMLFrameOwnerElement, isFrameOwnerElement()); class SubframeLoadingDisabler { public: @@ -94,6 +111,8 @@ public: static bool canLoadFrame(HTMLFrameOwnerElement& owner) { + if (owner.document().unloadStarted()) + return false; for (Node* node = &owner; node; node = node->parentOrShadowHostNode()) { if (disabledSubtreeRoots().contains(node)) return false; @@ -111,6 +130,8 @@ private: Node& m_root; }; +DEFINE_TYPE_CASTS(HTMLFrameOwnerElement, FrameOwner, owner, owner->isLocal(), owner.isLocal()); + } // namespace WebCore #endif // HTMLFrameOwnerElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp index cfa41341e71..0a00f463f19 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.cpp @@ -24,24 +24,23 @@ #include "config.h" #include "core/html/HTMLFrameSetElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/events/Event.h" #include "core/events/MouseEvent.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLFrameElement.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" #include "core/rendering/RenderFrameSet.h" namespace WebCore { using namespace HTMLNames; -HTMLFrameSetElement::HTMLFrameSetElement(Document& document) +inline HTMLFrameSetElement::HTMLFrameSetElement(Document& document) : HTMLElement(framesetTag, document) , m_border(6) , m_borderSet(false) @@ -54,10 +53,7 @@ HTMLFrameSetElement::HTMLFrameSetElement(Document& document) setHasCustomStyleCallbacks(); } -PassRefPtr<HTMLFrameSetElement> HTMLFrameSetElement::create(Document& document) -{ - return adoptRef(new HTMLFrameSetElement(document)); -} +DEFINE_NODE_FACTORY(HTMLFrameSetElement) bool HTMLFrameSetElement::isPresentationAttribute(const QualifiedName& name) const { @@ -79,12 +75,12 @@ void HTMLFrameSetElement::parseAttribute(const QualifiedName& name, const Atomic if (name == rowsAttr) { if (!value.isNull()) { m_rowLengths = parseListOfDimensions(value.string()); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } } else if (name == colsAttr) { if (!value.isNull()) { m_colLengths = parseListOfDimensions(value.string()); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } } else if (name == frameborderAttr) { if (!value.isNull()) { @@ -109,45 +105,45 @@ void HTMLFrameSetElement::parseAttribute(const QualifiedName& name, const Atomic } else if (name == bordercolorAttr) m_borderColorSet = !value.isEmpty(); else if (name == onloadAttr) - document().setWindowAttributeEventListener(EventTypeNames::load, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::load, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onbeforeunloadAttr) - document().setWindowAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::beforeunload, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onunloadAttr) - document().setWindowAttributeEventListener(EventTypeNames::unload, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::unload, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onpagehideAttr) - document().setWindowAttributeEventListener(EventTypeNames::pagehide, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::pagehide, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onpageshowAttr) - document().setWindowAttributeEventListener(EventTypeNames::pageshow, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::pageshow, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onblurAttr) - document().setWindowAttributeEventListener(EventTypeNames::blur, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::blur, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onerrorAttr) - document().setWindowAttributeEventListener(EventTypeNames::error, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::error, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onfocusAttr) - document().setWindowAttributeEventListener(EventTypeNames::focus, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::focus, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onfocusinAttr) - document().setWindowAttributeEventListener(EventTypeNames::focusin, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::focusin, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onfocusoutAttr) - document().setWindowAttributeEventListener(EventTypeNames::focusout, createAttributeEventListener(document().frame(), name, value)); -#if ENABLE(ORIENTATION_EVENTS) - else if (name == onorientationchangeAttr) - document().setWindowAttributeEventListener(EventTypeNames::orientationchange, createAttributeEventListener(document().frame(), name, value)); -#endif + document().setWindowAttributeEventListener(EventTypeNames::focusout, createAttributeEventListener(document().frame(), name, value, eventParameterName())); + else if (RuntimeEnabledFeatures::orientationEventEnabled() && name == onorientationchangeAttr) + document().setWindowAttributeEventListener(EventTypeNames::orientationchange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onhashchangeAttr) - document().setWindowAttributeEventListener(EventTypeNames::hashchange, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::hashchange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onmessageAttr) - document().setWindowAttributeEventListener(EventTypeNames::message, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::message, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onresizeAttr) - document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onscrollAttr) - document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onstorageAttr) - document().setWindowAttributeEventListener(EventTypeNames::storage, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::storage, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == ononlineAttr) - document().setWindowAttributeEventListener(EventTypeNames::online, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::online, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onofflineAttr) - document().setWindowAttributeEventListener(EventTypeNames::offline, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::offline, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else if (name == onpopstateAttr) - document().setWindowAttributeEventListener(EventTypeNames::popstate, createAttributeEventListener(document().frame(), name, value)); + document().setWindowAttributeEventListener(EventTypeNames::popstate, createAttributeEventListener(document().frame(), name, value, eventParameterName())); + else if (name == onlanguagechangeAttr) + document().setWindowAttributeEventListener(EventTypeNames::languagechange, createAttributeEventListener(document().frame(), name, value, eventParameterName())); else HTMLElement::parseAttribute(name, value); } @@ -171,21 +167,17 @@ void HTMLFrameSetElement::attach(const AttachContext& context) { // Inherit default settings from parent frameset // FIXME: This is not dynamic. - for (ContainerNode* node = parentNode(); node; node = node->parentNode()) { - if (node->hasTagName(framesetTag)) { - HTMLFrameSetElement* frameset = toHTMLFrameSetElement(node); - if (!m_frameborderSet) - m_frameborder = frameset->hasFrameBorder(); - if (m_frameborder) { - if (!m_borderSet) - m_border = frameset->border(); - if (!m_borderColorSet) - m_borderColorSet = frameset->hasBorderColor(); - } - if (!m_noresize) - m_noresize = frameset->noResize(); - break; + if (HTMLFrameSetElement* frameset = Traversal<HTMLFrameSetElement>::firstAncestor(*this)) { + if (!m_frameborderSet) + m_frameborder = frameset->hasFrameBorder(); + if (m_frameborder) { + if (!m_borderSet) + m_border = frameset->border(); + if (!m_borderColorSet) + m_borderColorSet = frameset->hasBorderColor(); } + if (!m_noresize) + m_noresize = frameset->noResize(); } HTMLElement::attach(context); @@ -214,17 +206,17 @@ Node::InsertionNotificationRequest HTMLFrameSetElement::insertedInto(ContainerNo void HTMLFrameSetElement::willRecalcStyle(StyleRecalcChange) { if (needsStyleRecalc() && renderer()) { - renderer()->setNeedsLayout(); + renderer()->setNeedsLayoutAndFullPaintInvalidation(); clearNeedsStyleRecalc(); } } -DOMWindow* HTMLFrameSetElement::anonymousNamedGetter(const AtomicString& name) +LocalDOMWindow* HTMLFrameSetElement::anonymousNamedGetter(const AtomicString& name) { - Node* frameNode = children()->namedItem(name); - if (!frameNode || !frameNode->hasTagName(HTMLNames::frameTag)) + Element* frameElement = children()->namedItem(name); + if (!isHTMLFrameElement(frameElement)) return 0; - Document* document = toHTMLFrameElement(frameNode)->contentDocument(); + Document* document = toHTMLFrameElement(frameElement)->contentDocument(); if (!document || !document->frame()) return 0; return document->domWindow(); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.h index 3138495cd2b..36ce2073a65 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.h @@ -24,6 +24,7 @@ #ifndef HTMLFrameSetElement_h #define HTMLFrameSetElement_h +#include "core/dom/Document.h" #include "core/html/HTMLDimension.h" #include "core/html/HTMLElement.h" @@ -31,7 +32,7 @@ namespace WebCore { class HTMLFrameSetElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLFrameSetElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLFrameSetElement); bool hasFrameBorder() const { return m_frameborder; } bool noResize() const { return m_noresize; } @@ -45,17 +46,15 @@ public: const Vector<HTMLDimension>& rowLengths() const { return m_rowLengths; } const Vector<HTMLDimension>& colLengths() const { return m_colLengths; } - DOMWindow* anonymousNamedGetter(const AtomicString&); + LocalDOMWindow* anonymousNamedGetter(const AtomicString&); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(blur); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(focus); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(load); + DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(resize); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(scroll); - -#if ENABLE(ORIENTATION_EVENTS) DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(orientationchange); -#endif private: explicit HTMLFrameSetElement(Document&); @@ -65,10 +64,10 @@ private: virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&); - virtual RenderObject* createRenderer(RenderStyle*); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void willRecalcStyle(StyleRecalcChange) OVERRIDE; @@ -86,8 +85,6 @@ private: bool m_noresize; }; -DEFINE_NODE_TYPE_CASTS(HTMLFrameSetElement, hasTagName(HTMLNames::framesetTag)); - } // namespace WebCore #endif // HTMLFrameSetElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.idl index 38a5f21424b..e7c6a243cf8 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLFrameSetElement.idl @@ -18,18 +18,21 @@ * Boston, MA 02110-1301, USA. */ -interface HTMLFrameSetElement : HTMLElement { - [ImplementedAs=anonymousNamedGetter, OverrideBuiltins, NotEnumerable] getter Window (DOMString name); +[ + OverrideBuiltins, +] interface HTMLFrameSetElement : HTMLElement { + [NotEnumerable] getter Window (DOMString name); [Reflect] attribute DOMString cols; [Reflect] attribute DOMString rows; - [Conditional=ORIENTATION_EVENTS] attribute EventHandler onorientationchange; + [RuntimeEnabled=OrientationEvent] attribute EventHandler onorientationchange; // Overrides of GlobalEventHandler attributes attribute EventHandler onblur; attribute EventHandler onerror; attribute EventHandler onfocus; attribute EventHandler onload; + attribute EventHandler onresize; attribute EventHandler onscroll; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.cpp index 7a6edf88eb5..9df1cad4af9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.cpp @@ -23,9 +23,9 @@ #include "config.h" #include "core/html/HTMLHRElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/CSSValuePool.h" #include "core/css/StylePropertySet.h" @@ -33,16 +33,13 @@ namespace WebCore { using namespace HTMLNames; -HTMLHRElement::HTMLHRElement(Document& document) +inline HTMLHRElement::HTMLHRElement(Document& document) : HTMLElement(hrTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLHRElement> HTMLHRElement::create(Document& document) -{ - return adoptRef(new HTMLHRElement(document)); -} +DEFINE_NODE_FACTORY(HTMLHRElement) bool HTMLHRElement::isPresentationAttribute(const QualifiedName& name) const { @@ -76,11 +73,13 @@ void HTMLHRElement::collectStyleForPresentationAttribute(const QualifiedName& na addHTMLColorToStyle(style, CSSPropertyBorderColor, value); addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value); } else if (name == noshadeAttr) { - addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid); + if (!hasAttribute(colorAttr)) { + addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid); - RefPtr<CSSPrimitiveValue> darkGrayValue = cssValuePool().createColorValue(Color::darkGray); - style->setProperty(CSSPropertyBorderColor, darkGrayValue); - style->setProperty(CSSPropertyBackgroundColor, darkGrayValue); + RefPtrWillBeRawPtr<CSSPrimitiveValue> darkGrayValue = cssValuePool().createColorValue(Color::darkGray); + style->setProperty(CSSPropertyBorderColor, darkGrayValue); + style->setProperty(CSSPropertyBackgroundColor, darkGrayValue); + } } else if (name == sizeAttr) { StringImpl* si = value.impl(); int size = si->toInt(); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.h index ec5bcb01442..79b2fc410b7 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHRElement.h @@ -29,9 +29,9 @@ namespace WebCore { class HTMLHRElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLHRElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLHRElement); - virtual bool canContainRangeEndPoint() const { return hasChildNodes(); } + virtual bool canContainRangeEndPoint() const OVERRIDE { return hasChildren(); } private: explicit HTMLHRElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.cpp index 8a25aa6a51d..494154590ac 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.cpp @@ -24,21 +24,18 @@ #include "config.h" #include "core/html/HTMLHeadElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" namespace WebCore { using namespace HTMLNames; -HTMLHeadElement::HTMLHeadElement(Document& document) +inline HTMLHeadElement::HTMLHeadElement(Document& document) : HTMLElement(headTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLHeadElement> HTMLHeadElement::create(Document& document) -{ - return adoptRef(new HTMLHeadElement(document)); -} +DEFINE_NODE_FACTORY(HTMLHeadElement) } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.h index 7abcac7df45..4a68f2e1e85 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.h @@ -30,14 +30,12 @@ namespace WebCore { class HTMLHeadElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLHeadElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLHeadElement); private: explicit HTMLHeadElement(Document&); }; -DEFINE_NODE_TYPE_CASTS(HTMLHeadElement, hasTagName(HTMLNames::headTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.idl index 738deb73d92..fb54cb5ab73 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHeadElement.idl @@ -18,5 +18,5 @@ */ interface HTMLHeadElement : HTMLElement { - [Reflect, TreatNullAs=NullString, MeasureAs=HTMLHeadElementProfile] attribute DOMString profile; + [Reflect, TreatNullAs=NullString, DeprecateAs=HTMLHeadElementProfile] attribute DOMString profile; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.cpp index 7e9c986e4b7..fb0431cd999 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.cpp @@ -31,9 +31,6 @@ inline HTMLHeadingElement::HTMLHeadingElement(const QualifiedName& tagName, Docu ScriptWrappable::init(this); } -PassRefPtr<HTMLHeadingElement> HTMLHeadingElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLHeadingElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLHeadingElement) } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.h index e99bac5867b..fb0a4d52761 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHeadingElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLHeadingElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLHeadingElement> create(const QualifiedName&, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLHeadingElement); private: HTMLHeadingElement(const QualifiedName&, Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.cpp index e4a56c917c4..991176eee99 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.cpp @@ -24,28 +24,25 @@ #include "config.h" #include "core/html/HTMLHtmlElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/DocumentParser.h" +#include "core/frame/LocalFrame.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/appcache/ApplicationCacheHost.h" -#include "core/frame/Frame.h" namespace WebCore { using namespace HTMLNames; -HTMLHtmlElement::HTMLHtmlElement(Document& document) +inline HTMLHtmlElement::HTMLHtmlElement(Document& document) : HTMLElement(htmlTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLHtmlElement> HTMLHtmlElement::create(Document& document) -{ - return adoptRef(new HTMLHtmlElement(document)); -} +DEFINE_NODE_FACTORY(HTMLHtmlElement) bool HTMLHtmlElement::isURLAttribute(const Attribute& attribute) const { @@ -65,7 +62,7 @@ void HTMLHtmlElement::insertedByParser() if (!documentLoader) return; - const AtomicString& manifest = getAttribute(manifestAttr); + const AtomicString& manifest = fastGetAttribute(manifestAttr); if (manifest.isEmpty()) documentLoader->applicationCacheHost()->selectCacheWithoutManifest(); else diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.h index 4976aac0c8c..77f43061f74 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.h @@ -30,7 +30,7 @@ namespace WebCore { class HTMLHtmlElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLHtmlElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLHtmlElement); void insertedByParser(); @@ -40,18 +40,6 @@ private: virtual bool isURLAttribute(const Attribute&) const OVERRIDE; }; -inline bool isHTMLHtmlElement(const Node* node) -{ - return node->hasTagName(HTMLNames::htmlTag); -} - -inline bool isHTMLHtmlElement(const Element* element) -{ - return element->hasTagName(HTMLNames::htmlTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLHtmlElement, hasTagName(HTMLNames::htmlTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.idl index 3e329da57d1..3099de60b2d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLHtmlElement.idl @@ -19,5 +19,4 @@ interface HTMLHtmlElement : HTMLElement { [Reflect] attribute DOMString version; - [Reflect, TreatNullAs=NullString, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds, MeasureAs=HTMLHtmlElementManifest] attribute DOMString manifest; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp index 016fba4ec0e..b447e52765a 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp @@ -25,8 +25,8 @@ #include "config.h" #include "core/html/HTMLIFrameElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLDocument.h" #include "core/rendering/RenderIFrame.h" @@ -39,17 +39,13 @@ inline HTMLIFrameElement::HTMLIFrameElement(Document& document) , m_didLoadNonEmptyDocument(false) { ScriptWrappable::init(this); - setHasCustomStyleCallbacks(); } -PassRefPtr<HTMLIFrameElement> HTMLIFrameElement::create(Document& document) -{ - return adoptRef(new HTMLIFrameElement(document)); -} +DEFINE_NODE_FACTORY(HTMLIFrameElement) bool HTMLIFrameElement::isPresentationAttribute(const QualifiedName& name) const { - if (name == widthAttr || name == heightAttr || name == alignAttr || name == frameborderAttr || name == seamlessAttr) + if (name == widthAttr || name == heightAttr || name == alignAttr || name == frameborderAttr) return true; return HTMLFrameElementBase::isPresentationAttribute(name); } @@ -63,7 +59,7 @@ void HTMLIFrameElement::collectStyleForPresentationAttribute(const QualifiedName else if (name == alignAttr) applyAlignmentAttributeToStyle(value, style); else if (name == frameborderAttr) { - // Frame border doesn't really match the HTML4 spec definition for iframes. It simply adds + // LocalFrame border doesn't really match the HTML4 spec definition for iframes. It simply adds // a presentational hint that the border should be off if set to zero. if (!value.toInt()) { // Add a rule that nulls out our border width. @@ -87,12 +83,9 @@ void HTMLIFrameElement::parseAttribute(const QualifiedName& name, const AtomicSt setSandboxFlags(value.isNull() ? SandboxNone : parseSandboxPolicy(value, invalidTokens)); if (!invalidTokens.isNull()) document().addConsoleMessage(OtherMessageSource, ErrorMessageLevel, "Error while parsing the 'sandbox' attribute: " + invalidTokens); - } else if (name == seamlessAttr) { - // If we're adding or removing the seamless attribute, we need to force the content document to recalculate its StyleResolver. - if (contentDocument()) - contentDocument()->styleResolverChanged(RecalcStyleDeferred); - } else + } else { HTMLFrameElementBase::parseAttribute(name, value); + } } bool HTMLIFrameElement::rendererIsNeeded(const RenderStyle& style) @@ -120,20 +113,6 @@ void HTMLIFrameElement::removedFrom(ContainerNode* insertionPoint) toHTMLDocument(document()).removeExtraNamedItem(m_name); } -bool HTMLIFrameElement::shouldDisplaySeamlessly() const -{ - return contentDocument() && contentDocument()->shouldDisplaySeamlesslyWithParent(); -} - -void HTMLIFrameElement::didRecalcStyle(StyleRecalcChange styleChange) -{ - if (!shouldDisplaySeamlessly()) - return; - Document* childDocument = contentDocument(); - if (shouldRecalcStyle(styleChange, childDocument)) - contentDocument()->recalcStyle(styleChange); -} - bool HTMLIFrameElement::isInteractiveContent() const { return true; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.h index eab2678af2c..9017d774a22 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.h @@ -30,9 +30,7 @@ namespace WebCore { class HTMLIFrameElement FINAL : public HTMLFrameElementBase { public: - static PassRefPtr<HTMLIFrameElement> create(Document&); - - bool shouldDisplaySeamlessly() const; + DECLARE_NODE_FACTORY(HTMLIFrameElement); private: explicit HTMLIFrameElement(Document&); @@ -44,10 +42,8 @@ private: virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&); - virtual RenderObject* createRenderer(RenderStyle*); - - virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE; + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual bool loadedNonEmptyDocument() const OVERRIDE { return m_didLoadNonEmptyDocument; } virtual void didLoadNonEmptyDocument() OVERRIDE { m_didLoadNonEmptyDocument = true; } @@ -57,8 +53,6 @@ private: bool m_didLoadNonEmptyDocument; }; -DEFINE_NODE_TYPE_CASTS(HTMLIFrameElement, hasTagName(HTMLNames::iframeTag)); - } // namespace WebCore #endif // HTMLIFrameElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl index d8a8a8eb700..90c3a7a77f9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLIFrameElement.idl @@ -27,9 +27,8 @@ interface HTMLIFrameElement : HTMLElement { [Reflect, TreatNullAs=NullString] attribute DOMString marginWidth; [Reflect] attribute DOMString name; [Reflect, TreatNullAs=NullString] attribute DOMString sandbox; - [Reflect, RuntimeEnabled=SeamlessIFrames] attribute boolean seamless; [Reflect] attribute DOMString scrolling; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly, LogPreviousValue] attribute DOMString src; [Reflect] attribute DOMString srcdoc; [Reflect] attribute DOMString width; @@ -39,5 +38,7 @@ interface HTMLIFrameElement : HTMLElement { // Extensions readonly attribute Window contentWindow; - [CheckSecurity=Node, RaisesException] SVGDocument getSVGDocument(); + [CheckSecurity=Node, RaisesException] Document getSVGDocument(); + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.cpp index d7d8c971b57..cd7063cdcf0 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.cpp @@ -23,60 +23,84 @@ #include "config.h" #include "core/html/HTMLImageElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" +#include "core/MediaTypeNames.h" +#include "core/css/MediaQueryMatcher.h" +#include "core/css/MediaValuesCached.h" +#include "core/css/parser/SizesAttributeParser.h" #include "core/dom/Attribute.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/fetch/ImageResource.h" #include "core/html/HTMLAnchorElement.h" +#include "core/html/HTMLCanvasElement.h" #include "core/html/HTMLFormElement.h" +#include "core/html/HTMLSourceElement.h" +#include "core/html/canvas/CanvasRenderingContext.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/parser/HTMLSrcsetParser.h" #include "core/rendering/RenderImage.h" - -using namespace std; +#include "platform/MIMETypeRegistry.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { using namespace HTMLNames; -HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form) +HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bool createdByParser) : HTMLElement(imgTag, document) - , m_imageLoader(this) - , m_form(form) + , m_imageLoader(HTMLImageLoader::create(this)) , m_compositeOperator(CompositeSourceOver) , m_imageDevicePixelRatio(1.0f) + , m_formWasSetByParser(false) + , m_elementCreatedByParser(createdByParser) { ScriptWrappable::init(this); - if (form) - form->registerImgElement(this); + if (form && form->inDocument()) { +#if ENABLE(OILPAN) + m_form = form; +#else + m_form = form->createWeakPtr(); +#endif + m_formWasSetByParser = true; + m_form->associate(*this); + m_form->didAssociateByParser(); + } } -PassRefPtr<HTMLImageElement> HTMLImageElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::create(Document& document) { - return adoptRef(new HTMLImageElement(document)); + return adoptRefWillBeNoop(new HTMLImageElement(document)); } -PassRefPtr<HTMLImageElement> HTMLImageElement::create(Document& document, HTMLFormElement* form) +PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::create(Document& document, HTMLFormElement* form, bool createdByParser) { - return adoptRef(new HTMLImageElement(document, form)); + return adoptRefWillBeNoop(new HTMLImageElement(document, form, createdByParser)); } HTMLImageElement::~HTMLImageElement() { +#if !ENABLE(OILPAN) if (m_form) - m_form->removeImgElement(this); + m_form->disassociate(*this); +#endif +} + +void HTMLImageElement::trace(Visitor* visitor) +{ + visitor->trace(m_imageLoader); + visitor->trace(m_form); + HTMLElement::trace(visitor); } -PassRefPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document& document, int width, int height) +PassRefPtrWillBeRawPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document& document, int width, int height) { - RefPtr<HTMLImageElement> image = adoptRef(new HTMLImageElement(document)); + RefPtrWillBeRawPtr<HTMLImageElement> image = adoptRefWillBeNoop(new HTMLImageElement(document)); if (width) image->setWidth(width); if (height) image->setHeight(height); + image->m_elementCreatedByParser = false; return image.release(); } @@ -116,7 +140,49 @@ const AtomicString HTMLImageElement::imageSourceURL() const HTMLFormElement* HTMLImageElement::formOwner() const { - return findFormAncestor(); + return m_form.get(); +} + +void HTMLImageElement::formRemovedFromTree(const Node& formRoot) +{ + ASSERT(m_form); + if (highestAncestorOrSelf() != formRoot) + resetFormOwner(); +} + +void HTMLImageElement::resetFormOwner() +{ + m_formWasSetByParser = false; + HTMLFormElement* nearestForm = findFormAncestor(); + if (m_form) { + if (nearestForm == m_form.get()) + return; + m_form->disassociate(*this); + } + if (nearestForm) { +#if ENABLE(OILPAN) + m_form = nearestForm; +#else + m_form = nearestForm->createWeakPtr(); +#endif + m_form->associate(*this); + } else { +#if ENABLE(OILPAN) + m_form = nullptr; +#else + m_form = WeakPtr<HTMLFormElement>(); +#endif + } +} + +void HTMLImageElement::setBestFitURLAndDPRFromImageCandidate(const ImageCandidate& candidate) +{ + m_bestFitImageURL = candidate.url(); + float candidateDensity = candidate.density(); + if (candidateDensity >= 0) + m_imageDevicePixelRatio = 1.0 / candidateDensity; + if (renderer() && renderer()->isImage()) + toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRatio); } void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicString& value) @@ -124,29 +190,18 @@ void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr if (name == altAttr) { if (renderer() && renderer()->isImage()) toRenderImage(renderer())->updateAltText(); - } else if (name == srcAttr || name == srcsetAttr) { - if (RuntimeEnabledFeatures::srcsetEnabled()) { - ImageCandidate candidate = bestFitSourceForImageAttributes(document().devicePixelRatio(), fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr)); - m_bestFitImageURL = candidate.toString(); - float candidateScaleFactor = candidate.scaleFactor(); - if (candidateScaleFactor > 0) - m_imageDevicePixelRatio = 1 / candidateScaleFactor; - if (renderer() && renderer()->isImage()) - toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRatio); - } - m_imageLoader.updateFromElementIgnoringPreviousError(); - } - else if (name == usemapAttr) + } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { + selectSourceURL(UpdateIgnorePreviousError); + } else if (name == usemapAttr) { setIsLink(!value.isNull()); - else if (name == onbeforeloadAttr) - setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value)); - else if (name == compositeAttr) { + } else if (name == compositeAttr) { // FIXME: images don't support blend modes in their compositing attribute. blink::WebBlendMode blendOp = blink::WebBlendModeNormal; if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp)) m_compositeOperator = CompositeSourceOver; - } else + } else { HTMLElement::parseAttribute(name, value); + } } const AtomicString& HTMLImageElement::altText() const @@ -154,10 +209,54 @@ const AtomicString& HTMLImageElement::altText() const // lets figure out the alt text.. magic stuff // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen // also heavily discussed by Hixie on bugzilla - if (!getAttribute(altAttr).isNull()) - return getAttribute(altAttr); + const AtomicString& alt = fastGetAttribute(altAttr); + if (!alt.isNull()) + return alt; // fall back to title attribute - return getAttribute(titleAttr); + return fastGetAttribute(titleAttr); +} + +static bool supportedImageType(const String& type) +{ + return MIMETypeRegistry::isSupportedImageResourceMIMEType(type); +} + +// http://picture.responsiveimages.org/#update-source-set +ImageCandidate HTMLImageElement::findBestFitImageFromPictureParent() +{ + ASSERT(isMainThread()); + Node* parent = parentNode(); + if (!parent || !isHTMLPictureElement(*parent)) + return ImageCandidate(); + for (Node* child = parent->firstChild(); child; child = child->nextSibling()) { + if (child == this) + return ImageCandidate(); + + if (!isHTMLSourceElement(*child)) + continue; + + HTMLSourceElement* source = toHTMLSourceElement(child); + String srcset = source->fastGetAttribute(srcsetAttr); + if (srcset.isEmpty()) + continue; + String type = source->fastGetAttribute(typeAttr); + if (!type.isEmpty() && !supportedImageType(type)) + continue; + + String media = source->fastGetAttribute(mediaAttr); + if (!media.isEmpty()) { + RefPtrWillBeRawPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(media); + if (!document().mediaQueryMatcher().evaluate(mediaQueries.get())) + continue; + } + + unsigned effectiveSize = SizesAttributeParser::findEffectiveSize(source->fastGetAttribute(sizesAttr), MediaValuesCached::create(document())); + ImageCandidate candidate = bestFitSourceForSrcsetAttribute(document().devicePixelRatio(), effectiveSize, source->fastGetAttribute(srcsetAttr)); + if (candidate.isEmpty()) + continue; + return candidate; + } + return ImageCandidate(); } RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) @@ -183,7 +282,7 @@ void HTMLImageElement::attach(const AttachContext& context) { HTMLElement::attach(context); - if (renderer() && renderer()->isImage() && !m_imageLoader.hasPendingBeforeLoadEvent()) { + if (renderer() && renderer()->isImage()) { RenderImage* renderImage = toRenderImage(renderer()); RenderImageResource* renderImageResource = renderImage->imageResource(); if (renderImageResource->hasImage()) @@ -191,41 +290,40 @@ void HTMLImageElement::attach(const AttachContext& context) // If we have no image at all because we have no src attribute, set // image height and width for the alt text instead. - if (!m_imageLoader.image() && !renderImageResource->cachedImage()) + if (!imageLoader().image() && !renderImageResource->cachedImage()) renderImage->setImageSizeForAltText(); else - renderImageResource->setImageResource(m_imageLoader.image()); + renderImageResource->setImageResource(imageLoader().image()); } } Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode* insertionPoint) { - // m_form can be non-null if it was set in constructor. - if (m_form && insertionPoint->highestAncestor() != m_form->highestAncestor()) { - m_form->removeImgElement(this); - m_form = 0; - } + if (!m_formWasSetByParser || insertionPoint->highestAncestorOrSelf() != m_form->highestAncestorOrSelf()) + resetFormOwner(); - if (!m_form) { - m_form = findFormAncestor(); - if (m_form) - m_form->registerImgElement(this); + bool imageWasModified = false; + if (RuntimeEnabledFeatures::pictureEnabled()) { + ImageCandidate candidate = findBestFitImageFromPictureParent(); + if (!candidate.isEmpty()) { + setBestFitURLAndDPRFromImageCandidate(candidate); + imageWasModified = true; + } } // If we have been inserted from a renderer-less document, // our loader may have not fetched the image, so do it now. - if (insertionPoint->inDocument() && !m_imageLoader.image()) - m_imageLoader.updateFromElement(); + if ((insertionPoint->inDocument() && !imageLoader().image()) || imageWasModified) + imageLoader().updateFromElement(m_elementCreatedByParser ? ImageLoader::ForceLoadImmediately : ImageLoader::LoadNormally); return HTMLElement::insertedInto(insertionPoint); } void HTMLImageElement::removedFrom(ContainerNode* insertionPoint) { - if (m_form) - m_form->removeImgElement(this); - m_form = 0; + if (!m_form || m_form->highestAncestorOrSelf() != highestAncestorOrSelf()) + resetFormOwner(); HTMLElement::removedFrom(insertionPoint); } @@ -239,8 +337,8 @@ int HTMLImageElement::width(bool ignorePendingStylesheets) return width; // if the image is available, use its width - if (m_imageLoader.image()) - return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).width(); + if (imageLoader().image()) + return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f).width(); } if (ignorePendingStylesheets) @@ -262,8 +360,8 @@ int HTMLImageElement::height(bool ignorePendingStylesheets) return height; // if the image is available, use its height - if (m_imageLoader.image()) - return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).height(); + if (imageLoader().image()) + return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f).height(); } if (ignorePendingStylesheets) @@ -277,18 +375,30 @@ int HTMLImageElement::height(bool ignorePendingStylesheets) int HTMLImageElement::naturalWidth() const { - if (!m_imageLoader.image()) + if (!imageLoader().image()) return 0; - return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).width(); + return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f).width(); } int HTMLImageElement::naturalHeight() const { - if (!m_imageLoader.image()) + if (!imageLoader().image()) return 0; - return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).height(); + return imageLoader().image()->imageSizeForRenderer(renderer(), 1.0f).height(); +} + +const String& HTMLImageElement::currentSrc() const +{ + // http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#dom-img-currentsrc + // The currentSrc IDL attribute must return the img element's current request's current URL. + // Initially, the pending request turns into current request when it is either available or broken. + // We use the image's dimensions as a proxy to it being in any of these states. + if (!imageLoader().image() || !imageLoader().image()->image() || !imageLoader().image()->image()->width()) + return emptyAtom; + + return imageLoader().image()->url().string(); } bool HTMLImageElement::isURLAttribute(const Attribute& attribute) const @@ -300,9 +410,19 @@ bool HTMLImageElement::isURLAttribute(const Attribute& attribute) const || HTMLElement::isURLAttribute(attribute); } +bool HTMLImageElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == srcAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLImageElement::subResourceAttributeName() const +{ + return srcAttr; +} + const AtomicString& HTMLImageElement::alt() const { - return getAttribute(altAttr); + return fastGetAttribute(altAttr); } bool HTMLImageElement::draggable() const @@ -355,21 +475,12 @@ int HTMLImageElement::y() const bool HTMLImageElement::complete() const { - return m_imageLoader.imageComplete(); -} - -void HTMLImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, src()); - // FIXME: What about when the usemap attribute begins with "#"? - addSubresourceURL(urls, document().completeURL(getAttribute(usemapAttr))); + return imageLoader().imageComplete(); } void HTMLImageElement::didMoveToNewDocument(Document& oldDocument) { - m_imageLoader.elementDidMoveToNewDocument(); + imageLoader().elementDidMoveToNewDocument(); HTMLElement::didMoveToNewDocument(oldDocument); } @@ -389,10 +500,10 @@ bool HTMLImageElement::isServerMap() const Image* HTMLImageElement::imageContents() { - if (!m_imageLoader.imageComplete()) + if (!imageLoader().imageComplete()) return 0; - return m_imageLoader.image()->image(); + return imageLoader().image()->image(); } bool HTMLImageElement::isInteractiveContent() const @@ -400,4 +511,86 @@ bool HTMLImageElement::isInteractiveContent() const return fastHasAttribute(usemapAttr); } +PassRefPtr<Image> HTMLImageElement::getSourceImageForCanvas(SourceImageMode, SourceImageStatus* status) const +{ + if (!complete() || !cachedImage()) { + *status = IncompleteSourceImageStatus; + return nullptr; + } + + if (cachedImage()->errorOccurred()) { + *status = UndecodableSourceImageStatus; + return nullptr; + } + + RefPtr<Image> sourceImage = cachedImage()->imageForRenderer(renderer()); + + // We need to synthesize a container size if a renderer is not available to provide one. + if (!renderer() && sourceImage->usesContainerSize()) + sourceImage->setContainerSize(sourceImage->size()); + + *status = NormalSourceImageStatus; + return sourceImage.release(); +} + +bool HTMLImageElement::wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const +{ + ImageResource* image = cachedImage(); + if (!image) + return false; + return !image->isAccessAllowed(destinationSecurityOrigin); +} + +FloatSize HTMLImageElement::sourceSize() const +{ + ImageResource* image = cachedImage(); + if (!image) + return FloatSize(); + LayoutSize size; + size = image->imageSizeForRenderer(renderer(), 1.0f); // FIXME: Not sure about this. + + return size; +} + +FloatSize HTMLImageElement::defaultDestinationSize() const +{ + ImageResource* image = cachedImage(); + if (!image) + return FloatSize(); + LayoutSize size; + size = image->imageSizeForRenderer(renderer(), 1.0f); // FIXME: Not sure about this. + if (renderer() && renderer()->isRenderImage() && image->image() && !image->image()->hasRelativeWidth()) + size.scale(toRenderImage(renderer())->imageDevicePixelRatio()); + return size; +} + +void HTMLImageElement::selectSourceURL(UpdateFromElementBehavior behavior) +{ + bool foundURL = false; + if (RuntimeEnabledFeatures::pictureEnabled()) { + ImageCandidate candidate = findBestFitImageFromPictureParent(); + if (!candidate.isEmpty()) { + setBestFitURLAndDPRFromImageCandidate(candidate); + foundURL = true; + } + } + + if (!foundURL) { + unsigned effectiveSize = 0; + if (RuntimeEnabledFeatures::pictureSizesEnabled()) + effectiveSize = SizesAttributeParser::findEffectiveSize(fastGetAttribute(sizesAttr), MediaValuesCached::create(document())); + ImageCandidate candidate = bestFitSourceForImageAttributes(document().devicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr)); + setBestFitURLAndDPRFromImageCandidate(candidate); + } + if (behavior == UpdateIgnorePreviousError) + imageLoader().updateFromElementIgnoringPreviousError(); + else + imageLoader().updateFromElement(); +} + +const KURL& HTMLImageElement::sourceURL() const +{ + return cachedImage()->response().url(); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.h index 05c5d81db3f..4328dceceba 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.h @@ -26,26 +26,30 @@ #include "core/html/HTMLElement.h" #include "core/html/HTMLImageLoader.h" +#include "core/html/canvas/CanvasImageSource.h" #include "platform/graphics/GraphicsTypes.h" +#include "wtf/WeakPtr.h" namespace WebCore { class HTMLFormElement; +class ImageCandidate; -class HTMLImageElement FINAL : public HTMLElement { - friend class HTMLFormElement; +class HTMLImageElement FINAL : public HTMLElement, public CanvasImageSource { public: - static PassRefPtr<HTMLImageElement> create(Document&); - static PassRefPtr<HTMLImageElement> create(Document&, HTMLFormElement*); - static PassRefPtr<HTMLImageElement> createForJSConstructor(Document&, int width, int height); + static PassRefPtrWillBeRawPtr<HTMLImageElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLImageElement> create(Document&, HTMLFormElement*, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLImageElement> createForJSConstructor(Document&, int width, int height); virtual ~HTMLImageElement(); + virtual void trace(Visitor*) OVERRIDE; int width(bool ignorePendingStylesheets = false); int height(bool ignorePendingStylesheets = false); int naturalWidth() const; int naturalHeight() const; + const String& currentSrc() const; bool isServerMap() const; @@ -53,10 +57,10 @@ public: CompositeOperator compositeOperator() const { return m_compositeOperator; } - ImageResource* cachedImage() const { return m_imageLoader.image(); } - void setImageResource(ImageResource* i) { m_imageLoader.setImage(i); }; + ImageResource* cachedImage() const { return imageLoader().image(); } + void setImageResource(ImageResource* i) { imageLoader().setImage(i); }; - void setLoadManually(bool loadManually) { m_imageLoader.setLoadManually(loadManually); } + void setLoadManually(bool loadManually) { imageLoader().setLoadManually(loadManually); } const AtomicString& alt() const; @@ -72,19 +76,33 @@ public: bool complete() const; - bool hasPendingActivity() const { return m_imageLoader.hasPendingActivity(); } + bool hasPendingActivity() const { return imageLoader().hasPendingActivity(); } - virtual bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE { return false; } - void addClient(ImageLoaderClient* client) { m_imageLoader.addClient(client); } - void removeClient(ImageLoaderClient* client) { m_imageLoader.removeClient(client); } + void addClient(ImageLoaderClient* client) { imageLoader().addClient(client); } + void removeClient(ImageLoaderClient* client) { imageLoader().removeClient(client); } virtual const AtomicString imageSourceURL() const OVERRIDE; virtual HTMLFormElement* formOwner() const OVERRIDE; - + void formRemovedFromTree(const Node& formRoot); + + // CanvasImageSourceImplementations + virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus*) const; + virtual bool wouldTaintOrigin(SecurityOrigin*) const OVERRIDE; + virtual FloatSize sourceSize() const OVERRIDE; + virtual FloatSize defaultDestinationSize() const OVERRIDE; + virtual const KURL& sourceURL() const OVERRIDE; + + enum UpdateFromElementBehavior { + UpdateNormal, + UpdateIgnorePreviousError + }; + // public so that HTMLPictureElement can call this as well. + void selectSourceURL(UpdateFromElementBehavior); protected: - explicit HTMLImageElement(Document&, HTMLFormElement* = 0); + explicit HTMLImageElement(Document&, HTMLFormElement* = 0, bool createdByParser = false); virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; @@ -96,15 +114,15 @@ private: virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; - virtual bool canStartSelection() const; + virtual bool canStartSelection() const OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; - virtual bool draggable() const; - - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; + virtual bool draggable() const OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; @@ -113,15 +131,24 @@ private: virtual bool isInteractiveContent() const OVERRIDE; virtual Image* imageContents() OVERRIDE; - HTMLImageLoader m_imageLoader; - HTMLFormElement* m_form; + void resetFormOwner(); + ImageCandidate findBestFitImageFromPictureParent(); + void setBestFitURLAndDPRFromImageCandidate(const ImageCandidate&); + HTMLImageLoader& imageLoader() const { return *m_imageLoader; } + + OwnPtrWillBeMember<HTMLImageLoader> m_imageLoader; +#if ENABLE(OILPAN) + Member<HTMLFormElement> m_form; +#else + WeakPtr<HTMLFormElement> m_form; +#endif CompositeOperator m_compositeOperator; AtomicString m_bestFitImageURL; float m_imageDevicePixelRatio; + bool m_formWasSetByParser; + bool m_elementCreatedByParser; }; -DEFINE_NODE_TYPE_CASTS(HTMLImageElement, hasTagName(HTMLNames::imgTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.idl index a5480236fd6..1914a5fad72 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLImageElement.idl @@ -21,28 +21,33 @@ // FIXME: NamedConstructor does not support optional without Default. Fortunately using Undefined makes // us use 0 which happens to be the default width and height anyway. [ - NamedConstructor=Image([Default=Undefined] optional long width, [Default=Undefined] optional long height) + NamedConstructor=Image([Default=Undefined] optional long width, [Default=Undefined] optional long height), + ConstructorCallWith=Document ] interface HTMLImageElement : HTMLElement { [Reflect] attribute DOMString align; [Reflect] attribute DOMString alt; [Reflect, TreatNullAs=NullString] attribute DOMString border; readonly attribute boolean complete; - [Reflect] attribute DOMString crossOrigin; + [Reflect, ReflectOnly="anonymous"|"use-credentials", ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString crossOrigin; attribute long height; [Reflect] attribute long hspace; [Reflect] attribute boolean isMap; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString longDesc; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString lowsrc; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString longDesc; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString lowsrc; [Reflect] attribute DOMString name; readonly attribute long naturalHeight; readonly attribute long naturalWidth; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; - [Reflect, RuntimeEnabled=Srcset] attribute DOMString srcset; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; + [Reflect] attribute DOMString srcset; + [Reflect, RuntimeEnabled=PictureSizes] attribute DOMString sizes; + [RuntimeEnabled=PictureSizes] readonly attribute DOMString currentSrc; [Reflect] attribute DOMString useMap; [Reflect] attribute long vspace; attribute long width; // Extensions - readonly attribute long x; - readonly attribute long y; + [MeasureAs=HTMLImageElementX] readonly attribute long x; + [MeasureAs=HTMLImageElementY] readonly attribute long y; + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp index 9a50c5f94db..1a909a71555 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp @@ -22,13 +22,12 @@ #include "config.h" #include "core/html/HTMLImageLoader.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Element.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/fetch/ImageResource.h" +#include "core/html/HTMLImageElement.h" #include "core/html/HTMLObjectElement.h" -#include "core/html/HTMLVideoElement.h" #include "core/html/parser/HTMLParserIdioms.h" namespace WebCore { @@ -45,12 +44,12 @@ HTMLImageLoader::~HTMLImageLoader() void HTMLImageLoader::dispatchLoadEvent() { // HTMLVideoElement uses this class to load the poster image, but it should not fire events for loading or failure. - if (isHTMLVideoElement(element())) + if (isHTMLVideoElement(*element())) return; bool errorOccurred = image()->errorOccurred(); - if (!errorOccurred && image()->response().httpStatusCode() >= 400) - errorOccurred = element()->hasTagName(HTMLNames::objectTag); // An <object> considers a 404 to be an error and should fire onerror. + if (isHTMLObjectElement(*element()) && !errorOccurred) + errorOccurred = (image()->response().httpStatusCode() >= 400); // An <object> considers a 404 to be an error and should fire onerror. element()->dispatchEvent(Event::create(errorOccurred ? EventTypeNames::error : EventTypeNames::load)); } @@ -63,12 +62,12 @@ void HTMLImageLoader::notifyFinished(Resource*) { ImageResource* cachedImage = image(); - RefPtr<Element> element = this->element(); + RefPtrWillBeRawPtr<Element> element = this->element(); ImageLoader::notifyFinished(cachedImage); bool loadError = cachedImage->errorOccurred() || cachedImage->response().httpStatusCode() >= 400; - if (loadError && element->hasTagName(HTMLNames::objectTag)) + if (loadError && isHTMLObjectElement(*element)) toHTMLObjectElement(element)->renderFallbackContent(); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.h b/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.h index 4ee2d8e419e..b9b93b8f9bd 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLImageLoader.h @@ -27,15 +27,21 @@ namespace WebCore { -class HTMLImageLoader : public ImageLoader { +class HTMLImageLoader FINAL : public ImageLoader { public: - HTMLImageLoader(Element*); + static PassOwnPtrWillBeRawPtr<HTMLImageLoader> create(Element* element) + { + return adoptPtrWillBeNoop(new HTMLImageLoader(element)); + } virtual ~HTMLImageLoader(); - virtual void dispatchLoadEvent(); - virtual String sourceURI(const AtomicString&) const; + virtual void dispatchLoadEvent() OVERRIDE; + virtual String sourceURI(const AtomicString&) const OVERRIDE; - virtual void notifyFinished(Resource*); + virtual void notifyFinished(Resource*) OVERRIDE; + +private: + explicit HTMLImageLoader(Element*); }; } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImport.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLImport.cpp deleted file mode 100644 index 8ac2d7d127c..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImport.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/html/HTMLImport.h" - -#include "core/dom/Document.h" - -namespace WebCore { - -Frame* HTMLImport::frame() -{ - return master()->frame(); -} - -Document* HTMLImport::master() -{ - return root()->document(); -} - -HTMLImportsController* HTMLImport::controller() -{ - return root()->toController(); -} - -void HTMLImport::appendChild(HTMLImport* child) -{ - if (isScriptBlocked()) - child->blockScript(); - if (lastChild() && !lastChild()->isDone()) - child->blockDocument(); - TreeNode<HTMLImport>::appendChild(child); - blockAfter(child); -} - -bool HTMLImport::areChilrenLoaded() const -{ - for (HTMLImport* child = firstChild(); child; child = child->next()) { - if (!child->isLoaded()) - return false; - } - - return true; -} - -bool HTMLImport::arePredecessorsLoaded() const -{ - HTMLImport* parent = this->parent(); - if (!parent) - return true; - - for (HTMLImport* sibling = parent->firstChild(); sibling; sibling = sibling->next()) { - if (sibling == this) - break; - if (!sibling->isLoaded()) - return false; - } - - return true; -} - -void HTMLImport::blockScript() -{ - m_scriptBlocked = true; -} - -void HTMLImport::unblockScript() -{ - bool wasBlocked = m_scriptBlocked; - m_scriptBlocked = false; - if (wasBlocked) - didUnblockScript(); -} - -void HTMLImport::didUnblockScript() -{ - ASSERT(!isDocumentBlocked()); - ASSERT(!isScriptBlocked()); - - if (!isProcessing()) - return; - - if (Document* document = this->document()) - document->didLoadAllImports(); -} - - -void HTMLImport::blockDocument() -{ - m_documentBlocked = true; -} - -void HTMLImport::unblockDocument() -{ - bool wasBlocked = m_documentBlocked; - m_documentBlocked = false; - if (wasBlocked) - didUnblockDocument(); -} - -void HTMLImport::didUnblockDocument() -{ - ASSERT(!isDocumentBlocked()); - ASSERT(isScriptBlocked()); -} - -inline bool HTMLImport::needsBlockingDocument() const -{ - ASSERT(isDocumentBlocked()); - HTMLImport* elder = previous(); - return (elder && !elder->isDone()); -} - -bool HTMLImport::unblock(HTMLImport* import) -{ - ASSERT(import->arePredecessorsLoaded()); - ASSERT(import->isScriptBlocked() || import->areChilrenLoaded()); - - if (import->isDocumentBlocked() && import->needsBlockingDocument()) - return false; - import->unblockDocument(); - - if (import->isScriptBlocked()) { - for (HTMLImport* child = import->firstChild(); child; child = child->next()) { - if (!unblock(child)) - return false; - } - } - - import->unblockScript(); - return import->isLoaded(); -} - -void HTMLImport::block(HTMLImport* import) -{ - for (HTMLImport* child = import; child; child = traverseNext(child, import)) - child->blockScript(); -} - -void HTMLImport::blockAfter(HTMLImport* child) -{ - ASSERT(child->parent() == this); - - for (HTMLImport* sibling = lastChild(); sibling; sibling = sibling->previous()) { - if (sibling == child) - break; - HTMLImport::block(sibling); - } - - this->blockScript(); - - if (HTMLImport* parent = this->parent()) - parent->blockAfter(this); -} - -bool HTMLImport::isMaster(Document* document) -{ - if (!document->import()) - return true; - return (document->import()->master() == document); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImport.h b/chromium/third_party/WebKit/Source/core/html/HTMLImport.h deleted file mode 100644 index 2c80c9775e9..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImport.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HTMLImport_h -#define HTMLImport_h - -#include "wtf/TreeNode.h" -#include "wtf/Vector.h" - -namespace WebCore { - -class Frame; -class Document; -class Frame; -class HTMLImportChild; -class HTMLImportRoot; -class HTMLImportsController; -class KURL; - -// -// # Basic Data Structure and Algorithms of HTML Imports implemenation. -// -// ## The Import Tree -// -// HTML Imports form a tree: -// -// * The root of the tree is HTMLImportsController, which is owned by the master -// document as a DocumentSupplement. HTMLImportsController has an abstract class called -// HTMLImportRoot to deal with cycler dependency. -// -// * The non-root nodes are HTMLImportChild, which is owned by LinkStyle, that is owned by HTMLLinkElement. -// LinkStyle is wired into HTMLImportChild by implementing HTMLImportChildClient interface -// -// * Both HTMLImportsController and HTMLImportChild are derived from HTMLImport superclass -// that models the tree data structure using WTF::TreeNode and provides a set of -// virtual functions. -// -// HTMLImportsController also owns all loaders in the tree and manages their lifetime through it. -// One assumption is that the tree is append-only and nodes are never inserted in the middle of the tree nor removed. -// -// -// HTMLImport <|- HTMLImportRoot <|- HTMLImportsController <- Document -// * -// | -// <|- HTMLImportChild <- LinkStyle <- HTMLLinkElement -// -// -// # Import Sharing and HTMLImportLoader -// -// The HTML Imports spec calls for de-dup mechanism to share already loaded imports. -// To implement this, the actual loading machinery is split out from HTMLImportChild to -// HTMLImportLoader, and each loader shares HTMLImportLoader with other loader if the URL is same. -// Check around HTMLImportsController::findLink() for more detail. -// -// Note that HTMLImportLoader provides HTMLImportLoaderClient to hook it up. -// As it can be shared, HTMLImportLoader supports multiple clients. -// -// HTMLImportChild (1)-->(*) HTMLImportLoader -// -// -// # Script Blocking -// -// The HTML parser blocks on <script> when preceding <link>s aren't finish loading imports. -// Each HTMLImport instance tracks such a blocking state, that is called "script-blocked" -// or HTMLImport::isScriptBlocked(). -// -// ## Blocking Imports -// -// Each imports can become being script-blocked when new imports are added to the import tree. -// For example, the parser of a parent import is blocked when new child import is given. -// See HTMLImport::appendChild() to see how it is handled. Note that this blocking-ness is -// transitive. HTMLImport::blockAfter() flips the flags iteratively to fullfill this transitivity. -// -// ## Unblocking Imports -// -// The blocking state can change when one of the imports finish loading. The Document notices it through -// HTMLImportRoot::blockerGone(). The blockerGone() triggers HTMLImport::unblockScript(), which traverses -// whole import tree and find unblock-able imports and unblock them. -// Unblocked imported documents are notified through Document::didLoadAllImports() so that -// it can resume its parser. -// -// # Document Blocking -// -// There is another type of blocking state that is called -// "document-blocked". If the import is document-blocked, it cannot -// create its own document object because sharable imported document -// can appear later. The spec defines the loading order of the -// import: The earlier one in the import-tree order should win and -// later ones should share earlier one. -// -// The "document-blocked" state keeps the tree node from loading its -// import until all preceding imports are ready t respect the -// order. Note that the node may fetch the bytes from the URL -// speculatively, even though it doesn't process it. -// -// The node is "document-unblocked" when there are unfinished, -// preceeding import loading. Unblocking attempt for -// "document-blocked" happens at the same timing as unblocking -// "script-blocked". -// - -// The superclass of HTMLImportsController and HTMLImportChild -// This represents the import tree data structure. -class HTMLImport : public TreeNode<HTMLImport> { -public: - static bool unblock(HTMLImport*); - static bool isMaster(Document*); - - virtual ~HTMLImport() { } - - Frame* frame(); - Document* master(); - HTMLImportsController* controller(); - - bool isLoaded() const { return !isScriptBlocked() && !isProcessing(); } - bool isScriptBlocked() const { return m_scriptBlocked; } - bool isDocumentBlocked() const { return m_documentBlocked; } - bool isBlocked() const { return m_scriptBlocked || m_documentBlocked; } - - void appendChild(HTMLImport*); - - virtual HTMLImportRoot* root() = 0; - virtual Document* document() const = 0; - virtual void wasDetachedFromDocument() = 0; - virtual void didFinishParsing() = 0; - virtual bool isProcessing() const = 0; - virtual bool isDone() const = 0; - -protected: - HTMLImport() - : m_scriptBlocked(false) - , m_documentBlocked(false) - { } - - virtual void didUnblockDocument(); - -private: - static void block(HTMLImport*); - - void blockAfter(HTMLImport* child); - void blockScript(); - void unblockScript(); - void didUnblockScript(); - - void blockDocument(); - void unblockDocument(); - - bool needsBlockingDocument() const; - bool arePredecessorsLoaded() const; - bool areChilrenLoaded() const; - - bool m_scriptBlocked; // If any of decendants or predecessors is in processing, the parser blocks on <script>. - bool m_documentBlocked; // If its predecessor is not done yet, the document creation is blocked. -}; - -// An abstract class to decouple its sublcass HTMLImportsController. -class HTMLImportRoot : public HTMLImport { -public: - virtual void blockerGone() = 0; - virtual HTMLImportsController* toController() = 0; - virtual HTMLImportChild* findLinkFor(const KURL&, HTMLImport* excluding = 0) const = 0; -}; - -} // namespace WebCore - -#endif // HTMLImport_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportChild.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLImportChild.cpp deleted file mode 100644 index 52445f355ea..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportChild.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/html/HTMLImportChild.h" - -#include "core/dom/Document.h" -#include "core/html/HTMLImportChildClient.h" -#include "core/html/HTMLImportLoader.h" - -namespace WebCore { - -HTMLImportChild::HTMLImportChild(const KURL& url, HTMLImportChildClient* client) - : m_url(url) - , m_client(client) -{ -} - -HTMLImportChild::~HTMLImportChild() -{ - // importDestroyed() should be called before the destruction. - ASSERT(!m_loader); -} - -void HTMLImportChild::wasAlreadyLoadedAs(HTMLImportChild* found) -{ - ASSERT(!m_loader); - ASSERT(m_client); - shareLoader(found); -} - -void HTMLImportChild::startLoading(const ResourcePtr<RawResource>& resource) -{ - ASSERT(!hasResource()); - ASSERT(!m_loader); - - HTMLImportResourceOwner::setResource(resource); - - // If the node is "document blocked", it cannot create HTMLImportLoader - // even if there is no sharable one found, as there is possibility that - // preceding imports load the sharable imports. - // In that case preceding one should win because it comes first in the tree order. - // See also didUnblockDocument(). - if (isDocumentBlocked()) - return; - - createLoader(); -} - -void HTMLImportChild::didFinish() -{ - if (m_client) - m_client->didFinish(); - clearResource(); - root()->blockerGone(); -} - -Document* HTMLImportChild::importedDocument() const -{ - if (!m_loader) - return 0; - return m_loader->importedDocument(); -} - -void HTMLImportChild::importDestroyed() -{ - if (parent()) - parent()->removeChild(this); - if (m_loader) { - m_loader->removeClient(this); - m_loader.clear(); - } -} - -HTMLImportRoot* HTMLImportChild::root() -{ - return parent() ? parent()->root() : 0; -} - -Document* HTMLImportChild::document() const -{ - return (m_loader && m_loader->isOwnedBy(this)) ? m_loader->document() : 0; -} - -void HTMLImportChild::wasDetachedFromDocument() -{ - // For imported documens this shouldn't be called because Document::m_import is - // cleared before Document is destroyed by HTMLImportChild::importDestroyed(). - ASSERT_NOT_REACHED(); -} - -void HTMLImportChild::didFinishParsing() -{ - ASSERT(m_loader->isOwnedBy(this)); - m_loader->didFinishParsing(); -} - -// Once all preceding imports are loaded and "document blocking" ends, -// HTMLImportChild can decide whether it should load the import by itself -// or it can share existing one. -void HTMLImportChild::didUnblockDocument() -{ - HTMLImport::didUnblockDocument(); - ASSERT(!isDocumentBlocked()); - ASSERT(!m_loader || !m_loader->isOwnedBy(this)); - - if (m_loader) - return; - if (HTMLImportChild* found = root()->findLinkFor(m_url, this)) - shareLoader(found); - else - createLoader(); -} - -void HTMLImportChild::createLoader() -{ - ASSERT(!isDocumentBlocked()); - ASSERT(!m_loader); - m_loader = HTMLImportLoader::create(this, parent()->document()->fetcher()); - m_loader->addClient(this); - m_loader->startLoading(resource()); -} - -void HTMLImportChild::shareLoader(HTMLImportChild* loader) -{ - ASSERT(!m_loader); - m_loader = loader->m_loader; - m_loader->addClient(this); - root()->blockerGone(); -} - -bool HTMLImportChild::isProcessing() const -{ - return m_loader && m_loader->isOwnedBy(this) && m_loader->isProcessing(); -} - -bool HTMLImportChild::isDone() const -{ - return m_loader && m_loader->isDone(); -} - -bool HTMLImportChild::isLoaded() const -{ - return m_loader->isLoaded(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportLoader.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLImportLoader.cpp deleted file mode 100644 index 5781c79791e..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportLoader.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/html/HTMLImportLoader.h" - -#include "core/dom/Document.h" -#include "core/dom/custom/CustomElementRegistrationContext.h" -#include "core/fetch/ResourceFetcher.h" -#include "core/frame/ContentSecurityPolicyResponseHeaders.h" -#include "core/html/HTMLDocument.h" -#include "core/html/HTMLImport.h" -#include "core/html/HTMLImportLoaderClient.h" -#include "core/loader/DocumentWriter.h" - - -namespace WebCore { - -PassRefPtr<HTMLImportLoader> HTMLImportLoader::create(HTMLImport* import, ResourceFetcher* fetcher) -{ - RefPtr<HTMLImportLoader> self = adoptRef(new HTMLImportLoader(import, fetcher)); - return self.release(); -} - -HTMLImportLoader::HTMLImportLoader(HTMLImport* import, ResourceFetcher* fetcher) - : m_import(import) - , m_fetcher(fetcher) - , m_state(StateLoading) -{ -} - -HTMLImportLoader::~HTMLImportLoader() -{ - if (m_importedDocument) - m_importedDocument->setImport(0); -} - -void HTMLImportLoader::startLoading(const ResourcePtr<RawResource>& resource) -{ - setResource(resource); -} - -void HTMLImportLoader::responseReceived(Resource* resource, const ResourceResponse& response) -{ - // Current canAccess() implementation isn't sufficient for catching cross-domain redirects: http://crbug.com/256976 - if (!m_fetcher->canAccess(resource, PotentiallyCORSEnabled)) { - setState(StateError); - return; - } - - setState(startWritingAndParsing(response)); -} - -void HTMLImportLoader::dataReceived(Resource*, const char* data, int length) -{ - RefPtr<DocumentWriter> protectingWriter(m_writer); - m_writer->addData(data, length); -} - -void HTMLImportLoader::notifyFinished(Resource* resource) -{ - // The writer instance indicates that a part of the document can be already loaded. - // We don't take such a case as an error because the partially-loaded document has been visible from script at this point. - if (resource->loadFailedOrCanceled() && !m_writer) { - setState(StateError); - return; - } - - setState(finishWriting()); -} - -HTMLImportLoader::State HTMLImportLoader::startWritingAndParsing(const ResourceResponse& response) -{ - DocumentInit init = DocumentInit(response.url(), 0, m_import->master()->contextDocument(), m_import) - .withRegistrationContext(m_import->master()->registrationContext()); - m_importedDocument = HTMLDocument::create(init); - m_importedDocument->initContentSecurityPolicy(ContentSecurityPolicyResponseHeaders(response)); - m_writer = DocumentWriter::create(m_importedDocument.get(), response.mimeType(), response.textEncodingName()); - - return StateLoading; -} - -HTMLImportLoader::State HTMLImportLoader::finishWriting() -{ - return StateWritten; -} - -HTMLImportLoader::State HTMLImportLoader::finishParsing() -{ - return StateReady; -} - -void HTMLImportLoader::setState(State state) -{ - if (m_state == state) - return; - - m_state = state; - - if (m_state == StateReady || m_state == StateError || m_state == StateWritten) { - if (RefPtr<DocumentWriter> writer = m_writer.release()) - writer->end(); - } - - // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here. - if (state == StateReady || state == StateError) - didFinish(); -} - -void HTMLImportLoader::didFinishParsing() -{ - setState(finishParsing()); -} - -Document* HTMLImportLoader::importedDocument() const -{ - if (m_state == StateError) - return 0; - return m_importedDocument.get(); -} - -bool HTMLImportLoader::isProcessing() const -{ - if (!m_importedDocument) - return !isDone(); - return m_importedDocument->parsing(); -} - -void HTMLImportLoader::didFinish() -{ - for (size_t i = 0; i < m_clients.size(); ++i) - m_clients[i]->didFinish(); - - clearResource(); - - ASSERT(!m_importedDocument || !m_importedDocument->parsing()); -} - -void HTMLImportLoader::addClient(HTMLImportLoaderClient* client) -{ - ASSERT(kNotFound == m_clients.find(client)); - m_clients.append(client); - if (isDone()) - client->didFinish(); -} - -void HTMLImportLoader::removeClient(HTMLImportLoaderClient* client) -{ - ASSERT(kNotFound != m_clients.find(client)); - m_clients.remove(m_clients.find(client)); -} - - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportResourceOwner.h b/chromium/third_party/WebKit/Source/core/html/HTMLImportResourceOwner.h deleted file mode 100644 index a8f5c52a193..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportResourceOwner.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HTMLImportResourceOwner_h -#define HTMLImportResourceOwner_h - -#include "core/fetch/RawResource.h" -#include "core/fetch/ResourcePtr.h" - -namespace WebCore { - -// A RawResourceClient implenetation which is responsible for -// owning RawResource object and adding/removing itself as a client -// according to its lifetime. -// -// FIXME: This could be geneeric ResouceOwner<ResourceType> once it is -// found that this class is broadly useful even outside HTMLImports module. -// -class HTMLImportResourceOwner : public RawResourceClient { -public: - HTMLImportResourceOwner(); - virtual ~HTMLImportResourceOwner(); - -protected: - const ResourcePtr<RawResource>& resource() const { return m_resource; } - - void setResource(const ResourcePtr<RawResource>&); - void clearResource(); - bool hasResource() const { return m_resource.get(); } - -private: - ResourcePtr<RawResource> m_resource; -}; - -} // namespace WebCore - -#endif // HTMLImportResourceOwner_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportsController.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLImportsController.cpp deleted file mode 100644 index bc057d50390..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportsController.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/html/HTMLImportsController.h" - -#include "core/dom/Document.h" -#include "core/fetch/ResourceFetcher.h" -#include "core/html/HTMLImportChild.h" -#include "core/html/HTMLImportChildClient.h" - -namespace WebCore { - -void HTMLImportsController::provideTo(Document* master) -{ - DEFINE_STATIC_LOCAL(const char*, name, ("HTMLImportsController")); - OwnPtr<HTMLImportsController> controller = adoptPtr(new HTMLImportsController(master)); - master->setImport(controller.get()); - DocumentSupplement::provideTo(master, name, controller.release()); -} - -HTMLImportsController::HTMLImportsController(Document* master) - : m_master(master) - , m_unblockTimer(this, &HTMLImportsController::unblockTimerFired) -{ -} - -HTMLImportsController::~HTMLImportsController() -{ - ASSERT(!m_master); -} - -void HTMLImportsController::clear() -{ - for (size_t i = 0; i < m_imports.size(); ++i) - m_imports[i]->importDestroyed(); - if (m_master) - m_master->setImport(0); - m_master = 0; -} - -HTMLImportChild* HTMLImportsController::createChild(const KURL& url, HTMLImport* parent, HTMLImportChildClient* client) -{ - OwnPtr<HTMLImportChild> loader = adoptPtr(new HTMLImportChild(url, client)); - parent->appendChild(loader.get()); - m_imports.append(loader.release()); - return m_imports.last().get(); -} - -HTMLImportChild* HTMLImportsController::load(HTMLImport* parent, HTMLImportChildClient* client, FetchRequest request) -{ - ASSERT(!request.url().isEmpty() && request.url().isValid()); - - if (HTMLImportChild* found = findLinkFor(request.url())) { - HTMLImportChild* child = createChild(request.url(), parent, client); - child->wasAlreadyLoadedAs(found); - return child; - } - - request.setCrossOriginAccessControl(securityOrigin(), DoNotAllowStoredCredentials); - ResourcePtr<RawResource> resource = parent->document()->fetcher()->fetchImport(request); - if (!resource) - return 0; - - HTMLImportChild* child = createChild(request.url(), parent, client); - // We set resource after the import tree is built since - // Resource::addClient() immediately calls back to feed the bytes when the resource is cached. - child->startLoading(resource); - - return child; -} - -void HTMLImportsController::showSecurityErrorMessage(const String& message) -{ - m_master->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); -} - -HTMLImportChild* HTMLImportsController::findLinkFor(const KURL& url, HTMLImport* excluding) const -{ - for (size_t i = 0; i < m_imports.size(); ++i) { - HTMLImportChild* candidate = m_imports[i].get(); - if (candidate != excluding && equalIgnoringFragmentIdentifier(candidate->url(), url) && !candidate->isDocumentBlocked()) - return candidate; - } - - return 0; -} - -SecurityOrigin* HTMLImportsController::securityOrigin() const -{ - return m_master->securityOrigin(); -} - -ResourceFetcher* HTMLImportsController::fetcher() const -{ - return m_master->fetcher(); -} - -HTMLImportRoot* HTMLImportsController::root() -{ - return this; -} - -Document* HTMLImportsController::document() const -{ - return m_master; -} - -void HTMLImportsController::wasDetachedFromDocument() -{ - clear(); -} - -void HTMLImportsController::didFinishParsing() -{ -} - -bool HTMLImportsController::isProcessing() const -{ - return m_master->parsing(); -} - -bool HTMLImportsController::isDone() const -{ - return !m_master->parsing(); -} - -void HTMLImportsController::blockerGone() -{ - scheduleUnblock(); -} - -void HTMLImportsController::scheduleUnblock() -{ - if (m_unblockTimer.isActive()) - return; - m_unblockTimer.startOneShot(0); -} - -void HTMLImportsController::unblockTimerFired(Timer<HTMLImportsController>*) -{ - do { - m_unblockTimer.stop(); - HTMLImport::unblock(this); - } while (m_unblockTimer.isActive()); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.cpp index 6d2e2e8eeb6..6cc8bddeacb 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.cpp @@ -29,12 +29,11 @@ #include "config.h" #include "core/html/HTMLInputElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" @@ -48,11 +47,12 @@ #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" #include "core/events/ScopedEventQueue.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/events/TouchEvent.h" #include "core/fileapi/FileList.h" -#include "core/frame/Frame.h" +#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLDataListElement.h" #include "core/html/HTMLFormElement.h" @@ -65,34 +65,33 @@ #include "core/html/forms/SearchInputType.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/shadow/ShadowElementNames.h" -#include "core/frame/UseCounter.h" #include "core/page/Chrome.h" #include "core/page/ChromeClient.h" -#include "core/page/Page.h" #include "core/rendering/RenderTextControlSingleLine.h" #include "core/rendering/RenderTheme.h" +#include "platform/ColorChooser.h" #include "platform/DateTimeChooser.h" #include "platform/Language.h" #include "platform/PlatformMouseEvent.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/text/PlatformLocale.h" #include "wtf/MathExtras.h" -using namespace std; - namespace WebCore { using namespace HTMLNames; -class ListAttributeTargetObserver : IdTargetObserver { - WTF_MAKE_FAST_ALLOCATED; +class ListAttributeTargetObserver : public IdTargetObserver { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<ListAttributeTargetObserver> create(const AtomicString& id, HTMLInputElement*); + static PassOwnPtrWillBeRawPtr<ListAttributeTargetObserver> create(const AtomicString& id, HTMLInputElement*); + virtual void trace(Visitor*) OVERRIDE; virtual void idTargetChanged() OVERRIDE; private: ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement*); - HTMLInputElement* m_element; + RawPtrWillBeMember<HTMLInputElement> m_element; }; // FIXME: According to HTML4, the length attribute's value can be arbitrarily @@ -111,7 +110,6 @@ HTMLInputElement::HTMLInputElement(Document& document, HTMLFormElement* form, bo , m_isChecked(false) , m_reflectsCheckedAttribute(true) , m_isIndeterminate(false) - , m_hasType(false) , m_isActivatedSubmit(false) , m_autocomplete(Uninitialized) , m_hasNonEmptyList(false) @@ -120,6 +118,8 @@ HTMLInputElement::HTMLInputElement(Document& document, HTMLFormElement* form, bo , m_valueAttributeWasUpdatedAfterParsing(false) , m_canReceiveDroppedFiles(false) , m_hasTouchEventHandler(false) + , m_shouldRevealPassword(false) + , m_needsToUpdateViewValue(true) , m_inputType(InputType::createText(*this)) , m_inputTypeView(m_inputType) { @@ -129,17 +129,26 @@ HTMLInputElement::HTMLInputElement(Document& document, HTMLFormElement* form, bo ScriptWrappable::init(this); } -PassRefPtr<HTMLInputElement> HTMLInputElement::create(Document& document, HTMLFormElement* form, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLInputElement> HTMLInputElement::create(Document& document, HTMLFormElement* form, bool createdByParser) { - RefPtr<HTMLInputElement> inputElement = adoptRef(new HTMLInputElement(document, form, createdByParser)); + RefPtrWillBeRawPtr<HTMLInputElement> inputElement = adoptRefWillBeNoop(new HTMLInputElement(document, form, createdByParser)); inputElement->ensureUserAgentShadowRoot(); return inputElement.release(); } +void HTMLInputElement::trace(Visitor* visitor) +{ + visitor->trace(m_inputType); + visitor->trace(m_inputTypeView); + visitor->trace(m_listAttributeTargetObserver); + visitor->trace(m_imageLoader); + HTMLTextFormControlElement::trace(visitor); +} + HTMLImageLoader* HTMLInputElement::imageLoader() { if (!m_imageLoader) - m_imageLoader = adoptPtr(new HTMLImageLoader(this)); + m_imageLoader = HTMLImageLoader::create(this); return m_imageLoader.get(); } @@ -148,10 +157,8 @@ void HTMLInputElement::didAddUserAgentShadowRoot(ShadowRoot&) m_inputTypeView->createShadowSubtree(); } -void HTMLInputElement::didAddShadowRoot(ShadowRoot& root) +void HTMLInputElement::willAddFirstAuthorShadowRoot() { - if (!root.isOldestAuthorShadowRoot()) - return; m_inputTypeView->destroyShadowSubtree(); m_inputTypeView = InputTypeView::create(*this); lazyReattachIfAttached(); @@ -159,15 +166,17 @@ void HTMLInputElement::didAddShadowRoot(ShadowRoot& root) HTMLInputElement::~HTMLInputElement() { +#if !ENABLE(OILPAN) // Need to remove form association while this is still an HTMLInputElement // so that virtual functions are called correctly. setForm(0); // setForm(0) may register this to a document-level radio button group. // We should unregister it to avoid accessing a deleted object. if (isRadioButton()) - document().formController()->checkedRadioButtons().removeButton(this); + document().formController().radioButtonGroupScope().removeButton(this); if (m_hasTouchEventHandler) - document().didRemoveEventTargetNode(this); + document().didRemoveTouchEventHandler(this); +#endif } const AtomicString& HTMLInputElement::name() const @@ -180,11 +189,6 @@ Vector<FileChooserFileInfo> HTMLInputElement::filesFromFileInputFormControlState return FileInputType::filesFromFormControlState(state); } -HTMLElement* HTMLInputElement::passwordGeneratorButtonElement() const -{ - return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementNames::passwordGenerator())); -} - bool HTMLInputElement::shouldAutocomplete() const { if (m_autocomplete != Uninitialized) @@ -339,7 +343,7 @@ bool HTMLInputElement::shouldShowFocusRingOnMouseFocus() const void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection) { if (isTextField()) { - if (!restorePreviousSelection || !hasCachedSelection()) + if (!restorePreviousSelection) select(); else restoreCachedSelection(); @@ -351,23 +355,28 @@ void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection) void HTMLInputElement::beginEditing() { + ASSERT(document().isActive()); + if (!document().isActive()) + return; + if (!isTextField()) return; - if (Frame* frame = document().frame()) - frame->spellChecker().didBeginEditing(this); + document().frame()->spellChecker().didBeginEditing(this); } void HTMLInputElement::endEditing() { + ASSERT(document().isActive()); + if (!document().isActive()) + return; + if (!isTextField()) return; - if (Frame* frame = document().frame()) { - frame->spellChecker().didEndEditingOnTextField(this); - if (Page* page = frame->page()) - page->chrome().client().didEndEditingOnTextField(*this); - } + LocalFrame* frame = document().frame(); + frame->spellChecker().didEndEditingOnTextField(this); + frame->host()->chrome().client().didEndEditingOnTextField(*this); } bool HTMLInputElement::shouldUseInputMethod() @@ -375,9 +384,9 @@ bool HTMLInputElement::shouldUseInputMethod() return m_inputType->shouldUseInputMethod(); } -void HTMLInputElement::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction) +void HTMLInputElement::handleFocusEvent(Element* oldFocusedElement, FocusType type) { - m_inputTypeView->handleFocusEvent(oldFocusedElement, direction); + m_inputTypeView->handleFocusEvent(oldFocusedElement, type); m_inputType->enableSecureTextInput(); } @@ -389,32 +398,17 @@ void HTMLInputElement::handleBlurEvent() void HTMLInputElement::setType(const AtomicString& type) { - // FIXME: This should just call setAttribute. No reason to handle the empty string specially. - // We should write a test case to show that setting to the empty string does not remove the - // attribute in other browsers and then fix this. Note that setting to null *does* remove - // the attribute and setAttribute implements that. - if (type.isEmpty()) - removeAttribute(typeAttr); - else - setAttribute(typeAttr, type); + setAttribute(typeAttr, type); } void HTMLInputElement::updateType() { const AtomicString& newTypeName = InputType::normalizeTypeName(fastGetAttribute(typeAttr)); - bool hadType = m_hasType; - m_hasType = true; - if (m_inputType->formControlType() == newTypeName) - return; - if (hadType && !InputType::canChangeFromAnotherType(newTypeName)) { - // Set the attribute back to the old value. - // Useful in case we were called from inside parseAttribute. - setAttribute(typeAttr, type()); + if (m_inputType->formControlType() == newTypeName) return; - } - RefPtr<InputType> newType = InputType::create(*this, newTypeName); + RefPtrWillBeRawPtr<InputType> newType = InputType::create(*this, newTypeName); removeFromRadioButtonGroup(); bool didStoreValue = m_inputType->storesValueSeparateFromAttribute(); @@ -453,16 +447,16 @@ void HTMLInputElement::updateType() } else updateValueIfNeeded(); - setFormControlValueMatchesRenderer(false); + m_needsToUpdateViewValue = true; m_inputTypeView->updateView(); if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) { ASSERT(elementData()); - if (const Attribute* height = getAttributeItem(heightAttr)) + if (const Attribute* height = findAttributeByName(heightAttr)) attributeChanged(heightAttr, height->value()); - if (const Attribute* width = getAttributeItem(widthAttr)) + if (const Attribute* width = findAttributeByName(widthAttr)) attributeChanged(widthAttr, width->value()); - if (const Attribute* align = getAttributeItem(alignAttr)) + if (const Attribute* align = findAttributeByName(alignAttr)) attributeChanged(alignAttr, align->value()); } @@ -514,11 +508,6 @@ bool HTMLInputElement::canStartSelection() const return HTMLTextFormControlElement::canStartSelection(); } -bool HTMLInputElement::canHaveSelection() const -{ - return isTextField(); -} - int HTMLInputElement::selectionStartForBinding(ExceptionState& exceptionState) const { if (!m_inputType->supportsSelectionAPI()) { @@ -648,9 +637,9 @@ void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicStr // We only need to setChanged if the form is looking at the default value right now. if (!hasDirtyValue()) { updatePlaceholderVisibility(false); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } - setFormControlValueMatchesRenderer(false); + m_needsToUpdateViewValue = true; setNeedsValidityCheck(); m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress; m_inputTypeView->valueAttributeChanged(); @@ -670,7 +659,7 @@ void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicStr int valueAsInteger = value.toInt(); m_size = valueAsInteger > 0 ? valueAsInteger : defaultSize; if (m_size != oldSize && renderer()) - renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } else if (name == altAttr) m_inputTypeView->altAttributeChanged(); else if (name == srcAttr) @@ -679,7 +668,7 @@ void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicStr // FIXME: ignore for the moment } else if (name == onsearchAttr) { // Search field and slider attributes all just cause updateFromElement to be called through style recalcing. - setAttributeEventListener(EventTypeNames::search, createAttributeEventListener(this, name, value)); + setAttributeEventListener(EventTypeNames::search, createAttributeEventListener(this, name, value, eventParameterName())); } else if (name == resultsAttr) { int oldResults = m_maxResults; m_maxResults = !value.isNull() ? std::min(value.toInt(), maxSavedResults) : -1; @@ -687,10 +676,10 @@ void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicStr // time to relayout for this change. if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0)) lazyReattachIfAttached(); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); UseCounter::count(document(), UseCounter::ResultsAttribute); } else if (name == incrementalAttr) { - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); UseCounter::count(document(), UseCounter::IncrementalAttribute); } else if (name == minAttr) { m_inputTypeView->minOrMaxAttributeChanged(); @@ -711,9 +700,6 @@ void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicStr } else if (name == patternAttr) { setNeedsValidityCheck(); UseCounter::count(document(), UseCounter::PatternAttribute); - } else if (name == precisionAttr) { - setNeedsValidityCheck(); - UseCounter::count(document(), UseCounter::PrecisionAttribute); } else if (name == disabledAttr) { HTMLTextFormControlElement::parseAttribute(name, value); m_inputTypeView->disabledAttributeChanged(); @@ -727,24 +713,7 @@ void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicStr listAttributeTargetChanged(); } UseCounter::count(document(), UseCounter::ListAttribute); - } -#if ENABLE(INPUT_SPEECH) - else if (name == webkitspeechAttr) { - if (RuntimeEnabledFeatures::speechInputEnabled() && m_inputType->shouldRespectSpeechAttribute()) { - // This renderer and its children have quite different layouts and - // styles depending on whether the speech button is visible or - // not. So we reset the whole thing and recreate to get the right - // styles and layout. - m_inputTypeView->destroyShadowSubtree(); - lazyReattachIfAttached(); - m_inputTypeView->createShadowSubtree(); - setFormControlValueMatchesRenderer(false); - } - UseCounter::count(document(), UseCounter::PrefixedSpeechAttribute); - } else if (name == onwebkitspeechchangeAttr) - setAttributeEventListener(EventTypeNames::webkitspeechchange, createAttributeEventListener(this, name, value)); -#endif - else if (name == webkitdirectoryAttr) { + } else if (name == webkitdirectoryAttr) { HTMLTextFormControlElement::parseAttribute(name, value); UseCounter::count(document(), UseCounter::PrefixedDirectoryAttribute); } @@ -777,9 +746,6 @@ RenderObject* HTMLInputElement::createRenderer(RenderStyle* style) void HTMLInputElement::attach(const AttachContext& context) { - if (!m_hasType) - updateType(); - HTMLTextFormControlElement::attach(context); m_inputTypeView->startResourceLoading(); @@ -792,7 +758,7 @@ void HTMLInputElement::attach(const AttachContext& context) void HTMLInputElement::detach(const AttachContext& context) { HTMLTextFormControlElement::detach(context); - setFormControlValueMatchesRenderer(false); + m_needsToUpdateViewValue = true; m_inputTypeView->closePopupView(); } @@ -804,9 +770,9 @@ String HTMLInputElement::altText() const String alt = fastGetAttribute(altAttr); // fall back to title attribute if (alt.isNull()) - alt = getAttribute(titleAttr); + alt = fastGetAttribute(titleAttr); if (alt.isNull()) - alt = getAttribute(valueAttr); + alt = fastGetAttribute(valueAttr); if (alt.isEmpty()) alt = locale().queryString(blink::WebLocalizedString::InputElementAltText); return alt; @@ -839,8 +805,10 @@ String HTMLInputElement::resultForDialogSubmit() void HTMLInputElement::resetImpl() { - if (m_inputType->storesValueSeparateFromAttribute()) + if (m_inputType->storesValueSeparateFromAttribute()) { setValue(String()); + setNeedsValidityCheck(); + } setChecked(hasAttribute(checkedAttr)); m_reflectsCheckedAttribute = true; @@ -861,14 +829,15 @@ void HTMLInputElement::setChecked(bool nowChecked, TextFieldEventBehavior eventB if (checked() == nowChecked) return; + RefPtrWillBeRawPtr<HTMLInputElement> protector(this); m_reflectsCheckedAttribute = false; m_isChecked = nowChecked; - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); - if (CheckedRadioButtons* buttons = checkedRadioButtons()) - buttons->updateCheckedState(this); + if (RadioButtonGroupScope* scope = radioButtonGroupScope()) + scope->updateCheckedState(this); if (renderer() && renderer()->style()->hasAppearance()) - RenderTheme::theme().stateChanged(renderer(), CheckedState); + RenderTheme::theme().stateChanged(renderer(), CheckedControlState); setNeedsValidityCheck(); @@ -887,6 +856,8 @@ void HTMLInputElement::setChecked(bool nowChecked, TextFieldEventBehavior eventB // definitely wrong in practice for these types of elements. if (eventBehavior != DispatchNoEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) { setTextAsOfLastFormControlChangeEvent(String()); + if (eventBehavior == DispatchInputAndChangeEvent) + dispatchFormControlInputEvent(); dispatchFormControlChangeEvent(); } @@ -903,7 +874,7 @@ void HTMLInputElement::setIndeterminate(bool newValue) didAffectSelector(AffectedSelectorIndeterminate); if (renderer() && renderer()->style()->hasAppearance()) - RenderTheme::theme().stateChanged(renderer(), CheckedState); + RenderTheme::theme().stateChanged(renderer(), CheckedControlState); } int HTMLInputElement::size() const @@ -927,7 +898,7 @@ void HTMLInputElement::copyNonAttributePropertiesFromElement(const Element& sour HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source); - setFormControlValueMatchesRenderer(false); + m_needsToUpdateViewValue = true; m_inputTypeView->updateView(); } @@ -973,9 +944,9 @@ void HTMLInputElement::setSuggestedValue(const String& value) { if (!m_inputType->canSetSuggestedValue()) return; - setFormControlValueMatchesRenderer(false); + m_needsToUpdateViewValue = true; m_suggestedValue = sanitizeValue(value); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); m_inputTypeView->updateView(); } @@ -983,7 +954,7 @@ void HTMLInputElement::setEditingValue(const String& value) { if (!renderer() || !isTextField()) return; - setInnerTextValue(value); + setInnerEditorValue(value); subtreeHasChanged(); unsigned max = value.length(); @@ -995,10 +966,16 @@ void HTMLInputElement::setEditingValue(const String& value) dispatchInputEvent(); } +void HTMLInputElement::setInnerEditorValue(const String& value) +{ + HTMLTextFormControlElement::setInnerEditorValue(value); + m_needsToUpdateViewValue = false; +} + void HTMLInputElement::setValue(const String& value, ExceptionState& exceptionState, TextFieldEventBehavior eventBehavior) { if (isFileUpload() && !value.isEmpty()) { - exceptionState.throwDOMException(InvalidStateError, "This input element accepts a filename, which may only be programatically set to the empty string."); + exceptionState.throwDOMException(InvalidStateError, "This input element accepts a filename, which may only be programmatically set to the empty string."); return; } setValue(value, eventBehavior); @@ -1009,13 +986,13 @@ void HTMLInputElement::setValue(const String& value, TextFieldEventBehavior even if (!m_inputType->canSetValue(value)) return; - RefPtr<HTMLInputElement> protector(this); + RefPtrWillBeRawPtr<HTMLInputElement> protector(this); EventQueueScope scope; String sanitizedValue = sanitizeValue(value); bool valueChanged = sanitizedValue != this->value(); setLastChangeWasNotUserEdit(); - setFormControlValueMatchesRenderer(false); + m_needsToUpdateViewValue = true; m_suggestedValue = String(); // Prevent TextFieldInputType::setValue from using the suggested value. m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior); @@ -1033,11 +1010,20 @@ void HTMLInputElement::setValueInternal(const String& sanitizedValue, TextFieldE { m_valueIfDirty = sanitizedValue; setNeedsValidityCheck(); + if (document().focusedElement() == this) + document().frameHost()->chrome().client().didUpdateTextOfFocusedElementByNonUserInput(); +} + +void HTMLInputElement::updateView() +{ + m_inputTypeView->updateView(); } -double HTMLInputElement::valueAsDate() const +double HTMLInputElement::valueAsDate(bool& isNull) const { - return m_inputType->valueAsDate(); + double date = m_inputType->valueAsDate(); + isNull = !std::isfinite(date); + return date; } void HTMLInputElement::setValueAsDate(double value, ExceptionState& exceptionState) @@ -1052,8 +1038,10 @@ double HTMLInputElement::valueAsNumber() const void HTMLInputElement::setValueAsNumber(double newValue, ExceptionState& exceptionState, TextFieldEventBehavior eventBehavior) { - if (!std::isfinite(newValue)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(newValue)); + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#dom-input-valueasnumber + // On setting, if the new value is infinite, then throw a TypeError exception. + if (std::isinf(newValue)) { + exceptionState.throwTypeError(ExceptionMessages::notAFiniteNumber(newValue)); return; } m_inputType->setValueAsDouble(newValue, eventBehavior, exceptionState); @@ -1070,8 +1058,7 @@ void HTMLInputElement::setValueFromRenderer(const String& value) ASSERT(value == sanitizeValue(value) || sanitizeValue(value).isEmpty()); m_valueIfDirty = value; - - setFormControlValueMatchesRenderer(true); + m_needsToUpdateViewValue = false; // Input event is fired by the Node::defaultEventHandler for editable controls. if (!isTextField()) @@ -1094,13 +1081,17 @@ void* HTMLInputElement::preDispatchEventHandler(Event* event) return 0; if (!event->isMouseEvent() || toMouseEvent(event)->button() != LeftButton) return 0; +#if ENABLE(OILPAN) + return m_inputTypeView->willDispatchClick(); +#else // FIXME: Check whether there are any cases where this actually ends up leaking. return m_inputTypeView->willDispatchClick().leakPtr(); +#endif } void HTMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch) { - OwnPtr<ClickHandlingState> state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch)); + OwnPtrWillBeRawPtr<ClickHandlingState> state = adoptPtrWillBeNoop(static_cast<ClickHandlingState*>(dataFromPreDispatch)); if (!state) return; m_inputTypeView->didDispatchClick(event, *state); @@ -1114,7 +1105,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) return; } - if (evt->isTouchEvent()) { + if (evt->isTouchEvent() && m_inputTypeView->hasTouchEventHandler()) { m_inputTypeView->handleTouchEvent(toTouchEvent(evt)); if (evt->defaultHandled()) return; @@ -1167,7 +1158,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) if (wasChangedSinceLastFormControlChangeEvent()) dispatchFormControlChangeEvent(); - RefPtr<HTMLFormElement> formForSubmission = m_inputTypeView->formForSubmission(); + RefPtrWillBeRawPtr<HTMLFormElement> formForSubmission = m_inputTypeView->formForSubmission(); // Form may never have been present, or may have been destroyed by code responding to the change event. if (formForSubmission) formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission()); @@ -1205,6 +1196,16 @@ bool HTMLInputElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == srcAttr || attribute.name() == formactionAttr || HTMLTextFormControlElement::isURLAttribute(attribute); } +bool HTMLInputElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return m_inputType->hasLegalLinkAttribute(name) || HTMLTextFormControlElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLInputElement::subResourceAttributeName() const +{ + return m_inputType->subResourceAttributeName(); +} + const AtomicString& HTMLInputElement::defaultValue() const { return fastGetAttribute(valueAttr); @@ -1269,11 +1270,6 @@ Vector<String> HTMLInputElement::acceptFileExtensions() return parseAcceptAttribute(fastGetAttribute(acceptAttr), isValidFileExtension); } -const AtomicString& HTMLInputElement::accept() const -{ - return fastGetAttribute(acceptAttr); -} - const AtomicString& HTMLInputElement::alt() const { return fastGetAttribute(altAttr); @@ -1320,7 +1316,7 @@ FileList* HTMLInputElement::files() return m_inputType->files(); } -void HTMLInputElement::setFiles(PassRefPtr<FileList> files) +void HTMLInputElement::setFiles(PassRefPtrWillBeRawPtr<FileList> files) { m_inputType->setFiles(files); } @@ -1349,11 +1345,6 @@ void HTMLInputElement::setCanReceiveDroppedFiles(bool canReceiveDroppedFiles) renderer()->updateFromElement(); } -String HTMLInputElement::visibleValue() const -{ - return m_inputType->visibleValue(); -} - String HTMLInputElement::sanitizeValue(const String& proposedValue) const { if (proposedValue.isNull()) @@ -1442,9 +1433,9 @@ void HTMLInputElement::didMoveToNewDocument(Document& oldDocument) imageLoader()->elementDidMoveToNewDocument(); if (isRadioButton()) - oldDocument.formController()->checkedRadioButtons().removeButton(this); + oldDocument.formController().radioButtonGroupScope().removeButton(this); if (m_hasTouchEventHandler) - oldDocument.didRemoveEventTargetNode(this); + oldDocument.didRemoveTouchEventHandler(this); if (m_hasTouchEventHandler) document().didAddTouchEventHandler(this); @@ -1452,11 +1443,10 @@ void HTMLInputElement::didMoveToNewDocument(Document& oldDocument) HTMLTextFormControlElement::didMoveToNewDocument(oldDocument); } -void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const +void HTMLInputElement::removeAllEventListeners() { - HTMLTextFormControlElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, src()); + HTMLTextFormControlElement::removeAllEventListeners(); + m_hasTouchEventHandler = false; } bool HTMLInputElement::recalcWillValidate() const @@ -1467,8 +1457,8 @@ bool HTMLInputElement::recalcWillValidate() const void HTMLInputElement::requiredAttributeChanged() { HTMLTextFormControlElement::requiredAttributeChanged(); - if (CheckedRadioButtons* buttons = checkedRadioButtons()) - buttons->requiredAttributeChanged(this); + if (RadioButtonGroupScope* scope = radioButtonGroupScope()) + scope->requiredAttributeChanged(this); m_inputTypeView->requiredAttributeChanged(); } @@ -1495,7 +1485,7 @@ HTMLDataListElement* HTMLInputElement::dataList() const Element* element = treeScope().getElementById(fastGetAttribute(listAttr)); if (!element) return 0; - if (!element->hasTagName(datalistTag)) + if (!isHTMLDataListElement(*element)) return 0; return toHTMLDataListElement(element); @@ -1506,7 +1496,7 @@ bool HTMLInputElement::hasValidDataListOptions() const HTMLDataListElement* dataList = this->dataList(); if (!dataList) return false; - RefPtr<HTMLCollection> options = dataList->options(); + RefPtrWillBeRawPtr<HTMLCollection> options = dataList->options(); for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); ++i) { if (isValidValue(option->value())) return true; @@ -1514,12 +1504,19 @@ bool HTMLInputElement::hasValidDataListOptions() const return false; } +void HTMLInputElement::setListAttributeTargetObserver(PassOwnPtrWillBeRawPtr<ListAttributeTargetObserver> newObserver) +{ + if (m_listAttributeTargetObserver) + m_listAttributeTargetObserver->unregister(); + m_listAttributeTargetObserver = newObserver; +} + void HTMLInputElement::resetListAttributeTargetObserver() { if (inDocument()) - m_listAttributeTargetObserver = ListAttributeTargetObserver::create(fastGetAttribute(listAttr), this); + setListAttributeTargetObserver(ListAttributeTargetObserver::create(fastGetAttribute(listAttr), this)); else - m_listAttributeTargetObserver = nullptr; + setListAttributeTargetObserver(nullptr); } void HTMLInputElement::listAttributeTargetChanged() @@ -1532,16 +1529,6 @@ bool HTMLInputElement::isSteppable() const return m_inputType->isSteppable(); } -#if ENABLE(INPUT_SPEECH) - -bool HTMLInputElement::isSpeechEnabled() const -{ - // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types. - return m_inputType->shouldRespectSpeechAttribute() && RuntimeEnabledFeatures::speechInputEnabled() && hasAttribute(webkitspeechAttr); -} - -#endif - bool HTMLInputElement::isTextButton() const { return m_inputType->isTextButton(); @@ -1577,11 +1564,6 @@ bool HTMLInputElement::isRangeControl() const return m_inputType->isRangeControl(); } -bool HTMLInputElement::isColorControl() const -{ - return m_inputType->isColorControl(); -} - bool HTMLInputElement::isText() const { return m_inputType->isTextType(); @@ -1607,11 +1589,6 @@ bool HTMLInputElement::isNumberField() const return m_inputType->isNumberField(); } -bool HTMLInputElement::isSubmitButton() const -{ - return m_inputType->isSubmitButton(); -} - bool HTMLInputElement::isTelephoneField() const { return m_inputType->isTelephoneField(); @@ -1669,7 +1646,7 @@ bool HTMLInputElement::supportsPlaceholder() const void HTMLInputElement::updatePlaceholderText() { - return m_inputType->updatePlaceholderText(); + return m_inputTypeView->updatePlaceholderText(); } void HTMLInputElement::parseMaxLengthAttribute(const AtomicString& value) @@ -1683,7 +1660,7 @@ void HTMLInputElement::parseMaxLengthAttribute(const AtomicString& value) m_maxLength = maxLength; if (oldMaxLength != maxLength) updateValueIfNeeded(); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); setNeedsValidityCheck(); } @@ -1705,61 +1682,42 @@ bool HTMLInputElement::shouldAppearIndeterminate() const return m_inputType->supportsIndeterminateAppearance() && indeterminate(); } -#if ENABLE(MEDIA_CAPTURE) -bool HTMLInputElement::capture() const -{ - if (!isFileUpload() || !fastHasAttribute(captureAttr)) - return false; - - // As per crbug.com/240252, emit a deprecation warning when the "capture" - // attribute is used as an enum. The spec has been updated and "capture" is - // supposed to be used as a boolean. - bool hasDeprecatedUsage = !fastGetAttribute(captureAttr).isNull(); - if (hasDeprecatedUsage) - UseCounter::countDeprecation(document(), UseCounter::CaptureAttributeAsEnum); - else - UseCounter::count(document(), UseCounter::CaptureAttributeAsEnum); - - return true; -} -#endif - bool HTMLInputElement::isInRequiredRadioButtonGroup() { ASSERT(isRadioButton()); - if (CheckedRadioButtons* buttons = checkedRadioButtons()) - return buttons->isInRequiredGroup(this); + if (RadioButtonGroupScope* scope = radioButtonGroupScope()) + return scope->isInRequiredGroup(this); return false; } HTMLInputElement* HTMLInputElement::checkedRadioButtonForGroup() const { - if (CheckedRadioButtons* buttons = checkedRadioButtons()) - return buttons->checkedButtonForGroup(name()); + if (RadioButtonGroupScope* scope = radioButtonGroupScope()) + return scope->checkedButtonForGroup(name()); return 0; } -CheckedRadioButtons* HTMLInputElement::checkedRadioButtons() const +RadioButtonGroupScope* HTMLInputElement::radioButtonGroupScope() const { if (!isRadioButton()) return 0; if (HTMLFormElement* formElement = form()) - return &formElement->checkedRadioButtons(); + return &formElement->radioButtonGroupScope(); if (inDocument()) - return &document().formController()->checkedRadioButtons(); + return &document().formController().radioButtonGroupScope(); return 0; } inline void HTMLInputElement::addToRadioButtonGroup() { - if (CheckedRadioButtons* buttons = checkedRadioButtons()) - buttons->addButton(this); + if (RadioButtonGroupScope* scope = radioButtonGroupScope()) + scope->addButton(this); } inline void HTMLInputElement::removeFromRadioButtonGroup() { - if (CheckedRadioButtons* buttons = checkedRadioButtons()) - buttons->removeButton(this); + if (RadioButtonGroupScope* scope = radioButtonGroupScope()) + scope->removeButton(this); } unsigned HTMLInputElement::height() const @@ -1782,9 +1740,9 @@ void HTMLInputElement::setWidth(unsigned width) setUnsignedIntegralAttribute(widthAttr, width); } -PassOwnPtr<ListAttributeTargetObserver> ListAttributeTargetObserver::create(const AtomicString& id, HTMLInputElement* element) +PassOwnPtrWillBeRawPtr<ListAttributeTargetObserver> ListAttributeTargetObserver::create(const AtomicString& id, HTMLInputElement* element) { - return adoptPtr(new ListAttributeTargetObserver(id, element)); + return adoptPtrWillBeNoop(new ListAttributeTargetObserver(id, element)); } ListAttributeTargetObserver::ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement* element) @@ -1793,6 +1751,12 @@ ListAttributeTargetObserver::ListAttributeTargetObserver(const AtomicString& id, { } +void ListAttributeTargetObserver::trace(Visitor* visitor) +{ + visitor->trace(m_element); + IdTargetObserver::trace(visitor); +} + void ListAttributeTargetObserver::idTargetChanged() { m_element->listAttributeTargetChanged(); @@ -1831,7 +1795,7 @@ bool HTMLInputElement::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters.locale = defaultLanguage(); else { AtomicString computedLocale = computeInheritedLanguage(); - parameters.locale = computedLocale.isEmpty() ? AtomicString(defaultLanguage()) : computedLocale; + parameters.locale = computedLocale.isEmpty() ? defaultLanguage() : computedLocale; } StepRange stepRange = createStepRange(RejectAny); @@ -1847,20 +1811,18 @@ bool HTMLInputElement::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters.currentValue = value(); parameters.doubleValue = m_inputType->valueAsDouble(); parameters.isAnchorElementRTL = computedStyle()->direction() == RTL; - if (RuntimeEnabledFeatures::dataListElementEnabled()) { - if (HTMLDataListElement* dataList = this->dataList()) { - RefPtr<HTMLCollection> options = dataList->options(); - for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); ++i) { - if (!isValidValue(option->value())) - continue; - DateTimeSuggestion suggestion; - suggestion.value = m_inputType->parseToNumber(option->value(), Decimal::nan()).toDouble(); - if (std::isnan(suggestion.value)) - continue; - suggestion.localizedValue = localizeValue(option->value()); - suggestion.label = option->value() == option->label() ? String() : option->label(); - parameters.suggestions.append(suggestion); - } + if (HTMLDataListElement* dataList = this->dataList()) { + RefPtrWillBeRawPtr<HTMLCollection> options = dataList->options(); + for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); ++i) { + if (!isValidValue(option->value())) + continue; + DateTimeSuggestion suggestion; + suggestion.value = m_inputType->parseToNumber(option->value(), Decimal::nan()).toDouble(); + if (std::isnan(suggestion.value)) + continue; + suggestion.localizedValue = localizeValue(option->value()); + suggestion.label = option->value() == option->label() ? String() : option->label(); + parameters.suggestions.append(suggestion); } } return true; @@ -1871,11 +1833,24 @@ bool HTMLInputElement::supportsInputModeAttribute() const return m_inputType->supportsInputModeAttribute(); } +void HTMLInputElement::setShouldRevealPassword(bool value) +{ + if (m_shouldRevealPassword == value) + return; + m_shouldRevealPassword = value; + lazyReattachIfAttached(); +} + bool HTMLInputElement::isInteractiveContent() const { return m_inputType->isInteractiveContent(); } +bool HTMLInputElement::supportsAutofocus() const +{ + return m_inputType->isInteractiveContent(); +} + #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) PassRefPtr<RenderStyle> HTMLInputElement::customStyleForRenderer() { @@ -1883,4 +1858,9 @@ PassRefPtr<RenderStyle> HTMLInputElement::customStyleForRenderer() } #endif +bool HTMLInputElement::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue) +{ + return m_inputType->shouldDispatchFormControlChangeEvent(oldValue, newValue); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.h index 4e61ec102c2..4bf5c86a1ec 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.h @@ -31,39 +31,39 @@ namespace WebCore { -class CheckedRadioButtons; class DragData; class ExceptionState; class FileList; class HTMLDataListElement; class HTMLImageLoader; class HTMLOptionElement; -class Icon; class InputType; class InputTypeView; class KURL; class ListAttributeTargetObserver; +class RadioButtonGroupScope; struct DateTimeChooserParameters; class HTMLInputElement : public HTMLTextFormControlElement { public: - static PassRefPtr<HTMLInputElement> create(Document&, HTMLFormElement*, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLInputElement> create(Document&, HTMLFormElement*, bool createdByParser); virtual ~HTMLInputElement(); + virtual void trace(Visitor*) OVERRIDE; DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitspeechchange); - virtual bool shouldAutocomplete() const; + virtual bool shouldAutocomplete() const OVERRIDE FINAL; // For ValidityState - virtual bool hasBadInput() const OVERRIDE; - virtual bool patternMismatch() const OVERRIDE; - virtual bool rangeUnderflow() const OVERRIDE; - virtual bool rangeOverflow() const; - virtual bool stepMismatch() const OVERRIDE; - virtual bool tooLong() const OVERRIDE; - virtual bool typeMismatch() const OVERRIDE; - virtual bool valueMissing() const OVERRIDE; - virtual String validationMessage() const OVERRIDE; + virtual bool hasBadInput() const OVERRIDE FINAL; + virtual bool patternMismatch() const OVERRIDE FINAL; + virtual bool rangeUnderflow() const OVERRIDE FINAL; + virtual bool rangeOverflow() const OVERRIDE FINAL; + virtual bool stepMismatch() const OVERRIDE FINAL; + virtual bool tooLong() const OVERRIDE FINAL; + virtual bool typeMismatch() const OVERRIDE FINAL; + virtual bool valueMissing() const OVERRIDE FINAL; + virtual String validationMessage() const OVERRIDE FINAL; // Returns the minimum value for type=date, number, or range. Don't call this for other types. double minimum() const; @@ -94,7 +94,6 @@ public: bool isPasswordField() const; bool isCheckbox() const; bool isRangeControl() const; - bool isColorControl() const; // FIXME: It's highly likely that any call site calling this function should instead // be using a different one. Many input elements behave like text fields, and in addition @@ -106,7 +105,6 @@ public: bool isFileUpload() const; bool isImageButton() const; bool isNumberField() const; - bool isSubmitButton() const; bool isTelephoneField() const; bool isURLField() const; bool isDateField() const; @@ -115,12 +113,6 @@ public: bool isTimeField() const; bool isWeekField() const; -#if ENABLE(INPUT_SPEECH) - bool isSpeechEnabled() const; -#endif - - HTMLElement* passwordGeneratorButtonElement() const; - bool checked() const { return m_isChecked; } void setChecked(bool, TextFieldEventBehavior = DispatchNoEvent); @@ -136,7 +128,7 @@ public: void setType(const AtomicString&); - String value() const; + virtual String value() const OVERRIDE; void setValue(const String&, ExceptionState&, TextFieldEventBehavior = DispatchNoEvent); void setValue(const String&, TextFieldEventBehavior = DispatchNoEvent); void setValueForUser(const String&); @@ -149,15 +141,12 @@ public: String localizeValue(const String&) const; - // The value which is drawn by a renderer. - String visibleValue() const; - const String& suggestedValue() const; void setSuggestedValue(const String&); void setEditingValue(const String&); - double valueAsDate() const; + double valueAsDate(bool& isNull) const; void setValueAsDate(double, ExceptionState&); double valueAsNumber() const; @@ -176,15 +165,16 @@ public: void setSelectionRangeForBinding(int start, int end, ExceptionState&); void setSelectionRangeForBinding(int start, int end, const String& direction, ExceptionState&); - virtual bool rendererIsNeeded(const RenderStyle&); - virtual RenderObject* createRenderer(RenderStyle*); - virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE FINAL; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual void detach(const AttachContext& = AttachContext()) OVERRIDE FINAL; + virtual void updateFocusAppearance(bool restorePreviousSelection) OVERRIDE FINAL; // FIXME: For isActivatedSubmit and setActivatedSubmit, we should use the NVI-idiom here by making // it private virtual in all classes and expose a public method in HTMLFormControlElement to call // the private virtual method. - virtual bool isActivatedSubmit() const; - virtual void setActivatedSubmit(bool flag); + virtual bool isActivatedSubmit() const OVERRIDE FINAL; + virtual void setActivatedSubmit(bool flag) OVERRIDE FINAL; String altText() const; @@ -195,7 +185,6 @@ public: Vector<String> acceptMIMETypes(); Vector<String> acceptFileExtensions(); - const AtomicString& accept() const; const AtomicString& alt() const; void setSize(unsigned); @@ -203,20 +192,19 @@ public: KURL src() const; - virtual int maxLength() const; + int maxLength() const; void setMaxLength(int, ExceptionState&); bool multiple() const; FileList* files(); - void setFiles(PassRefPtr<FileList>); + void setFiles(PassRefPtrWillBeRawPtr<FileList>); // Returns true if the given DragData has more than one dropped files. bool receiveDroppedFiles(const DragData*); String droppedFileSystemId(); - Icon* icon() const; // These functions are used for rendering the input active during a // drag-and-drop operation. bool canReceiveDroppedFiles() const; @@ -239,6 +227,9 @@ public: // Functions for InputType classes. void setValueInternal(const String&, TextFieldEventBehavior); bool valueAttributeWasUpdatedAfterParsing() const { return m_valueAttributeWasUpdatedAfterParsing; } + void updateView(); + bool needsToUpdateViewValue() const { return m_needsToUpdateViewValue; } + virtual void setInnerEditorValue(const String&) OVERRIDE; void cacheSelectionInResponseToSetValue(int caretOffset) { cacheSelection(caretOffset, caretOffset, SelectionHasNoDirection); } @@ -247,10 +238,6 @@ public: String defaultToolTip() const; -#if ENABLE(MEDIA_CAPTURE) - bool capture() const; -#endif - static const int maximumLength; unsigned height() const; @@ -258,20 +245,20 @@ public: void setHeight(unsigned); void setWidth(unsigned); - virtual void blur() OVERRIDE; + virtual void blur() OVERRIDE FINAL; void defaultBlur(); - virtual const AtomicString& name() const OVERRIDE; + virtual const AtomicString& name() const OVERRIDE FINAL; void beginEditing(); void endEditing(); static Vector<FileChooserFileInfo> filesFromFileInputFormControlState(const FormControlState&); - virtual bool matchesReadOnlyPseudoClass() const OVERRIDE; - virtual bool matchesReadWritePseudoClass() const OVERRIDE; - virtual void setRangeText(const String& replacement, ExceptionState&) OVERRIDE; - virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&) OVERRIDE; + virtual bool matchesReadOnlyPseudoClass() const OVERRIDE FINAL; + virtual bool matchesReadWritePseudoClass() const OVERRIDE FINAL; + virtual void setRangeText(const String& replacement, ExceptionState&) OVERRIDE FINAL; + virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&) OVERRIDE FINAL; bool hasImageLoader() const { return m_imageLoader; } HTMLImageLoader* imageLoader(); @@ -280,105 +267,109 @@ public: bool supportsInputModeAttribute() const; + void setShouldRevealPassword(bool value); + bool shouldRevealPassword() const { return m_shouldRevealPassword; } + protected: HTMLInputElement(Document&, HTMLFormElement*, bool createdByParser); - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; private: enum AutoCompleteSetting { Uninitialized, On, Off }; - virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE; - virtual void didAddShadowRoot(ShadowRoot&) OVERRIDE; + virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE FINAL; + virtual void willAddFirstAuthorShadowRoot() OVERRIDE FINAL; - virtual void willChangeForm() OVERRIDE; - virtual void didChangeForm() OVERRIDE; + virtual void willChangeForm() OVERRIDE FINAL; + virtual void didChangeForm() OVERRIDE FINAL; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; - virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; + virtual void removedFrom(ContainerNode*) OVERRIDE FINAL; + virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE FINAL; + virtual void removeAllEventListeners() OVERRIDE FINAL; - virtual bool hasCustomFocusLogic() const OVERRIDE; - virtual bool isKeyboardFocusable() const OVERRIDE; - virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE; - virtual bool isEnumeratable() const; - virtual bool isInteractiveContent() const OVERRIDE; - virtual bool supportLabels() const OVERRIDE; - virtual void updateFocusAppearance(bool restorePreviousSelection); - virtual bool shouldUseInputMethod(); + virtual bool hasCustomFocusLogic() const OVERRIDE FINAL; + virtual bool isKeyboardFocusable() const OVERRIDE FINAL; + virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE FINAL; + virtual bool isEnumeratable() const OVERRIDE FINAL; + virtual bool isInteractiveContent() const OVERRIDE FINAL; + virtual bool supportLabels() const OVERRIDE FINAL; + virtual bool shouldUseInputMethod() OVERRIDE FINAL; - virtual bool isTextFormControl() const { return isTextField(); } + virtual bool isTextFormControl() const OVERRIDE FINAL { return isTextField(); } - virtual bool canTriggerImplicitSubmission() const { return isTextField(); } + virtual bool canTriggerImplicitSubmission() const OVERRIDE FINAL { return isTextField(); } - virtual const AtomicString& formControlType() const; + virtual const AtomicString& formControlType() const OVERRIDE FINAL; - virtual bool shouldSaveAndRestoreFormControlState() const OVERRIDE; - virtual FormControlState saveFormControlState() const OVERRIDE; - virtual void restoreFormControlState(const FormControlState&) OVERRIDE; + virtual bool shouldSaveAndRestoreFormControlState() const OVERRIDE FINAL; + virtual FormControlState saveFormControlState() const OVERRIDE FINAL; + virtual void restoreFormControlState(const FormControlState&) OVERRIDE FINAL; - virtual bool canStartSelection() const; + virtual bool canStartSelection() const OVERRIDE FINAL; - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE FINAL; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; - virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; - virtual void finishParsingChildren(); - - virtual void copyNonAttributePropertiesFromElement(const Element&); + virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE FINAL; + virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE FINAL; + virtual void finishParsingChildren() OVERRIDE FINAL; - virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; + virtual void copyNonAttributePropertiesFromElement(const Element&) OVERRIDE FINAL; - virtual bool appendFormData(FormDataList&, bool) OVERRIDE; - virtual String resultForDialogSubmit() OVERRIDE; + virtual void attach(const AttachContext& = AttachContext()) OVERRIDE FINAL; - virtual bool canBeSuccessfulSubmitButton() const OVERRIDE; + virtual bool appendFormData(FormDataList&, bool) OVERRIDE FINAL; + virtual String resultForDialogSubmit() OVERRIDE FINAL; - virtual void resetImpl() OVERRIDE; + virtual bool canBeSuccessfulSubmitButton() const OVERRIDE FINAL; - virtual void* preDispatchEventHandler(Event*); - virtual void postDispatchEventHandler(Event*, void* dataFromPreDispatch); + virtual void resetImpl() OVERRIDE FINAL; + virtual bool supportsAutofocus() const OVERRIDE FINAL; - virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - virtual bool isInRange() const; - virtual bool isOutOfRange() const; + virtual void* preDispatchEventHandler(Event*) OVERRIDE FINAL; + virtual void postDispatchEventHandler(Event*, void* dataFromPreDispatch) OVERRIDE FINAL; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; + virtual bool isURLAttribute(const Attribute&) const OVERRIDE FINAL; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE FINAL; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE FINAL; + virtual bool isInRange() const OVERRIDE FINAL; + virtual bool isOutOfRange() const OVERRIDE FINAL; - bool supportsMaxLength() const { return isTextType(); } bool isTextType() const; bool tooLong(const String&, NeedsToCheckDirtyFlag) const; - virtual bool supportsPlaceholder() const; - virtual void updatePlaceholderText(); - virtual bool isEmptyValue() const OVERRIDE { return innerTextValue().isEmpty(); } - virtual bool isEmptySuggestedValue() const { return suggestedValue().isEmpty(); } - virtual void handleFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE; - virtual void handleBlurEvent(); + virtual bool supportsPlaceholder() const OVERRIDE FINAL; + virtual void updatePlaceholderText() OVERRIDE FINAL; + virtual bool isEmptyValue() const OVERRIDE FINAL { return innerEditorValue().isEmpty(); } + virtual bool isEmptySuggestedValue() const OVERRIDE FINAL { return suggestedValue().isEmpty(); } + virtual void handleFocusEvent(Element* oldFocusedElement, FocusType) OVERRIDE FINAL; + virtual void handleBlurEvent() OVERRIDE FINAL; - virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); } - virtual bool isRequiredFormControl() const; - virtual bool recalcWillValidate() const; - virtual void requiredAttributeChanged() OVERRIDE; + virtual bool isOptionalFormControl() const OVERRIDE FINAL { return !isRequiredFormControl(); } + virtual bool isRequiredFormControl() const OVERRIDE FINAL; + virtual bool recalcWillValidate() const OVERRIDE FINAL; + virtual void requiredAttributeChanged() OVERRIDE FINAL; void updateType(); - virtual void subtreeHasChanged(); + virtual void subtreeHasChanged() OVERRIDE FINAL; + void setListAttributeTargetObserver(PassOwnPtrWillBeRawPtr<ListAttributeTargetObserver>); void resetListAttributeTargetObserver(); void parseMaxLengthAttribute(const AtomicString&); void updateValueIfNeeded(); - bool canHaveSelection() const; - // Returns null if this isn't associated with any radio button group. - CheckedRadioButtons* checkedRadioButtons() const; + RadioButtonGroupScope* radioButtonGroupScope() const; void addToRadioButtonGroup(); void removeFromRadioButtonGroup(); #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE; #endif + virtual bool shouldDispatchFormControlChangeEvent(String&, String&) OVERRIDE; + AtomicString m_name; String m_valueIfDirty; String m_suggestedValue; @@ -388,7 +379,6 @@ private: bool m_isChecked : 1; bool m_reflectsCheckedAttribute : 1; bool m_isIndeterminate : 1; - bool m_hasType : 1; bool m_isActivatedSubmit : 1; unsigned m_autocomplete : 2; // AutoCompleteSetting bool m_hasNonEmptyList : 1; @@ -397,16 +387,16 @@ private: bool m_valueAttributeWasUpdatedAfterParsing : 1; bool m_canReceiveDroppedFiles : 1; bool m_hasTouchEventHandler : 1; - RefPtr<InputType> m_inputType; - RefPtr<InputTypeView> m_inputTypeView; + bool m_shouldRevealPassword : 1; + bool m_needsToUpdateViewValue : 1; + RefPtrWillBeMember<InputType> m_inputType; + RefPtrWillBeMember<InputTypeView> m_inputTypeView; // The ImageLoader must be owned by this element because the loader code assumes // that it lives as long as its owning element lives. If we move the loader into // the ImageInput object we may delete the loader while this element lives on. - OwnPtr<HTMLImageLoader> m_imageLoader; - OwnPtr<ListAttributeTargetObserver> m_listAttributeTargetObserver; + OwnPtrWillBeMember<HTMLImageLoader> m_imageLoader; + OwnPtrWillBeMember<ListAttributeTargetObserver> m_listAttributeTargetObserver; }; -DEFINE_NODE_TYPE_CASTS(HTMLInputElement, hasTagName(HTMLNames::inputTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.idl index 6c2fa4e818d..8f44cfb2c30 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLInputElement.idl @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#htmlinputelement + interface HTMLInputElement : HTMLElement { [Reflect] attribute DOMString accept; [Reflect] attribute DOMString align; @@ -33,7 +35,7 @@ interface HTMLInputElement : HTMLElement { // The 'files' attribute is intentionally not readonly. // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22682 attribute FileList files; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString formAction; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString formAction; [CustomElementCallbacks] attribute DOMString formEnctype; [CustomElementCallbacks] attribute DOMString formMethod; [Reflect] attribute boolean formNoValidate; @@ -41,7 +43,7 @@ interface HTMLInputElement : HTMLElement { [CustomElementCallbacks] attribute unsigned long height; attribute boolean indeterminate; [RuntimeEnabled=InputModeAttribute, Reflect] attribute DOMString inputMode; - [RuntimeEnabled=DataListElement] readonly attribute HTMLElement list; + readonly attribute HTMLElement list; [Reflect] attribute DOMString max; [RaisesException=Setter, CustomElementCallbacks] attribute long maxLength; [Reflect] attribute DOMString min; @@ -52,15 +54,15 @@ interface HTMLInputElement : HTMLElement { [Reflect] attribute boolean readOnly; [Reflect] attribute boolean required; [RaisesException=Setter, CustomElementCallbacks] attribute unsigned long size; // Changed string -> long -> unsigned long - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; [Reflect] attribute DOMString step; [CustomElementCallbacks] attribute DOMString type; // readonly dropped as part of DOM level 2 [CustomElementCallbacks] attribute DOMString defaultValue; [Reflect] attribute DOMString useMap; // See the discussion in https://bugs.webkit.org/show_bug.cgi?id=100085 [TreatNullAs=NullString, RaisesException=Setter, CustomElementCallbacks] attribute DOMString value; - [RaisesException=Setter, CustomElementCallbacks] attribute Date valueAsDate; - [RaisesException=Setter, CustomElementCallbacks] attribute double valueAsNumber; + [RaisesException=Setter, CustomElementCallbacks] attribute Date? valueAsDate; + [RaisesException=Setter, CustomElementCallbacks] attribute unrestricted double valueAsNumber; [RaisesException, CustomElementCallbacks] void stepUp(optional long n); [RaisesException, CustomElementCallbacks] void stepDown(optional long n); @@ -83,7 +85,7 @@ interface HTMLInputElement : HTMLElement { [RaisesException] void setRangeText(DOMString replacement, unsigned long start, unsigned long end, - [Default=NullString] optional DOMString selectionMode); + optional DOMString selectionMode = null); [RaisesException, ImplementedAs=setSelectionRangeForBinding] void setSelectionRange([Default=Undefined] optional long start, @@ -91,11 +93,8 @@ interface HTMLInputElement : HTMLElement { optional DOMString direction); // Non-standard attributes - [Reflect, RuntimeEnabled=DirectoryUpload] attribute boolean webkitdirectory; - [Reflect] attribute boolean incremental; - [Conditional=INPUT_SPEECH, Reflect, RuntimeEnabled=SpeechInput] attribute boolean webkitSpeech; - [Conditional=INPUT_SPEECH, Reflect, RuntimeEnabled=SpeechInput] attribute boolean webkitGrammar; - [Conditional=INPUT_SPEECH] attribute EventHandler onwebkitspeechchange; + [Reflect, MeasureAs=PrefixedDirectoryAttribute] attribute boolean webkitdirectory; + [Reflect, MeasureAs=IncrementalAttribute] attribute boolean incremental; // See http://www.w3.org/TR/html-media-capture/ [Conditional=MEDIA_CAPTURE, Reflect] attribute boolean capture; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.cpp index e6c80d009ae..231ee99672c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.cpp @@ -25,8 +25,8 @@ #include "config.h" #include "core/html/HTMLKeygenElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/Text.h" #include "core/dom/shadow/ShadowRoot.h" @@ -46,7 +46,13 @@ HTMLKeygenElement::HTMLKeygenElement(Document& document, HTMLFormElement* form) : HTMLFormControlElementWithState(keygenTag, document, form) { ScriptWrappable::init(this); - ensureUserAgentShadowRoot(); +} + +PassRefPtrWillBeRawPtr<HTMLKeygenElement> HTMLKeygenElement::create(Document& document, HTMLFormElement* form) +{ + RefPtrWillBeRawPtr<HTMLKeygenElement> keygen = adoptRefWillBeNoop(new HTMLKeygenElement(document, form)); + keygen->ensureUserAgentShadowRoot(); + return keygen.release(); } void HTMLKeygenElement::didAddUserAgentShadowRoot(ShadowRoot& root) @@ -57,10 +63,10 @@ void HTMLKeygenElement::didAddUserAgentShadowRoot(ShadowRoot& root) getSupportedKeySizes(locale(), keys); // Create a select element with one option element for each key size. - RefPtr<HTMLSelectElement> select = HTMLSelectElement::create(document()); - select->setPseudo(keygenSelectPseudoId); + RefPtrWillBeRawPtr<HTMLSelectElement> select = HTMLSelectElement::create(document()); + select->setShadowPseudoId(keygenSelectPseudoId); for (size_t i = 0; i < keys.size(); ++i) { - RefPtr<HTMLOptionElement> option = HTMLOptionElement::create(document()); + RefPtrWillBeRawPtr<HTMLOptionElement> option = HTMLOptionElement::create(document()); option->appendChild(Text::create(document(), keys[i])); select->appendChild(option); } @@ -112,4 +118,9 @@ bool HTMLKeygenElement::isInteractiveContent() const return true; } +bool HTMLKeygenElement::supportsAutofocus() const +{ + return true; +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.h index 292a78ea29d..7c4f783caa1 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.h @@ -32,10 +32,7 @@ class HTMLSelectElement; class HTMLKeygenElement FINAL : public HTMLFormControlElementWithState { public: - static PassRefPtr<HTMLKeygenElement> create(Document& document, HTMLFormElement* form) - { - return adoptRef(new HTMLKeygenElement(document, form)); - } + static PassRefPtrWillBeRawPtr<HTMLKeygenElement> create(Document&, HTMLFormElement*); virtual bool willValidate() const OVERRIDE { return false; } @@ -54,6 +51,7 @@ private: virtual bool isEnumeratable() const OVERRIDE { return true; } virtual bool isInteractiveContent() const OVERRIDE; + virtual bool supportsAutofocus() const OVERRIDE; virtual bool supportLabels() const OVERRIDE { return true; } virtual void resetImpl() OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.idl index 59af63817b0..4484e2b7b11 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLKeygenElement.idl @@ -33,7 +33,7 @@ interface HTMLKeygenElement : HTMLElement { [Reflect] attribute DOMString challenge; [Reflect] attribute boolean disabled; [ImplementedAs=formOwner] readonly attribute HTMLFormElement form; - [Reflect] attribute DOMString keytype; + [Reflect, ReflectOnly="rsa", ReflectMissing="rsa"] attribute DOMString keytype; [Reflect] attribute DOMString name; readonly attribute DOMString type; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.cpp index aba20072981..c74defe7134 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.cpp @@ -23,25 +23,23 @@ #include "config.h" #include "core/html/HTMLLIElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" +#include "core/dom/NodeRenderingTraversal.h" #include "core/rendering/RenderListItem.h" namespace WebCore { using namespace HTMLNames; -HTMLLIElement::HTMLLIElement(Document& document) +inline HTMLLIElement::HTMLLIElement(Document& document) : HTMLElement(liTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLLIElement> HTMLLIElement::create(Document& document) -{ - return adoptRef(new HTMLLIElement(document)); -} +DEFINE_NODE_FACTORY(HTMLLIElement) bool HTMLLIElement::isPresentationAttribute(const QualifiedName& name) const { @@ -85,23 +83,23 @@ void HTMLLIElement::attach(const AttachContext& context) if (renderer() && renderer()->isListItem()) { RenderListItem* listItemRenderer = toRenderListItem(renderer()); + ASSERT(!document().childNeedsDistributionRecalc()); + // Find the enclosing list node. Element* listNode = 0; Element* current = this; while (!listNode) { - current = current->parentElement(); + current = NodeRenderingTraversal::parentElement(current); if (!current) break; - if (current->hasTagName(ulTag) || current->hasTagName(olTag)) + if (isHTMLUListElement(*current) || isHTMLOListElement(*current)) listNode = current; } // If we are not in a list, tell the renderer so it can position us inside. // We don't want to change our style to say "inside" since that would affect nested nodes. - if (!listNode) { + if (!listNode) listItemRenderer->setNotInList(true); - listItemRenderer->updateMarkerLocation(); - } parseValue(fastGetAttribute(valueAttr)); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.h index a16f4b06f85..d71b76c73a5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLIElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLLIElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLLIElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLLIElement); private: explicit HTMLLIElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp index 6e8fa3d5ea0..ffaa6316873 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp @@ -25,23 +25,25 @@ #include "config.h" #include "core/html/HTMLLabelElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/dom/Document.h" #include "core/dom/ElementTraversal.h" -#include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/editing/FrameSelection.h" +#include "core/events/MouseEvent.h" +#include "core/frame/LocalFrame.h" #include "core/html/FormAssociatedElement.h" namespace WebCore { using namespace HTMLNames; -static bool supportsLabels(Element* element) +static bool supportsLabels(const Element& element) { - if (!element || !element->isHTMLElement()) + if (!element.isHTMLElement()) return false; - if (!toHTMLElement(element)->isLabelable()) + if (!toHTMLElement(element).isLabelable()) return false; - return toLabelableElement(element)->supportLabels(); + return toLabelableElement(element).supportLabels(); } inline HTMLLabelElement::HTMLLabelElement(Document& document) @@ -50,10 +52,7 @@ inline HTMLLabelElement::HTMLLabelElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLLabelElement> HTMLLabelElement::create(Document& document) -{ - return adoptRef(new HTMLLabelElement(document)); -} +DEFINE_NODE_FACTORY(HTMLLabelElement) bool HTMLLabelElement::rendererIsFocusable() const { @@ -61,16 +60,15 @@ bool HTMLLabelElement::rendererIsFocusable() const return that->isContentEditable(); } -LabelableElement* HTMLLabelElement::control() +LabelableElement* HTMLLabelElement::control() const { const AtomicString& controlId = getAttribute(forAttr); if (controlId.isNull()) { // Search the children and descendants of the label element for a form element. // per http://dev.w3.org/html5/spec/Overview.html#the-label-element // the form element must be "labelable form-associated element". - Element* element = this; - while ((element = ElementTraversal::next(*element, this))) { - if (!supportsLabels(element)) + for (Element* element = ElementTraversal::next(*this, this); element; element = ElementTraversal::next(*element, this)) { + if (!supportsLabels(*element)) continue; return toLabelableElement(element); } @@ -78,7 +76,7 @@ LabelableElement* HTMLLabelElement::control() } if (Element* element = treeScope().getElementById(controlId)) { - if (supportsLabels(element)) + if (supportsLabels(*element)) return toLabelableElement(element); } @@ -87,7 +85,7 @@ LabelableElement* HTMLLabelElement::control() HTMLFormElement* HTMLLabelElement::formOwner() const { - return FormAssociatedElement::findAssociatedForm(this, 0); + return FormAssociatedElement::findAssociatedForm(this); } void HTMLLabelElement::setActive(bool down) @@ -138,7 +136,19 @@ void HTMLLabelElement::defaultEventHandler(Event* evt) static bool processingClick = false; if (evt->type() == EventTypeNames::click && !processingClick) { - RefPtr<HTMLElement> element = control(); + // If the click is not simulated and the text of label element is + // selected, do not pass the event to control element. + // Note: a click event may be not a mouse event if created by + // document.createEvent(). + if (evt->isMouseEvent() && !toMouseEvent(evt)->isSimulated()) { + if (LocalFrame* frame = document().frame()) { + if (frame->selection().selection().isRange()) + return; + } + } + + + RefPtrWillBeRawPtr<HTMLElement> element = control(); // If we can't find a control or if the control received the click // event, then there's no need for us to do anything. @@ -152,7 +162,7 @@ void HTMLLabelElement::defaultEventHandler(Event* evt) document().updateLayoutIgnorePendingStylesheets(); if (element->isMouseFocusable()) - element->focus(true, FocusDirectionMouse); + element->focus(true, FocusTypeMouse); // Click the corresponding control. element->dispatchSimulatedClick(evt); @@ -173,13 +183,13 @@ bool HTMLLabelElement::willRespondToMouseClickEvents() return HTMLElement::willRespondToMouseClickEvents(); } -void HTMLLabelElement::focus(bool, FocusDirection direction) +void HTMLLabelElement::focus(bool, FocusType type) { // to match other browsers, always restore previous selection if (HTMLElement* element = control()) - element->focus(true, direction); + element->focus(true, type); if (isFocusable()) - HTMLElement::focus(true, direction); + HTMLElement::focus(true, type); } void HTMLLabelElement::accessKeyAction(bool sendMouseEvents) diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.h index 8ad7c6770ae..2e585d8e7ac 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLabelElement.h @@ -31,9 +31,9 @@ namespace WebCore { class HTMLLabelElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLLabelElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLLabelElement); - LabelableElement* control(); + LabelableElement* control() const; virtual bool willRespondToMouseClickEvents() OVERRIDE; @@ -45,30 +45,18 @@ private: virtual bool rendererIsFocusable() const OVERRIDE; virtual bool isInteractiveContent() const OVERRIDE; - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; // Overridden to update the hover/active state of the corresponding control. virtual void setActive(bool = true) OVERRIDE; virtual void setHovered(bool = true) OVERRIDE; // Overridden to either click() or focus() the corresponding control. - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; - virtual void focus(bool restorePreviousSelection, FocusDirection) OVERRIDE; + virtual void focus(bool restorePreviousSelection, FocusType) OVERRIDE; }; -inline bool isHTMLLabelElement(const Node* node) -{ - return node->hasTagName(HTMLNames::labelTag); -} - -inline bool isHTMLLabelElement(const Element* element) -{ - return element->hasTagName(HTMLNames::labelTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLLabelElement, hasTagName(HTMLNames::labelTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp index f15aed3010b..d5d32b16d89 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "core/html/HTMLLegendElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/ElementTraversal.h" #include "core/html/HTMLFieldSetElement.h" #include "core/html/HTMLFormControlElement.h" @@ -41,39 +41,30 @@ inline HTMLLegendElement::HTMLLegendElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLLegendElement> HTMLLegendElement::create(Document& document) -{ - return adoptRef(new HTMLLegendElement(document)); -} +DEFINE_NODE_FACTORY(HTMLLegendElement) HTMLFormControlElement* HTMLLegendElement::associatedControl() { // Check if there's a fieldset belonging to this legend. Element* fieldset = parentElement(); - while (fieldset && !fieldset->hasTagName(fieldsetTag)) + while (fieldset && !isHTMLFieldSetElement(*fieldset)) fieldset = fieldset->parentElement(); if (!fieldset) return 0; // Find first form element inside the fieldset that is not a legend element. // FIXME: Should we consider tabindex? - Element* element = fieldset; - while ((element = ElementTraversal::next(*element, fieldset))) { - if (element->isFormControlElement()) - return toHTMLFormControlElement(element); - } - - return 0; + return Traversal<HTMLFormControlElement>::next(*fieldset, fieldset); } -void HTMLLegendElement::focus(bool, FocusDirection direction) +void HTMLLegendElement::focus(bool, FocusType type) { if (isFocusable()) - Element::focus(true, direction); + Element::focus(true, type); // To match other browsers' behavior, never restore previous selection. if (HTMLFormControlElement* control = associatedControl()) - control->focus(false, direction); + control->focus(false, type); } void HTMLLegendElement::accessKeyAction(bool sendMouseEvents) @@ -88,7 +79,7 @@ HTMLFormElement* HTMLLegendElement::form() const // its parent, then the form attribute must return the same value as the // form attribute on that fieldset element. Otherwise, it must return null. ContainerNode* fieldset = parentNode(); - if (!fieldset || !fieldset->hasTagName(fieldsetTag)) + if (!isHTMLFieldSetElement(fieldset)) return 0; return toHTMLFieldSetElement(fieldset)->formOwner(); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.h index 74290a8ea33..e456be8a7ee 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLegendElement.h @@ -32,7 +32,7 @@ class HTMLFormControlElement; class HTMLLegendElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLLegendElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLLegendElement); HTMLFormElement* form() const; @@ -42,12 +42,10 @@ private: // Control in the legend's fieldset that gets focus and access key. HTMLFormControlElement* associatedControl(); - virtual void accessKeyAction(bool sendMouseEvents); - virtual void focus(bool restorePreviousSelection, FocusDirection) OVERRIDE; + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; + virtual void focus(bool restorePreviousSelection, FocusType) OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLLegendElement, hasTagName(HTMLNames::legendTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index eea0d9d3d27..f36b9200c18 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp @@ -25,61 +25,136 @@ #include "config.h" #include "core/html/HTMLLinkElement.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/HTMLNames.h" #include "core/css/MediaList.h" #include "core/css/MediaQueryEvaluator.h" #include "core/css/StyleSheetContents.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" +#include "core/dom/StyleEngine.h" #include "core/events/Event.h" #include "core/events/EventSender.h" -#include "core/dom/StyleEngine.h" #include "core/fetch/CSSStyleSheetResource.h" #include "core/fetch/FetchRequest.h" #include "core/fetch/ResourceFetcher.h" -#include "core/html/LinkImport.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/html/LinkManifest.h" +#include "core/html/imports/LinkImport.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" +#include "core/rendering/style/StyleInheritedData.h" +#include "platform/RuntimeEnabledFeatures.h" #include "wtf/StdLibExtras.h" namespace WebCore { using namespace HTMLNames; +template <typename CharacterType> +static void parseSizes(const CharacterType* value, unsigned length, Vector<IntSize>& iconSizes) +{ + enum State { + ParseStart, + ParseWidth, + ParseHeight + }; + int width = 0; + unsigned start = 0; + unsigned i = 0; + State state = ParseStart; + bool invalid = false; + for (; i < length; ++i) { + if (state == ParseWidth) { + if (value[i] == 'x' || value[i] == 'X') { + if (i == start) { + invalid = true; + break; + } + width = charactersToInt(value + start, i - start); + start = i + 1; + state = ParseHeight; + } else if (value[i] < '0' || value[i] > '9') { + invalid = true; + break; + } + } else if (state == ParseHeight) { + if (value[i] == ' ') { + if (i == start) { + invalid = true; + break; + } + int height = charactersToInt(value + start, i - start); + iconSizes.append(IntSize(width, height)); + start = i + 1; + state = ParseStart; + } else if (value[i] < '0' || value[i] > '9') { + invalid = true; + break; + } + } else if (state == ParseStart) { + if (value[i] >= '0' && value[i] <= '9') { + start = i; + state = ParseWidth; + } else if (value[i] != ' ') { + invalid = true; + break; + } + } + } + if (invalid || state == ParseWidth || (state == ParseHeight && start == i)) { + iconSizes.clear(); + return; + } + if (state == ParseHeight && i > start) { + int height = charactersToInt(value + start, i - start); + iconSizes.append(IntSize(width, height)); + } +} + static LinkEventSender& linkLoadEventSender() { DEFINE_STATIC_LOCAL(LinkEventSender, sharedLoadEventSender, (EventTypeNames::load)); return sharedLoadEventSender; } +void HTMLLinkElement::parseSizesAttribute(const AtomicString& value, Vector<IntSize>& iconSizes) +{ + ASSERT(iconSizes.isEmpty()); + if (value.isEmpty()) + return; + if (value.is8Bit()) + parseSizes(value.characters8(), value.length(), iconSizes); + else + parseSizes(value.characters16(), value.length(), iconSizes); +} + inline HTMLLinkElement::HTMLLinkElement(Document& document, bool createdByParser) : HTMLElement(linkTag, document) , m_linkLoader(this) , m_sizes(DOMSettableTokenList::create()) , m_createdByParser(createdByParser) , m_isInShadowTree(false) - , m_beforeLoadRecurseCount(0) { ScriptWrappable::init(this); } -PassRefPtr<HTMLLinkElement> HTMLLinkElement::create(Document& document, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLLinkElement> HTMLLinkElement::create(Document& document, bool createdByParser) { - return adoptRef(new HTMLLinkElement(document, createdByParser)); + return adoptRefWillBeNoop(new HTMLLinkElement(document, createdByParser)); } HTMLLinkElement::~HTMLLinkElement() { +#if !ENABLE(OILPAN) m_link.clear(); if (inDocument()) document().styleEngine()->removeStyleSheetCandidateNode(this); +#endif linkLoadEventSender().cancelEvent(this); } @@ -96,6 +171,7 @@ void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicStri process(); } else if (name == sizesAttr) { m_sizes->setValue(value); + parseSizesAttribute(value, m_iconSizes); process(); } else if (name == mediaAttr) { m_media = value.string().lower(); @@ -103,9 +179,7 @@ void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicStri } else if (name == disabledAttr) { if (LinkStyle* link = linkStyle()) link->setDisabledState(!value.isNull()); - } else if (name == onbeforeloadAttr) - setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value)); - else { + } else { if (name == titleAttr) { if (LinkStyle* link = linkStyle()) link->setSheetTitle(value); @@ -117,25 +191,12 @@ void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicStri bool HTMLLinkElement::shouldLoadLink() { - bool continueLoad = true; - RefPtr<Document> originalDocument(document()); - int recursionRank = ++m_beforeLoadRecurseCount; - if (!dispatchBeforeLoadEvent(getNonEmptyURLAttribute(hrefAttr))) - continueLoad = false; - - // A beforeload handler might have removed us from the document or changed the document. - if (continueLoad && (!inDocument() || document() != originalDocument)) - continueLoad = false; - - // If the beforeload handler recurses into the link element by mutating it, we should only - // let the latest (innermost) mutation occur. - if (recursionRank != m_beforeLoadRecurseCount) - continueLoad = false; - - if (recursionRank == 1) - m_beforeLoadRecurseCount = 0; + return inDocument(); +} - return continueLoad; +bool HTMLLinkElement::loadLink(const String& type, const KURL& url) +{ + return m_linkLoader.loadLink(m_relAttribute, fastGetAttribute(HTMLNames::crossoriginAttr), type, url, document()); } LinkResource* HTMLLinkElement::linkResourceToProcess() @@ -147,11 +208,13 @@ LinkResource* HTMLLinkElement::linkResourceToProcess() } if (!m_link) { - if (m_relAttribute.isImport() && RuntimeEnabledFeatures::htmlImportsEnabled()) + if (m_relAttribute.isImport() && RuntimeEnabledFeatures::htmlImportsEnabled()) { m_link = LinkImport::create(this); - else { - OwnPtr<LinkStyle> link = LinkStyle::create(this); - if (fastHasAttribute(disabledAttr)) + } else if (m_relAttribute.isManifest() && RuntimeEnabledFeatures::manifestEnabled()) { + m_link = LinkManifest::create(this); + } else { + OwnPtrWillBeRawPtr<LinkStyle> link = LinkStyle::create(this); + if (fastHasAttribute(disabledAttr) || m_relAttribute.isTransitionExitingStylesheet()) link->setDisabledState(true); m_link = link.release(); } @@ -187,6 +250,14 @@ void HTMLLinkElement::process() link->process(); } +void HTMLLinkElement::enableIfExitTransitionStyle() +{ + if (m_relAttribute.isTransitionExitingStylesheet()) { + if (LinkStyle* link = linkStyle()) + link->setDisabledState(false); + } +} + Node::InsertionNotificationRequest HTMLLinkElement::insertedInto(ContainerNode* insertionPoint) { HTMLElement::insertedInto(insertionPoint); @@ -200,6 +271,10 @@ Node::InsertionNotificationRequest HTMLLinkElement::insertedInto(ContainerNode* document().styleEngine()->addStyleSheetCandidateNode(this, m_createdByParser); process(); + + if (m_link) + m_link->ownerInserted(); + return InsertionDone; } @@ -217,7 +292,7 @@ void HTMLLinkElement::removedFrom(ContainerNode* insertionPoint) } document().styleEngine()->removeStyleSheetCandidateNode(this); - RefPtr<StyleSheet> removedSheet = sheet(); + RefPtrWillBeRawPtr<StyleSheet> removedSheet = sheet(); if (m_link) m_link->ownerRemoved(); @@ -309,6 +384,22 @@ bool HTMLLinkElement::isURLAttribute(const Attribute& attribute) const return attribute.name().localName() == hrefAttr || HTMLElement::isURLAttribute(attribute); } +bool HTMLLinkElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == hrefAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLLinkElement::subResourceAttributeName() const +{ + // If the link element is not css, ignore it. + if (equalIgnoringCase(getAttribute(typeAttr), "text/css")) { + // FIXME: Add support for extracting links of sub-resources which + // are inside style-sheet such as @import, @font-face, url(), etc. + return hrefAttr; + } + return HTMLElement::subResourceAttributeName(); +} + KURL HTMLLinkElement::href() const { return document().completeURL(getAttribute(hrefAttr)); @@ -319,14 +410,14 @@ const AtomicString& HTMLLinkElement::rel() const return getAttribute(relAttr); } -String HTMLLinkElement::target() const +const AtomicString& HTMLLinkElement::type() const { - return getAttribute(targetAttr); + return getAttribute(typeAttr); } -const AtomicString& HTMLLinkElement::type() const +bool HTMLLinkElement::async() const { - return getAttribute(typeAttr); + return fastHasAttribute(HTMLNames::asyncAttr); } IconType HTMLLinkElement::iconType() const @@ -334,38 +425,26 @@ IconType HTMLLinkElement::iconType() const return m_relAttribute.iconType(); } -String HTMLLinkElement::iconSizes() const +const Vector<IntSize>& HTMLLinkElement::iconSizes() const { - return m_sizes->toString(); + return m_iconSizes; } -void HTMLLinkElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const +DOMSettableTokenList* HTMLLinkElement::sizes() const { - HTMLElement::addSubresourceAttributeURLs(urls); - - // Favicons are handled by a special case in LegacyWebArchive::create() - if (m_relAttribute.iconType() != InvalidIcon) - return; - - if (!m_relAttribute.isStyleSheet()) - return; - - // Append the URL of this link element. - addSubresourceURL(urls, href()); - - // Walk the URLs linked by the linked-to stylesheet. - if (CSSStyleSheet* styleSheet = const_cast<HTMLLinkElement*>(this)->sheet()) - styleSheet->contents()->addSubresourceStyleURLs(urls); + return m_sizes.get(); } -DOMSettableTokenList* HTMLLinkElement::sizes() const +void HTMLLinkElement::trace(Visitor* visitor) { - return m_sizes.get(); + visitor->trace(m_link); + visitor->trace(m_sizes); + HTMLElement::trace(visitor); } -PassOwnPtr<LinkStyle> LinkStyle::create(HTMLLinkElement* owner) +PassOwnPtrWillBeRawPtr<LinkStyle> LinkStyle::create(HTMLLinkElement* owner) { - return adoptPtr(new LinkStyle(owner)); + return adoptPtrWillBeNoop(new LinkStyle(owner)); } LinkStyle::LinkStyle(HTMLLinkElement* owner) @@ -380,8 +459,10 @@ LinkStyle::LinkStyle(HTMLLinkElement* owner) LinkStyle::~LinkStyle() { +#if !ENABLE(OILPAN) if (m_sheet) m_sheet->clearOwnerNode(); +#endif } Document& LinkStyle::document() @@ -397,11 +478,11 @@ void LinkStyle::setCSSStyleSheet(const String& href, const KURL& baseURL, const } // Completing the sheet load may cause scripts to execute. - RefPtr<Node> protector(m_owner); + RefPtrWillBeRawPtr<Node> protector(m_owner.get()); - CSSParserContext parserContext(m_owner->document(), baseURL, charset); + CSSParserContext parserContext(m_owner->document(), 0, baseURL, charset); - if (RefPtr<StyleSheetContents> restoredSheet = const_cast<CSSStyleSheetResource*>(cachedStyleSheet)->restoreParsedStyleSheet(parserContext)) { + if (RefPtrWillBeRawPtr<StyleSheetContents> restoredSheet = const_cast<CSSStyleSheetResource*>(cachedStyleSheet)->restoreParsedStyleSheet(parserContext)) { ASSERT(restoredSheet->isCacheable()); ASSERT(!restoredSheet->isLoading()); @@ -412,12 +493,11 @@ void LinkStyle::setCSSStyleSheet(const String& href, const KURL& baseURL, const m_sheet->setTitle(m_owner->title()); m_loading = false; - sheetLoaded(); - notifyLoadedSheetAndAllCriticalSubresources(false); + restoredSheet->checkLoaded(); return; } - RefPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(href, parserContext); + RefPtrWillBeRawPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(href, parserContext); if (m_sheet) clearSheet(); @@ -465,7 +545,7 @@ void LinkStyle::clearSheet() ASSERT(m_sheet); ASSERT(m_sheet->ownerNode() == m_owner); m_sheet->clearOwnerNode(); - m_sheet = 0; + m_sheet = nullptr; } bool LinkStyle::styleSheetIsLoading() const @@ -488,7 +568,7 @@ void LinkStyle::addPendingSheet(PendingSheetType type) m_owner->document().styleEngine()->addPendingSheet(); } -void LinkStyle::removePendingSheet(RemovePendingSheetNotificationType notification) +void LinkStyle::removePendingSheet() { PendingSheetType type = m_pendingSheetType; m_pendingSheetType = None; @@ -501,14 +581,11 @@ void LinkStyle::removePendingSheet(RemovePendingSheetNotificationType notificati // Document::removePendingSheet() triggers the style selector recalc for blocking sheets. // FIXME: We don't have enough knowledge at this point to know if we're adding or removing a sheet // so we can't call addedStyleSheet() or removedStyleSheet(). - m_owner->document().styleResolverChanged(RecalcStyleImmediately); + m_owner->document().styleResolverChanged(); return; } - m_owner->document().styleEngine()->removePendingSheet(m_owner, - notification == RemovePendingSheetNotifyImmediately - ? StyleEngine::RemovePendingSheetNotifyImmediately - : StyleEngine::RemovePendingSheetNotifyLater); + m_owner->document().styleEngine()->removePendingSheet(m_owner); } void LinkStyle::setDisabledState(bool disabled) @@ -548,7 +625,7 @@ void LinkStyle::setDisabledState(bool disabled) process(); } else { // FIXME: We don't have enough knowledge here to know if we should call addedStyleSheet() or removedStyleSheet(). - m_owner->document().styleResolverChanged(RecalcStyleDeferred); + m_owner->document().styleResolverChanged(); } } } @@ -566,14 +643,14 @@ void LinkStyle::process() return; if (!document().contentSecurityPolicy()->allowImageFromSource(builder.url())) return; - if (document().frame()) + if (document().frame() && document().frame()->loader().client()) document().frame()->loader().client()->dispatchDidChangeIcons(m_owner->relAttribute().iconType()); } if (!m_owner->loadLink(type, builder.url())) return; - if ((m_disabledState != Disabled) && m_owner->relAttribute().isStyleSheet() + if ((m_disabledState != Disabled) && (m_owner->relAttribute().isStyleSheet() || m_owner->relAttribute().isTransitionExitingStylesheet()) && shouldLoadResource() && builder.url().isValid()) { if (resource()) { @@ -584,15 +661,17 @@ void LinkStyle::process() if (!m_owner->shouldLoadLink()) return; - Frame* frame = loadingFrame(); m_loading = true; bool mediaQueryMatches = true; if (!m_owner->media().isEmpty()) { - RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(document()); - RefPtr<MediaQuerySet> media = MediaQuerySet::create(m_owner->media()); - MediaQueryEvaluator evaluator(frame->view()->mediaType(), frame, documentStyle.get()); - mediaQueryMatches = evaluator.eval(media.get()); + LocalFrame* frame = loadingFrame(); + if (Document* document = loadingFrame()->document()) { + RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(*document); + RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(m_owner->media()); + MediaQueryEvaluator evaluator(frame->view()->mediaType(), frame); + mediaQueryMatches = evaluator.eval(media.get()); + } } // Don't hold up render tree construction and script execution on stylesheets @@ -602,6 +681,9 @@ void LinkStyle::process() // Load stylesheets that are not needed for the rendering immediately with low priority. FetchRequest request = builder.build(blocking); + AtomicString crossOriginMode = m_owner->fastGetAttribute(HTMLNames::crossoriginAttr); + if (!crossOriginMode.isNull()) + request.setCrossOriginAccessControl(document().securityOrigin(), crossOriginMode); setResource(document().fetcher()->fetchCSSStyleSheet(request)); if (!resource()) { @@ -611,7 +693,7 @@ void LinkStyle::process() } } else if (m_sheet) { // we no longer contain a stylesheet, e.g. perhaps rel or type was changed - RefPtr<StyleSheet> removedSheet = m_sheet; + RefPtrWillBeRawPtr<StyleSheet> removedSheet = m_sheet.get(); clearSheet(); document().removedStyleSheet(removedSheet.get()); } @@ -629,7 +711,13 @@ void LinkStyle::ownerRemoved() clearSheet(); if (styleSheetIsLoading()) - removePendingSheet(RemovePendingSheetNotifyLater); + removePendingSheet(); +} + +void LinkStyle::trace(Visitor* visitor) +{ + visitor->trace(m_sheet); + LinkResource::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.h index 28b01dff582..e9ac4431e35 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.h @@ -56,9 +56,9 @@ typedef EventSender<HTMLLinkElement> LinkEventSender; // sticking current way so far. // class LinkStyle FINAL : public LinkResource, ResourceOwner<StyleSheetResource> { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<LinkStyle> create(HTMLLinkElement* owner); + static PassOwnPtrWillBeRawPtr<LinkStyle> create(HTMLLinkElement* owner); explicit LinkStyle(HTMLLinkElement* owner); virtual ~LinkStyle(); @@ -67,6 +67,7 @@ public: virtual void process() OVERRIDE; virtual void ownerRemoved() OVERRIDE; virtual bool hasLoaded() const OVERRIDE { return m_loadedSheet; } + virtual void trace(Visitor*) OVERRIDE; void startLoadingDynamicSheet(); void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred); @@ -84,7 +85,7 @@ public: CSSStyleSheet* sheet() const { return m_sheet.get(); } private: - // From ResourceClient + // From StyleSheetResourceClient virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource*) OVERRIDE; enum DisabledState { @@ -99,17 +100,12 @@ private: Blocking }; - enum RemovePendingSheetNotificationType { - RemovePendingSheetNotifyImmediately, - RemovePendingSheetNotifyLater - }; - void clearSheet(); void addPendingSheet(PendingSheetType); - void removePendingSheet(RemovePendingSheetNotificationType = RemovePendingSheetNotifyImmediately); + void removePendingSheet(); Document& document(); - RefPtr<CSSStyleSheet> m_sheet; + RefPtrWillBeMember<CSSStyleSheet> m_sheet; DisabledState m_disabledState; PendingSheetType m_pendingSheetType; bool m_loading; @@ -120,7 +116,7 @@ private: class HTMLLinkElement FINAL : public HTMLElement, public LinkLoaderClient { public: - static PassRefPtr<HTMLLinkElement> create(Document&, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLLinkElement> create(Document&, bool createdByParser); virtual ~HTMLLinkElement(); KURL href() const; @@ -129,35 +125,46 @@ public: String typeValue() const { return m_type; } const LinkRelAttribute& relAttribute() const { return m_relAttribute; } - virtual String target() const; - const AtomicString& type() const; IconType iconType() const; - // the icon size string as parsed from the HTML attribute - String iconSizes() const; + // the icon sizes as parsed from the HTML attribute + const Vector<IntSize>& iconSizes() const; + + bool async() const; CSSStyleSheet* sheet() const { return linkStyle() ? linkStyle()->sheet() : 0; } Document* import() const; bool styleSheetIsLoading() const; + bool isImport() const { return linkImport(); } bool isDisabled() const { return linkStyle() && linkStyle()->isDisabled(); } bool isEnabledViaScript() const { return linkStyle() && linkStyle()->isEnabledViaScript(); } + void enableIfExitTransitionStyle(); + DOMSettableTokenList* sizes() const; void dispatchPendingEvent(LinkEventSender*); void scheduleEvent(); + void dispatchEventImmediately(); static void dispatchPendingLoadEvents(); // From LinkLoaderClient virtual bool shouldLoadLink() OVERRIDE; // For LinkStyle - bool loadLink(const String& type, const KURL& url) { return m_linkLoader.loadLink(m_relAttribute, type, url, document()); } + bool loadLink(const String& type, const KURL&); bool isAlternate() const { return linkStyle()->isUnset() && m_relAttribute.isAlternate(); } bool shouldProcessStyle() { return linkResourceToProcess() && linkStyle(); } + bool isCreatedByParser() const { return m_createdByParser; } + + // Parse the icon size attribute into |iconSizes|, make this method public + // visible for testing purpose. + static void parseSizesAttribute(const AtomicString& value, Vector<IntSize>& iconSizes); + + virtual void trace(Visitor*) OVERRIDE; private: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; @@ -173,11 +180,12 @@ private: virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; virtual bool sheetLoaded() OVERRIDE; virtual void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred) OVERRIDE; virtual void startLoadingDynamicSheet() OVERRIDE; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const OVERRIDE; - virtual void finishParsingChildren(); + virtual void finishParsingChildren() OVERRIDE; // From LinkLoaderClient virtual void linkLoaded() OVERRIDE; @@ -190,21 +198,19 @@ private: private: HTMLLinkElement(Document&, bool createdByParser); - OwnPtr<LinkResource> m_link; + OwnPtrWillBeMember<LinkResource> m_link; LinkLoader m_linkLoader; String m_type; String m_media; - RefPtr<DOMSettableTokenList> m_sizes; + RefPtrWillBeMember<DOMSettableTokenList> m_sizes; + Vector<IntSize> m_iconSizes; LinkRelAttribute m_relAttribute; bool m_createdByParser; bool m_isInShadowTree; - int m_beforeLoadRecurseCount; }; -DEFINE_NODE_TYPE_CASTS(HTMLLinkElement, hasTagName(HTMLNames::linkTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.idl index 73c2426ce04..3ba1aff4c50 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElement.idl @@ -22,7 +22,8 @@ interface HTMLLinkElement : HTMLElement { [Reflect] attribute boolean disabled; [Reflect] attribute DOMString charset; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString href; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString href; + [Reflect, ReflectOnly="anonymous"|"use-credentials", ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString crossOrigin; [Reflect] attribute DOMString hreflang; [Reflect] attribute DOMString media; [Reflect] attribute DOMString rel; @@ -35,4 +36,6 @@ interface HTMLLinkElement : HTMLElement { readonly attribute StyleSheet sheet; [RuntimeEnabled=HTMLImports] readonly attribute Document import; + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLLinkElementSizesAttributeTest.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElementSizesAttributeTest.cpp new file mode 100644 index 00000000000..62cce281a90 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLLinkElementSizesAttributeTest.cpp @@ -0,0 +1,77 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/HTMLLinkElement.h" + +#include <gtest/gtest.h> + +using namespace WebCore; + +namespace { + +class HTMLLinkElementSizesAttributeTest : public testing::Test { +}; + +TEST(HTMLLinkElementSizesAttributeTest, parseSizes) +{ + AtomicString sizesAttribute = "32x33"; + Vector<IntSize> sizes; + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(1U, sizes.size()); + EXPECT_EQ(32, sizes[0].width()); + EXPECT_EQ(33, sizes[0].height()); + + UChar attribute[] = {'3', '2', 'x', '3', '3', 0}; + sizesAttribute = attribute; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(1U, sizes.size()); + EXPECT_EQ(32, sizes[0].width()); + EXPECT_EQ(33, sizes[0].height()); + + + sizesAttribute = " 32x33 16X17 128x129 "; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(3U, sizes.size()); + EXPECT_EQ(32, sizes[0].width()); + EXPECT_EQ(33, sizes[0].height()); + EXPECT_EQ(16, sizes[1].width()); + EXPECT_EQ(17, sizes[1].height()); + EXPECT_EQ(128, sizes[2].width()); + EXPECT_EQ(129, sizes[2].height()); + + sizesAttribute = "any"; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(0U, sizes.size()); + + sizesAttribute = "32x33 32"; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(0U, sizes.size()); + + sizesAttribute = "32x33 32x"; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(0U, sizes.size()); + + sizesAttribute = "32x33 x32"; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(0U, sizes.size()); + + sizesAttribute = "32x33 any"; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(0U, sizes.size()); + + sizesAttribute = "32x33, 64x64"; + sizes.clear(); + HTMLLinkElement::parseSizesAttribute(sizesAttribute, sizes); + ASSERT_EQ(0U, sizes.size()); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.cpp index d1f055a2fc6..27a525c1b33 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "core/html/HTMLMapElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/ElementTraversal.h" #include "core/html/HTMLAreaElement.h" @@ -30,22 +30,17 @@ #include "core/html/HTMLImageElement.h" #include "core/rendering/HitTestResult.h" -using namespace std; - namespace WebCore { using namespace HTMLNames; -HTMLMapElement::HTMLMapElement(Document& document) +inline HTMLMapElement::HTMLMapElement(Document& document) : HTMLElement(mapTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLMapElement> HTMLMapElement::create(Document& document) -{ - return adoptRef(new HTMLMapElement(document)); -} +DEFINE_NODE_FACTORY(HTMLMapElement) HTMLMapElement::~HTMLMapElement() { @@ -54,15 +49,12 @@ HTMLMapElement::~HTMLMapElement() bool HTMLMapElement::mapMouseEvent(LayoutPoint location, const LayoutSize& size, HitTestResult& result) { HTMLAreaElement* defaultArea = 0; - Element* element = this; - while ((element = ElementTraversal::next(*element, this))) { - if (isHTMLAreaElement(element)) { - HTMLAreaElement* areaElt = toHTMLAreaElement(element); - if (areaElt->isDefault()) { - if (!defaultArea) - defaultArea = areaElt; - } else if (areaElt->mapMouseEvent(location, size, result)) - return true; + for (HTMLAreaElement* area = Traversal<HTMLAreaElement>::firstWithin(*this); area; area = Traversal<HTMLAreaElement>::next(*area, this)) { + if (area->isDefault()) { + if (!defaultArea) + defaultArea = area; + } else if (area->mapMouseEvent(location, size, result)) { + return true; } } @@ -75,17 +67,16 @@ bool HTMLMapElement::mapMouseEvent(LayoutPoint location, const LayoutSize& size, HTMLImageElement* HTMLMapElement::imageElement() { - RefPtr<HTMLCollection> images = document().images(); - for (unsigned i = 0; Node* curr = images->item(i); i++) { - if (!curr->hasTagName(imgTag)) - continue; + RefPtrWillBeRawPtr<HTMLCollection> images = document().images(); + for (unsigned i = 0; Element* curr = images->item(i); ++i) { + ASSERT(isHTMLImageElement(curr)); // The HTMLImageElement's useMap() value includes the '#' symbol at the beginning, // which has to be stripped off. - HTMLImageElement* imageElement = toHTMLImageElement(curr); - String useMapName = imageElement->getAttribute(usemapAttr).string().substring(1); + HTMLImageElement& imageElement = toHTMLImageElement(*curr); + String useMapName = imageElement.getAttribute(usemapAttr).string().substring(1); if (equalIgnoringCase(useMapName, m_name)) - return imageElement; + return &imageElement; } return 0; @@ -108,7 +99,7 @@ void HTMLMapElement::parseAttribute(const QualifiedName& name, const AtomicStrin String mapName = value; if (mapName[0] == '#') mapName = mapName.substring(1); - m_name = document().isHTMLDocument() ? mapName.lower() : mapName; + m_name = AtomicString(document().isHTMLDocument() ? mapName.lower() : mapName); if (inDocument()) treeScope().addImageMap(this); @@ -118,7 +109,7 @@ void HTMLMapElement::parseAttribute(const QualifiedName& name, const AtomicStrin HTMLElement::parseAttribute(name, value); } -PassRefPtr<HTMLCollection> HTMLMapElement::areas() +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLMapElement::areas() { return ensureCachedHTMLCollection(MapAreas); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.h index cdd5c7654a8..36ca426bc0b 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMapElement.h @@ -32,7 +32,7 @@ class HTMLImageElement; class HTMLMapElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLMapElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLMapElement); virtual ~HTMLMapElement(); const AtomicString& getName() const { return m_name; } @@ -40,7 +40,7 @@ public: bool mapMouseEvent(LayoutPoint location, const LayoutSize&, HitTestResult&); HTMLImageElement* imageElement(); - PassRefPtr<HTMLCollection> areas(); + PassRefPtrWillBeRawPtr<HTMLCollection> areas(); private: explicit HTMLMapElement(Document&); @@ -53,8 +53,6 @@ private: AtomicString m_name; }; -DEFINE_NODE_TYPE_CASTS(HTMLMapElement, hasTagName(HTMLNames::mapTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp index 882cb06c454..491755fbf41 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp @@ -23,10 +23,10 @@ #include "config.h" #include "core/html/HTMLMarqueeElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/dom/ExceptionCode.h" #include "core/rendering/RenderMarquee.h" @@ -41,9 +41,9 @@ inline HTMLMarqueeElement::HTMLMarqueeElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLMarqueeElement> HTMLMarqueeElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLMarqueeElement> HTMLMarqueeElement::create(Document& document) { - RefPtr<HTMLMarqueeElement> marqueeElement(adoptRef(new HTMLMarqueeElement(document))); + RefPtrWillBeRawPtr<HTMLMarqueeElement> marqueeElement(adoptRefWillBeNoop(new HTMLMarqueeElement(document))); marqueeElement->suspendIfNeeded(); return marqueeElement.release(); } @@ -57,6 +57,12 @@ int HTMLMarqueeElement::minimumDelay() const return 0; } +void HTMLMarqueeElement::didMoveToNewDocument(Document& oldDocument) +{ + ActiveDOMObject::didMoveToNewExecutionContext(&document()); + HTMLElement::didMoveToNewDocument(oldDocument); +} + bool HTMLMarqueeElement::isPresentationAttribute(const QualifiedName& name) const { if (name == widthAttr || name == heightAttr || name == bgcolorAttr || name == vspaceAttr || name == hspaceAttr || name == scrollamountAttr || name == scrolldelayAttr || name == loopAttr || name == behaviorAttr || name == directionAttr) diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h index 90add468471..129ed22392d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h @@ -25,6 +25,7 @@ #include "core/dom/ActiveDOMObject.h" #include "core/html/HTMLElement.h" +#include "platform/Timer.h" namespace WebCore { @@ -33,14 +34,14 @@ class RenderMarquee; class HTMLMarqueeElement FINAL : public HTMLElement, private ActiveDOMObject { public: - static PassRefPtr<HTMLMarqueeElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLMarqueeElement> create(Document&); int minimumDelay() const; // DOM Functions void start(); - void stop(); + virtual void stop() OVERRIDE; int scrollAmount() const; void setScrollAmount(int, ExceptionState&); @@ -56,20 +57,20 @@ public: private: explicit HTMLMarqueeElement(Document&); + virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; + virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; // ActiveDOMObject - virtual void suspend(); - virtual void resume(); + virtual void suspend() OVERRIDE; + virtual void resume() OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE FINAL; + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; RenderMarquee* renderMarquee() const; }; -DEFINE_NODE_TYPE_CASTS(HTMLMarqueeElement, hasTagName(HTMLNames::marqueeTag)); - } // namespace WebCore #endif // HTMLMarqueeElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index c43d49009f1..ed492e58133 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp @@ -27,55 +27,52 @@ #include "core/html/HTMLMediaElement.h" #include <limits> -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/HTMLNames.h" #include "core/css/MediaList.h" -#include "core/css/MediaQueryEvaluator.h" #include "core/dom/Attribute.h" #include "core/dom/ExceptionCode.h" #include "core/dom/FullscreenElementStack.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "core/frame/UseCounter.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLMediaSource.h" #include "core/html/HTMLSourceElement.h" #include "core/html/HTMLTrackElement.h" #include "core/html/MediaController.h" #include "core/html/MediaError.h" #include "core/html/MediaFragmentURIParser.h" -#include "core/html/MediaKeyError.h" -#include "core/html/MediaKeyEvent.h" #include "core/html/TimeRanges.h" #include "core/html/shadow/MediaControls.h" +#include "core/html/track/AudioTrack.h" +#include "core/html/track/AudioTrackList.h" #include "core/html/track/InbandTextTrack.h" #include "core/html/track/TextTrackCueList.h" #include "core/html/track/TextTrackList.h" +#include "core/html/track/VideoTrack.h" +#include "core/html/track/VideoTrackList.h" #include "core/loader/FrameLoader.h" -#include "core/rendering/RenderLayerCompositor.h" #include "core/rendering/RenderVideo.h" #include "core/rendering/RenderView.h" -// FIXME: Remove dependency on modules/encryptedmedia (http://crbug.com/242754). -#include "modules/encryptedmedia/MediaKeyNeededEvent.h" -#include "modules/encryptedmedia/MediaKeys.h" -#include "modules/mediastream/MediaStreamRegistry.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" #include "platform/ContentType.h" #include "platform/Language.h" #include "platform/Logging.h" #include "platform/MIMETypeFromURL.h" #include "platform/MIMETypeRegistry.h" #include "platform/NotImplemented.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/UserGestureIndicator.h" #include "platform/graphics/GraphicsLayer.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" +#include "public/platform/WebContentDecryptionModule.h" #include "public/platform/WebInbandTextTrack.h" #include "wtf/CurrentTime.h" #include "wtf/MathExtras.h" @@ -85,12 +82,13 @@ #if ENABLE(WEB_AUDIO) #include "platform/audio/AudioSourceProvider.h" -#include "modules/webaudio/MediaElementAudioSourceNode.h" +#include "platform/audio/AudioSourceProviderClient.h" #endif -using namespace std; using blink::WebInbandTextTrack; +using blink::WebMediaPlayer; using blink::WebMimeRegistry; +using blink::WebMediaPlayerClient; namespace WebCore { @@ -126,19 +124,19 @@ static const char* boolString(bool val) static const char mediaSourceBlobProtocol[] = "blob"; using namespace HTMLNames; -using namespace std; -typedef HashMap<Document*, HashSet<HTMLMediaElement*> > DocumentElementSetMap; +typedef WillBeHeapHashSet<RawPtrWillBeWeakMember<HTMLMediaElement> > WeakMediaElementSet; +typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<Document>, WeakMediaElementSet> DocumentElementSetMap; static DocumentElementSetMap& documentToElementSetMap() { - DEFINE_STATIC_LOCAL(DocumentElementSetMap, map, ()); - return map; + DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<DocumentElementSetMap>, map, (adoptPtrWillBeNoop(new DocumentElementSetMap()))); + return *map; } static void addElementToDocumentMap(HTMLMediaElement* element, Document* document) { DocumentElementSetMap& map = documentToElementSetMap(); - HashSet<HTMLMediaElement*> set = map.take(document); + WeakMediaElementSet set = map.take(document); set.add(element); map.add(document, set); } @@ -146,33 +144,14 @@ static void addElementToDocumentMap(HTMLMediaElement* element, Document* documen static void removeElementFromDocumentMap(HTMLMediaElement* element, Document* document) { DocumentElementSetMap& map = documentToElementSetMap(); - HashSet<HTMLMediaElement*> set = map.take(document); + WeakMediaElementSet set = map.take(document); set.remove(element); if (!set.isEmpty()) map.add(document, set); } -static void throwExceptionForMediaKeyException(MediaPlayer::MediaKeyException exception, ExceptionState& exceptionState) -{ - switch (exception) { - case MediaPlayer::NoError: - return; - case MediaPlayer::InvalidPlayerState: - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - case MediaPlayer::KeySystemNotSupported: - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return; - case MediaPlayer::InvalidAccess: - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - - ASSERT_NOT_REACHED(); - return; -} - class TrackDisplayUpdateScope { + STACK_ALLOCATED(); public: TrackDisplayUpdateScope(HTMLMediaElement* mediaElement) { @@ -186,9 +165,55 @@ public: } private: - HTMLMediaElement* m_mediaElement; + RawPtrWillBeMember<HTMLMediaElement> m_mediaElement; }; +static const AtomicString& AudioKindToString(WebMediaPlayerClient::AudioTrackKind kind) +{ + switch (kind) { + case WebMediaPlayerClient::AudioTrackKindNone: + return emptyAtom; + case WebMediaPlayerClient::AudioTrackKindAlternative: + return AudioTrack::alternativeKeyword(); + case WebMediaPlayerClient::AudioTrackKindDescriptions: + return AudioTrack::descriptionsKeyword(); + case WebMediaPlayerClient::AudioTrackKindMain: + return AudioTrack::mainKeyword(); + case WebMediaPlayerClient::AudioTrackKindMainDescriptions: + return AudioTrack::mainDescriptionsKeyword(); + case WebMediaPlayerClient::AudioTrackKindTranslation: + return AudioTrack::translationKeyword(); + case WebMediaPlayerClient::AudioTrackKindCommentary: + return AudioTrack::commentaryKeyword(); + } + + ASSERT_NOT_REACHED(); + return emptyAtom; +} + +static const AtomicString& VideoKindToString(WebMediaPlayerClient::VideoTrackKind kind) +{ + switch (kind) { + case WebMediaPlayerClient::VideoTrackKindNone: + return emptyAtom; + case WebMediaPlayerClient::VideoTrackKindAlternative: + return VideoTrack::alternativeKeyword(); + case WebMediaPlayerClient::VideoTrackKindCaptions: + return VideoTrack::captionsKeyword(); + case WebMediaPlayerClient::VideoTrackKindMain: + return VideoTrack::mainKeyword(); + case WebMediaPlayerClient::VideoTrackKindSign: + return VideoTrack::signKeyword(); + case WebMediaPlayerClient::VideoTrackKindSubtitles: + return VideoTrack::subtitlesKeyword(); + case WebMediaPlayerClient::VideoTrackKindCommentary: + return VideoTrack::commentaryKeyword(); + } + + ASSERT_NOT_REACHED(); + return emptyAtom; +} + static bool canLoadURL(const KURL& url, const ContentType& contentType, const String& keySystem) { DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); @@ -241,12 +266,26 @@ WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& return blink::Platform::current()->mimeRegistry()->supportsMediaMIMEType(type, typeCodecs, system); } -HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& document, bool createdByParser) +URLRegistry* HTMLMediaElement::s_mediaStreamRegistry = 0; + +void HTMLMediaElement::setMediaStreamRegistry(URLRegistry* registry) +{ + ASSERT(!s_mediaStreamRegistry); + s_mediaStreamRegistry = registry; +} + +bool HTMLMediaElement::isMediaStreamURL(const String& url) +{ + return s_mediaStreamRegistry ? s_mediaStreamRegistry->contains(url) : false; +} + +HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& document) : HTMLElement(tagName, document) , ActiveDOMObject(&document) , m_loadTimer(this, &HTMLMediaElement::loadTimerFired) , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired) , m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFired) + , m_audioTracksTimer(this, &HTMLMediaElement::audioTracksTimerFired) , m_playedTimeRanges() , m_asyncEventQueue(GenericEventQueue::create(this)) , m_playbackRate(1.0f) @@ -256,14 +295,14 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum , m_readyStateMaximum(HAVE_NOTHING) , m_volume(1.0f) , m_lastSeekTime(0) - , m_previousProgressTime(numeric_limits<double>::max()) - , m_duration(numeric_limits<double>::quiet_NaN()) + , m_previousProgressTime(std::numeric_limits<double>::max()) + , m_duration(std::numeric_limits<double>::quiet_NaN()) , m_lastTimeUpdateEventWallTime(0) - , m_lastTimeUpdateEventMovieTime(numeric_limits<double>::max()) + , m_lastTimeUpdateEventMovieTime(std::numeric_limits<double>::max()) , m_loadState(WaitingForSource) + , m_deferredLoadState(NotDeferred) + , m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired) , m_webLayer(0) - , m_opaque(false) - , m_restrictions(RequirePageConsentToLoadMediaRestriction) , m_preload(MediaPlayer::Auto) , m_displayMode(Unknown) , m_cachedTime(MediaPlayer::invalidTime()) @@ -272,6 +311,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum , m_fragmentStartTime(MediaPlayer::invalidTime()) , m_fragmentEndTime(MediaPlayer::invalidTime()) , m_pendingActionFlags(0) + , m_userGestureRequiredForPlay(false) , m_playing(false) , m_shouldDelayLoadEvent(false) , m_haveFiredLoadedData(false) @@ -284,18 +324,21 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum , m_sentEndEvent(false) , m_pausedInternal(false) , m_closedCaptionsVisible(false) - , m_loadInitiatedByUserGesture(false) , m_completelyLoaded(false) , m_havePreparedToPlay(false) - , m_parsingInProgress(createdByParser) , m_tracksAreReady(true) , m_haveVisibleTextTrack(false) , m_processingPreferenceChange(false) +#if ENABLE(OILPAN) + , m_isFinalizing(false) +#endif , m_lastTextTrackUpdateTime(-1) - , m_textTracks(0) + , m_audioTracks(AudioTrackList::create(*this)) + , m_videoTracks(VideoTrackList::create(*this)) + , m_textTracks(nullptr) , m_ignoreTrackDisplayUpdate(0) #if ENABLE(WEB_AUDIO) - , m_audioSourceNode(0) + , m_audioSourceNode(nullptr) #endif { ASSERT(RuntimeEnabledFeatures::mediaEnabled()); @@ -303,45 +346,54 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); ScriptWrappable::init(this); - if (document.settings()) { - if (document.settings()->mediaPlaybackRequiresUserGesture()) { - addBehaviorRestriction(RequireUserGestureForRateChangeRestriction); - addBehaviorRestriction(RequireUserGestureForLoadRestriction); - } - if (document.settings()->mediaFullscreenRequiresUserGesture()) { - addBehaviorRestriction(RequireUserGestureForFullscreenRestriction); - } - } + if (document.settings() && document.settings()->mediaPlaybackRequiresUserGesture()) + m_userGestureRequiredForPlay = true; setHasCustomStyleCallbacks(); addElementToDocumentMap(this, &document); - } HTMLMediaElement::~HTMLMediaElement() { WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); +#if ENABLE(OILPAN) + // If the HTMLMediaElement dies with the document we are not + // allowed to touch the document to adjust delay load event counts + // because the document could have been already + // destructed. However, if the HTMLMediaElement dies with the + // document there is no need to change the delayed load counts + // because no load event will fire anyway. If the document is + // still alive we do have to decrement the load delay counts. We + // determine if the document is alive via the ActiveDOMObject + // which is a context lifecycle observer. If the Document has been + // destructed ActiveDOMObject::executionContext() returns 0. + if (ActiveDOMObject::executionContext()) + setShouldDelayLoadEvent(false); +#else + // HTMLMediaElement and m_asyncEventQueue always become unreachable + // together. So HTMLMediaElemenet and m_asyncEventQueue are destructed in + // the same GC. We don't need to close it explicitly in Oilpan. m_asyncEventQueue->close(); setShouldDelayLoadEvent(false); + if (m_textTracks) m_textTracks->clearOwner(); - if (m_textTracks) { - for (unsigned i = 0; i < m_textTracks->length(); ++i) - m_textTracks->item(i)->clearClient(); - } + m_audioTracks->shutdown(); + m_videoTracks->shutdown(); if (m_mediaController) { m_mediaController->removeMediaElement(this); - m_mediaController = 0; + m_mediaController = nullptr; } +#endif closeMediaSource(); - setMediaKeys(0); - +#if !ENABLE(OILPAN) removeElementFromDocumentMap(this, &document()); +#endif // Destroying the player may cause a resource load to be canceled, // which could result in userCancelledLoad() being called back. @@ -350,6 +402,10 @@ HTMLMediaElement::~HTMLMediaElement() // See http://crbug.com/233654 for more details. m_completelyLoaded = true; + // With Oilpan load events on the Document are always delayed during + // sweeping so we don't need to explicitly increment and decrement + // load event delay counts. +#if !ENABLE(OILPAN) // Destroying the player may cause a resource load to be canceled, // which could result in Document::dispatchWindowLoadEvent() being // called via ResourceFetch::didLoadResource() then @@ -357,10 +413,33 @@ HTMLMediaElement::~HTMLMediaElement() // object destruction, we use Document::incrementLoadEventDelayCount(). // See http://crbug.com/275223 for more details. document().incrementLoadEventDelayCount(); +#endif + +#if ENABLE(OILPAN) + // Oilpan: the player must be released, but the player object + // cannot safely access this player client any longer as parts of + // it may have been finalized already (like the media element's + // supplementable table.) Handled for now by entering an + // is-finalizing state, which is explicitly checked for if the + // player tries to access the media element during shutdown. + // + // FIXME: Oilpan: move the media player to the heap instead and + // avoid having to finalize it from here; this whole #if block + // could then be removed (along with the state bit it depends on.) + // crbug.com/378229 + m_isFinalizing = true; +#endif - clearMediaPlayerAndAudioSourceProviderClient(); + // The m_audioSourceNode is either dead already or it is dying together with + // this HTMLMediaElement which it strongly keeps alive. +#if ENABLE(WEB_AUDIO) && !ENABLE(OILPAN) + ASSERT(!m_audioSourceNode); +#endif + clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); +#if !ENABLE(OILPAN) document().decrementLoadEventDelayCount(); +#endif } void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) @@ -382,9 +461,9 @@ void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) addElementToDocumentMap(this, &document()); // FIXME: This is a temporary fix to prevent this object from causing the - // MediaPlayer to dereference Frame and FrameLoader pointers from the + // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the // previous document. A proper fix would provide a mechanism to allow this - // object to refresh the MediaPlayer's Frame and FrameLoader references on + // object to refresh the MediaPlayer's LocalFrame and FrameLoader references on // document changes so that playback can be resumed properly. userCancelledLoad(); @@ -392,14 +471,10 @@ void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) // and there is no risk of dispatching a load event from within the destructor. oldDocument.decrementLoadEventDelayCount(); + ActiveDOMObject::didMoveToNewExecutionContext(&document()); HTMLElement::didMoveToNewDocument(oldDocument); } -bool HTMLMediaElement::hasCustomFocusLogic() const -{ - return true; -} - bool HTMLMediaElement::supportsFocus() const { if (ownerDocument()->isMediaDocument()) @@ -422,9 +497,9 @@ void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicStr clearMediaPlayer(LoadMediaResource); scheduleDelayedAction(LoadMediaResource); } - } else if (name == controlsAttr) + } else if (name == controlsAttr) { configureMediaControls(); - else if (name == preloadAttr) { + } else if (name == preloadAttr) { if (equalIgnoringCase(value, "none")) m_preload = MediaPlayer::None; else if (equalIgnoringCase(value, "metadata")) @@ -437,30 +512,21 @@ void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicStr // The attribute must be ignored if the autoplay attribute is present if (!autoplay() && m_player) - m_player->setPreload(m_preload); + setPlayerPreload(); - } else if (name == mediagroupAttr) + } else if (name == mediagroupAttr && RuntimeEnabledFeatures::mediaControllerEnabled()) { setMediaGroup(value); - else if (name == onbeforeloadAttr) - setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value)); - else + } else { HTMLElement::parseAttribute(name, value); + } } void HTMLMediaElement::finishParsingChildren() { HTMLElement::finishParsingChildren(); - m_parsingInProgress = false; - - if (!RuntimeEnabledFeatures::videoTrackEnabled()) - return; - for (Node* node = firstChild(); node; node = node->nextSibling()) { - if (node->hasTagName(trackTag)) { - scheduleDelayedAction(LoadTextTrackResource); - break; - } - } + if (Traversal<HTMLTrackElement>::firstChild(*this)) + scheduleDelayedAction(LoadTextTrackResource); } bool HTMLMediaElement::rendererIsNeeded(const RenderStyle& style) @@ -473,11 +539,6 @@ RenderObject* HTMLMediaElement::createRenderer(RenderStyle*) return new RenderMedia(this); } -bool HTMLMediaElement::childShouldCreateRenderer(const Node& child) const -{ - return hasMediaControls() && HTMLElement::childShouldCreateRenderer(child); -} - Node::InsertionNotificationRequest HTMLMediaElement::insertedInto(ContainerNode* insertionPoint) { WTF_LOG(Media, "HTMLMediaElement::insertedInto"); @@ -490,8 +551,12 @@ Node::InsertionNotificationRequest HTMLMediaElement::insertedInto(ContainerNode* scheduleDelayedAction(LoadMediaResource); } + return InsertionShouldCallDidNotifySubtreeInsertions; +} + +void HTMLMediaElement::didNotifySubtreeInsertionsToDocument() +{ configureMediaControls(); - return InsertionDone; } void HTMLMediaElement::removedFrom(ContainerNode* insertionPoint) @@ -499,7 +564,7 @@ void HTMLMediaElement::removedFrom(ContainerNode* insertionPoint) WTF_LOG(Media, "HTMLMediaElement::removedFrom"); m_active = false; - if (insertionPoint->inDocument()) { + if (insertionPoint->inDocument() && insertionPoint->document().isActive()) { configureMediaControls(); if (m_networkState > NETWORK_EMPTY) pause(); @@ -531,33 +596,36 @@ void HTMLMediaElement::scheduleDelayedAction(DelayedActionType actionType) m_pendingActionFlags |= LoadMediaResource; } - if (RuntimeEnabledFeatures::videoTrackEnabled() && (actionType & LoadTextTrackResource)) + if (actionType & LoadTextTrackResource) m_pendingActionFlags |= LoadTextTrackResource; if (!m_loadTimer.isActive()) - m_loadTimer.startOneShot(0); + m_loadTimer.startOneShot(0, FROM_HERE); } void HTMLMediaElement::scheduleNextSourceChild() { // Schedule the timer to try the next <source> element WITHOUT resetting state ala prepareForLoad. m_pendingActionFlags |= LoadMediaResource; - m_loadTimer.startOneShot(0); + m_loadTimer.startOneShot(0, FROM_HERE); } void HTMLMediaElement::scheduleEvent(const AtomicString& eventName) { + scheduleEvent(Event::createCancelable(eventName)); +} + +void HTMLMediaElement::scheduleEvent(PassRefPtrWillBeRawPtr<Event> event) +{ #if LOG_MEDIA_EVENTS - WTF_LOG(Media, "HTMLMediaElement::scheduleEvent - scheduling '%s'", eventName.string().ascii().data()); + WTF_LOG(Media, "HTMLMediaElement::scheduleEvent - scheduling '%s'", event->type().ascii().data()); #endif - m_asyncEventQueue->enqueueEvent(Event::createCancelable(eventName)); + m_asyncEventQueue->enqueueEvent(event); } void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*) { - RefPtr<HTMLMediaElement> protect(this); // loadNextSourceChild may fire 'beforeload', which can make arbitrary DOM mutations. - - if (RuntimeEnabledFeatures::videoTrackEnabled() && (m_pendingActionFlags & LoadTextTrackResource)) + if (m_pendingActionFlags & LoadTextTrackResource) configureTextTracks(); if (m_pendingActionFlags & LoadMediaResource) { @@ -570,7 +638,7 @@ void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*) m_pendingActionFlags = 0; } -PassRefPtr<MediaError> HTMLMediaElement::error() const +PassRefPtrWillBeRawPtr<MediaError> HTMLMediaElement::error() const { return m_error; } @@ -585,8 +653,11 @@ HTMLMediaElement::NetworkState HTMLMediaElement::networkState() const return m_networkState; } -String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySystem, const KURL& url) const +String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySystem) const { + if (!keySystem.isNull()) + UseCounter::count(document(), UseCounter::CanPlayTypeKeySystem); + WebMimeRegistry::SupportsType support = supportsType(ContentType(mimeType), keySystem); String canPlay; @@ -604,26 +675,18 @@ String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySy break; } - WTF_LOG(Media, "HTMLMediaElement::canPlayType(%s, %s, %s) -> %s", mimeType.utf8().data(), keySystem.utf8().data(), url.elidedString().utf8().data(), canPlay.utf8().data()); + WTF_LOG(Media, "HTMLMediaElement::canPlayType(%s, %s) -> %s", mimeType.utf8().data(), keySystem.utf8().data(), canPlay.utf8().data()); return canPlay; } void HTMLMediaElement::load() { - RefPtr<HTMLMediaElement> protect(this); // loadInternal may result in a 'beforeload' event, which can make arbitrary DOM mutations. - WTF_LOG(Media, "HTMLMediaElement::load()"); - if (document().settings() && !document().settings()->mediaEnabled()) - return; - - if (userGestureRequiredForLoad() && !UserGestureIndicator::processingUserGesture()) - return; + if (UserGestureIndicator::processingUserGesture()) + m_userGestureRequiredForPlay = false; - m_loadInitiatedByUserGesture = UserGestureIndicator::processingUserGesture(); - if (m_loadInitiatedByUserGesture) - removeBehaviorsRestrictionsAfterFirstUserGesture(); prepareForLoad(); loadInternal(); prepareToPlay(); @@ -636,6 +699,9 @@ void HTMLMediaElement::prepareForLoad() // Perform the cleanup required for the resource load algorithm to run. stopPeriodicTimers(); m_loadTimer.stop(); + cancelDeferredLoad(); + // FIXME: Figure out appropriate place to reset LoadTextTrackResource if necessary and set m_pendingActionFlags to 0 here. + m_pendingActionFlags &= ~LoadMediaResource; m_sentEndEvent = false; m_sentStalledEvent = false; m_haveFiredLoadedData = false; @@ -645,7 +711,7 @@ void HTMLMediaElement::prepareForLoad() // 1 - Abort any already-running instance of the resource selection algorithm for this element. m_loadState = WaitingForSource; - m_currentSourceNode = 0; + m_currentSourceNode = nullptr; // 2 - If there are any tasks from the media element's media element event task source in // one of the task queues, then remove those tasks. @@ -656,30 +722,53 @@ void HTMLMediaElement::prepareForLoad() if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) scheduleEvent(EventTypeNames::abort); - closeMediaSource(); - createMediaPlayer(); // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps if (m_networkState != NETWORK_EMPTY) { + // 4.1 - Queue a task to fire a simple event named emptied at the media element. + scheduleEvent(EventTypeNames::emptied); + + // 4.2 - If a fetching process is in progress for the media element, the user agent should stop it. m_networkState = NETWORK_EMPTY; + + // 4.3 - Forget the media element's media-resource-specific tracks. + forgetResourceSpecificTracks(); + + // 4.4 - If readyState is not set to HAVE_NOTHING, then set it to that state. m_readyState = HAVE_NOTHING; m_readyStateMaximum = HAVE_NOTHING; - refreshCachedTime(); + + // 4.5 - If the paused attribute is false, then set it to true. m_paused = true; + + // 4.6 - If seeking is true, set it to false. m_seeking = false; + + // 4.7 - Set the current playback position to 0. + // Set the official playback position to 0. + // If this changed the official playback position, then queue a task to fire a simple event named timeupdate at the media element. + // FIXME: Add support for firing this event. + + // 4.8 - Set the initial playback position to 0. + // FIXME: Make this less subtle. The position only becomes 0 because of the createMediaPlayer() call + // above. + refreshCachedTime(); invalidateCachedTime(); - scheduleEvent(EventTypeNames::emptied); + + // 4.9 - Set the timeline offset to Not-a-Number (NaN). + // 4.10 - Update the duration attribute to Not-a-Number (NaN). + + updateMediaController(); - if (RuntimeEnabledFeatures::videoTrackEnabled()) - updateActiveTextTrackCues(0); + updateActiveTextTrackCues(0); } // 5 - Set the playbackRate attribute to the value of the defaultPlaybackRate attribute. setPlaybackRate(defaultPlaybackRate()); // 6 - Set the error attribute to null and the autoplaying flag to true. - m_error = 0; + m_error = nullptr; m_autoplaying = true; // 7 - Invoke the media element's resource selection algorithm. @@ -693,8 +782,11 @@ void HTMLMediaElement::prepareForLoad() // 2 - Asynchronously await a stable state. m_playedTimeRanges = TimeRanges::create(); + + // FIXME: Investigate whether these can be moved into m_networkState != NETWORK_EMPTY block above + // so they are closer to the relevant spec steps. m_lastSeekTime = 0; - m_duration = numeric_limits<double>::quiet_NaN(); + m_duration = std::numeric_limits<double>::quiet_NaN(); // The spec doesn't say to block the load event until we actually run the asynchronous section // algorithm, but do it now because we won't start that until after the timer fires and the @@ -706,26 +798,14 @@ void HTMLMediaElement::prepareForLoad() void HTMLMediaElement::loadInternal() { - // Some of the code paths below this function dispatch the BeforeLoad event. This ASSERT helps - // us catch those bugs more quickly without needing all the branches to align to actually - // trigger the event. - ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); - - // Once the page has allowed an element to load media, it is free to load at will. This allows a - // playlist that starts in a foreground tab to continue automatically if the tab is subsequently - // put in the the background. - removeBehaviorRestriction(RequirePageConsentToLoadMediaRestriction); - // HTMLMediaElement::textTracksAreReady will need "... the text tracks whose mode was not in the // disabled state when the element's resource selection algorithm last started". - if (RuntimeEnabledFeatures::videoTrackEnabled()) { - m_textTracksWhenResourceSelectionBegan.clear(); - if (m_textTracks) { - for (unsigned i = 0; i < m_textTracks->length(); ++i) { - TextTrack* track = m_textTracks->item(i); - if (track->mode() != TextTrack::disabledKeyword()) - m_textTracksWhenResourceSelectionBegan.append(track); - } + m_textTracksWhenResourceSelectionBegan.clear(); + if (m_textTracks) { + for (unsigned i = 0; i < m_textTracks->length(); ++i) { + TextTrack* track = m_textTracks->item(i); + if (track->mode() != TextTrack::disabledKeyword()) + m_textTracksWhenResourceSelectionBegan.append(track); } } @@ -741,19 +821,13 @@ void HTMLMediaElement::selectMediaResource() // 3 - If the media element has a src attribute, then let mode be attribute. Mode mode = attribute; if (!fastHasAttribute(srcAttr)) { - Node* node; - for (node = firstChild(); node; node = node->nextSibling()) { - if (node->hasTagName(sourceTag)) - break; - } - // Otherwise, if the media element does not have a src attribute but has a source // element child, then let mode be children and let candidate be the first such // source element child in tree order. - if (node) { + if (HTMLSourceElement* element = Traversal<HTMLSourceElement>::firstChild(*this)) { mode = children; - m_nextChildNodeToConsider = node; - m_currentSourceNode = 0; + m_nextChildNodeToConsider = element; + m_currentSourceNode = nullptr; } else { // Otherwise the media element has neither a src attribute nor a source element // child: set the networkState to NETWORK_EMPTY, and abort these steps; the @@ -787,7 +861,7 @@ void HTMLMediaElement::selectMediaResource() return; } - if (!isSafeToLoadURL(mediaURL, Complain) || !dispatchBeforeLoadEvent(mediaURL.string())) { + if (!isSafeToLoadURL(mediaURL, Complain)) { mediaLoadingFailed(MediaPlayer::FormatError); return; } @@ -828,7 +902,7 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType, c WTF_LOG(Media, "HTMLMediaElement::loadResource(%s, %s, %s)", urlForLoggingMedia(url).utf8().data(), contentType.raw().utf8().data(), keySystem.utf8().data()); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) { mediaLoadingFailed(MediaPlayer::FormatError); return; @@ -843,16 +917,13 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType, c WTF_LOG(Media, "HTMLMediaElement::loadResource - m_currentSrc -> %s", urlForLoggingMedia(m_currentSrc).utf8().data()); - if (MediaStreamRegistry::registry().lookupMediaStreamDescriptor(url.string())) - removeBehaviorRestriction(RequireUserGestureForRateChangeRestriction); - startProgressEventTimer(); // Reset display mode to force a recalculation of what to show because we are resetting the player. setDisplayMode(Unknown); if (!autoplay()) - m_player->setPreload(m_preload); + setPlayerPreload(); if (fastHasAttribute(mutedAttr)) m_muted = true; @@ -860,20 +931,34 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType, c ASSERT(!m_mediaSource); - if (url.protocolIs(mediaSourceBlobProtocol)) - m_mediaSource = HTMLMediaSource::lookup(url.string()); + bool attemptLoad = true; - if (m_mediaSource) { - if (m_mediaSource->attachToElement(this)) { - m_player->load(url, m_mediaSource); + if (url.protocolIs(mediaSourceBlobProtocol)) { + if (isMediaStreamURL(url.string())) { + m_userGestureRequiredForPlay = false; } else { - // Forget our reference to the MediaSource, so we leave it alone - // while processing remainder of load failure. - m_mediaSource = 0; - mediaLoadingFailed(MediaPlayer::FormatError); + m_mediaSource = HTMLMediaSource::lookup(url.string()); + + if (m_mediaSource) { + if (!m_mediaSource->attachToElement(this)) { + // Forget our reference to the MediaSource, so we leave it alone + // while processing remainder of load failure. + m_mediaSource = nullptr; + attemptLoad = false; + } + } + } + } + + if (attemptLoad && canLoadURL(url, contentType, keySystem)) { + ASSERT(!webMediaPlayer()); + + if (!m_havePreparedToPlay && !autoplay() && m_preload == MediaPlayer::None) { + WTF_LOG(Media, "HTMLMediaElement::loadResource : Delaying load because preload == 'none'"); + deferLoad(); + } else { + startPlayerLoad(); } - } else if (canLoadURL(url, contentType, keySystem)) { - m_player->load(url); } else { mediaLoadingFailed(MediaPlayer::FormatError); } @@ -886,6 +971,118 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType, c renderer()->updateFromElement(); } +void HTMLMediaElement::startPlayerLoad() +{ + // Filter out user:pass as those two URL components aren't + // considered for media resource fetches (including for the CORS + // use-credentials mode.) That behavior aligns with Gecko, with IE + // being more restrictive and not allowing fetches to such URLs. + // + // Spec reference: http://whatwg.org/c/#concept-media-load-resource + // + // FIXME: when the HTML spec switches to specifying resource + // fetches in terms of Fetch (http://fetch.spec.whatwg.org), and + // along with that potentially also specifying a setting for its + // 'authentication flag' to control how user:pass embedded in a + // media resource URL should be treated, then update the handling + // here to match. + KURL requestURL = m_currentSrc; + if (!requestURL.user().isEmpty()) + requestURL.setUser(String()); + if (!requestURL.pass().isEmpty()) + requestURL.setPass(String()); + + m_player->load(loadType(), requestURL, corsMode()); +} + +void HTMLMediaElement::setPlayerPreload() +{ + m_player->setPreload(m_preload); + + if (loadIsDeferred() && m_preload != MediaPlayer::None) + startDeferredLoad(); +} + +bool HTMLMediaElement::loadIsDeferred() const +{ + return m_deferredLoadState != NotDeferred; +} + +void HTMLMediaElement::deferLoad() +{ + // This implements the "optional" step 3 from the resource fetch algorithm. + ASSERT(!m_deferredLoadTimer.isActive()); + ASSERT(m_deferredLoadState == NotDeferred); + // 1. Set the networkState to NETWORK_IDLE. + // 2. Queue a task to fire a simple event named suspend at the element. + changeNetworkStateFromLoadingToIdle(); + // 3. Queue a task to set the element's delaying-the-load-event + // flag to false. This stops delaying the load event. + m_deferredLoadTimer.startOneShot(0, FROM_HERE); + // 4. Wait for the task to be run. + m_deferredLoadState = WaitingForStopDelayingLoadEventTask; + // Continued in executeDeferredLoad(). +} + +void HTMLMediaElement::cancelDeferredLoad() +{ + m_deferredLoadTimer.stop(); + m_deferredLoadState = NotDeferred; +} + +void HTMLMediaElement::executeDeferredLoad() +{ + ASSERT(m_deferredLoadState >= WaitingForTrigger); + + // resource fetch algorithm step 3 - continued from deferLoad(). + + // 5. Wait for an implementation-defined event (e.g. the user requesting that the media element begin playback). + // This is assumed to be whatever 'event' ended up calling this method. + cancelDeferredLoad(); + // 6. Set the element's delaying-the-load-event flag back to true (this + // delays the load event again, in case it hasn't been fired yet). + setShouldDelayLoadEvent(true); + // 7. Set the networkState to NETWORK_LOADING. + m_networkState = NETWORK_LOADING; + + startProgressEventTimer(); + + startPlayerLoad(); +} + +void HTMLMediaElement::startDeferredLoad() +{ + if (m_deferredLoadState == WaitingForTrigger) { + executeDeferredLoad(); + return; + } + ASSERT(m_deferredLoadState == WaitingForStopDelayingLoadEventTask); + m_deferredLoadState = ExecuteOnStopDelayingLoadEventTask; +} + +void HTMLMediaElement::deferredLoadTimerFired(Timer<HTMLMediaElement>*) +{ + setShouldDelayLoadEvent(false); + + if (m_deferredLoadState == ExecuteOnStopDelayingLoadEventTask) { + executeDeferredLoad(); + return; + } + ASSERT(m_deferredLoadState == WaitingForStopDelayingLoadEventTask); + m_deferredLoadState = WaitingForTrigger; +} + +WebMediaPlayer::LoadType HTMLMediaElement::loadType() const +{ + if (m_mediaSource) + return WebMediaPlayer::LoadTypeMediaSource; + + if (isMediaStreamURL(m_currentSrc.string())) + return WebMediaPlayer::LoadTypeMediaStream; + + return WebMediaPlayer::LoadTypeURL; +} + static bool trackIndexCompare(TextTrack* a, TextTrack* b) { @@ -923,8 +1120,6 @@ void HTMLMediaElement::updateActiveTextTrackCues(double movieTime) if (ignoreTrackDisplayUpdateRequests()) return; - WTF_LOG(Media, "HTMLMediaElement::updateActiveTextTrackCues"); - // 1 - Let current cues be a list of cues, initialized to contain all the // cues of all the hidden, showing, or showing by default text tracks of the // media element (not the disabled ones) whose start times are less than or @@ -965,7 +1160,7 @@ void HTMLMediaElement::updateActiveTextTrackCues(double movieTime) double cueEndTime = potentiallySkippedCues[i].high(); // Consider cues that may have been missed since the last seek time. - if (cueStartTime > max(m_lastSeekTime, lastTime) && cueEndTime < movieTime) + if (cueStartTime > std::max(m_lastSeekTime, lastTime) && cueEndTime < movieTime) missedCues.append(potentiallySkippedCues[i]); } } @@ -1079,7 +1274,7 @@ void HTMLMediaElement::updateActiveTextTrackCues(double movieTime) affectedTracks.append(eventTasks[i].second->track()); // 13 - Queue each task in events, in list order. - RefPtr<Event> event; + RefPtrWillBeRawPtr<Event> event = nullptr; // Each event in eventTasks may be either an enterEvent or an exitEvent, // depending on the time that is associated with the event. This @@ -1111,7 +1306,7 @@ void HTMLMediaElement::updateActiveTextTrackCues(double movieTime) // 15 - For each text track in affected tracks, in the list order, queue a // task to fire a simple event named cuechange at the TextTrack object, and, ... for (size_t i = 0; i < affectedTracks.size(); ++i) { - RefPtr<Event> event = Event::create(EventTypeNames::cuechange); + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::cuechange); event->setTarget(affectedTracks[i]); m_asyncEventQueue->enqueueEvent(event.release()); @@ -1119,7 +1314,7 @@ void HTMLMediaElement::updateActiveTextTrackCues(double movieTime) // ... if the text track has a corresponding track element, to then fire a // simple event named cuechange at the track element as well. if (affectedTracks[i]->trackType() == TextTrack::TrackElement) { - RefPtr<Event> event = Event::create(EventTypeNames::cuechange); + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::cuechange); HTMLTrackElement* trackElement = static_cast<LoadableTextTrack*>(affectedTracks[i])->trackElement(); ASSERT(trackElement); event->setTarget(trackElement); @@ -1163,9 +1358,9 @@ bool HTMLMediaElement::textTracksAreReady() const void HTMLMediaElement::textTrackReadyStateChanged(TextTrack* track) { - if (m_player && m_textTracksWhenResourceSelectionBegan.contains(track)) { + if (webMediaPlayer()&& m_textTracksWhenResourceSelectionBegan.contains(track)) { if (track->readinessState() != TextTrack::Loading) - setReadyState(m_player->readyState()); + setReadyState(static_cast<ReadyState>(webMediaPlayer()->readyState())); } else { // The track readiness state might have changed as a result of the user // clicking the captions button. In this case, a check whether all the @@ -1184,10 +1379,7 @@ void HTMLMediaElement::textTrackModeChanged(TextTrack* track) // or showing by default for the first time, the user agent must immediately and synchronously // run the following algorithm ... - for (Node* node = firstChild(); node; node = node->nextSibling()) { - if (!node->hasTagName(trackTag)) - continue; - HTMLTrackElement* trackElement = toHTMLTrackElement(node); + for (HTMLTrackElement* trackElement = Traversal<HTMLTrackElement>::firstChild(*this); trackElement; trackElement = Traversal<HTMLTrackElement>::nextSibling(*trackElement)) { if (trackElement->track() != track) continue; @@ -1203,8 +1395,9 @@ void HTMLMediaElement::textTrackModeChanged(TextTrack* track) } break; } - } else if (track->trackType() == TextTrack::AddTrack && track->mode() != TextTrack::disabledKeyword()) + } else if (track->trackType() == TextTrack::AddTrack && track->mode() != TextTrack::disabledKeyword()) { textTrackAddCues(track, track->cues()); + } configureTextTrackDisplay(AssumeVisibleChange); @@ -1251,14 +1444,14 @@ void HTMLMediaElement::textTrackRemoveCues(TextTrack*, const TextTrackCueList* c textTrackRemoveCue(cues->item(i)->track(), cues->item(i)); } -void HTMLMediaElement::textTrackAddCue(TextTrack* track, PassRefPtr<TextTrackCue> cue) +void HTMLMediaElement::textTrackAddCue(TextTrack* track, PassRefPtrWillBeRawPtr<TextTrackCue> cue) { if (track->mode() == TextTrack::disabledKeyword()) return; // Negative duration cues need be treated in the interval tree as // zero-length cues. - double endTime = max(cue->startTime(), cue->endTime()); + double endTime = std::max(cue->startTime(), cue->endTime()); CueInterval interval = m_cueTree.createInterval(cue->startTime(), endTime, cue.get()); if (!m_cueTree.contains(interval)) @@ -1266,11 +1459,11 @@ void HTMLMediaElement::textTrackAddCue(TextTrack* track, PassRefPtr<TextTrackCue updateActiveTextTrackCues(currentTime()); } -void HTMLMediaElement::textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue> cue) +void HTMLMediaElement::textTrackRemoveCue(TextTrack*, PassRefPtrWillBeRawPtr<TextTrackCue> cue) { // Negative duration cues need to be treated in the interval tree as // zero-length cues. - double endTime = max(cue->startTime(), cue->endTime()); + double endTime = std::max(cue->startTime(), cue->endTime()); CueInterval interval = m_cueTree.createInterval(cue->startTime(), endTime, cue.get()); m_cueTree.remove(interval); @@ -1299,7 +1492,7 @@ bool HTMLMediaElement::isSafeToLoadURL(const KURL& url, InvalidURLAction actionI return false; } - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame || !document().securityOrigin()->canDisplay(url)) { if (actionIfInvalid == Complain) FrameLoader::reportLocalLoadFailed(frame, url.elidedString()); @@ -1322,7 +1515,7 @@ void HTMLMediaElement::startProgressEventTimer() m_previousProgressTime = WTF::currentTime(); // 350ms is not magic, it is in the spec! - m_progressEventTimer.startRepeating(0.350); + m_progressEventTimer.startRepeating(0.350, FROM_HERE); } void HTMLMediaElement::waitForSourceChange() @@ -1350,7 +1543,7 @@ void HTMLMediaElement::noneSupported() stopPeriodicTimers(); m_loadState = WaitingForSource; - m_currentSourceNode = 0; + m_currentSourceNode = nullptr; // 4.8.10.5 // 6 - Reaching this step indicates that the media resource failed to load or that the given @@ -1361,6 +1554,7 @@ void HTMLMediaElement::noneSupported() m_error = MediaError::create(MediaError::MEDIA_ERR_SRC_NOT_SUPPORTED); // 6.2 - Forget the media element's media-resource-specific text tracks. + forgetResourceSpecificTracks(); // 6.3 - Set the element's networkState attribute to the NETWORK_NO_SOURCE value. m_networkState = NETWORK_NO_SOURCE; @@ -1382,7 +1576,7 @@ void HTMLMediaElement::noneSupported() renderer()->updateFromElement(); } -void HTMLMediaElement::mediaEngineError(PassRefPtr<MediaError> err) +void HTMLMediaElement::mediaEngineError(PassRefPtrWillBeRawPtr<MediaError> err) { WTF_LOG(Media, "HTMLMediaElement::mediaEngineError(%d)", static_cast<int>(err->code())); @@ -1408,7 +1602,7 @@ void HTMLMediaElement::mediaEngineError(PassRefPtr<MediaError> err) setShouldDelayLoadEvent(false); // 6 - Abort the overall resource selection algorithm. - m_currentSourceNode = 0; + m_currentSourceNode = nullptr; } void HTMLMediaElement::cancelPendingEventsAndCallbacks() @@ -1416,10 +1610,8 @@ void HTMLMediaElement::cancelPendingEventsAndCallbacks() WTF_LOG(Media, "HTMLMediaElement::cancelPendingEventsAndCallbacks"); m_asyncEventQueue->cancelAllEvents(); - for (Node* node = firstChild(); node; node = node->nextSibling()) { - if (node->hasTagName(sourceTag)) - toHTMLSourceElement(node)->cancelPendingErrorEvent(); - } + for (HTMLSourceElement* source = Traversal<HTMLSourceElement>::firstChild(*this); source; source = Traversal<HTMLSourceElement>::nextSibling(*source)) + source->cancelPendingErrorEvent(); } void HTMLMediaElement::mediaPlayerNetworkStateChanged() @@ -1435,11 +1627,18 @@ void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState error) // <source> children, schedule the next one if (m_readyState < HAVE_METADATA && m_loadState == LoadingFromSourceElement) { + // resource selection algorithm + // Step 9.Otherwise.9 - Failed with elements: Queue a task, using the DOM manipulation task source, to fire a simple event named error at the candidate element. if (m_currentSourceNode) m_currentSourceNode->scheduleErrorEvent(); else WTF_LOG(Media, "HTMLMediaElement::setNetworkState - error event not sent, <source> was removed"); + // 9.Otherwise.10 - Asynchronously await a stable state. The synchronous section consists of all the remaining steps of this algorithm until the algorithm says the synchronous section has ended. + + // 9.Otherwise.11 - Forget the media element's media-resource-specific tracks. + forgetResourceSpecificTracks(); + if (havePotentialSourceChild()) { WTF_LOG(Media, "HTMLMediaElement::setNetworkState - scheduling next <source>"); scheduleNextSourceChild(); @@ -1459,10 +1658,8 @@ void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState error) noneSupported(); updateDisplayState(); - if (hasMediaControls()) { + if (hasMediaControls()) mediaControls()->reset(); - mediaControls()->reportedError(); - } } void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state) @@ -1500,30 +1697,27 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state) changeNetworkStateFromLoadingToIdle(); m_completelyLoaded = true; } - - if (hasMediaControls()) - mediaControls()->updateStatusDisplay(); } void HTMLMediaElement::changeNetworkStateFromLoadingToIdle() { + ASSERT(m_player); m_progressEventTimer.stop(); - if (hasMediaControls() && m_player->didLoadingProgress()) - mediaControls()->bufferingProgressed(); // Schedule one last progress event so we guarantee that at least one is fired // for files that load very quickly. - scheduleEvent(EventTypeNames::progress); + if (m_player->didLoadingProgress()) + scheduleEvent(EventTypeNames::progress); scheduleEvent(EventTypeNames::suspend); m_networkState = NETWORK_IDLE; } void HTMLMediaElement::mediaPlayerReadyStateChanged() { - setReadyState(m_player->readyState()); + setReadyState(static_cast<ReadyState>(webMediaPlayer()->readyState())); } -void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) +void HTMLMediaElement::setReadyState(ReadyState state) { WTF_LOG(Media, "HTMLMediaElement::setReadyState(%d) - current state is %d,", static_cast<int>(state), static_cast<int>(m_readyState)); @@ -1531,9 +1725,9 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) bool wasPotentiallyPlaying = potentiallyPlaying(); ReadyState oldState = m_readyState; - ReadyState newState = static_cast<ReadyState>(state); + ReadyState newState = state; - bool tracksAreReady = !RuntimeEnabledFeatures::videoTrackEnabled() || textTracksAreReady(); + bool tracksAreReady = textTracksAreReady(); if (newState == oldState && m_tracksAreReady == tracksAreReady) return; @@ -1576,11 +1770,20 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) } if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { + createPlaceholderTracksIfNecessary(); + prepareMediaFragmentURI(); + + selectInitialTracksIfNecessary(); + + m_duration = duration(); scheduleEvent(EventTypeNames::durationchange); + + if (isHTMLVideoElement(*this)) + scheduleEvent(EventTypeNames::resize); scheduleEvent(EventTypeNames::loadedmetadata); if (hasMediaControls()) - mediaControls()->loadedMetadata(); + mediaControls()->reset(); if (renderer()) renderer()->updateFromElement(); } @@ -1604,154 +1807,33 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) } if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA && tracksAreReady) { - if (oldState <= HAVE_CURRENT_DATA) + if (oldState <= HAVE_CURRENT_DATA) { scheduleEvent(EventTypeNames::canplay); + if (isPotentiallyPlaying) + scheduleEvent(EventTypeNames::playing); + } - scheduleEvent(EventTypeNames::canplaythrough); - - if (isPotentiallyPlaying && oldState <= HAVE_CURRENT_DATA) - scheduleEvent(EventTypeNames::playing); - - if (m_autoplaying && m_paused && autoplay() && !document().isSandboxed(SandboxAutomaticFeatures) && !userGestureRequiredForRateChange()) { + if (m_autoplaying && m_paused && autoplay() && !document().isSandboxed(SandboxAutomaticFeatures) && !m_userGestureRequiredForPlay) { m_paused = false; invalidateCachedTime(); scheduleEvent(EventTypeNames::play); scheduleEvent(EventTypeNames::playing); } + scheduleEvent(EventTypeNames::canplaythrough); + shouldUpdateDisplayState = true; } if (shouldUpdateDisplayState) { updateDisplayState(); - if (hasMediaControls()) { + if (hasMediaControls()) mediaControls()->refreshClosedCaptionsButtonVisibility(); - mediaControls()->updateStatusDisplay(); - } } updatePlayState(); updateMediaController(); - if (RuntimeEnabledFeatures::videoTrackEnabled()) - updateActiveTextTrackCues(currentTime()); -} - -void HTMLMediaElement::mediaPlayerKeyAdded(const String& keySystem, const String& sessionId) -{ - MediaKeyEventInit initializer; - initializer.keySystem = keySystem; - initializer.sessionId = sessionId; - initializer.bubbles = false; - initializer.cancelable = false; - - RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyadded, initializer); - event->setTarget(this); - m_asyncEventQueue->enqueueEvent(event.release()); -} - -void HTMLMediaElement::mediaPlayerKeyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode errorCode, unsigned short systemCode) -{ - MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; - switch (errorCode) { - case MediaPlayerClient::UnknownError: - mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; - break; - case MediaPlayerClient::ClientError: - mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT; - break; - case MediaPlayerClient::ServiceError: - mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_SERVICE; - break; - case MediaPlayerClient::OutputError: - mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_OUTPUT; - break; - case MediaPlayerClient::HardwareChangeError: - mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_HARDWARECHANGE; - break; - case MediaPlayerClient::DomainError: - mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_DOMAIN; - break; - } - - MediaKeyEventInit initializer; - initializer.keySystem = keySystem; - initializer.sessionId = sessionId; - initializer.errorCode = MediaKeyError::create(mediaKeyErrorCode); - initializer.systemCode = systemCode; - initializer.bubbles = false; - initializer.cancelable = false; - - RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyerror, initializer); - event->setTarget(this); - m_asyncEventQueue->enqueueEvent(event.release()); -} - -void HTMLMediaElement::mediaPlayerKeyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const KURL& defaultURL) -{ - MediaKeyEventInit initializer; - initializer.keySystem = keySystem; - initializer.sessionId = sessionId; - initializer.message = Uint8Array::create(message, messageLength); - initializer.defaultURL = defaultURL; - initializer.bubbles = false; - initializer.cancelable = false; - - RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeymessage, initializer); - event->setTarget(this); - m_asyncEventQueue->enqueueEvent(event.release()); -} - -bool HTMLMediaElement::mediaPlayerKeyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) -{ - if (!hasEventListeners(EventTypeNames::webkitneedkey)) { - m_error = MediaError::create(MediaError::MEDIA_ERR_ENCRYPTED); - scheduleEvent(EventTypeNames::error); - return false; - } - - MediaKeyEventInit initializer; - initializer.keySystem = keySystem; - initializer.sessionId = sessionId; - initializer.initData = Uint8Array::create(initData, initDataLength); - initializer.bubbles = false; - initializer.cancelable = false; - - RefPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitneedkey, initializer); - event->setTarget(this); - m_asyncEventQueue->enqueueEvent(event.release()); - return true; -} - -bool HTMLMediaElement::mediaPlayerKeyNeeded(Uint8Array* initData) -{ - if (!hasEventListeners("webkitneedkey")) { - m_error = MediaError::create(MediaError::MEDIA_ERR_ENCRYPTED); - scheduleEvent(EventTypeNames::error); - return false; - } - - MediaKeyNeededEventInit initializer; - initializer.initData = initData; - initializer.bubbles = false; - initializer.cancelable = false; - - RefPtr<Event> event = MediaKeyNeededEvent::create(EventTypeNames::webkitneedkey, initializer); - event->setTarget(this); - m_asyncEventQueue->enqueueEvent(event.release()); - - return true; -} - -void HTMLMediaElement::setMediaKeys(MediaKeys* mediaKeys) -{ - if (m_mediaKeys == mediaKeys) - return; - - if (m_mediaKeys) - m_mediaKeys->setMediaElement(0); - m_mediaKeys = mediaKeys; - if (m_mediaKeys) - m_mediaKeys->setMediaElement(this); + updateActiveTextTrackCues(currentTime()); } void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*) @@ -1769,8 +1851,6 @@ void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*) m_sentStalledEvent = false; if (renderer()) renderer()->updateFromElement(); - if (hasMediaControls()) - mediaControls()->bufferingProgressed(); } else if (timedelta > 3.0 && !m_sentStalledEvent) { scheduleEvent(EventTypeNames::stalled); m_sentStalledEvent = true; @@ -1797,7 +1877,9 @@ void HTMLMediaElement::prepareToPlay() if (m_havePreparedToPlay) return; m_havePreparedToPlay = true; - m_player->prepareToPlay(); + + if (loadIsDeferred()) + startDeferredLoad(); } void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) @@ -1808,7 +1890,7 @@ void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) // 1 - If the media element's readyState is HAVE_NOTHING, then raise an InvalidStateError exception. if (m_readyState == HAVE_NOTHING || !m_player) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The element's readyState is HAVE_NOTHING."); return; } @@ -1827,14 +1909,15 @@ void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) // 3 - Set the seeking IDL attribute to true. // The flag will be cleared when the engine tells us the time has actually changed. + bool previousSeekStillPending = m_seeking; m_seeking = true; // 5 - If the new playback position is later than the end of the media resource, then let it be the end // of the media resource instead. - time = min(time, duration()); + time = std::min(time, duration()); // 6 - If the new playback position is less than the earliest possible position, let it be that position instead. - time = max(time, 0.0); + time = std::max(time, 0.0); // Ask the media engine for the time value in the movie's time scale before comparing with current time. This // is necessary because if the seek time is not equal to currentTime but the delta is less than the movie's @@ -1859,14 +1942,11 @@ void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) // cancel poster display. bool noSeekRequired = !seekableRanges->length() || (time == now && displayMode() != Poster); - // Always notify the media engine of a seek if the source is not closed. This ensures that the source is - // always in a flushed state when the 'seeking' event fires. - if (m_mediaSource && m_mediaSource->isClosed()) - noSeekRequired = false; - if (noSeekRequired) { if (time == now) { scheduleEvent(EventTypeNames::seeking); + if (previousSeekStillPending) + return; // FIXME: There must be a stable state before timeupdate+seeked are dispatched and seeking // is reset to false. See http://crbug.com/266631 scheduleTimeupdateEvent(false); @@ -1918,7 +1998,7 @@ HTMLMediaElement::ReadyState HTMLMediaElement::readyState() const bool HTMLMediaElement::hasAudio() const { - return m_player ? m_player->hasAudio() : false; + return webMediaPlayer() && webMediaPlayer()->hasAudio(); } bool HTMLMediaElement::seeking() const @@ -1977,7 +2057,7 @@ double HTMLMediaElement::currentTime() const void HTMLMediaElement::setCurrentTime(double time, ExceptionState& exceptionState) { if (m_mediaController) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The element is slaved to a MediaController."); return; } seek(time, exceptionState); @@ -1986,12 +2066,12 @@ void HTMLMediaElement::setCurrentTime(double time, ExceptionState& exceptionStat double HTMLMediaElement::duration() const { if (!m_player || m_readyState < HAVE_METADATA) - return numeric_limits<double>::quiet_NaN(); + return std::numeric_limits<double>::quiet_NaN(); // FIXME: Refactor so m_duration is kept current (in both MSE and // non-MSE cases) once we have transitioned from HAVE_NOTHING -> // HAVE_METADATA. Currently, m_duration may be out of date for at least MSE - // case because MediaSourceBase and SourceBuffer do not notify the element + // case because MediaSource and SourceBuffer do not notify the element // directly upon duration changes caused by endOfStream, remove, or append // operations; rather the notification is triggered by the WebMediaPlayer // implementation observing that the underlying engine has updated duration @@ -2016,10 +2096,11 @@ double HTMLMediaElement::defaultPlaybackRate() const void HTMLMediaElement::setDefaultPlaybackRate(double rate) { - if (m_defaultPlaybackRate != rate) { - m_defaultPlaybackRate = rate; - scheduleEvent(EventTypeNames::ratechange); - } + if (m_defaultPlaybackRate == rate) + return; + + m_defaultPlaybackRate = rate; + scheduleEvent(EventTypeNames::ratechange); } double HTMLMediaElement::playbackRate() const @@ -2037,13 +2118,22 @@ void HTMLMediaElement::setPlaybackRate(double rate) scheduleEvent(EventTypeNames::ratechange); } - if (m_player && potentiallyPlaying() && m_player->rate() != rate && !m_mediaController) - m_player->setRate(rate); + updatePlaybackRate(); +} + +double HTMLMediaElement::effectivePlaybackRate() const +{ + return m_mediaController ? m_mediaController->playbackRate() : m_playbackRate; +} + +HTMLMediaElement::DirectionOfPlayback HTMLMediaElement::directionOfPlayback() const +{ + return m_playbackRate >= 0 ? Forward : Backward; } void HTMLMediaElement::updatePlaybackRate() { - double effectiveRate = m_mediaController ? m_mediaController->playbackRate() : m_playbackRate; + double effectiveRate = effectivePlaybackRate(); if (m_player && potentiallyPlaying() && m_player->rate() != effectiveRate) m_player->setRate(effectiveRate); } @@ -2053,7 +2143,7 @@ bool HTMLMediaElement::ended() const // 4.8.10.8 Playing the media resource // The ended attribute must return true if the media element has ended // playback and the direction of playback is forwards, and false otherwise. - return endedPlayback() && m_playbackRate > 0; + return endedPlayback() && directionOfPlayback() == Forward; } bool HTMLMediaElement::autoplay() const @@ -2079,7 +2169,7 @@ String HTMLMediaElement::preload() const return String(); } -void HTMLMediaElement::setPreload(const String& preload) +void HTMLMediaElement::setPreload(const AtomicString& preload) { WTF_LOG(Media, "HTMLMediaElement::setPreload(%s)", preload.utf8().data()); setAttribute(preloadAttr, preload); @@ -2089,10 +2179,10 @@ void HTMLMediaElement::play() { WTF_LOG(Media, "HTMLMediaElement::play()"); - if (userGestureRequiredForRateChange() && !UserGestureIndicator::processingUserGesture()) + if (m_userGestureRequiredForPlay && !UserGestureIndicator::processingUserGesture()) return; if (UserGestureIndicator::processingUserGesture()) - removeBehaviorsRestrictionsAfterFirstUserGesture(); + m_userGestureRequiredForPlay = false; playInternal(); } @@ -2131,18 +2221,6 @@ void HTMLMediaElement::pause() { WTF_LOG(Media, "HTMLMediaElement::pause()"); - if (userGestureRequiredForRateChange() && !UserGestureIndicator::processingUserGesture()) - return; - - pauseInternal(); -} - - -void HTMLMediaElement::pauseInternal() -{ - WTF_LOG(Media, "HTMLMediaElement::pauseInternal"); - - // 4.8.10.9. Playing the media resource if (!m_player || m_networkState == NETWORK_EMPTY) scheduleDelayedAction(LoadMediaResource); @@ -2163,89 +2241,7 @@ void HTMLMediaElement::closeMediaSource() return; m_mediaSource->close(); - m_mediaSource = 0; -} - -void HTMLMediaElement::webkitGenerateKeyRequest(const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState& exceptionState) -{ - if (keySystem.isEmpty()) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return; - } - - if (!m_player) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - const unsigned char* initDataPointer = 0; - unsigned initDataLength = 0; - if (initData) { - initDataPointer = initData->data(); - initDataLength = initData->length(); - } - - MediaPlayer::MediaKeyException result = m_player->generateKeyRequest(keySystem, initDataPointer, initDataLength); - throwExceptionForMediaKeyException(result, exceptionState); -} - -void HTMLMediaElement::webkitGenerateKeyRequest(const String& keySystem, ExceptionState& exceptionState) -{ - webkitGenerateKeyRequest(keySystem, Uint8Array::create(0), exceptionState); -} - -void HTMLMediaElement::webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState& exceptionState) -{ - if (keySystem.isEmpty()) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return; - } - - if (!key) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return; - } - - if (!key->length()) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - if (!m_player) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - const unsigned char* initDataPointer = 0; - unsigned initDataLength = 0; - if (initData) { - initDataPointer = initData->data(); - initDataLength = initData->length(); - } - - MediaPlayer::MediaKeyException result = m_player->addKey(keySystem, key->data(), key->length(), initDataPointer, initDataLength, sessionId); - throwExceptionForMediaKeyException(result, exceptionState); -} - -void HTMLMediaElement::webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState& exceptionState) -{ - webkitAddKey(keySystem, key, Uint8Array::create(0), String(), exceptionState); -} - -void HTMLMediaElement::webkitCancelKeyRequest(const String& keySystem, const String& sessionId, ExceptionState& exceptionState) -{ - if (keySystem.isEmpty()) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return; - } - - if (!m_player) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - MediaPlayer::MediaKeyException result = m_player->cancelKeyRequest(keySystem, sessionId); - throwExceptionForMediaKeyException(result, exceptionState); + m_mediaSource = nullptr; } bool HTMLMediaElement::loop() const @@ -2261,7 +2257,7 @@ void HTMLMediaElement::setLoop(bool b) bool HTMLMediaElement::controls() const { - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); // always show controls when scripting is disabled if (frame && !frame->script().canExecuteScripts(NotAboutToExecuteScript)) @@ -2289,16 +2285,17 @@ void HTMLMediaElement::setVolume(double vol, ExceptionState& exceptionState) { WTF_LOG(Media, "HTMLMediaElement::setVolume(%f)", vol); + if (m_volume == vol) + return; + if (vol < 0.0f || vol > 1.0f) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexOutsideRange("volume", vol, 0.0, ExceptionMessages::InclusiveBound, 1.0, ExceptionMessages::InclusiveBound)); return; } - if (m_volume != vol) { - m_volume = vol; - updateVolume(); - scheduleEvent(EventTypeNames::volumechange); - } + m_volume = vol; + updateVolume(); + scheduleEvent(EventTypeNames::volumechange); } bool HTMLMediaElement::muted() const @@ -2310,55 +2307,14 @@ void HTMLMediaElement::setMuted(bool muted) { WTF_LOG(Media, "HTMLMediaElement::setMuted(%s)", boolString(muted)); - if (m_muted != muted) { - m_muted = muted; - if (m_player) { - m_player->setMuted(m_muted); - if (hasMediaControls()) - mediaControls()->changedMute(); - } - scheduleEvent(EventTypeNames::volumechange); - } -} - -void HTMLMediaElement::togglePlayState() -{ - WTF_LOG(Media, "HTMLMediaElement::togglePlayState - canPlay() is %s", boolString(canPlay())); - - // We can safely call the internal play/pause methods, which don't check restrictions, because - // this method is only called from the built-in media controller - if (canPlay()) { - updatePlaybackRate(); - playInternal(); - } else - pauseInternal(); -} - -void HTMLMediaElement::beginScrubbing() -{ - WTF_LOG(Media, "HTMLMediaElement::beginScrubbing - paused() is %s", boolString(paused())); + if (m_muted == muted) + return; - if (!paused()) { - if (ended()) { - // Because a media element stays in non-paused state when it reaches end, playback resumes - // when the slider is dragged from the end to another position unless we pause first. Do - // a "hard pause" so an event is generated, since we want to stay paused after scrubbing finishes. - pause(); - } else { - // Not at the end but we still want to pause playback so the media engine doesn't try to - // continue playing during scrubbing. Pause without generating an event as we will - // unpause after scrubbing finishes. - setPausedInternal(true); - } - } -} + m_muted = muted; -void HTMLMediaElement::endScrubbing() -{ - WTF_LOG(Media, "HTMLMediaElement::endScrubbing - m_pausedInternal is %s", boolString(m_pausedInternal)); + updateVolume(); - if (m_pausedInternal) - setPausedInternal(false); + scheduleEvent(EventTypeNames::volumechange); } // The spec says to fire periodic timeupdate events (those sent while playing) every @@ -2371,32 +2327,32 @@ void HTMLMediaElement::startPlaybackProgressTimer() return; m_previousProgressTime = WTF::currentTime(); - m_playbackProgressTimer.startRepeating(maxTimeupdateEventFrequency); + m_playbackProgressTimer.startRepeating(maxTimeupdateEventFrequency, FROM_HERE); } void HTMLMediaElement::playbackProgressTimerFired(Timer<HTMLMediaElement>*) { ASSERT(m_player); - if (m_fragmentEndTime != MediaPlayer::invalidTime() && currentTime() >= m_fragmentEndTime && m_playbackRate > 0) { + if (m_fragmentEndTime != MediaPlayer::invalidTime() && currentTime() >= m_fragmentEndTime && directionOfPlayback() == Forward) { m_fragmentEndTime = MediaPlayer::invalidTime(); if (!m_mediaController && !m_paused) { + UseCounter::count(document(), UseCounter::HTMLMediaElementPauseAtFragmentEnd); // changes paused to true and fires a simple event named pause at the media element. - pauseInternal(); + pause(); } } if (!m_seeking) scheduleTimeupdateEvent(true); - if (!m_playbackRate) + if (!effectivePlaybackRate()) return; if (!m_paused && hasMediaControls()) mediaControls()->playbackProgressed(); - if (RuntimeEnabledFeatures::videoTrackEnabled()) - updateActiveTextTrackCues(currentTime()); + updateActiveTextTrackCues(currentTime()); } void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent) @@ -2418,38 +2374,139 @@ void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent) } } -bool HTMLMediaElement::canPlay() const +bool HTMLMediaElement::togglePlayStateWillPlay() const { - return paused() || ended() || m_readyState < HAVE_METADATA; + if (m_mediaController) + return m_mediaController->paused() || m_mediaController->isRestrained(); + return paused(); } -double HTMLMediaElement::percentLoaded() const +void HTMLMediaElement::togglePlayState() { - if (!m_player) + if (m_mediaController) { + if (m_mediaController->isRestrained()) + m_mediaController->play(); + else if (m_mediaController->paused()) + m_mediaController->unpause(); + else + m_mediaController->pause(); + } else { + if (paused()) + play(); + else + pause(); + } +} + +AudioTrackList& HTMLMediaElement::audioTracks() +{ + ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); + return *m_audioTracks; +} + +void HTMLMediaElement::audioTrackChanged() +{ + WTF_LOG(Media, "HTMLMediaElement::audioTrackChanged()"); + ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); + + audioTracks().scheduleChangeEvent(); + + // FIXME: Add call on m_mediaSource to notify it of track changes once the SourceBuffer.audioTracks attribute is added. + + if (!m_audioTracksTimer.isActive()) + m_audioTracksTimer.startOneShot(0, FROM_HERE); +} + +void HTMLMediaElement::audioTracksTimerFired(Timer<HTMLMediaElement>*) +{ + Vector<WebMediaPlayer::TrackId> enabledTrackIds; + for (unsigned i = 0; i < audioTracks().length(); ++i) { + AudioTrack* track = audioTracks().anonymousIndexedGetter(i); + if (track->enabled()) + enabledTrackIds.append(track->trackId()); + } + + webMediaPlayer()->enabledAudioTracksChanged(enabledTrackIds); +} + +WebMediaPlayer::TrackId HTMLMediaElement::addAudioTrack(const String& id, blink::WebMediaPlayerClient::AudioTrackKind kind, const AtomicString& label, const AtomicString& language, bool enabled) +{ + AtomicString kindString = AudioKindToString(kind); + WTF_LOG(Media, "HTMLMediaElement::addAudioTrack('%s', '%s', '%s', '%s', %d)", + id.ascii().data(), kindString.ascii().data(), label.ascii().data(), language.ascii().data(), enabled); + + if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) return 0; - double duration = m_player->duration(); - if (!duration || std::isinf(duration)) + RefPtrWillBeRawPtr<AudioTrack> audioTrack = AudioTrack::create(id, kindString, label, language, enabled); + audioTracks().add(audioTrack); + + return audioTrack->trackId(); +} + +void HTMLMediaElement::removeAudioTrack(WebMediaPlayer::TrackId trackId) +{ + WTF_LOG(Media, "HTMLMediaElement::removeAudioTrack()"); + + if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) + return; + + audioTracks().remove(trackId); +} + +VideoTrackList& HTMLMediaElement::videoTracks() +{ + ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); + return *m_videoTracks; +} + +void HTMLMediaElement::selectedVideoTrackChanged(WebMediaPlayer::TrackId* selectedTrackId) +{ + WTF_LOG(Media, "HTMLMediaElement::selectedVideoTrackChanged()"); + ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); + + if (selectedTrackId) + videoTracks().trackSelected(*selectedTrackId); + + // FIXME: Add call on m_mediaSource to notify it of track changes once the SourceBuffer.videoTracks attribute is added. + + webMediaPlayer()->selectedVideoTrackChanged(selectedTrackId); +} + +WebMediaPlayer::TrackId HTMLMediaElement::addVideoTrack(const String& id, blink::WebMediaPlayerClient::VideoTrackKind kind, const AtomicString& label, const AtomicString& language, bool selected) +{ + AtomicString kindString = VideoKindToString(kind); + WTF_LOG(Media, "HTMLMediaElement::addVideoTrack('%s', '%s', '%s', '%s', %d)", + id.ascii().data(), kindString.ascii().data(), label.ascii().data(), language.ascii().data(), selected); + + if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) return 0; - double buffered = 0; - RefPtr<TimeRanges> timeRanges = m_player->buffered(); - for (unsigned i = 0; i < timeRanges->length(); ++i) { - double start = timeRanges->start(i, IGNORE_EXCEPTION); - double end = timeRanges->end(i, IGNORE_EXCEPTION); - buffered += end - start; - } - return buffered / duration; + // If another track was selected (potentially by the user), leave it selected. + if (selected && videoTracks().selectedIndex() != -1) + selected = false; + + RefPtrWillBeRawPtr<VideoTrack> videoTrack = VideoTrack::create(id, kindString, label, language, selected); + videoTracks().add(videoTrack); + + return videoTrack->trackId(); } -void HTMLMediaElement::mediaPlayerDidAddTrack(WebInbandTextTrack* webTrack) +void HTMLMediaElement::removeVideoTrack(WebMediaPlayer::TrackId trackId) { - if (!RuntimeEnabledFeatures::videoTrackEnabled()) + WTF_LOG(Media, "HTMLMediaElement::removeVideoTrack()"); + + if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) return; + videoTracks().remove(trackId); +} + +void HTMLMediaElement::mediaPlayerDidAddTextTrack(WebInbandTextTrack* webTrack) +{ // 4.8.10.12.2 Sourcing in-band text tracks // 1. Associate the relevant data with a new text track and its corresponding new TextTrack object. - RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), this, webTrack); + RefPtrWillBeRawPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), webTrack); // 2. Set the new text track's kind, label, and language based on the semantics of the relevant data, // as defined by the relevant specification. If there is no label in that data, then the label must @@ -2474,24 +2531,21 @@ void HTMLMediaElement::mediaPlayerDidAddTrack(WebInbandTextTrack* webTrack) // 9. Fire an event with the name addtrack, that does not bubble and is not cancelable, and that uses the TrackEvent // interface, with the track attribute initialized to the text track's TextTrack object, at the media element's // textTracks attribute's TextTrackList object. - addTrack(textTrack.get()); + addTextTrack(textTrack.get()); } -void HTMLMediaElement::mediaPlayerDidRemoveTrack(WebInbandTextTrack* webTrack) +void HTMLMediaElement::mediaPlayerDidRemoveTextTrack(WebInbandTextTrack* webTrack) { - if (!RuntimeEnabledFeatures::videoTrackEnabled()) - return; - if (!m_textTracks) return; // This cast is safe because we created the InbandTextTrack with the WebInbandTextTrack - // passed to mediaPlayerDidAddTrack. - RefPtr<InbandTextTrack> textTrack = static_cast<InbandTextTrack*>(webTrack->client()); + // passed to mediaPlayerDidAddTextTrack. + RefPtrWillBeRawPtr<InbandTextTrack> textTrack = static_cast<InbandTextTrack*>(webTrack->client()); if (!textTrack) return; - removeTrack(textTrack.get()); + removeTextTrack(textTrack.get()); } void HTMLMediaElement::closeCaptionTracksChanged() @@ -2500,49 +2554,47 @@ void HTMLMediaElement::closeCaptionTracksChanged() mediaControls()->closedCaptionTracksChanged(); } -void HTMLMediaElement::addTrack(TextTrack* track) +void HTMLMediaElement::addTextTrack(TextTrack* track) { textTracks()->append(track); closeCaptionTracksChanged(); } -void HTMLMediaElement::removeTrack(TextTrack* track) +void HTMLMediaElement::removeTextTrack(TextTrack* track) { TrackDisplayUpdateScope scope(this); - TextTrackCueList* cues = track->cues(); - if (cues) - textTrackRemoveCues(track, cues); m_textTracks->remove(track); closeCaptionTracksChanged(); } -void HTMLMediaElement::removeAllInbandTracks() +void HTMLMediaElement::forgetResourceSpecificTracks() { - if (!m_textTracks) - return; + // Implements the "forget the media element's media-resource-specific tracks" algorithm. + // The order is explicitly specified as text, then audio, and finally video. Also + // 'removetrack' events should not be fired. + if (m_textTracks) { + TrackDisplayUpdateScope scope(this); + m_textTracks->removeAllInbandTracks(); + closeCaptionTracksChanged(); + } - TrackDisplayUpdateScope scope(this); - for (int i = m_textTracks->length() - 1; i >= 0; --i) { - TextTrack* track = m_textTracks->item(i); + m_audioTracks->removeAll(); + m_videoTracks->removeAll(); - if (track->trackType() == TextTrack::InBand) - removeTrack(track); - } + m_audioTracksTimer.stop(); } -PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const String& kind, const String& label, const String& language, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, const AtomicString& label, const AtomicString& language, ExceptionState& exceptionState) { - ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); - // 4.8.10.12.4 Text track API // The addTextTrack(kind, label, language) method of media elements, when invoked, must run the following steps: // 1. If kind is not one of the following strings, then throw a SyntaxError exception and abort these steps if (!TextTrack::isValidKindKeyword(kind)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return 0; + exceptionState.throwDOMException(SyntaxError, "The 'kind' provided ('" + kind + "') is invalid."); + return nullptr; } // 2. If the label argument was omitted, let label be the empty string. @@ -2551,13 +2603,13 @@ PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const String& kind, const S // 5. Create a new text track corresponding to the new object, and set its text track kind to kind, its text // track label to label, its text track language to language... - RefPtr<TextTrack> textTrack = TextTrack::create(document(), this, kind, label, language); + RefPtrWillBeRawPtr<TextTrack> textTrack = TextTrack::create(document(), kind, label, language); // Note, due to side effects when changing track parameters, we have to // first append the track to the text track list. // 6. Add the new text track to the media element's list of text tracks. - addTrack(textTrack.get()); + addTextTrack(textTrack.get()); // ... its text track readiness state to the text track loaded state ... textTrack->setReadinessState(TextTrack::Loaded); @@ -2570,55 +2622,41 @@ PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const String& kind, const S TextTrackList* HTMLMediaElement::textTracks() { - ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); - if (!m_textTracks) m_textTracks = TextTrackList::create(this); return m_textTracks.get(); } -void HTMLMediaElement::didAddTrack(HTMLTrackElement* trackElement) +void HTMLMediaElement::didAddTrackElement(HTMLTrackElement* trackElement) { - ASSERT(trackElement->hasTagName(trackTag)); - - if (!RuntimeEnabledFeatures::videoTrackEnabled()) - return; - // 4.8.10.12.3 Sourcing out-of-band text tracks // When a track element's parent element changes and the new parent is a media element, // then the user agent must add the track element's corresponding text track to the // media element's list of text tracks ... [continues in TextTrackList::append] - RefPtr<TextTrack> textTrack = trackElement->track(); + RefPtrWillBeRawPtr<TextTrack> textTrack = trackElement->track(); if (!textTrack) return; - addTrack(textTrack.get()); + addTextTrack(textTrack.get()); // Do not schedule the track loading until parsing finishes so we don't start before all tracks // in the markup have been added. - if (!m_parsingInProgress) + if (isFinishedParsingChildren()) scheduleDelayedAction(LoadTextTrackResource); if (hasMediaControls()) mediaControls()->closedCaptionTracksChanged(); } -void HTMLMediaElement::didRemoveTrack(HTMLTrackElement* trackElement) +void HTMLMediaElement::didRemoveTrackElement(HTMLTrackElement* trackElement) { - ASSERT(trackElement->hasTagName(trackTag)); - - if (!RuntimeEnabledFeatures::videoTrackEnabled()) - return; - #if !LOG_DISABLED - if (trackElement->hasTagName(trackTag)) { - KURL url = trackElement->getNonEmptyURLAttribute(srcAttr); - WTF_LOG(Media, "HTMLMediaElement::didRemoveTrack - 'src' is %s", urlForLoggingMedia(url).utf8().data()); - } + KURL url = trackElement->getNonEmptyURLAttribute(srcAttr); + WTF_LOG(Media, "HTMLMediaElement::didRemoveTrackElement - 'src' is %s", urlForLoggingMedia(url).utf8().data()); #endif - RefPtr<TextTrack> textTrack = trackElement->track(); + RefPtrWillBeRawPtr<TextTrack> textTrack = trackElement->track(); if (!textTrack) return; @@ -2631,7 +2669,7 @@ void HTMLMediaElement::didRemoveTrack(HTMLTrackElement* trackElement) // When a track element's parent element changes and the old parent was a media element, // then the user agent must remove the track element's corresponding text track from the // media element's list of text tracks. - removeTrack(textTrack.get()); + removeTextTrack(textTrack.get()); size_t index = m_textTracksWhenResourceSelectionBegan.find(textTrack.get()); if (index != kNotFound) @@ -2643,32 +2681,20 @@ static int textTrackLanguageSelectionScore(const TextTrack& track) if (track.language().isEmpty()) return 0; - Vector<String> languages = userPreferredLanguages(); + Vector<AtomicString> languages = userPreferredLanguages(); size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track.language(), languages); if (languageMatchIndex >= languages.size()) return 0; - // Matching a track language is more important than matching track type, so this multiplier must be - // greater than the maximum value returned by textTrackSelectionScore. - return (languages.size() - languageMatchIndex) * 10; + return languages.size() - languageMatchIndex; } -static int textTrackSelectionScore(const TextTrack& track, Settings* settings) +static int textTrackSelectionScore(const TextTrack& track) { - int trackScore = 0; - - if (!settings) - return trackScore; - if (track.kind() != TextTrack::captionsKeyword() && track.kind() != TextTrack::subtitlesKeyword()) - return trackScore; - - if (track.kind() == TextTrack::subtitlesKeyword() && settings->shouldDisplaySubtitles()) - trackScore = 1; - else if (track.kind() == TextTrack::captionsKeyword() && settings->shouldDisplayCaptions()) - trackScore = 1; + return 0; - return trackScore + textTrackLanguageSelectionScore(track); + return textTrackLanguageSelectionScore(track); } void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group) @@ -2677,21 +2703,19 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group) WTF_LOG(Media, "HTMLMediaElement::configureTextTrackGroup(%d)", group.kind); - Settings* settings = document().settings(); - // First, find the track in the group that should be enabled (if any). - Vector<RefPtr<TextTrack> > currentlyEnabledTracks; - RefPtr<TextTrack> trackToEnable; - RefPtr<TextTrack> defaultTrack; - RefPtr<TextTrack> fallbackTrack; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> > currentlyEnabledTracks; + RefPtrWillBeRawPtr<TextTrack> trackToEnable = nullptr; + RefPtrWillBeRawPtr<TextTrack> defaultTrack = nullptr; + RefPtrWillBeRawPtr<TextTrack> fallbackTrack = nullptr; int highestTrackScore = 0; for (size_t i = 0; i < group.tracks.size(); ++i) { - RefPtr<TextTrack> textTrack = group.tracks[i]; + RefPtrWillBeRawPtr<TextTrack> textTrack = group.tracks[i]; if (m_processingPreferenceChange && textTrack->mode() == TextTrack::showingKeyword()) currentlyEnabledTracks.append(textTrack); - int trackScore = textTrackSelectionScore(*textTrack, settings); + int trackScore = textTrackSelectionScore(*textTrack); if (trackScore) { // * If the text track kind is { [subtitles or captions] [descriptions] } and the user has indicated an interest in having a // track with this text track kind, text track language, and text track label enabled, and there is no @@ -2732,7 +2756,7 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group) if (currentlyEnabledTracks.size()) { for (size_t i = 0; i < currentlyEnabledTracks.size(); ++i) { - RefPtr<TextTrack> textTrack = currentlyEnabledTracks[i]; + RefPtrWillBeRawPtr<TextTrack> textTrack = currentlyEnabledTracks[i]; if (textTrack != trackToEnable) textTrack->setMode(TextTrack::disabledKeyword()); } @@ -2754,7 +2778,7 @@ void HTMLMediaElement::configureTextTracks() return; for (size_t i = 0; i < m_textTracks->length(); ++i) { - RefPtr<TextTrack> textTrack = m_textTracks->item(i); + RefPtrWillBeRawPtr<TextTrack> textTrack = m_textTracks->item(i); if (!textTrack) continue; @@ -2809,8 +2833,8 @@ bool HTMLMediaElement::havePotentialSourceChild() { // Stash the current <source> node and next nodes so we can restore them after checking // to see there is another potential. - RefPtr<HTMLSourceElement> currentSourceNode = m_currentSourceNode; - RefPtr<Node> nextNode = m_nextChildNodeToConsider; + RefPtrWillBeRawPtr<HTMLSourceElement> currentSourceNode = m_currentSourceNode; + RefPtrWillBeRawPtr<Node> nextNode = m_nextChildNodeToConsider; KURL nextURL = selectNextSourceChild(0, 0, DoNothing); @@ -2844,7 +2868,6 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType* contentType, String* k String system; bool lookingForStartNode = m_nextChildNodeToConsider; bool canUseSourceElement = false; - bool okToLoadSourceURL; NodeVector potentialSourceNodes; getChildNodes(*this, potentialSourceNodes); @@ -2855,12 +2878,11 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType* contentType, String* k continue; lookingForStartNode = false; - if (!node->hasTagName(sourceTag)) + if (!isHTMLSourceElement(*node)) continue; if (node->parentNode() != this) continue; - UseCounter::count(document(), UseCounter::SourceElementCandidate); source = toHTMLSourceElement(node); // If candidate does not have a src attribute, or if its src attribute's value is the empty string ... jump down to the failed step below @@ -2872,19 +2894,6 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType* contentType, String* k if (mediaURL.isEmpty()) goto check_again; - if (source->fastHasAttribute(mediaAttr)) { - MediaQueryEvaluator screenEval("screen", document().frame(), renderer() ? renderer()->style() : 0); - RefPtr<MediaQuerySet> media = MediaQuerySet::create(source->media()); -#if !LOG_DISABLED - if (shouldLog) - WTF_LOG(Media, "HTMLMediaElement::selectNextSourceChild - 'media' is %s", source->media().string().utf8().data()); -#endif - if (!screenEval.eval(media.get())) { - UseCounter::count(document(), UseCounter::SourceElementNonMatchingMedia); - goto check_again; - } - } - type = source->type(); // FIXME(82965): Add support for keySystem in <source> and set system from source. if (type.isEmpty() && mediaURL.protocolIsData()) @@ -2899,16 +2908,7 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType* contentType, String* k } // Is it safe to load this url? - okToLoadSourceURL = isSafeToLoadURL(mediaURL, actionIfInvalid) && dispatchBeforeLoadEvent(mediaURL.string()); - - // A 'beforeload' event handler can mutate the DOM, so check to see if the source element is still a child node. - if (node->parentNode() != this) { - WTF_LOG(Media, "HTMLMediaElement::selectNextSourceChild : 'beforeload' removed current element"); - source = 0; - goto check_again; - } - - if (!okToLoadSourceURL) + if (!isSafeToLoadURL(mediaURL, actionIfInvalid)) goto check_again; // Making it this far means the <source> looks reasonable. @@ -2927,8 +2927,8 @@ check_again: m_currentSourceNode = source; m_nextChildNodeToConsider = source->nextSibling(); } else { - m_currentSourceNode = 0; - m_nextChildNodeToConsider = 0; + m_currentSourceNode = nullptr; + m_nextChildNodeToConsider = nullptr; } #if !LOG_DISABLED @@ -2943,10 +2943,8 @@ void HTMLMediaElement::sourceWasAdded(HTMLSourceElement* source) WTF_LOG(Media, "HTMLMediaElement::sourceWasAdded(%p)", source); #if !LOG_DISABLED - if (source->hasTagName(sourceTag)) { - KURL url = source->getNonEmptyURLAttribute(srcAttr); - WTF_LOG(Media, "HTMLMediaElement::sourceWasAdded - 'src' is %s", urlForLoggingMedia(url).utf8().data()); - } + KURL url = source->getNonEmptyURLAttribute(srcAttr); + WTF_LOG(Media, "HTMLMediaElement::sourceWasAdded - 'src' is %s", urlForLoggingMedia(url).utf8().data()); #endif // We should only consider a <source> element when there is not src attribute at all. @@ -2991,10 +2989,8 @@ void HTMLMediaElement::sourceWasRemoved(HTMLSourceElement* source) WTF_LOG(Media, "HTMLMediaElement::sourceWasRemoved(%p)", source); #if !LOG_DISABLED - if (source->hasTagName(sourceTag)) { - KURL url = source->getNonEmptyURLAttribute(srcAttr); - WTF_LOG(Media, "HTMLMediaElement::sourceWasRemoved - 'src' is %s", urlForLoggingMedia(url).utf8().data()); - } + KURL url = source->getNonEmptyURLAttribute(srcAttr); + WTF_LOG(Media, "HTMLMediaElement::sourceWasRemoved - 'src' is %s", urlForLoggingMedia(url).utf8().data()); #endif if (source != m_currentSourceNode && source != m_nextChildNodeToConsider) @@ -3008,7 +3004,7 @@ void HTMLMediaElement::sourceWasRemoved(HTMLSourceElement* source) // Clear the current source node pointer, but don't change the movie as the spec says: // 4.8.8 - Dynamically modifying a source element and its attribute when the element is already // inserted in a video or audio element will have no effect. - m_currentSourceNode = 0; + m_currentSourceNode = nullptr; WTF_LOG(Media, "HTMLMediaElement::sourceRemoved - m_currentSourceNode set to 0"); } } @@ -3017,8 +3013,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged() { WTF_LOG(Media, "HTMLMediaElement::mediaPlayerTimeChanged"); - if (RuntimeEnabledFeatures::videoTrackEnabled()) - updateActiveTextTrackCues(currentTime()); + updateActiveTextTrackCues(currentTime()); invalidateCachedTime(); @@ -3036,7 +3031,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged() // When the current playback position reaches the end of the media resource when the direction of // playback is forwards, then the user agent must follow these steps: - if (!std::isnan(dur) && dur && now >= dur && m_playbackRate > 0) { + if (!std::isnan(dur) && dur && now >= dur && directionOfPlayback() == Forward) { // If the media element has a loop attribute specified and does not have a current media controller, if (loop() && !m_mediaController) { m_sentEndEvent = false; @@ -3070,17 +3065,22 @@ void HTMLMediaElement::mediaPlayerTimeChanged() void HTMLMediaElement::mediaPlayerDurationChanged() { WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDurationChanged"); - durationChanged(duration()); + // FIXME: Change MediaPlayerClient & WebMediaPlayer to convey + // the currentTime when the duration change occured. The current + // WebMediaPlayer implementations always clamp currentTime() to + // duration() so the requestSeek condition here is always false. + durationChanged(duration(), currentTime() > duration()); } -void HTMLMediaElement::durationChanged(double duration) +void HTMLMediaElement::durationChanged(double duration, bool requestSeek) { - WTF_LOG(Media, "HTMLMediaElement::durationChanged(%f)", duration); + WTF_LOG(Media, "HTMLMediaElement::durationChanged(%f, %d)", duration, requestSeek); // Abort if duration unchanged. if (m_duration == duration) return; + WTF_LOG(Media, "HTMLMediaElement::durationChanged : %f -> %f", m_duration, duration); m_duration = duration; scheduleEvent(EventTypeNames::durationchange); @@ -3089,7 +3089,7 @@ void HTMLMediaElement::durationChanged(double duration) if (renderer()) renderer()->updateFromElement(); - if (currentTime() > duration) + if (requestSeek) seek(duration, IGNORE_EXCEPTION); } @@ -3101,7 +3101,7 @@ void HTMLMediaElement::mediaPlayerPlaybackStateChanged() return; if (m_player->paused()) - pauseInternal(); + pause(); else playInternal(); } @@ -3109,6 +3109,11 @@ void HTMLMediaElement::mediaPlayerPlaybackStateChanged() void HTMLMediaElement::mediaPlayerRequestFullscreen() { WTF_LOG(Media, "HTMLMediaElement::mediaPlayerRequestFullscreen"); + + // The player is responsible for only invoking this callback in response to + // user interaction or when it is technically required to play the video. + UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); + enterFullscreen(); } @@ -3130,14 +3135,15 @@ void HTMLMediaElement::mediaPlayerRepaint() updateDisplayState(); if (renderer()) - renderer()->repaint(); + renderer()->paintInvalidationForWholeRenderer(); } void HTMLMediaElement::mediaPlayerSizeChanged() { WTF_LOG(Media, "HTMLMediaElement::mediaPlayerSizeChanged"); - if (m_readyState > HAVE_NOTHING) + ASSERT(hasVideo()); // "resize" makes no sense absent video. + if (m_readyState > HAVE_NOTHING && isHTMLVideoElement(*this)) scheduleEvent(EventTypeNames::resize); if (renderer()) @@ -3190,7 +3196,7 @@ bool HTMLMediaElement::potentiallyPlaying() const bool HTMLMediaElement::couldPlayIfEnoughData() const { - return !paused() && !endedPlayback() && !stoppedDueToErrors() && !pausedForUserInteraction(); + return !paused() && !endedPlayback() && !stoppedDueToErrors(); } bool HTMLMediaElement::endedPlayback() const @@ -3210,15 +3216,13 @@ bool HTMLMediaElement::endedPlayback() const // of playback is forwards, Either the media element does not have a loop attribute specified, // or the media element has a current media controller. double now = currentTime(); - if (m_playbackRate > 0) + if (directionOfPlayback() == Forward) return dur > 0 && now >= dur && (!loop() || m_mediaController); // or the current playback position is the earliest possible position and the direction // of playback is backwards - if (m_playbackRate < 0) - return now <= 0; - - return false; + ASSERT(directionOfPlayback() == Backward); + return now <= 0; } bool HTMLMediaElement::stoppedDueToErrors() const @@ -3232,17 +3236,17 @@ bool HTMLMediaElement::stoppedDueToErrors() const return false; } -bool HTMLMediaElement::pausedForUserInteraction() const +void HTMLMediaElement::updateVolume() { -// return !paused() && m_readyState >= HAVE_FUTURE_DATA && [UA requires a decitions from the user] - return false; + if (webMediaPlayer()) + webMediaPlayer()->setVolume(playerVolume()); + + if (hasMediaControls()) + mediaControls()->updateVolume(); } -void HTMLMediaElement::updateVolume() +double HTMLMediaElement::playerVolume() const { - if (!m_player) - return; - double volumeMultiplier = 1; bool shouldMute = m_muted; @@ -3251,11 +3255,7 @@ void HTMLMediaElement::updateVolume() shouldMute = m_mediaController->muted(); } - m_player->setMuted(shouldMute); - m_player->setVolume(m_volume * volumeMultiplier); - - if (hasMediaControls()) - mediaControls()->changedVolume(); + return shouldMute ? 0 : m_volume * volumeMultiplier; } void HTMLMediaElement::updatePlayState() @@ -3286,8 +3286,8 @@ void HTMLMediaElement::updatePlayState() if (playerPaused) { // Set rate, muted before calling play in case they were set before the media engine was setup. // The media engine should just stash the rate and muted values since it isn't already playing. - m_player->setRate(m_playbackRate); - m_player->setMuted(m_muted); + m_player->setRate(effectivePlaybackRate()); + updateVolume(); m_player->play(); } @@ -3368,40 +3368,42 @@ void HTMLMediaElement::userCancelledLoad() setShouldDelayLoadEvent(false); // 6 - Abort the overall resource selection algorithm. - m_currentSourceNode = 0; + m_currentSourceNode = nullptr; // Reset m_readyState since m_player is gone. m_readyState = HAVE_NOTHING; updateMediaController(); - if (RuntimeEnabledFeatures::videoTrackEnabled()) - updateActiveTextTrackCues(0); + updateActiveTextTrackCues(0); } -void HTMLMediaElement::clearMediaPlayerAndAudioSourceProviderClient() +void HTMLMediaElement::clearMediaPlayerAndAudioSourceProviderClientWithoutLocking() { #if ENABLE(WEB_AUDIO) - if (m_audioSourceNode) - m_audioSourceNode->lock(); - if (audioSourceProvider()) audioSourceProvider()->setClient(0); #endif - m_player.clear(); - -#if ENABLE(WEB_AUDIO) - if (m_audioSourceNode) - m_audioSourceNode->unlock(); -#endif } void HTMLMediaElement::clearMediaPlayer(int flags) { - removeAllInbandTracks(); + forgetResourceSpecificTracks(); closeMediaSource(); - clearMediaPlayerAndAudioSourceProviderClient(); + cancelDeferredLoad(); + +#if ENABLE(WEB_AUDIO) + if (m_audioSourceNode) + m_audioSourceNode->lock(); +#endif + + clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); + +#if ENABLE(WEB_AUDIO) + if (m_audioSourceNode) + m_audioSourceNode->unlock(); +#endif stopPeriodicTimers(); m_loadTimer.stop(); @@ -3440,8 +3442,12 @@ bool HTMLMediaElement::hasPendingActivity() const void HTMLMediaElement::contextDestroyed() { + // With Oilpan the ExecutionContext is weakly referenced from the media + // controller and so it will clear itself on destruction. +#if !ENABLE(OILPAN) if (m_mediaController) m_mediaController->clearExecutionContext(); +#endif ActiveDOMObject::contextDestroyed(); } @@ -3454,32 +3460,30 @@ void HTMLMediaElement::enterFullscreen() { WTF_LOG(Media, "HTMLMediaElement::enterFullscreen"); - if (document().settings() && document().settings()->fullScreenEnabled()) - FullscreenElementStack::from(&document())->requestFullScreenForElement(this, 0, FullscreenElementStack::ExemptIFrameAllowFullScreenRequirement); + FullscreenElementStack::from(document()).requestFullScreenForElement(this, 0, FullscreenElementStack::ExemptIFrameAllowFullScreenRequirement); } void HTMLMediaElement::exitFullscreen() { WTF_LOG(Media, "HTMLMediaElement::exitFullscreen"); - if (document().settings() && document().settings()->fullScreenEnabled() && isFullscreen()) - FullscreenElementStack::from(&document())->webkitCancelFullScreen(); + FullscreenElementStack::from(document()).webkitCancelFullScreen(); } void HTMLMediaElement::didBecomeFullscreenElement() { if (hasMediaControls()) mediaControls()->enteredFullscreen(); - if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && isVideo()) - document().renderView()->compositor()->setCompositingLayersNeedRebuild(true); + if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && isHTMLVideoElement(*this)) + document().renderView()->compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree); } void HTMLMediaElement::willStopBeingFullscreenElement() { if (hasMediaControls()) mediaControls()->exitedFullscreen(); - if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && isVideo()) - document().renderView()->compositor()->setCompositingLayersNeedRebuild(true); + if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && isHTMLVideoElement(*this)) + document().renderView()->compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree); } blink::WebLayer* HTMLMediaElement::platformLayer() const @@ -3489,7 +3493,7 @@ blink::WebLayer* HTMLMediaElement::platformLayer() const bool HTMLMediaElement::hasClosedCaptions() const { - if (RuntimeEnabledFeatures::videoTrackEnabled() && m_textTracks) { + if (m_textTracks) { for (unsigned i = 0; i < m_textTracks->length(); ++i) { if (m_textTracks->item(i)->readinessState() == TextTrack::FailedToLoad) continue; @@ -3526,27 +3530,25 @@ void HTMLMediaElement::setClosedCaptionsVisible(bool closedCaptionVisible) m_closedCaptionsVisible = closedCaptionVisible; - if (RuntimeEnabledFeatures::videoTrackEnabled()) { - m_processingPreferenceChange = true; - markCaptionAndSubtitleTracksAsUnconfigured(); - m_processingPreferenceChange = false; + m_processingPreferenceChange = true; + markCaptionAndSubtitleTracksAsUnconfigured(); + m_processingPreferenceChange = false; - updateTextTrackDisplay(); - } + updateTextTrackDisplay(); } unsigned HTMLMediaElement::webkitAudioDecodedByteCount() const { - if (!m_player) + if (!webMediaPlayer()) return 0; - return m_player->audioDecodedByteCount(); + return webMediaPlayer()->audioDecodedByteCount(); } unsigned HTMLMediaElement::webkitVideoDecodedByteCount() const { - if (!m_player) + if (!webMediaPlayer()) return 0; - return m_player->videoDecodedByteCount(); + return webMediaPlayer()->videoDecodedByteCount(); } bool HTMLMediaElement::isURLAttribute(const Attribute& attribute) const @@ -3590,11 +3592,10 @@ bool HTMLMediaElement::createMediaControls() if (hasMediaControls()) return true; - RefPtr<MediaControls> mediaControls = MediaControls::create(document()); + RefPtrWillBeRawPtr<MediaControls> mediaControls = MediaControls::create(*this); if (!mediaControls) return false; - mediaControls->setMediaController(m_mediaController ? m_mediaController.get() : static_cast<MediaControllerInterface*>(this)); mediaControls->reset(); if (isFullscreen()) mediaControls->enteredFullscreen(); @@ -3618,6 +3619,7 @@ void HTMLMediaElement::configureMediaControls() if (!hasMediaControls() && !createMediaControls()) return; + mediaControls()->reset(); mediaControls()->show(); } @@ -3652,10 +3654,8 @@ void HTMLMediaElement::configureTextTrackDisplay(VisibilityChangeAssumption assu mediaControls()->changedClosedCaptionsVisibility(); - if (RuntimeEnabledFeatures::videoTrackEnabled()) { - updateActiveTextTrackCues(currentTime()); - updateTextTrackDisplay(); - } + updateActiveTextTrackCues(currentTime()); + updateTextTrackDisplay(); } void HTMLMediaElement::markCaptionAndSubtitleTracksAsUnconfigured() @@ -3669,7 +3669,7 @@ void HTMLMediaElement::markCaptionAndSubtitleTracksAsUnconfigured() // captions and non-default tracks should be displayed based on language // preferences if the user has turned captions on). for (unsigned i = 0; i < m_textTracks->length(); ++i) { - RefPtr<TextTrack> textTrack = m_textTracks->item(i); + RefPtrWillBeRawPtr<TextTrack> textTrack = m_textTracks->item(i); String kind = textTrack->kind(); if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captionsKeyword()) @@ -3678,7 +3678,6 @@ void HTMLMediaElement::markCaptionAndSubtitleTracksAsUnconfigured() configureTextTracks(); } - void* HTMLMediaElement::preDispatchEventHandler(Event* event) { if (event && event->type() == EventTypeNames::webkitfullscreenchange) @@ -3694,14 +3693,13 @@ void HTMLMediaElement::createMediaPlayer() m_audioSourceNode->lock(); #endif - if (m_mediaSource) - closeMediaSource(); + closeMediaSource(); m_player = MediaPlayer::create(this); #if ENABLE(WEB_AUDIO) if (m_audioSourceNode) { - // When creating the player, make sure its AudioSourceProvider knows about the MediaElementAudioSourceNode. + // When creating the player, make sure its AudioSourceProvider knows about the client. if (audioSourceProvider()) audioSourceProvider()->setClient(m_audioSourceNode); @@ -3711,7 +3709,7 @@ void HTMLMediaElement::createMediaPlayer() } #if ENABLE(WEB_AUDIO) -void HTMLMediaElement::setAudioSourceNode(MediaElementAudioSourceNode* sourceNode) +void HTMLMediaElement::setAudioSourceNode(AudioSourceProviderClient* sourceNode) { m_audioSourceNode = sourceNode; @@ -3745,7 +3743,7 @@ void HTMLMediaElement::setMediaGroup(const AtomicString& group) // attribute is set, changed, or removed, the user agent must run the following steps: // 1. Let m [this] be the media element in question. // 2. Let m have no current media controller, if it currently has one. - setControllerInternal(0); + setControllerInternal(nullptr); // 3. If m's mediagroup attribute is being removed, then abort these steps. if (group.isNull() || group.isEmpty()) @@ -3753,8 +3751,8 @@ void HTMLMediaElement::setMediaGroup(const AtomicString& group) // 4. If there is another media element whose Document is the same as m's Document (even if one or both // of these elements are not actually in the Document), - HashSet<HTMLMediaElement*> elements = documentToElementSetMap().get(&document()); - for (HashSet<HTMLMediaElement*>::iterator i = elements.begin(); i != elements.end(); ++i) { + WeakMediaElementSet elements = documentToElementSetMap().get(&document()); + for (WeakMediaElementSet::iterator i = elements.begin(); i != elements.end(); ++i) { if (*i == this) continue; @@ -3776,7 +3774,7 @@ MediaController* HTMLMediaElement::controller() const return m_mediaController.get(); } -void HTMLMediaElement::setController(PassRefPtr<MediaController> controller) +void HTMLMediaElement::setController(PassRefPtrWillBeRawPtr<MediaController> controller) { // 4.8.10.11.2 Media controllers: controller attribute. // On setting, it must first remove the element's mediagroup attribute, if any, @@ -3785,7 +3783,7 @@ void HTMLMediaElement::setController(PassRefPtr<MediaController> controller) setControllerInternal(controller); } -void HTMLMediaElement::setControllerInternal(PassRefPtr<MediaController> controller) +void HTMLMediaElement::setControllerInternal(PassRefPtrWillBeRawPtr<MediaController> controller) { if (m_mediaController) m_mediaController->removeMediaElement(this); @@ -3794,9 +3792,6 @@ void HTMLMediaElement::setControllerInternal(PassRefPtr<MediaController> control if (m_mediaController) m_mediaController->addMediaElement(this); - - if (hasMediaControls()) - mediaControls()->setMediaController(m_mediaController ? m_mediaController.get() : static_cast<MediaControllerInterface*>(this)); } void HTMLMediaElement::updateMediaController() @@ -3809,11 +3804,11 @@ bool HTMLMediaElement::isBlocked() const { // A media element is a blocked media element if its readyState attribute is in the // HAVE_NOTHING state, the HAVE_METADATA state, or the HAVE_CURRENT_DATA state, + // or if the element has paused for user interaction or paused for in-band content. if (m_readyState <= HAVE_CURRENT_DATA) return true; - // or if the element has paused for user interaction. - return pausedForUserInteraction(); + return false; } bool HTMLMediaElement::isBlockedOnMediaController() const @@ -3857,6 +3852,8 @@ void HTMLMediaElement::prepareMediaFragmentURI() } else m_fragmentEndTime = MediaPlayer::invalidTime(); + // FIXME: Add support for selecting tracks by ID with the Media Fragments track dimension. + if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE_FUTURE_DATA) prepareToPlay(); } @@ -3865,22 +3862,19 @@ void HTMLMediaElement::applyMediaFragmentURI() { if (m_fragmentStartTime != MediaPlayer::invalidTime()) { m_sentEndEvent = false; + UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragmentStart); seek(m_fragmentStartTime, IGNORE_EXCEPTION); } } -MediaPlayerClient::CORSMode HTMLMediaElement::mediaPlayerCORSMode() const +WebMediaPlayer::CORSMode HTMLMediaElement::corsMode() const { - if (!fastHasAttribute(crossoriginAttr)) - return Unspecified; - if (equalIgnoringCase(fastGetAttribute(crossoriginAttr), "use-credentials")) - return UseCredentials; - return Anonymous; -} - -void HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture() -{ - m_restrictions = NoRestrictions; + const AtomicString& crossOriginMode = fastGetAttribute(crossoriginAttr); + if (crossOriginMode.isNull()) + return WebMediaPlayer::CORSModeUnspecified; + if (equalIgnoringCase(crossOriginMode, "use-credentials")) + return WebMediaPlayer::CORSModeUseCredentials; + return WebMediaPlayer::CORSModeAnonymous; } void HTMLMediaElement::mediaPlayerSetWebLayer(blink::WebLayer* webLayer) @@ -3890,22 +3884,19 @@ void HTMLMediaElement::mediaPlayerSetWebLayer(blink::WebLayer* webLayer) // If either of the layers is null we need to enable or disable compositing. This is done by triggering a style recalc. if (!m_webLayer || !webLayer) - scheduleLayerUpdate(); + setNeedsCompositingUpdate(); if (m_webLayer) GraphicsLayer::unregisterContentsLayer(m_webLayer); m_webLayer = webLayer; if (m_webLayer) { - m_webLayer->setOpaque(m_opaque); GraphicsLayer::registerContentsLayer(m_webLayer); } } -void HTMLMediaElement::mediaPlayerSetOpaque(bool opaque) +void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMediaSource) { - m_opaque = opaque; - if (m_webLayer) - m_webLayer->setOpaque(m_opaque); + m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); } bool HTMLMediaElement::isInteractiveContent() const @@ -3913,4 +3904,67 @@ bool HTMLMediaElement::isInteractiveContent() const return fastHasAttribute(controlsAttr); } +void HTMLMediaElement::defaultEventHandler(Event* event) +{ + if (event->type() == EventTypeNames::focusin) { + if (hasMediaControls()) + mediaControls()->mediaElementFocused(); + } + HTMLElement::defaultEventHandler(event); +} + +void HTMLMediaElement::trace(Visitor* visitor) +{ + visitor->trace(m_asyncEventQueue); + visitor->trace(m_error); + visitor->trace(m_currentSourceNode); + visitor->trace(m_nextChildNodeToConsider); + visitor->trace(m_audioTracks); + visitor->trace(m_videoTracks); + visitor->trace(m_textTracks); + visitor->trace(m_textTracksWhenResourceSelectionBegan); + visitor->trace(m_mediaController); +#if ENABLE(WEB_AUDIO) + visitor->registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::clearWeakMembers>(this); +#endif + WillBeHeapSupplementable<HTMLMediaElement>::trace(visitor); + HTMLElement::trace(visitor); +} + +void HTMLMediaElement::createPlaceholderTracksIfNecessary() +{ + if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) + return; + + // Create a placeholder audio track if the player says it has audio but it didn't explicitly announce the tracks. + if (hasAudio() && !audioTracks().length()) + addAudioTrack("audio", WebMediaPlayerClient::AudioTrackKindMain, "Audio Track", "", true); + + // Create a placeholder video track if the player says it has video but it didn't explicitly announce the tracks. + if (webMediaPlayer() && webMediaPlayer()->hasVideo() && !videoTracks().length()) + addVideoTrack("video", WebMediaPlayerClient::VideoTrackKindMain, "Video Track", "", true); +} + +void HTMLMediaElement::selectInitialTracksIfNecessary() +{ + if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) + return; + + // Enable the first audio track if an audio track hasn't been enabled yet. + if (audioTracks().length() > 0 && !audioTracks().hasEnabledTrack()) + audioTracks().anonymousIndexedGetter(0)->setEnabled(true); + + // Select the first video track if a video track hasn't been selected yet. + if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) + videoTracks().anonymousIndexedGetter(0)->setSelected(true); +} + +#if ENABLE(WEB_AUDIO) +void HTMLMediaElement::clearWeakMembers(Visitor* visitor) +{ + if (!visitor->isAlive(m_audioSourceNode) && audioSourceProvider()) + audioSourceProvider()->setClient(0); +} +#endif + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.h index 18374c781bb..5b2756e307c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.h @@ -29,15 +29,16 @@ #include "core/dom/ActiveDOMObject.h" #include "core/events/GenericEventQueue.h" #include "core/html/HTMLElement.h" -#include "core/html/MediaControllerInterface.h" #include "core/html/track/TextTrack.h" #include "core/html/track/TextTrackCue.h" #include "core/html/track/vtt/VTTCue.h" #include "platform/PODIntervalTree.h" #include "platform/graphics/media/MediaPlayer.h" +#include "public/platform/WebMediaPlayerClient.h" #include "public/platform/WebMimeRegistry.h" namespace blink { +class WebContentDecryptionModule; class WebInbandTextTrack; class WebLayer; } @@ -46,8 +47,9 @@ namespace WebCore { #if ENABLE(WEB_AUDIO) class AudioSourceProvider; -class MediaElementAudioSourceNode; +class AudioSourceProviderClient; #endif +class AudioTrackList; class ContentType; class Event; class ExceptionState; @@ -57,10 +59,11 @@ class KURL; class MediaController; class MediaControls; class MediaError; -class MediaKeys; class HTMLMediaSource; class TextTrackList; class TimeRanges; +class URLRegistry; +class VideoTrackList; typedef PODIntervalTree<double, TextTrackCue*> CueIntervalTree; typedef CueIntervalTree::IntervalType CueInterval; @@ -70,20 +73,27 @@ typedef Vector<CueInterval> CueList; // But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it // no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement. -class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, public ActiveDOMObject, public MediaControllerInterface - , private TextTrackClient +class HTMLMediaElement : public HTMLElement, public WillBeHeapSupplementable<HTMLMediaElement>, public MediaPlayerClient, public ActiveDOMObject { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLMediaElement); public: static blink::WebMimeRegistry::SupportsType supportsType(const ContentType&, const String& keySystem = String()); - MediaPlayer* player() const { return m_player.get(); } + static void setMediaStreamRegistry(URLRegistry*); + static bool isMediaStreamURL(const String& url); - virtual bool isVideo() const = 0; - virtual bool hasVideo() const OVERRIDE { return false; } - virtual bool hasAudio() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; +#if ENABLE(WEB_AUDIO) + void clearWeakMembers(Visitor*); +#endif + + // Do not use player(). + // FIXME: Replace all uses with webMediaPlayer() and remove this API. + MediaPlayer* player() const { return m_player.get(); } + blink::WebMediaPlayer* webMediaPlayer() const { return m_player ? m_player->webMediaPlayer() : 0; } - // Eventually overloaded in HTMLVideoElement - virtual bool supportsFullscreen() const OVERRIDE { return false; }; + virtual bool hasVideo() const { return false; } + bool hasAudio() const; bool supportsSave() const; @@ -99,7 +109,7 @@ public: bool isActive() const { return m_active; } // error state - PassRefPtr<MediaError> error() const; + PassRefPtrWillBeRawPtr<MediaError> error() const; // network state void setSrc(const AtomicString&); @@ -109,13 +119,14 @@ public: NetworkState networkState() const; String preload() const; - void setPreload(const String&); + void setPreload(const AtomicString&); PassRefPtr<TimeRanges> buffered() const; void load(); - String canPlayType(const String& mimeType, const String& keySystem = String(), const KURL& = KURL()) const; + String canPlayType(const String& mimeType, const String& keySystem = String()) const; // ready state + enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA }; ReadyState readyState() const; bool seeking() const; @@ -144,22 +155,7 @@ public: // media source extensions void closeMediaSource(); - void durationChanged(double duration); - - // encrypted media extensions - void webkitGenerateKeyRequest(const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState&); - void webkitGenerateKeyRequest(const String& keySystem, ExceptionState&); - void webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState&); - void webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState&); - void webkitCancelKeyRequest(const String& keySystem, const String& sessionId, ExceptionState&); - - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyadded); - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyerror); - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeymessage); - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitneedkey); - - MediaKeys* mediaKeys() const { return m_mediaKeys.get(); } - void setMediaKeys(MediaKeys*); + void durationChanged(double duration, bool requestSeek); // controls bool controls() const; @@ -169,47 +165,61 @@ public: bool muted() const; void setMuted(bool); + // play/pause toggling that uses the media controller if present. togglePlayStateWillPlay() is + // true if togglePlayState() will call play() or unpause() on the media element or controller. + bool togglePlayStateWillPlay() const; void togglePlayState(); - void beginScrubbing(); - void endScrubbing(); - bool canPlay() const; + AudioTrackList& audioTracks(); + void audioTrackChanged(); - double percentLoaded() const; + VideoTrackList& videoTracks(); + void selectedVideoTrackChanged(blink::WebMediaPlayer::TrackId*); - PassRefPtr<TextTrack> addTextTrack(const String& kind, const String& label, const String& language, ExceptionState&); - PassRefPtr<TextTrack> addTextTrack(const String& kind, const String& label, ExceptionState& exceptionState) { return addTextTrack(kind, label, emptyString(), exceptionState); } - PassRefPtr<TextTrack> addTextTrack(const String& kind, ExceptionState& exceptionState) { return addTextTrack(kind, emptyString(), emptyString(), exceptionState); } + PassRefPtrWillBeRawPtr<TextTrack> addTextTrack(const AtomicString& kind, const AtomicString& label, const AtomicString& language, ExceptionState&); + PassRefPtrWillBeRawPtr<TextTrack> addTextTrack(const AtomicString& kind, const AtomicString& label, ExceptionState& exceptionState) { return addTextTrack(kind, label, emptyAtom, exceptionState); } + PassRefPtrWillBeRawPtr<TextTrack> addTextTrack(const AtomicString& kind, ExceptionState& exceptionState) { return addTextTrack(kind, emptyAtom, emptyAtom, exceptionState); } TextTrackList* textTracks(); CueList currentlyActiveCues() const { return m_currentlyActiveCues; } - void addTrack(TextTrack*); - void removeTrack(TextTrack*); - void removeAllInbandTracks(); + void addTextTrack(TextTrack*); + void removeTextTrack(TextTrack*); void closeCaptionTracksChanged(); void notifyMediaPlayerOfTextTrackChanges(); - void didAddTrack(HTMLTrackElement*); - void didRemoveTrack(HTMLTrackElement*); + // Implements the "forget the media element's media-resource-specific tracks" algorithm in the HTML5 spec. + void forgetResourceSpecificTracks(); + + void didAddTrackElement(HTMLTrackElement*); + void didRemoveTrackElement(HTMLTrackElement*); + + blink::WebMediaPlayer::TrackId addAudioTrack(const String& id, blink::WebMediaPlayerClient::AudioTrackKind, const AtomicString& label, const AtomicString& language, bool enabled); + void removeAudioTrack(blink::WebMediaPlayer::TrackId); + blink::WebMediaPlayer::TrackId addVideoTrack(const String& id, blink::WebMediaPlayerClient::VideoTrackKind, const AtomicString& label, const AtomicString& language, bool selected); + void removeVideoTrack(blink::WebMediaPlayer::TrackId); - virtual void mediaPlayerDidAddTrack(blink::WebInbandTextTrack*) OVERRIDE; - virtual void mediaPlayerDidRemoveTrack(blink::WebInbandTextTrack*) OVERRIDE; + virtual void mediaPlayerDidAddTextTrack(blink::WebInbandTextTrack*) OVERRIDE FINAL; + virtual void mediaPlayerDidRemoveTextTrack(blink::WebInbandTextTrack*) OVERRIDE FINAL; + // FIXME: Remove this when WebMediaPlayerClientImpl::loadInternal does not depend on it. + virtual KURL mediaPlayerPosterURL() OVERRIDE { return KURL(); } - struct TrackGroup { + class TrackGroup { + STACK_ALLOCATED(); + public: enum GroupKind { CaptionsAndSubtitles, Description, Chapter, Metadata, Other }; - TrackGroup(GroupKind kind) - : visibleTrack(0) - , defaultTrack(0) + explicit TrackGroup(GroupKind kind) + : visibleTrack(nullptr) + , defaultTrack(nullptr) , kind(kind) , hasSrcLang(false) { } - Vector<RefPtr<TextTrack> > tracks; - RefPtr<TextTrack> visibleTrack; - RefPtr<TextTrack> defaultTrack; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> > tracks; + RefPtrWillBeMember<TextTrack> visibleTrack; + RefPtrWillBeMember<TextTrack> defaultTrack; GroupKind kind; bool hasSrcLang; }; @@ -227,20 +237,19 @@ public: void updateTextTrackDisplay(); void textTrackReadyStateChanged(TextTrack*); - // TextTrackClient - virtual void textTrackKindChanged(TextTrack*) OVERRIDE; - virtual void textTrackModeChanged(TextTrack*) OVERRIDE; - virtual void textTrackAddCues(TextTrack*, const TextTrackCueList*) OVERRIDE; - virtual void textTrackRemoveCues(TextTrack*, const TextTrackCueList*) OVERRIDE; - virtual void textTrackAddCue(TextTrack*, PassRefPtr<TextTrackCue>) OVERRIDE; - virtual void textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue>) OVERRIDE; + void textTrackKindChanged(TextTrack*); + void textTrackModeChanged(TextTrack*); + void textTrackAddCues(TextTrack*, const TextTrackCueList*); + void textTrackRemoveCues(TextTrack*, const TextTrackCueList*); + void textTrackAddCue(TextTrack*, PassRefPtrWillBeRawPtr<TextTrackCue>); + void textTrackRemoveCue(TextTrack*, PassRefPtrWillBeRawPtr<TextTrackCue>); // EventTarget function. // Both Node (via HTMLElement) and ActiveDOMObject define this method, which // causes an ambiguity error at compile time. This class's constructor // ensures that both implementations return document, so return the result // of one of them here. - virtual ExecutionContext* executionContext() const OVERRIDE { return HTMLElement::executionContext(); } + using HTMLElement::executionContext; bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); } @@ -260,12 +269,12 @@ public: bool isPlaying() const { return m_playing; } // ActiveDOMObject functions. - virtual bool hasPendingActivity() const OVERRIDE; - virtual void contextDestroyed() OVERRIDE; + virtual bool hasPendingActivity() const OVERRIDE FINAL; + virtual void contextDestroyed() OVERRIDE FINAL; #if ENABLE(WEB_AUDIO) - MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; } - void setAudioSourceNode(MediaElementAudioSourceNode*); + AudioSourceProviderClient* audioSourceNode() { return m_audioSourceNode; } + void setAudioSourceNode(AudioSourceProviderClient*); AudioSourceProvider* audioSourceProvider(); #endif @@ -274,44 +283,34 @@ public: bool isSafeToLoadURL(const KURL&, InvalidURLAction); MediaController* controller() const; - void setController(PassRefPtr<MediaController>); // Resets the MediaGroup and sets the MediaController. + void setController(PassRefPtrWillBeRawPtr<MediaController>); // Resets the MediaGroup and sets the MediaController. + + void scheduleEvent(PassRefPtrWillBeRawPtr<Event>); + + // Current volume that should be used by the webMediaPlayer(). This method takes muted state + // and m_mediaController multipliers into account. + double playerVolume() const; + +#if ENABLE(OILPAN) + bool isFinalizing() const { return m_isFinalizing; } +#endif protected: - HTMLMediaElement(const QualifiedName&, Document&, bool); + HTMLMediaElement(const QualifiedName&, Document&); virtual ~HTMLMediaElement(); virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual void finishParsingChildren() OVERRIDE; + virtual void finishParsingChildren() OVERRIDE FINAL; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; - enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video }; + enum DisplayMode { Unknown, Poster, PosterWaitingForVideo, Video }; DisplayMode displayMode() const { return m_displayMode; } virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; } - virtual bool isMediaElement() const OVERRIDE { return true; } - - void setControllerInternal(PassRefPtr<MediaController>); - - // Restrictions to change default behaviors. - enum BehaviorRestrictionFlags { - NoRestrictions = 0, - RequireUserGestureForLoadRestriction = 1 << 0, - RequireUserGestureForRateChangeRestriction = 1 << 1, - RequireUserGestureForFullscreenRestriction = 1 << 2, - RequirePageConsentToLoadMediaRestriction = 1 << 3, - }; - typedef unsigned BehaviorRestrictions; - - bool userGestureRequiredForLoad() const { return m_restrictions & RequireUserGestureForLoadRestriction; } - bool userGestureRequiredForRateChange() const { return m_restrictions & RequireUserGestureForRateChangeRestriction; } - bool userGestureRequiredForFullscreen() const { return m_restrictions & RequireUserGestureForFullscreenRestriction; } - bool pageConsentRequiredForLoad() const { return m_restrictions & RequirePageConsentToLoadMediaRestriction; } - - void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; } - void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; } + void setControllerInternal(PassRefPtrWillBeRawPtr<MediaController>); bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0; } void beginIgnoringTrackDisplayUpdateRequests(); @@ -320,51 +319,42 @@ protected: private: void createMediaPlayer(); - virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE { return true; } - virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; } + virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE FINAL { return true; } + virtual bool areAuthorShadowsAllowed() const OVERRIDE FINAL { return false; } - virtual bool hasCustomFocusLogic() const OVERRIDE; - virtual bool supportsFocus() const OVERRIDE; - virtual bool isMouseFocusable() const OVERRIDE; + virtual bool supportsFocus() const OVERRIDE FINAL; + virtual bool isMouseFocusable() const OVERRIDE FINAL; virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; - virtual bool childShouldCreateRenderer(const Node& child) const OVERRIDE; - virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; - virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE; + virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE FINAL; + virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE; + virtual void removedFrom(ContainerNode*) OVERRIDE FINAL; + virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE FINAL; - virtual void didBecomeFullscreenElement() OVERRIDE; - virtual void willStopBeingFullscreenElement() OVERRIDE; - virtual bool isInteractiveContent() const OVERRIDE; + virtual void didBecomeFullscreenElement() OVERRIDE FINAL; + virtual void willStopBeingFullscreenElement() OVERRIDE FINAL; + virtual bool isInteractiveContent() const OVERRIDE FINAL; + virtual void defaultEventHandler(Event*) OVERRIDE FINAL; // ActiveDOMObject functions. - virtual void stop() OVERRIDE; + virtual void stop() OVERRIDE FINAL; virtual void updateDisplayState() { } - void setReadyState(MediaPlayer::ReadyState); + void setReadyState(ReadyState); void setNetworkState(MediaPlayer::NetworkState); - virtual void mediaPlayerNetworkStateChanged() OVERRIDE; - virtual void mediaPlayerReadyStateChanged() OVERRIDE; - virtual void mediaPlayerTimeChanged() OVERRIDE; - virtual void mediaPlayerDurationChanged() OVERRIDE; - virtual void mediaPlayerPlaybackStateChanged() OVERRIDE; - virtual void mediaPlayerRequestFullscreen() OVERRIDE; - virtual void mediaPlayerRequestSeek(double) OVERRIDE; - virtual void mediaPlayerRepaint() OVERRIDE; - virtual void mediaPlayerSizeChanged() OVERRIDE; - - virtual void mediaPlayerKeyAdded(const String& keySystem, const String& sessionId) OVERRIDE; - virtual void mediaPlayerKeyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode) OVERRIDE; - virtual void mediaPlayerKeyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const KURL& defaultURL) OVERRIDE; - virtual bool mediaPlayerKeyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) OVERRIDE; - virtual bool mediaPlayerKeyNeeded(Uint8Array*) OVERRIDE; - - virtual CORSMode mediaPlayerCORSMode() const OVERRIDE; - - virtual void mediaPlayerSetWebLayer(blink::WebLayer*) OVERRIDE; - virtual void mediaPlayerSetOpaque(bool) OVERRIDE; + virtual void mediaPlayerNetworkStateChanged() OVERRIDE FINAL; + virtual void mediaPlayerReadyStateChanged() OVERRIDE FINAL; + virtual void mediaPlayerTimeChanged() OVERRIDE FINAL; + virtual void mediaPlayerDurationChanged() OVERRIDE FINAL; + virtual void mediaPlayerPlaybackStateChanged() OVERRIDE FINAL; + virtual void mediaPlayerRequestFullscreen() OVERRIDE FINAL; + virtual void mediaPlayerRequestSeek(double) OVERRIDE FINAL; + virtual void mediaPlayerRepaint() OVERRIDE FINAL; + virtual void mediaPlayerSizeChanged() OVERRIDE FINAL; + virtual void mediaPlayerSetWebLayer(blink::WebLayer*) OVERRIDE FINAL; + virtual void mediaPlayerMediaSourceOpened(blink::WebMediaSource*) OVERRIDE FINAL; void loadTimerFired(Timer<HTMLMediaElement>*); void progressEventTimerFired(Timer<HTMLMediaElement>*); @@ -379,19 +369,24 @@ private: void addPlayedRange(double start, double end); void scheduleTimeupdateEvent(bool periodicEvent); - void scheduleEvent(const AtomicString& eventName); + void scheduleEvent(const AtomicString& eventName); // FIXME: Rename to scheduleNamedEvent for clarity. // loading + void prepareForLoad(); + void loadInternal(); void selectMediaResource(); void loadResource(const KURL&, ContentType&, const String& keySystem); + void startPlayerLoad(); + void setPlayerPreload(); + blink::WebMediaPlayer::LoadType loadType() const; void scheduleNextSourceChild(); void loadNextSourceChild(); void userCancelledLoad(); void clearMediaPlayer(int flags); - void clearMediaPlayerAndAudioSourceProviderClient(); + void clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); bool havePotentialSourceChild(); void noneSupported(); - void mediaEngineError(PassRefPtr<MediaError> err); + void mediaEngineError(PassRefPtrWillBeRawPtr<MediaError>); void cancelPendingEventsAndCallbacks(); void waitForSourceChange(); void prepareToPlay(); @@ -400,17 +395,22 @@ private: void mediaLoadingFailed(MediaPlayer::NetworkState); + // deferred loading (preload=none) + bool loadIsDeferred() const; + void deferLoad(); + void cancelDeferredLoad(); + void startDeferredLoad(); + void executeDeferredLoad(); + void deferredLoadTimerFired(Timer<HTMLMediaElement>*); + void updateActiveTextTrackCues(double); HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const; void markCaptionAndSubtitleTracksAsUnconfigured(); - // These "internal" functions do not check user gesture restrictions. - void loadInternal(); + // This does not check user gesture restrictions. void playInternal(); - void pauseInternal(); - void prepareForLoad(); void allowVideoRendering(); void updateVolume(); @@ -418,14 +418,11 @@ private: bool potentiallyPlaying() const; bool endedPlayback() const; bool stoppedDueToErrors() const; - bool pausedForUserInteraction() const; bool couldPlayIfEnoughData() const; // Pauses playback without changing any states or generating events void setPausedInternal(bool); - void setPlaybackRateInternal(double); - void setShouldDelayLoadEvent(bool); void invalidateCachedTime(); void refreshCachedTime() const; @@ -437,25 +434,44 @@ private: void prepareMediaFragmentURI(); void applyMediaFragmentURI(); - virtual void* preDispatchEventHandler(Event*) OVERRIDE; + virtual void* preDispatchEventHandler(Event*) OVERRIDE FINAL; void changeNetworkStateFromLoadingToIdle(); - void removeBehaviorsRestrictionsAfterFirstUserGesture(); - const AtomicString& mediaGroup() const; void setMediaGroup(const AtomicString&); void updateMediaController(); bool isBlocked() const; bool isBlockedOnMediaController() const; - bool hasCurrentSrc() const { return !m_currentSrc.isEmpty(); } bool isAutoplaying() const { return m_autoplaying; } + blink::WebMediaPlayer::CORSMode corsMode() const; + + // Returns the "direction of playback" value as specified in the HTML5 spec. + enum DirectionOfPlayback { Backward, Forward }; + DirectionOfPlayback directionOfPlayback() const; + + // Returns the "effective playback rate" value as specified in the HTML5 spec. + double effectivePlaybackRate() const; + + // Creates placeholder AudioTrack and/or VideoTrack objects when WebMemediaPlayer objects + // advertise they have audio and/or video, but don't explicitly signal them via + // addAudioTrack() and addVideoTrack(). + // FIXME: Remove this once all WebMediaPlayer implementations properly report their track info. + void createPlaceholderTracksIfNecessary(); + + // Sets the selected/enabled tracks if they aren't set before we initially + // transition to HAVE_METADATA. + void selectInitialTracksIfNecessary(); + + void audioTracksTimerFired(Timer<HTMLMediaElement>*); + Timer<HTMLMediaElement> m_loadTimer; Timer<HTMLMediaElement> m_progressEventTimer; Timer<HTMLMediaElement> m_playbackProgressTimer; + Timer<HTMLMediaElement> m_audioTracksTimer; RefPtr<TimeRanges> m_playedTimeRanges; - OwnPtr<GenericEventQueue> m_asyncEventQueue; + OwnPtrWillBeMember<GenericEventQueue> m_asyncEventQueue; double m_playbackRate; double m_defaultPlaybackRate; @@ -464,12 +480,11 @@ private: ReadyState m_readyStateMaximum; KURL m_currentSrc; - RefPtr<MediaError> m_error; + RefPtrWillBeMember<MediaError> m_error; double m_volume; double m_lastSeekTime; - unsigned m_previousProgress; double m_previousProgressTime; // Cached duration to suppress duplicate events if duration unchanged. @@ -484,14 +499,27 @@ private: // Loading state. enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement }; LoadState m_loadState; - RefPtr<HTMLSourceElement> m_currentSourceNode; - RefPtr<Node> m_nextChildNodeToConsider; + RefPtrWillBeMember<HTMLSourceElement> m_currentSourceNode; + RefPtrWillBeMember<Node> m_nextChildNodeToConsider; + + // "Deferred loading" state (for preload=none). + enum DeferredLoadState { + // The load is not deferred. + NotDeferred, + // The load is deferred, and waiting for the task to set the + // delaying-the-load-event flag (to false). + WaitingForStopDelayingLoadEventTask, + // The load is the deferred, and waiting for a triggering event. + WaitingForTrigger, + // The load is deferred, and waiting for the task to set the + // delaying-the-load-event flag, after which the load will be executed. + ExecuteOnStopDelayingLoadEventTask + }; + DeferredLoadState m_deferredLoadState; + Timer<HTMLMediaElement> m_deferredLoadTimer; OwnPtr<MediaPlayer> m_player; blink::WebLayer* m_webLayer; - bool m_opaque; - - BehaviorRestrictions m_restrictions; MediaPlayer::Preload m_preload; @@ -510,6 +538,7 @@ private: PendingActionFlags m_pendingActionFlags; // FIXME: MediaElement has way too many state bits. + bool m_userGestureRequiredForPlay : 1; bool m_playing : 1; bool m_shouldDelayLoadEvent : 1; bool m_haveFiredLoadedData : 1; @@ -529,18 +558,22 @@ private: bool m_closedCaptionsVisible : 1; - bool m_loadInitiatedByUserGesture : 1; bool m_completelyLoaded : 1; bool m_havePreparedToPlay : 1; - bool m_parsingInProgress : 1; + bool m_delayingLoadForPreloadNone : 1; bool m_tracksAreReady : 1; bool m_haveVisibleTextTrack : 1; bool m_processingPreferenceChange : 1; +#if ENABLE(OILPAN) + bool m_isFinalizing : 1; +#endif double m_lastTextTrackUpdateTime; - RefPtr<TextTrackList> m_textTracks; - Vector<RefPtr<TextTrack> > m_textTracksWhenResourceSelectionBegan; + RefPtrWillBeMember<AudioTrackList> m_audioTracks; + RefPtrWillBeMember<VideoTrackList> m_videoTracks; + RefPtrWillBeMember<TextTrackList> m_textTracks; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> > m_textTracksWhenResourceSelectionBegan; CueIntervalTree m_cueTree; @@ -549,17 +582,17 @@ private: #if ENABLE(WEB_AUDIO) // This is a weak reference, since m_audioSourceNode holds a reference to us. - // The value is set just after the MediaElementAudioSourceNode is created. - // The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode(). - MediaElementAudioSourceNode* m_audioSourceNode; + // FIXME: Oilpan: Consider making this a strongly traced pointer with oilpan where strong cycles are not a problem. + RawPtrWillBeWeakMember<AudioSourceProviderClient> m_audioSourceNode; #endif friend class MediaController; - RefPtr<MediaController> m_mediaController; + RefPtrWillBeMember<MediaController> m_mediaController; + friend class Internals; friend class TrackDisplayUpdateScope; - RefPtr<MediaKeys> m_mediaKeys; + static URLRegistry* s_mediaStreamRegistry; }; #ifndef NDEBUG @@ -581,17 +614,17 @@ struct ValueToString<TextTrackCue*> { }; #endif -inline bool isHTMLMediaElement(Node* node) +inline bool isHTMLMediaElement(const Element& element) { - return node && node->isElementNode() && toElement(node)->isMediaElement(); + return isHTMLAudioElement(element) || isHTMLVideoElement(element); } -inline bool isHTMLMediaElement(const Node& node) +inline bool isHTMLMediaElement(const HTMLElement& element) { - return node.isElementNode() && toElement(node).isMediaElement(); + return isHTMLAudioElement(element) || isHTMLVideoElement(element); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLMediaElement); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLMediaElement); } //namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.idl index a4dbf6fdf6d..3d87a591ba3 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMediaElement.idl @@ -24,17 +24,18 @@ */ [ + ActiveDOMObject, RuntimeEnabled=Media, - ActiveDOMObject + TypeChecking=Unrestricted, ] interface HTMLMediaElement : HTMLElement { // error state - readonly attribute MediaError error; + [TypeChecking=Interface|Nullable] readonly attribute MediaError? error; // network state - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; - [URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] readonly attribute DOMString currentSrc; - [Reflect] attribute DOMString crossOrigin; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; + [URL, LogActivity=SetterOnly] readonly attribute DOMString currentSrc; + [Reflect, ReflectOnly="anonymous"|"use-credentials", ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString crossOrigin; const unsigned short NETWORK_EMPTY = 0; const unsigned short NETWORK_IDLE = 1; @@ -45,7 +46,7 @@ readonly attribute TimeRanges buffered; void load(); - DOMString canPlayType([Default=Undefined] optional DOMString type, [Default=Undefined, TreatNullAs=NullString, TreatUndefinedAs=NullString] optional DOMString keySystem); + DOMString canPlayType(DOMString type, [Default=Undefined, TreatNullAs=NullString, TreatUndefinedAs=NullString] optional DOMString keySystem); // ready state const unsigned short HAVE_NOTHING = 0; @@ -58,7 +59,7 @@ // playback state [RaisesException=Setter] attribute double currentTime; - readonly attribute double duration; + readonly attribute unrestricted double duration; readonly attribute boolean paused; attribute double defaultPlaybackRate; attribute double playbackRate; @@ -71,8 +72,8 @@ void pause(); // media controller - [Reflect] attribute DOMString mediaGroup; - [StrictTypeChecking] attribute MediaController controller; + [RuntimeEnabled=MediaController, Reflect] attribute DOMString mediaGroup; + [RuntimeEnabled=MediaController, TypeChecking=Interface|Nullable] attribute MediaController? controller; // controls attribute boolean controls; @@ -81,8 +82,10 @@ [Reflect=muted] attribute boolean defaultMuted; // tracks - [RuntimeEnabled=VideoTrack] readonly attribute TextTrackList textTracks; - [RuntimeEnabled=VideoTrack, RaisesException] TextTrack addTextTrack(DOMString kind, optional DOMString label, optional DOMString language); + [RuntimeEnabled=AudioVideoTracks] readonly attribute AudioTrackList audioTracks; + [RuntimeEnabled=AudioVideoTracks] readonly attribute VideoTrackList videoTracks; + readonly attribute TextTrackList textTracks; + [RaisesException] TextTrack addTextTrack(DOMString kind, optional DOMString label, optional DOMString language); // WebKit extensions @@ -90,15 +93,5 @@ [MeasureAs=PrefixedAudioDecodedByteCount] readonly attribute unsigned long webkitAudioDecodedByteCount; [MeasureAs=PrefixedVideoDecodedByteCount] readonly attribute unsigned long webkitVideoDecodedByteCount; - // FIXME: add DeprecateAs=PrefixedMediaGenerateKeyRequest when MediaKeys is ready. - [RuntimeEnabled=PrefixedEncryptedMedia, RaisesException] void webkitGenerateKeyRequest([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem, optional Uint8Array initData); - [RuntimeEnabled=PrefixedEncryptedMedia, RaisesException] void webkitAddKey([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem, Uint8Array key, optional Uint8Array initData, [Default=NullString] optional DOMString sessionId); - [RuntimeEnabled=PrefixedEncryptedMedia, RaisesException] void webkitCancelKeyRequest([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem, [Default=NullString] optional DOMString sessionId); - - [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitkeyadded; - [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitkeyerror; - [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitkeymessage; - [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitneedkey; - - [RuntimeEnabled=EncryptedMedia] attribute MediaKeys mediaKeys; + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMediaSource.h b/chromium/third_party/WebKit/Source/core/html/HTMLMediaSource.h index f40206ce094..14baccb8e49 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMediaSource.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMediaSource.h @@ -31,7 +31,6 @@ #ifndef HTMLMediaSource_h #define HTMLMediaSource_h -#include "core/html/HTMLMediaElement.h" #include "core/html/URLRegistry.h" #include "wtf/Forward.h" @@ -41,6 +40,7 @@ class WebMediaSource; namespace WebCore { +class HTMLMediaElement; class TimeRanges; class HTMLMediaSource : public URLRegistrable { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.cpp index 2783c047b6a..5643bc146a5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "core/html/HTMLMenuElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -35,9 +35,6 @@ inline HTMLMenuElement::HTMLMenuElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLMenuElement> HTMLMenuElement::create(Document& document) -{ - return adoptRef(new HTMLMenuElement(document)); -} +DEFINE_NODE_FACTORY(HTMLMenuElement) } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.h index b1fdab64b05..4df4c6d101c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMenuElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLMenuElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLMenuElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLMenuElement); private: explicit HTMLMenuElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement-in.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement-in.cpp index 02060a45742..78505207eb5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement-in.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement-in.cpp @@ -23,9 +23,12 @@ #include "config.h" #include "core/html/HTMLMetaElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/loader/FrameLoaderClient.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { @@ -51,10 +54,7 @@ inline HTMLMetaElement::HTMLMetaElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLMetaElement> HTMLMetaElement::create(Document& document) -{ - return adoptRef(new HTMLMetaElement(document)); -} +DEFINE_NODE_FACTORY(HTMLMetaElement) static bool isInvalidSeparator(UChar c) { @@ -72,13 +72,12 @@ void HTMLMetaElement::parseContentAttribute(const String& content, KeyValuePairC bool error = false; // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior. - int keyBegin, keyEnd; - int valueBegin, valueEnd; + unsigned keyBegin, keyEnd; + unsigned valueBegin, valueEnd; - int i = 0; - int length = content.length(); String buffer = content.lower(); - while (i < length) { + unsigned length = buffer.length(); + for (unsigned i = 0; i < length; /* no increment here */) { // skip to first non-separator, but don't skip past the end of the string while (isSeparator(buffer[i])) { if (i >= length) @@ -90,6 +89,8 @@ void HTMLMetaElement::parseContentAttribute(const String& content, KeyValuePairC // skip to first separator while (!isSeparator(buffer[i])) { error |= isInvalidSeparator(buffer[i]); + if (i >= length) + break; i++; } keyEnd = i; @@ -113,6 +114,8 @@ void HTMLMetaElement::parseContentAttribute(const String& content, KeyValuePairC // skip to first separator while (!isSeparator(buffer[i])) { error |= isInvalidSeparator(buffer[i]); + if (i >= length) + break; i++; } valueEnd = i; @@ -177,10 +180,10 @@ Length HTMLMetaElement::parseViewportValueAsLength(const String& keyString, cons DEFINE_ARRAY_FOR_MATCHING(characters, valueString, 13); SWITCH(characters, length) { CASE("device-width") { - return Length(100, ViewportPercentageWidth); + return Length(DeviceWidth); } CASE("device-height") { - return Length(100, ViewportPercentageHeight); + return Length(DeviceHeight); } } @@ -192,7 +195,7 @@ Length HTMLMetaElement::parseViewportValueAsLength(const String& keyString, cons return Length(clampLengthValue(value), Fixed); } -float HTMLMetaElement::parseViewportValueAsZoom(const String& keyString, const String& valueString) +float HTMLMetaElement::parseViewportValueAsZoom(const String& keyString, const String& valueString, bool& computedValueMatchesParsedValue) { // 1) Non-negative number values are translated to <number> values. // 2) Negative number values are translated to auto. @@ -200,6 +203,7 @@ float HTMLMetaElement::parseViewportValueAsZoom(const String& keyString, const S // 4) device-width and device-height are translated to 10.0. // 5) no and unknown values are translated to 0.0 + computedValueMatchesParsedValue = false; unsigned length = valueString.length(); DEFINE_ARRAY_FOR_MATCHING(characters, valueString, 13); SWITCH(characters, length) { @@ -228,37 +232,44 @@ float HTMLMetaElement::parseViewportValueAsZoom(const String& keyString, const S if (!value && document().settings() && document().settings()->viewportMetaZeroValuesQuirk()) return ViewportDescription::ValueAuto; - return clampScaleValue(value); + float clampedValue = clampScaleValue(value); + if (clampedValue == value) + computedValueMatchesParsedValue = true; + + return clampedValue; } -float HTMLMetaElement::parseViewportValueAsUserZoom(const String& keyString, const String& valueString) +bool HTMLMetaElement::parseViewportValueAsUserZoom(const String& keyString, const String& valueString, bool& computedValueMatchesParsedValue) { // yes and no are used as keywords. // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes. // Numbers in the range <-1, 1>, and unknown values, are mapped to no. + computedValueMatchesParsedValue = false; unsigned length = valueString.length(); DEFINE_ARRAY_FOR_MATCHING(characters, valueString, 13); SWITCH(characters, length) { CASE("yes") { - return 1; + computedValueMatchesParsedValue = true; + return true; } CASE("no") { - return 0; + computedValueMatchesParsedValue = true; + return false; } CASE("device-width") { - return 1; + return true; } CASE("device-height") { - return 1; + return true; } } float value = parsePositiveNumber(keyString, valueString); if (fabs(value) < 1) - return 0; + return false; - return 1; + return true; } float HTMLMetaElement::parseViewportValueAsDPI(const String& keyString, const String& valueString) @@ -313,19 +324,19 @@ void HTMLMetaElement::processViewportKeyValuePair(const String& keyString, const return; } CASE("initial-scale") { - description->zoom = parseViewportValueAsZoom(keyString, valueString); + description->zoom = parseViewportValueAsZoom(keyString, valueString, description->zoomIsExplicit); return; } CASE("minimum-scale") { - description->minZoom = parseViewportValueAsZoom(keyString, valueString); + description->minZoom = parseViewportValueAsZoom(keyString, valueString, description->minZoomIsExplicit); return; } CASE("maximum-scale") { - description->maxZoom = parseViewportValueAsZoom(keyString, valueString); + description->maxZoom = parseViewportValueAsZoom(keyString, valueString, description->maxZoomIsExplicit); return; } CASE("user-scalable") { - description->userZoom = parseViewportValueAsUserZoom(keyString, valueString); + description->userZoom = parseViewportValueAsUserZoom(keyString, valueString, description->userZoomIsExplicit); return; } CASE("target-densitydpi") { @@ -333,6 +344,10 @@ void HTMLMetaElement::processViewportKeyValuePair(const String& keyString, const reportViewportWarning(TargetDensityDpiUnsupported, String(), String()); return; } + CASE("minimal-ui") { + // Ignore vendor-specific argument. + return; + } } reportViewportWarning(UnrecognizedViewportArgumentKeyError, keyString, String()); } @@ -355,11 +370,10 @@ static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode) switch (errorCode) { case TruncatedViewportArgumentValueError: case TargetDensityDpiUnsupported: - return WarningMessageLevel; case UnrecognizedViewportArgumentKeyError: case UnrecognizedViewportArgumentValueError: case MaximumScaleTooLargeError: - return ErrorMessageLevel; + return WarningMessageLevel; } ASSERT_NOT_REACHED(); @@ -385,9 +399,6 @@ void HTMLMetaElement::processViewportContentAttribute(const String& content, Vie { ASSERT(!content.isNull()); - if (!document().settings()) - return; - if (!document().shouldOverrideLegacyDescription(origin)) return; @@ -405,18 +416,6 @@ void HTMLMetaElement::processViewportContentAttribute(const String& content, Vie descriptionFromLegacyTag.minZoom = std::min(descriptionFromLegacyTag.minZoom, float(5)); } - const Settings* settings = document().settings(); - - if (descriptionFromLegacyTag.maxWidth.isAuto()) { - if (descriptionFromLegacyTag.zoom == ViewportDescription::ValueAuto) { - descriptionFromLegacyTag.minWidth = Length(ExtendToZoom); - descriptionFromLegacyTag.maxWidth = Length(settings->layoutFallbackWidth(), Fixed); - } else if (descriptionFromLegacyTag.maxHeight.isAuto()) { - descriptionFromLegacyTag.minWidth = Length(ExtendToZoom); - descriptionFromLegacyTag.maxWidth = Length(ExtendToZoom); - } - } - document().setViewportDescription(descriptionFromLegacyTag); } @@ -435,9 +434,24 @@ void HTMLMetaElement::parseAttribute(const QualifiedName& name, const AtomicStri Node::InsertionNotificationRequest HTMLMetaElement::insertedInto(ContainerNode* insertionPoint) { HTMLElement::insertedInto(insertionPoint); - if (insertionPoint->inDocument()) - process(); - return InsertionDone; + return InsertionShouldCallDidNotifySubtreeInsertions; +} + +void HTMLMetaElement::didNotifySubtreeInsertionsToDocument() +{ + process(); +} + +static bool inDocumentHead(HTMLMetaElement* element) +{ + if (!element->inDocument()) + return false; + + for (Element* current = element; current; current = current->parentElement()) { + if (isHTMLHeadElement(*current)) + return true; + } + return false; } void HTMLMetaElement::process() @@ -451,24 +465,26 @@ void HTMLMetaElement::process() return; const AtomicString& nameValue = fastGetAttribute(nameAttr); - if (nameValue.isNull()) { - // Get the document to process the tag, but only if we're actually part of DOM - // tree (changing a meta tag while it's not in the tree shouldn't have any effect - // on the document). - const AtomicString& httpEquivValue = fastGetAttribute(http_equivAttr); - if (!httpEquivValue.isNull()) - document().processHttpEquiv(httpEquivValue, contentValue); - return; + if (!nameValue.isEmpty()) { + if (equalIgnoringCase(nameValue, "viewport")) + processViewportContentAttribute(contentValue, ViewportDescription::ViewportMeta); + else if (equalIgnoringCase(nameValue, "referrer")) + document().processReferrerPolicy(contentValue); + else if (equalIgnoringCase(nameValue, "handheldfriendly") && equalIgnoringCase(contentValue, "true")) + processViewportContentAttribute("width=device-width", ViewportDescription::HandheldFriendlyMeta); + else if (equalIgnoringCase(nameValue, "mobileoptimized")) + processViewportContentAttribute("width=device-width, initial-scale=1", ViewportDescription::MobileOptimizedMeta); + else if (RuntimeEnabledFeatures::themeColorEnabled() && equalIgnoringCase(nameValue, "theme-color") && document().frame()) + document().frame()->loader().client()->dispatchDidChangeThemeColor(); } - if (equalIgnoringCase(nameValue, "viewport")) - processViewportContentAttribute(contentValue, ViewportDescription::ViewportMeta); - else if (equalIgnoringCase(nameValue, "referrer")) - document().processReferrerPolicy(contentValue); - else if (equalIgnoringCase(nameValue, "handheldfriendly") && equalIgnoringCase(contentValue, "true")) - processViewportContentAttribute("width=device-width", ViewportDescription::HandheldFriendlyMeta); - else if (equalIgnoringCase(nameValue, "mobileoptimized")) - processViewportContentAttribute("width=device-width, initial-scale=1", ViewportDescription::MobileOptimizedMeta); + // Get the document to process the tag, but only if we're actually part of DOM + // tree (changing a meta tag while it's not in the tree shouldn't have any effect + // on the document). + + const AtomicString& httpEquivValue = fastGetAttribute(http_equivAttr); + if (!httpEquivValue.isEmpty()) + document().processHttpEquiv(httpEquivValue, contentValue, inDocumentHead(this)); } const AtomicString& HTMLMetaElement::content() const diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement.h index c859a33c744..ccdeffbc96c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMetaElement.h @@ -23,6 +23,7 @@ #ifndef HTMLMetaElement_h #define HTMLMetaElement_h +#include "core/dom/ViewportDescription.h" #include "core/html/HTMLElement.h" namespace WebCore { @@ -37,7 +38,7 @@ enum ViewportErrorCode { class HTMLMetaElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLMetaElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLMetaElement); const AtomicString& content() const; const AtomicString& httpEquiv() const; @@ -52,12 +53,13 @@ private: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; + virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE; float parsePositiveNumber(const String& key, const String& value, bool* ok = 0); Length parseViewportValueAsLength(const String& key, const String& value); - float parseViewportValueAsZoom(const String& key, const String& value); - float parseViewportValueAsUserZoom(const String& key, const String& value); + float parseViewportValueAsZoom(const String& key, const String& value, bool& computedValueMatchesParsedValue); + bool parseViewportValueAsUserZoom(const String& key, const String& value, bool& computedValueMatchesParsedValue); float parseViewportValueAsDPI(const String& key, const String& value); void reportViewportWarning(ViewportErrorCode, const String& replacement1, const String& replacement2); @@ -66,8 +68,6 @@ private: void processViewportContentAttribute(const String& content, ViewportDescription::Type origin); }; -DEFINE_NODE_TYPE_CASTS(HTMLMetaElement, hasTagName(HTMLNames::metaTag)); - } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp index 41e536d9944..f745a7aeaa3 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp @@ -22,10 +22,10 @@ #include "core/html/HTMLMeterElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/dom/ExceptionCode.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/parser/HTMLParserIdioms.h" @@ -47,11 +47,11 @@ HTMLMeterElement::~HTMLMeterElement() { } -PassRefPtr<HTMLMeterElement> HTMLMeterElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLMeterElement> HTMLMeterElement::create(Document& document) { - RefPtr<HTMLMeterElement> meter = adoptRef(new HTMLMeterElement(document)); + RefPtrWillBeRawPtr<HTMLMeterElement> meter = adoptRefWillBeNoop(new HTMLMeterElement(document)); meter->ensureUserAgentShadowRoot(); - return meter; + return meter.release(); } RenderObject* HTMLMeterElement::createRenderer(RenderStyle* style) @@ -70,47 +70,35 @@ void HTMLMeterElement::parseAttribute(const QualifiedName& name, const AtomicStr LabelableElement::parseAttribute(name, value); } -double HTMLMeterElement::min() const +double HTMLMeterElement::value() const { - return getFloatingPointAttribute(minAttr, 0); + double value = getFloatingPointAttribute(valueAttr, 0); + return std::min(std::max(value, min()), max()); } -void HTMLMeterElement::setMin(double min, ExceptionState& exceptionState) +void HTMLMeterElement::setValue(double value) { - if (!std::isfinite(min)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(min)); - return; - } - setFloatingPointAttribute(minAttr, min); + setFloatingPointAttribute(valueAttr, value); } -double HTMLMeterElement::max() const +double HTMLMeterElement::min() const { - return std::max(getFloatingPointAttribute(maxAttr, std::max(1.0, min())), min()); + return getFloatingPointAttribute(minAttr, 0); } -void HTMLMeterElement::setMax(double max, ExceptionState& exceptionState) +void HTMLMeterElement::setMin(double min) { - if (!std::isfinite(max)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(max)); - return; - } - setFloatingPointAttribute(maxAttr, max); + setFloatingPointAttribute(minAttr, min); } -double HTMLMeterElement::value() const +double HTMLMeterElement::max() const { - double value = getFloatingPointAttribute(valueAttr, 0); - return std::min(std::max(value, min()), max()); + return std::max(getFloatingPointAttribute(maxAttr, std::max(1.0, min())), min()); } -void HTMLMeterElement::setValue(double value, ExceptionState& exceptionState) +void HTMLMeterElement::setMax(double max) { - if (!std::isfinite(value)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(value)); - return; - } - setFloatingPointAttribute(valueAttr, value); + setFloatingPointAttribute(maxAttr, max); } double HTMLMeterElement::low() const @@ -119,12 +107,8 @@ double HTMLMeterElement::low() const return std::min(std::max(low, min()), max()); } -void HTMLMeterElement::setLow(double low, ExceptionState& exceptionState) +void HTMLMeterElement::setLow(double low) { - if (!std::isfinite(low)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(low)); - return; - } setFloatingPointAttribute(lowAttr, low); } @@ -134,12 +118,8 @@ double HTMLMeterElement::high() const return std::min(std::max(high, low()), max()); } -void HTMLMeterElement::setHigh(double high, ExceptionState& exceptionState) +void HTMLMeterElement::setHigh(double high) { - if (!std::isfinite(high)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(high)); - return; - } setFloatingPointAttribute(highAttr, high); } @@ -149,12 +129,8 @@ double HTMLMeterElement::optimum() const return std::min(std::max(optimum, min()), max()); } -void HTMLMeterElement::setOptimum(double optimum, ExceptionState& exceptionState) +void HTMLMeterElement::setOptimum(double optimum) { - if (!std::isfinite(optimum)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(optimum)); - return; - } setFloatingPointAttribute(optimumAttr, optimum); } @@ -223,10 +199,10 @@ void HTMLMeterElement::didAddUserAgentShadowRoot(ShadowRoot& root) { ASSERT(!m_value); - RefPtr<MeterInnerElement> inner = MeterInnerElement::create(document()); + RefPtrWillBeRawPtr<MeterInnerElement> inner = MeterInnerElement::create(document()); root.appendChild(inner); - RefPtr<MeterBarElement> bar = MeterBarElement::create(document()); + RefPtrWillBeRawPtr<MeterBarElement> bar = MeterBarElement::create(document()); m_value = MeterValueElement::create(document()); m_value->setWidthPercentage(0); m_value->updatePseudo(); @@ -235,4 +211,10 @@ void HTMLMeterElement::didAddUserAgentShadowRoot(ShadowRoot& root) inner->appendChild(bar); } +void HTMLMeterElement::trace(Visitor* visitor) +{ + visitor->trace(m_value); + LabelableElement::trace(visitor); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.h index e815e602442..44d9e6fd20c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.h @@ -31,7 +31,7 @@ class RenderMeter; class HTMLMeterElement FINAL : public LabelableElement { public: - static PassRefPtr<HTMLMeterElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLMeterElement> create(Document&); enum GaugeRegion { GaugeRegionOptimum, @@ -39,28 +39,30 @@ public: GaugeRegionEvenLessGood }; + double value() const; + void setValue(double); + double min() const; - void setMin(double, ExceptionState&); + void setMin(double); double max() const; - void setMax(double, ExceptionState&); - - double value() const; - void setValue(double, ExceptionState&); + void setMax(double); double low() const; - void setLow(double, ExceptionState&); + void setLow(double); double high() const; - void setHigh(double, ExceptionState&); + void setHigh(double); double optimum() const; - void setOptimum(double, ExceptionState&); + void setOptimum(double); double valueRatio() const; GaugeRegion gaugeRegion() const; - bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE { return false; } + + virtual void trace(Visitor*) OVERRIDE; private: explicit HTMLMeterElement(Document&); @@ -71,23 +73,15 @@ private: virtual bool supportLabels() const OVERRIDE { return true; } - virtual bool recalcWillValidate() const { return false; } - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; void didElementStateChange(); virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE; - RefPtr<MeterValueElement> m_value; + RefPtrWillBeMember<MeterValueElement> m_value; }; -inline bool isHTMLMeterElement(Node* node) -{ - return node->hasTagName(HTMLNames::meterTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLMeterElement, hasTagName(HTMLNames::meterTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.idl index fde8591538e..144f83ec411 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLMeterElement.idl @@ -17,12 +17,16 @@ * Boston, MA 02110-1301, USA. */ -interface HTMLMeterElement : HTMLElement { - [RaisesException=Setter] attribute double value; - [RaisesException=Setter] attribute double min; - [RaisesException=Setter] attribute double max; - [RaisesException=Setter] attribute double low; - [RaisesException=Setter] attribute double high; - [RaisesException=Setter] attribute double optimum; +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#htmlmeterelement + +[ + TypeChecking=Unrestricted, +] interface HTMLMeterElement : HTMLElement { + attribute double value; + attribute double min; + attribute double max; + attribute double low; + attribute double high; + attribute double optimum; readonly attribute NodeList labels; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLModElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLModElement.cpp index e609ef53499..bf4fbd48407 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLModElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLModElement.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "core/html/HTMLModElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -35,14 +35,21 @@ inline HTMLModElement::HTMLModElement(const QualifiedName& tagName, Document& do ScriptWrappable::init(this); } -PassRefPtr<HTMLModElement> HTMLModElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLModElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLModElement) bool HTMLModElement::isURLAttribute(const Attribute& attribute) const { return attribute.name() == citeAttr || HTMLElement::isURLAttribute(attribute); } +bool HTMLModElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == citeAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLModElement::subResourceAttributeName() const +{ + return citeAttr; +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLModElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLModElement.h index 7fcc7c93edf..cf112ccdcbc 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLModElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLModElement.h @@ -30,12 +30,14 @@ namespace WebCore { class HTMLModElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLModElement> create(const QualifiedName&, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLModElement); private: HTMLModElement(const QualifiedName&, Document&); virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; }; } //namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLModElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLModElement.idl index c066b68c0ec..3c9bf9f9792 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLModElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLModElement.idl @@ -18,6 +18,6 @@ */ interface HTMLModElement : HTMLElement { - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString cite; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString cite; [Reflect] attribute DOMString dateTime; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.cpp index 9941f554c51..a4829862410 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.cpp @@ -23,83 +23,23 @@ #include "config.h" #include "core/html/HTMLNameCollection.h" -#include "HTMLNames.h" -#include "core/dom/Element.h" -#include "core/dom/ElementTraversal.h" #include "core/dom/NodeRareData.h" -#include "core/html/HTMLEmbedElement.h" -#include "core/html/HTMLObjectElement.h" namespace WebCore { -using namespace HTMLNames; - -HTMLNameCollection::HTMLNameCollection(Node* document, CollectionType type, const AtomicString& name) - : HTMLCollection(document, type, OverridesItemAfter) +HTMLNameCollection::HTMLNameCollection(ContainerNode& document, CollectionType type, const AtomicString& name) + : HTMLCollection(document, type, DoesNotOverrideItemAfter) , m_name(name) { } HTMLNameCollection::~HTMLNameCollection() { - ASSERT(ownerNode()); - ASSERT(ownerNode()->isDocumentNode()); ASSERT(type() == WindowNamedItems || type() == DocumentNamedItems); - - ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type(), m_name); +#if !ENABLE(OILPAN) + ASSERT(ownerNode().isDocumentNode()); + ownerNode().nodeLists()->removeCache(this, type(), m_name); +#endif } -Element* HTMLNameCollection::virtualItemAfter(unsigned& offsetInArray, Element* previous) const -{ - ASSERT_UNUSED(offsetInArray, !offsetInArray); - ASSERT(previous != ownerNode()); - - Element* current; - if (!previous) - current = ElementTraversal::firstWithin(*ownerNode()); - else - current = ElementTraversal::next(*previous, ownerNode()); - - for (; current; current = ElementTraversal::next(*current, ownerNode())) { - switch (type()) { - case WindowNamedItems: - // find only images, forms, applets, embeds and objects by name, - // but anything by id - if (current->hasTagName(imgTag) - || current->hasTagName(formTag) - || current->hasTagName(appletTag) - || current->hasTagName(embedTag) - || current->hasTagName(objectTag)) { - if (current->getNameAttribute() == m_name) - return current; - } - if (current->getIdAttribute() == m_name) - return current; - break; - case DocumentNamedItems: - // find images, forms, applets, embeds, objects and iframes by name, - // applets and object by id, and images by id but only if they have - // a name attribute (this very strange rule matches IE) - if (current->hasTagName(formTag) - || current->hasTagName(iframeTag) - || (current->hasTagName(embedTag) && toHTMLEmbedElement(current)->isExposed())) { - if (current->getNameAttribute() == m_name) - return current; - } else if (current->hasTagName(appletTag) - || (current->hasTagName(objectTag) && toHTMLObjectElement(current)->isExposed())) { - if (current->getNameAttribute() == m_name || current->getIdAttribute() == m_name) - return current; - } else if (current->hasTagName(imgTag)) { - if (current->getNameAttribute() == m_name || (current->getIdAttribute() == m_name && current->hasName())) - return current; - } - break; - default: - ASSERT_NOT_REACHED(); - } - } - - return 0; -} - -} +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.h b/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.h index 435d4395860..b7ce7d4317d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLNameCollection.h @@ -24,26 +24,16 @@ #define HTMLNameCollection_h #include "core/html/HTMLCollection.h" - #include "wtf/text/AtomicString.h" namespace WebCore { -class Document; - -class HTMLNameCollection FINAL : public HTMLCollection { +class HTMLNameCollection : public HTMLCollection { public: - static PassRefPtr<HTMLNameCollection> create(Node* document, CollectionType type, const AtomicString& name) - { - return adoptRef(new HTMLNameCollection(document, type, name)); - } - - ~HTMLNameCollection(); - -private: - HTMLNameCollection(Node*, CollectionType, const AtomicString& name); + virtual ~HTMLNameCollection(); - virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE; +protected: + HTMLNameCollection(ContainerNode&, CollectionType, const AtomicString& name); AtomicString m_name; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportResourceOwner.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLNoEmbedElement.cpp index 3a3109c477d..aa6800d7a0f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportResourceOwner.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLNoEmbedElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -29,32 +29,29 @@ */ #include "config.h" -#include "core/html/HTMLImportResourceOwner.h" +#include "core/html/HTMLNoEmbedElement.h" + +#include "core/HTMLNames.h" +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" +#include "core/loader/FrameLoader.h" namespace WebCore { -HTMLImportResourceOwner::HTMLImportResourceOwner() -{ -} +using namespace HTMLNames; -HTMLImportResourceOwner::~HTMLImportResourceOwner() +inline HTMLNoEmbedElement::HTMLNoEmbedElement(Document& document) + : HTMLElement(noembedTag, document) { - clearResource(); } -void HTMLImportResourceOwner::setResource(const ResourcePtr<RawResource>& resource) -{ - ASSERT(!hasResource()); - m_resource = resource; - m_resource->addClient(this); -} +DEFINE_NODE_FACTORY(HTMLNoEmbedElement) -void HTMLImportResourceOwner::clearResource() +bool HTMLNoEmbedElement::rendererIsNeeded(const RenderStyle& style) { - if (!hasResource()) - return; - m_resource->removeClient(this); - m_resource = 0; + if (document().frame()->loader().allowPlugins(NotAboutToInstantiatePlugin)) + return false; + return Element::rendererIsNeeded(style); } -} // namespace WebCore +} diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLNoEmbedElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLNoEmbedElement.h new file mode 100644 index 00000000000..1575f4d483c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLNoEmbedElement.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLNoEmbedElement_h +#define HTMLNoEmbedElement_h + +#include "core/html/HTMLElement.h" + +namespace WebCore { + +// <noembed> is an HTMLElement in script, but we use a separate interface here +// so HTMLElement's rendererIsNeeded doesn't need to know about it. +class HTMLNoEmbedElement FINAL : public HTMLElement { +public: + DECLARE_NODE_FACTORY(HTMLNoEmbedElement); + +private: + explicit HTMLNoEmbedElement(Document&); + + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; +}; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/ime/Composition.h b/chromium/third_party/WebKit/Source/core/html/HTMLNoScriptElement.cpp index 43054668f0d..7357a74e251 100644 --- a/chromium/third_party/WebKit/Source/core/html/ime/Composition.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLNoScriptElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -28,36 +28,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Composition_h -#define Composition_h +#include "config.h" +#include "core/html/HTMLNoScriptElement.h" -#include "bindings/v8/ScriptWrappable.h" -#include "wtf/PassOwnPtr.h" -#include "wtf/text/WTFString.h" +#include "bindings/v8/ScriptController.h" +#include "core/HTMLNames.h" +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -class InputMethodContext; +using namespace HTMLNames; -class Composition : public ScriptWrappable { -public: - static PassOwnPtr<Composition> create(InputMethodContext*); - ~Composition(); +inline HTMLNoScriptElement::HTMLNoScriptElement(Document& document) + : HTMLElement(noscriptTag, document) +{ +} - void ref(); - void deref(); +DEFINE_NODE_FACTORY(HTMLNoScriptElement) - String text() const; - int selectionStart() const; - int selectionEnd() const; - const Vector<unsigned>& getSegments() const; +bool HTMLNoScriptElement::rendererIsNeeded(const RenderStyle& style) +{ + if (document().frame()->script().canExecuteScripts(NotAboutToExecuteScript)) + return false; + return Element::rendererIsNeeded(style); -private: - explicit Composition(InputMethodContext*); +} - InputMethodContext* m_inputMethodContext; -}; - -} // namespace WebCore - -#endif // Composition_h +} diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLNoScriptElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLNoScriptElement.h new file mode 100644 index 00000000000..ace1a493f0e --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLNoScriptElement.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLNoScriptElement_h +#define HTMLNoScriptElement_h + +#include "core/html/HTMLElement.h" + +namespace WebCore { + +// <noscript> is an HTMLElement in script, but we use a separate interface here +// so HTMLElement's rendererIsNeeded doesn't need to know about it. +class HTMLNoScriptElement FINAL : public HTMLElement { +public: + DECLARE_NODE_FACTORY(HTMLNoScriptElement); + +private: + explicit HTMLNoScriptElement(Document&); + + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; +}; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.cpp index 03675516a07..40ac89d6349 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.cpp @@ -23,16 +23,16 @@ #include "config.h" #include "core/html/HTMLOListElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/rendering/RenderListItem.h" namespace WebCore { using namespace HTMLNames; -HTMLOListElement::HTMLOListElement(Document& document) +inline HTMLOListElement::HTMLOListElement(Document& document) : HTMLElement(olTag, document) , m_start(0xBADBEEF) , m_itemCount(0) @@ -43,10 +43,7 @@ HTMLOListElement::HTMLOListElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLOListElement> HTMLOListElement::create(Document& document) -{ - return adoptRef(new HTMLOListElement(document)); -} +DEFINE_NODE_FACTORY(HTMLOListElement) bool HTMLOListElement::isPresentationAttribute(const QualifiedName& name) const { @@ -100,6 +97,9 @@ void HTMLOListElement::setStart(int start) void HTMLOListElement::updateItemValues() { + if (!renderer()) + return; + document().updateDistributionForNodeIfNeeded(this); RenderListItem::updateItemValuesForOrderedList(this); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.h index 0da2e2c713d..407c9166979 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOListElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLOListElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLOListElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLOListElement); int start() const { return m_hasExplicitStart ? m_start : (m_isReversed ? itemCount() : 1); } void setStart(int); @@ -64,8 +64,6 @@ private: bool m_shouldRecalculateItemCount : 1; }; -DEFINE_NODE_TYPE_CASTS(HTMLOListElement, hasTagName(HTMLNames::olTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp index 87a5c3eae98..3a503060ff6 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp @@ -24,14 +24,13 @@ #include "config.h" #include "core/html/HTMLObjectElement.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/ElementTraversal.h" -#include "core/dom/NodeList.h" +#include "core/dom/TagCollection.h" #include "core/dom/Text.h" #include "core/dom/shadow/ShadowRoot.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/fetch/ImageResource.h" #include "core/html/FormDataList.h" #include "core/html/HTMLDocument.h" @@ -53,22 +52,30 @@ inline HTMLObjectElement::HTMLObjectElement(Document& document, HTMLFormElement* : HTMLPlugInElement(objectTag, document, createdByParser, ShouldNotPreferPlugInsForImages) , m_useFallbackContent(false) { - setForm(form ? form : findFormAncestor()); ScriptWrappable::init(this); + associateByParser(form); } inline HTMLObjectElement::~HTMLObjectElement() { +#if !ENABLE(OILPAN) setForm(0); +#endif } -PassRefPtr<HTMLObjectElement> HTMLObjectElement::create(Document& document, HTMLFormElement* form, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLObjectElement> HTMLObjectElement::create(Document& document, HTMLFormElement* form, bool createdByParser) { - RefPtr<HTMLObjectElement> element = adoptRef(new HTMLObjectElement(document, form, createdByParser)); + RefPtrWillBeRawPtr<HTMLObjectElement> element = adoptRefWillBeNoop(new HTMLObjectElement(document, form, createdByParser)); element->ensureUserAgentShadowRoot(); return element.release(); } +void HTMLObjectElement::trace(Visitor* visitor) +{ + FormAssociatedElement::trace(visitor); + HTMLPlugInElement::trace(visitor); +} + RenderWidget* HTMLObjectElement::existingRenderWidget() const { return renderPart(); // This will return 0 if the renderer is not a RenderPart. @@ -98,24 +105,24 @@ void HTMLObjectElement::parseAttribute(const QualifiedName& name, const AtomicSt size_t pos = m_serviceType.find(";"); if (pos != kNotFound) m_serviceType = m_serviceType.left(pos); - if (renderer()) - setNeedsWidgetUpdate(true); + // FIXME: What is the right thing to do here? Should we supress the + // reload stuff when a persistable widget-type is specified? + reloadPluginOnAttributeChange(name); + if (!renderer()) + requestPluginCreationWithoutRendererIfPossible(); } else if (name == dataAttr) { m_url = stripLeadingAndTrailingHTMLSpaces(value); - if (renderer()) { + if (renderer() && isImageType()) { setNeedsWidgetUpdate(true); - if (isImageType()) { - if (!m_imageLoader) - m_imageLoader = adoptPtr(new HTMLImageLoader(this)); - m_imageLoader->updateFromElementIgnoringPreviousError(); - } + if (!m_imageLoader) + m_imageLoader = HTMLImageLoader::create(this); + m_imageLoader->updateFromElementIgnoringPreviousError(); + } else { + reloadPluginOnAttributeChange(name); } } else if (name == classidAttr) { m_classId = value; - if (renderer()) - setNeedsWidgetUpdate(true); - } else if (name == onbeforeloadAttr) { - setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value)); + reloadPluginOnAttributeChange(name); } else { HTMLPlugInElement::parseAttribute(name, value); } @@ -126,7 +133,7 @@ static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramV // Some plugins don't understand the "data" attribute of the OBJECT tag (i.e. Real and WMP // require "src" attribute). int srcIndex = -1, dataIndex = -1; - for (unsigned int i = 0; i < paramNames->size(); ++i) { + for (unsigned i = 0; i < paramNames->size(); ++i) { if (equalIgnoringCase((*paramNames)[i], "src")) srcIndex = i; else if (equalIgnoringCase((*paramNames)[i], "data")) @@ -147,11 +154,7 @@ void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<S // Scan the PARAM children and store their name/value pairs. // Get the URL and type from the params if we don't already have them. - for (Node* child = firstChild(); child; child = child->nextSibling()) { - if (!child->hasTagName(paramTag)) - continue; - - HTMLParamElement* p = toHTMLParamElement(child); + for (HTMLParamElement* p = Traversal<HTMLParamElement>::firstChild(*this); p; p = Traversal<HTMLParamElement>::nextSibling(*p)) { String name = p->name(); if (name.isEmpty()) continue; @@ -185,12 +188,13 @@ void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<S // Turn the attributes of the <object> element into arrays, but don't override <param> values. if (hasAttributes()) { - for (unsigned i = 0; i < attributeCount(); ++i) { - const Attribute* attribute = attributeItem(i); - const AtomicString& name = attribute->name().localName(); + AttributeCollection attributes = this->attributes(); + AttributeCollection::const_iterator end = attributes.end(); + for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { + const AtomicString& name = it->name().localName(); if (!uniqueParamNames.contains(name.impl())) { paramNames.append(name.string()); - paramValues.append(attribute->value().string()); + paramValues.append(it->value().string()); } } } @@ -217,8 +221,9 @@ bool HTMLObjectElement::hasFallbackContent() const if (child->isTextNode()) { if (!toText(child)->containsOnlyWhitespace()) return true; - } else if (!child->hasTagName(paramTag)) + } else if (!isHTMLParamElement(*child)) { return true; + } } return false; } @@ -237,7 +242,7 @@ bool HTMLObjectElement::shouldAllowQuickTimeClassIdQuirk() || !equalIgnoringCase(classId(), "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) return false; - RefPtr<NodeList> metaElements = document().getElementsByTagName(HTMLNames::metaTag.localName()); + RefPtrWillBeRawPtr<TagCollection> metaElements = document().getElementsByTagName(HTMLNames::metaTag.localName()); unsigned length = metaElements->length(); for (unsigned i = 0; i < length; ++i) { ASSERT(metaElements->item(i)->isHTMLElement()); @@ -262,6 +267,30 @@ bool HTMLObjectElement::hasValidClassId() return classId().isEmpty(); } +void HTMLObjectElement::reloadPluginOnAttributeChange(const QualifiedName& name) +{ + // Following, + // http://www.whatwg.org/specs/web-apps/current-work/#the-object-element + // (Enumerated list below "Whenever one of the following conditions occur:") + // + // the updating of certain attributes should bring about "redetermination" + // of what the element contains. + bool needsInvalidation; + if (name == typeAttr) { + needsInvalidation = !fastHasAttribute(classidAttr) && !fastHasAttribute(dataAttr); + } else if (name == dataAttr) { + needsInvalidation = !fastHasAttribute(classidAttr); + } else if (name == classidAttr) { + needsInvalidation = true; + } else { + ASSERT_NOT_REACHED(); + needsInvalidation = false; + } + setNeedsWidgetUpdate(true); + if (needsInvalidation) + setNeedsStyleRecalc(SubtreeStyleChange); +} + // FIXME: This should be unified with HTMLEmbedElement::updateWidget and // moved down into HTMLPluginElement.cpp void HTMLObjectElement::updateWidgetInternal() @@ -270,14 +299,18 @@ void HTMLObjectElement::updateWidgetInternal() ASSERT(needsWidgetUpdate()); setNeedsWidgetUpdate(false); // FIXME: This should ASSERT isFinishedParsingChildren() instead. - if (!isFinishedParsingChildren()) + if (!isFinishedParsingChildren()) { + dispatchErrorEvent(); return; + } // FIXME: I'm not sure it's ever possible to get into updateWidget during a // removal, but just in case we should avoid loading the frame to prevent // security bugs. - if (!SubframeLoadingDisabler::canLoadFrame(*this)) + if (!SubframeLoadingDisabler::canLoadFrame(*this)) { + dispatchErrorEvent(); return; + } String url = this->url(); String serviceType = m_serviceType; @@ -288,20 +321,21 @@ void HTMLObjectElement::updateWidgetInternal() parametersForPlugin(paramNames, paramValues, url, serviceType); // Note: url is modified above by parametersForPlugin. - if (!allowedToLoadFrameURL(url)) + if (!allowedToLoadFrameURL(url)) { + dispatchErrorEvent(); return; + } - bool fallbackContent = hasFallbackContent(); - renderEmbeddedObject()->setHasFallbackContent(fallbackContent); - - RefPtr<HTMLObjectElement> protect(this); // beforeload and plugin loading can make arbitrary DOM mutations. - bool beforeLoadAllowedLoad = dispatchBeforeLoadEvent(url); - if (!renderer()) // Do not load the plugin if beforeload removed this element or its renderer. + // FIXME: Is it possible to get here without a renderer now that we don't have beforeload events? + if (!renderer()) return; - bool success = beforeLoadAllowedLoad && hasValidClassId() && requestObject(url, serviceType, paramNames, paramValues); - if (!success && fallbackContent) - renderFallbackContent(); + if (!hasValidClassId() || !requestObject(url, serviceType, paramNames, paramValues)) { + if (!url.isEmpty()) + dispatchErrorEvent(); + if (hasFallbackContent()) + renderFallbackContent(); + } } bool HTMLObjectElement::rendererIsNeeded(const RenderStyle& style) @@ -329,7 +363,7 @@ void HTMLObjectElement::childrenChanged(bool changedByParser, Node* beforeChange { if (inDocument() && !useFallbackContent()) { setNeedsWidgetUpdate(true); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } HTMLPlugInElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } @@ -341,6 +375,16 @@ bool HTMLObjectElement::isURLAttribute(const Attribute& attribute) const || HTMLPlugInElement::isURLAttribute(attribute); } +bool HTMLObjectElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == classidAttr || name == dataAttr || name == codebaseAttr || HTMLPlugInElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLObjectElement::subResourceAttributeName() const +{ + return dataAttr; +} + const AtomicString HTMLObjectElement::imageSourceURL() const { return getAttribute(dataAttr); @@ -385,12 +429,12 @@ void HTMLObjectElement::renderFallbackContent() bool HTMLObjectElement::isExposed() const { // http://www.whatwg.org/specs/web-apps/current-work/#exposed - for (Node* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) { - if (ancestor->hasTagName(objectTag) && toHTMLObjectElement(ancestor)->isExposed()) + for (HTMLObjectElement* ancestor = Traversal<HTMLObjectElement>::firstAncestor(*this); ancestor; ancestor = Traversal<HTMLObjectElement>::firstAncestor(*ancestor)) { + if (ancestor->isExposed()) return false; } - for (Node* node = firstChild(); node; node = NodeTraversal::next(*node, this)) { - if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) + for (HTMLElement* element = Traversal<HTMLElement>::firstWithin(*this); element; element = Traversal<HTMLElement>::next(*element, this)) { + if (isHTMLObjectElement(*element) || isHTMLEmbedElement(*element)) return false; } return true; @@ -401,33 +445,20 @@ bool HTMLObjectElement::containsJavaApplet() const if (MIMETypeRegistry::isJavaAppletMIMEType(getAttribute(typeAttr))) return true; - for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSkippingChildren(*child, this)) { - if (child->hasTagName(paramTag) + for (HTMLElement* child = Traversal<HTMLElement>::firstChild(*this); child; child = Traversal<HTMLElement>::nextSibling(*child)) { + if (isHTMLParamElement(*child) && equalIgnoringCase(child->getNameAttribute(), "type") && MIMETypeRegistry::isJavaAppletMIMEType(child->getAttribute(valueAttr).string())) return true; - if (child->hasTagName(objectTag) && toHTMLObjectElement(child)->containsJavaApplet()) + if (isHTMLObjectElement(*child) && toHTMLObjectElement(*child).containsJavaApplet()) return true; - if (child->hasTagName(appletTag)) + if (isHTMLAppletElement(*child)) return true; } return false; } -void HTMLObjectElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLPlugInElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, document().completeURL(getAttribute(dataAttr))); - - // FIXME: Passing a string that starts with "#" to the completeURL function does - // not seem like it would work. The image element has similar but not identical code. - const AtomicString& useMap = getAttribute(usemapAttr); - if (useMap.startsWith('#')) - addSubresourceURL(urls, document().completeURL(useMap)); -} - void HTMLObjectElement::didMoveToNewDocument(Document& oldDocument) { FormAssociatedElement::didMoveToNewDocument(oldDocument); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.h index fc2c20860b5..ae30514a0e0 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.h @@ -31,9 +31,12 @@ namespace WebCore { class HTMLFormElement; class HTMLObjectElement FINAL : public HTMLPlugInElement, public FormAssociatedElement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLObjectElement); + public: - static PassRefPtr<HTMLObjectElement> create(Document&, HTMLFormElement*, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLObjectElement> create(Document&, HTMLFormElement*, bool createdByParser); virtual ~HTMLObjectElement(); + virtual void trace(Visitor*) OVERRIDE; const String& classId() const { return m_classId; } @@ -41,14 +44,15 @@ public: bool containsJavaApplet() const; + virtual bool hasFallbackContent() const OVERRIDE; virtual bool useFallbackContent() const OVERRIDE; virtual void renderFallbackContent() OVERRIDE; - virtual bool isFormControlElement() const { return false; } + virtual bool isFormControlElement() const OVERRIDE { return false; } - virtual bool isEnumeratable() const { return true; } + virtual bool isEnumeratable() const OVERRIDE { return true; } virtual bool isInteractiveContent() const OVERRIDE; - virtual bool appendFormData(FormDataList&, bool); + virtual bool appendFormData(FormDataList&, bool) OVERRIDE; virtual bool isObjectElement() const OVERRIDE { return true; } @@ -58,10 +62,12 @@ public: bool checkValidity() { return true; } virtual void setCustomValidity(const String&) OVERRIDE { } +#if !ENABLE(OILPAN) using Node::ref; using Node::deref; +#endif - virtual bool canContainRangeEndPoint() const { return useFallbackContent(); } + virtual bool canContainRangeEndPoint() const OVERRIDE { return useFallbackContent(); } bool isExposed() const; @@ -75,25 +81,23 @@ private: virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; virtual const AtomicString imageSourceURL() const OVERRIDE; virtual RenderWidget* existingRenderWidget() const OVERRIDE; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; - virtual void updateWidgetInternal() OVERRIDE; void updateDocNamedItem(); void reattachFallbackContent(); - bool hasFallbackContent() const; - // FIXME: This function should not deal with url or serviceType // so that we can better share code between <object> and <embed>. void parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues, String& url, String& serviceType); @@ -101,8 +105,12 @@ private: bool shouldAllowQuickTimeClassIdQuirk(); bool hasValidClassId(); - virtual void refFormAssociatedElement() { ref(); } - virtual void derefFormAssociatedElement() { deref(); } + void reloadPluginOnAttributeChange(const QualifiedName&); + +#if !ENABLE(OILPAN) + virtual void refFormAssociatedElement() OVERRIDE { ref(); } + virtual void derefFormAssociatedElement() OVERRIDE { deref(); } +#endif virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; } virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return true; } @@ -111,9 +119,13 @@ private: bool m_useFallbackContent : 1; }; -DEFINE_NODE_TYPE_CASTS(HTMLObjectElement, hasTagName(HTMLNames::objectTag)); +// Intentionally left unimplemented, template specialization needs to be provided for specific +// return types. +template<typename T> inline const T& toElement(const FormAssociatedElement&); +template<typename T> inline const T* toElement(const FormAssociatedElement*); -inline const HTMLObjectElement* toHTMLObjectElement(const FormAssociatedElement* element) +// Make toHTMLObjectElement() accept a FormAssociatedElement as input instead of a Node. +template<> inline const HTMLObjectElement* toElement<HTMLObjectElement>(const FormAssociatedElement* element) { ASSERT_WITH_SECURITY_IMPLICATION(!element || !element->isFormControlElement()); const HTMLObjectElement* objectElement = static_cast<const HTMLObjectElement*>(element); @@ -123,7 +135,7 @@ inline const HTMLObjectElement* toHTMLObjectElement(const FormAssociatedElement* return objectElement; } -inline const HTMLObjectElement& toHTMLObjectElement(const FormAssociatedElement& element) +template<> inline const HTMLObjectElement& toElement<HTMLObjectElement>(const FormAssociatedElement& element) { ASSERT_WITH_SECURITY_IMPLICATION(!element.isFormControlElement()); const HTMLObjectElement& objectElement = static_cast<const HTMLObjectElement&>(element); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.idl index 2393f057dd9..b6c7ccee7c2 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLObjectElement.idl @@ -28,7 +28,7 @@ [Reflect, TreatNullAs=NullString] attribute DOMString border; [Reflect, URL] attribute DOMString codeBase; [Reflect] attribute DOMString codeType; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString data; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString data; [Reflect] attribute boolean declare; [Reflect] attribute DOMString height; [Reflect] attribute long hspace; @@ -51,5 +51,7 @@ [Custom, NotEnumerable] getter Node (DOMString name); [Custom] setter Node (DOMString name, Node value); - [CheckSecurity=Node, RaisesException] SVGDocument getSVGDocument(); + [CheckSecurity=Node, RaisesException] Document getSVGDocument(); + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp index c9963b0ece4..01c307a46d6 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "core/html/HTMLOptGroupElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/NodeRenderStyle.h" #include "core/html/HTMLSelectElement.h" @@ -42,10 +42,7 @@ inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(Document& document) -{ - return adoptRef(new HTMLOptGroupElement(document)); -} +DEFINE_NODE_FACTORY(HTMLOptGroupElement) bool HTMLOptGroupElement::isDisabledFormControl() const { @@ -58,12 +55,6 @@ bool HTMLOptGroupElement::rendererIsFocusable() const return renderStyle() && renderStyle()->display() != NONE; } -const AtomicString& HTMLOptGroupElement::formControlType() const -{ - DEFINE_STATIC_LOCAL(const AtomicString, optgroup, ("optgroup", AtomicString::ConstructFromLiteral)); - return optgroup; -} - void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { recalcSelectOptions(); @@ -81,21 +72,17 @@ void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic void HTMLOptGroupElement::recalcSelectOptions() { - ContainerNode* select = parentNode(); - while (select && !select->hasTagName(selectTag)) - select = select->parentNode(); - if (select) - toHTMLSelectElement(select)->setRecalcListItems(); + if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestor(*this)) + select->setRecalcListItems(); } void HTMLOptGroupElement::attach(const AttachContext& context) { + if (context.resolvedStyle) { + ASSERT(!m_style || m_style == context.resolvedStyle); + m_style = context.resolvedStyle; + } HTMLElement::attach(context); - // If after attaching nothing called styleForRenderer() on this node we - // manually cache the value. This happens if our parent doesn't have a - // renderer like <optgroup> or if it doesn't allow children like <select>. - if (!m_style && parentNode()->renderStyle()) - updateNonRenderStyle(); } void HTMLOptGroupElement::detach(const AttachContext& context) @@ -106,7 +93,12 @@ void HTMLOptGroupElement::detach(const AttachContext& context) void HTMLOptGroupElement::updateNonRenderStyle() { + bool oldDisplayNoneStatus = isDisplayNone(); m_style = originalStyleForRenderer(); + if (oldDisplayNoneStatus != isDisplayNone()) { + if (HTMLSelectElement* select = ownerSelectElement()) + select->updateListOnRenderer(); + } } RenderStyle* HTMLOptGroupElement::nonRendererStyle() const @@ -116,8 +108,6 @@ RenderStyle* HTMLOptGroupElement::nonRendererStyle() const PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer() { - // styleForRenderer is called whenever a new style should be associated - // with an Element so now is a good time to update our cached style. updateNonRenderStyle(); return m_style; } @@ -136,14 +126,7 @@ String HTMLOptGroupElement::groupLabelText() const HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const { - ContainerNode* select = parentNode(); - while (select && !select->hasTagName(selectTag)) - select = select->parentNode(); - - if (!select) - return 0; - - return toHTMLSelectElement(select); + return Traversal<HTMLSelectElement>::firstAncestor(*this); } void HTMLOptGroupElement::accessKeyAction(bool) @@ -154,4 +137,10 @@ void HTMLOptGroupElement::accessKeyAction(bool) select->accessKeyAction(false); } +bool HTMLOptGroupElement::isDisplayNone() const +{ + RenderStyle* style = nonRendererStyle(); + return style && style->display() == NONE; +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h index 54ed7b5647d..a6674e0784e 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h @@ -32,26 +32,27 @@ class HTMLSelectElement; class HTMLOptGroupElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLOptGroupElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLOptGroupElement); virtual bool isDisabledFormControl() const OVERRIDE; HTMLSelectElement* ownerSelectElement() const; String groupLabelText() const; + bool isDisplayNone() const; + private: explicit HTMLOptGroupElement(Document&); - virtual const AtomicString& formControlType() const; virtual bool rendererIsFocusable() const OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&) { return false; } + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE { return false; } virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; // <optgroup> never has a renderer so we manually manage a cached style. void updateNonRenderStyle(); @@ -63,23 +64,6 @@ private: RefPtr<RenderStyle> m_style; }; -inline bool isHTMLOptGroupElement(const Node* node) -{ - return node->hasTagName(HTMLNames::optgroupTag); -} - -inline bool isHTMLOptGroupElement(const Element* element) -{ - return element->hasTagName(HTMLNames::optgroupTag); -} - -inline bool isHTMLOptGroupElement(const Element& element) -{ - return element.hasTagName(HTMLNames::optgroupTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLOptGroupElement, hasTagName(HTMLNames::optgroupTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp index 0240fb2871e..79239f43d70 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp @@ -27,15 +27,14 @@ #include "config.h" #include "core/html/HTMLOptionElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/NodeRenderStyle.h" #include "core/dom/NodeTraversal.h" #include "core/dom/ScriptLoader.h" #include "core/dom/Text.h" #include "core/html/HTMLDataListElement.h" -#include "core/html/HTMLOptGroupElement.h" #include "core/html/HTMLSelectElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/rendering/RenderTheme.h" @@ -55,21 +54,18 @@ HTMLOptionElement::HTMLOptionElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::create(Document& document) { - return adoptRef(new HTMLOptionElement(document)); + return adoptRefWillBeNoop(new HTMLOptionElement(document)); } -PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document& document, const String& data, const AtomicString& value, +PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document& document, const String& data, const AtomicString& value, bool defaultSelected, bool selected, ExceptionState& exceptionState) { - RefPtr<HTMLOptionElement> element = adoptRef(new HTMLOptionElement(document)); - - RefPtr<Text> text = Text::create(document, data.isNull() ? "" : data); - - element->appendChild(text.release(), exceptionState); + RefPtrWillBeRawPtr<HTMLOptionElement> element = adoptRefWillBeNoop(new HTMLOptionElement(document)); + element->appendChild(Text::create(document, data.isNull() ? "" : data), exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; if (!value.isNull()) element->setValue(value); @@ -82,12 +78,15 @@ PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document void HTMLOptionElement::attach(const AttachContext& context) { - HTMLElement::attach(context); - // If after attaching nothing called styleForRenderer() on this node we - // manually cache the value. This happens if our parent doesn't have a - // renderer like <optgroup> or if it doesn't allow children like <select>. - if (!m_style && parentNode()->renderStyle()) + AttachContext optionContext(context); + if (context.resolvedStyle) { + ASSERT(!m_style || m_style == context.resolvedStyle); + m_style = context.resolvedStyle; + } else { updateNonRenderStyle(); + optionContext.resolvedStyle = m_style.get(); + } + HTMLElement::attach(optionContext); } void HTMLOptionElement::detach(const AttachContext& context) @@ -122,12 +121,12 @@ String HTMLOptionElement::text() const void HTMLOptionElement::setText(const String &text, ExceptionState& exceptionState) { - RefPtr<Node> protectFromMutationEvents(this); + RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this); // Changing the text causes a recalc of a select's items, which will reset the selected // index to the first item if the select is single selection with a menu list. We attempt to // preserve the selected item. - RefPtr<HTMLSelectElement> select = ownerSelectElement(); + RefPtrWillBeRawPtr<HTMLSelectElement> select = ownerSelectElement(); bool selectIsMenuList = select && select->usesMenuList(); int oldSelectedIndex = selectIsMenuList ? select->selectedIndex() : -1; @@ -146,8 +145,7 @@ void HTMLOptionElement::setText(const String &text, ExceptionState& exceptionSta void HTMLOptionElement::accessKeyAction(bool) { - HTMLSelectElement* select = ownerSelectElement(); - if (select) + if (HTMLSelectElement* select = ownerSelectElement()) select->accessKeySetSelectedIndex(index()); } @@ -161,12 +159,12 @@ int HTMLOptionElement::index() const int optionIndex = 0; - const Vector<HTMLElement*>& items = selectElement->listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = selectElement->listItems(); size_t length = items.size(); for (size_t i = 0; i < length; ++i) { - if (!items[i]->hasTagName(optionTag)) + if (!isHTMLOptionElement(*items[i])) continue; - if (items[i] == this) + if (items[i].get() == this) return optionIndex; ++optionIndex; } @@ -185,7 +183,7 @@ void HTMLOptionElement::parseAttribute(const QualifiedName& name, const AtomicSt if (oldDisabled != m_disabled) { didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); if (renderer() && renderer()->style()->hasAppearance()) - RenderTheme::theme().stateChanged(renderer(), EnabledState); + RenderTheme::theme().stateChanged(renderer(), EnabledControlState); } } else if (name == selectedAttr) { if (bool willBeSelected = !value.isNull()) @@ -207,17 +205,17 @@ void HTMLOptionElement::setValue(const AtomicString& value) setAttribute(valueAttr, value); } -bool HTMLOptionElement::selected() +bool HTMLOptionElement::selected() const { if (HTMLSelectElement* select = ownerSelectElement()) { // If a stylesheet contains option:checked selectors, this function is // called during parsing. updateListItemSelectedStates() is O(N) where N // is the number of option elements, so the <select> parsing would be - // O(N^2) without isParsingInProgress check. Also, + // O(N^2) without the isFinishedParsingChildren check. Also, // updateListItemSelectedStates() determines default selection, and we'd // like to avoid to determine default selection with incomplete option // list. - if (select->isParsingInProgress()) + if (!select->isFinishedParsingChildren()) return m_isSelected; select->updateListItemSelectedStates(); } @@ -258,23 +256,12 @@ void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const { - for (ContainerNode* parent = parentNode(); parent ; parent = parent->parentNode()) { - if (parent->hasTagName(datalistTag)) - return toHTMLDataListElement(parent); - } - return 0; + return Traversal<HTMLDataListElement>::firstAncestor(*this); } HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const { - ContainerNode* select = parentNode(); - while (select && !select->hasTagName(selectTag)) - select = select->parentNode(); - - if (!select) - return 0; - - return toHTMLSelectElement(select); + return Traversal<HTMLSelectElement>::firstAncestor(*this); } String HTMLOptionElement::label() const @@ -292,7 +279,12 @@ void HTMLOptionElement::setLabel(const AtomicString& label) void HTMLOptionElement::updateNonRenderStyle() { + bool oldDisplayNoneStatus = isDisplayNone(); m_style = originalStyleForRenderer(); + if (oldDisplayNoneStatus != isDisplayNone()) { + if (HTMLSelectElement* select = ownerSelectElement()) + select->updateListOnRenderer(); + } } RenderStyle* HTMLOptionElement::nonRendererStyle() const @@ -302,26 +294,26 @@ RenderStyle* HTMLOptionElement::nonRendererStyle() const PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer() { - // styleForRenderer is called whenever a new style should be associated - // with an Element so now is a good time to update our cached style. updateNonRenderStyle(); return m_style; } -void HTMLOptionElement::didRecalcStyle(StyleRecalcChange) +void HTMLOptionElement::didRecalcStyle(StyleRecalcChange change) { - // FIXME: This is nasty, we ask our owner select to repaint even if the new - // style is exactly the same. + if (change == NoChange) + return; + + // FIXME: We ask our owner select to repaint regardless of which property changed. if (HTMLSelectElement* select = ownerSelectElement()) { if (RenderObject* renderer = select->renderer()) - renderer->repaint(); + renderer->paintInvalidationForWholeRenderer(); } } String HTMLOptionElement::textIndentedToRespectGroupLabel() const { ContainerNode* parent = parentNode(); - if (parent && isHTMLOptGroupElement(parent)) + if (parent && isHTMLOptGroupElement(*parent)) return " " + text(); return text(); } @@ -331,7 +323,7 @@ bool HTMLOptionElement::isDisabledFormControl() const if (ownElementDisabled()) return true; if (Element* parent = parentElement()) - return isHTMLOptGroupElement(parent) && parent->isDisabledFormControl(); + return isHTMLOptGroupElement(*parent) && parent->isDisabledFormControl(); return false; } @@ -368,11 +360,22 @@ String HTMLOptionElement::collectOptionInnerText() const HTMLFormElement* HTMLOptionElement::form() const { - HTMLSelectElement* selectElement = ownerSelectElement(); - if (!selectElement) - return 0; + if (HTMLSelectElement* selectElement = ownerSelectElement()) + return selectElement->formOwner(); - return selectElement->formOwner(); + return 0; +} + +bool HTMLOptionElement::isDisplayNone() const +{ + ContainerNode* parent = parentNode(); + // Check for parent optgroup having display NONE + if (parent && isHTMLOptGroupElement(*parent)) { + if (toHTMLOptGroupElement(*parent).isDisplayNone()) + return true; + } + RenderStyle* style = nonRendererStyle(); + return style && style->display() == NONE; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.h index 1f79a1bd81a..65e1a2394b8 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.h @@ -35,11 +35,11 @@ class HTMLSelectElement; class HTMLOptionElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLOptionElement> create(Document&); - static PassRefPtr<HTMLOptionElement> createForJSConstructor(Document&, const String& data, const AtomicString& value, + static PassRefPtrWillBeRawPtr<HTMLOptionElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLOptionElement> createForJSConstructor(Document&, const String& data, const AtomicString& value, bool defaultSelected, bool selected, ExceptionState&); - virtual String text() const; + String text() const; void setText(const String&, ExceptionState&); int index() const; @@ -47,7 +47,7 @@ public: String value() const; void setValue(const AtomicString&); - bool selected(); + bool selected() const; void setSelected(bool); HTMLDataListElement* ownerDataListElement() const; @@ -66,27 +66,28 @@ public: HTMLFormElement* form() const; + bool isDisplayNone() const; + private: explicit HTMLOptionElement(Document&); virtual bool rendererIsFocusable() const OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&) { return false; } + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE { return false; } virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; - virtual void accessKeyAction(bool); + virtual void accessKeyAction(bool) OVERRIDE; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; // <option> never has a renderer so we manually manage a cached style. void updateNonRenderStyle(); virtual RenderStyle* nonRendererStyle() const OVERRIDE; virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE; - - void didRecalcStyle(StyleRecalcChange) OVERRIDE; + virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE; String collectOptionInnerText() const; @@ -95,8 +96,6 @@ private: RefPtr<RenderStyle> m_style; }; -DEFINE_NODE_TYPE_CASTS(HTMLOptionElement, hasTagName(HTMLNames::optionTag)); - } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.idl index 41c6592f239..d57d72a5a97 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptionElement.idl @@ -19,7 +19,11 @@ */ [ - NamedConstructor=Option([Default=NullString] optional DOMString data, [Default=NullString] optional DOMString value, [Default=Undefined] optional boolean defaultSelected, [Default=Undefined] optional boolean selected), + NamedConstructor=Option(optional DOMString data = null, + optional DOMString value = null, + [Default=Undefined] optional boolean defaultSelected, + [Default=Undefined] optional boolean selected), + ConstructorCallWith=Document, RaisesException=Constructor ] interface HTMLOptionElement : HTMLElement { [Reflect] attribute boolean disabled; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp index aae87b078b9..e27e0e1629d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2006, 2011, 2012 Apple Computer, Inc. + * Copyright (C) 2014 Samsung Electronics. 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 @@ -30,24 +31,50 @@ namespace WebCore { -HTMLOptionsCollection::HTMLOptionsCollection(Node* select) +HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select) : HTMLCollection(select, SelectOptions, DoesNotOverrideItemAfter) { - ASSERT(select->hasTagName(HTMLNames::selectTag)); + ASSERT(isHTMLSelectElement(select)); ScriptWrappable::init(this); } -PassRefPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(Node* select, CollectionType) +void HTMLOptionsCollection::supportedPropertyNames(Vector<String>& names) { - return adoptRef(new HTMLOptionsCollection(select)); + // As per http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmloptionscollection: + // The supported property names consist of the non-empty values of all the id and name attributes of all the elements + // represented by the collection, in tree order, ignoring later duplicates, with the id of an element preceding its + // name if it contributes both, they differ from each other, and neither is the duplicate of an earlier entry. + HashSet<AtomicString> existingNames; + unsigned length = this->length(); + for (unsigned i = 0; i < length; ++i) { + Element* element = item(i); + ASSERT(element); + const AtomicString& idAttribute = element->getIdAttribute(); + if (!idAttribute.isEmpty()) { + HashSet<AtomicString>::AddResult addResult = existingNames.add(idAttribute); + if (addResult.isNewEntry) + names.append(idAttribute); + } + const AtomicString& nameAttribute = element->getNameAttribute(); + if (!nameAttribute.isEmpty()) { + HashSet<AtomicString>::AddResult addResult = existingNames.add(nameAttribute); + if (addResult.isNewEntry) + names.append(nameAttribute); + } + } +} + +PassRefPtrWillBeRawPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(ContainerNode& select, CollectionType) +{ + return adoptRefWillBeNoop(new HTMLOptionsCollection(select)); } -void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, ExceptionState& exceptionState) +void HTMLOptionsCollection::add(PassRefPtrWillBeRawPtr<HTMLOptionElement> element, ExceptionState& exceptionState) { add(element, length(), exceptionState); } -void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, int index, ExceptionState& exceptionState) +void HTMLOptionsCollection::add(PassRefPtrWillBeRawPtr<HTMLOptionElement> element, int index, ExceptionState& exceptionState) { HTMLOptionElement* newOption = element.get(); @@ -61,19 +88,19 @@ void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, int index return; } - HTMLSelectElement* select = toHTMLSelectElement(ownerNode()); + HTMLSelectElement& select = toHTMLSelectElement(ownerNode()); if (index == -1 || unsigned(index) >= length()) - select->add(newOption, 0, exceptionState); + select.add(newOption, 0, exceptionState); else - select->add(newOption, toHTMLOptionElement(item(index)), exceptionState); + select.addBeforeOptionAtIndex(newOption, index, exceptionState); ASSERT(!exceptionState.hadException()); } void HTMLOptionsCollection::remove(int index) { - toHTMLSelectElement(ownerNode())->remove(index); + toHTMLSelectElement(ownerNode()).remove(index); } void HTMLOptionsCollection::remove(HTMLOptionElement* option) @@ -83,22 +110,22 @@ void HTMLOptionsCollection::remove(HTMLOptionElement* option) int HTMLOptionsCollection::selectedIndex() const { - return toHTMLSelectElement(ownerNode())->selectedIndex(); + return toHTMLSelectElement(ownerNode()).selectedIndex(); } void HTMLOptionsCollection::setSelectedIndex(int index) { - toHTMLSelectElement(ownerNode())->setSelectedIndex(index); + toHTMLSelectElement(ownerNode()).setSelectedIndex(index); } void HTMLOptionsCollection::setLength(unsigned length, ExceptionState& exceptionState) { - toHTMLSelectElement(ownerNode())->setLength(length, exceptionState); + toHTMLSelectElement(ownerNode()).setLength(length, exceptionState); } -void HTMLOptionsCollection::anonymousNamedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtr<Node>& returnValue1) +void HTMLOptionsCollection::namedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtrWillBeRawPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtrWillBeRawPtr<Element>& returnValue1) { - Vector<RefPtr<Node> > namedItems; + WillBeHeapVector<RefPtrWillBeMember<Element> > namedItems; this->namedItems(name, namedItems); if (!namedItems.size()) @@ -110,25 +137,19 @@ void HTMLOptionsCollection::anonymousNamedGetter(const AtomicString& name, bool& return; } + // FIXME: The spec and Firefox do not return a NodeList. They always return the first matching Element. returnValue0Enabled = true; returnValue0 = NamedNodesCollection::create(namedItems); } -bool HTMLOptionsCollection::anonymousIndexedSetterRemove(unsigned index, ExceptionState& exceptionState) -{ - HTMLSelectElement* base = toHTMLSelectElement(ownerNode()); - base->remove(index); - return true; -} - -bool HTMLOptionsCollection::anonymousIndexedSetter(unsigned index, PassRefPtr<HTMLOptionElement> value, ExceptionState& exceptionState) +bool HTMLOptionsCollection::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeRawPtr<HTMLOptionElement> value, ExceptionState& exceptionState) { - HTMLSelectElement* base = toHTMLSelectElement(ownerNode()); - if (!value) { - exceptionState.throwTypeError(ExceptionMessages::failedToSet(String::number(index), "HTMLOptionsCollection", "The element provided was not an HTMLOptionElement.")); + HTMLSelectElement& base = toHTMLSelectElement(ownerNode()); + if (!value) { // undefined or null + base.remove(index); return true; } - base->setOption(index, value.get(), exceptionState); + base.setOption(index, value.get(), exceptionState); return true; } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h b/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h index fe5ad5d746e..bb888abf002 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.h @@ -34,10 +34,10 @@ class HTMLSelectElement; class HTMLOptionsCollection FINAL : public HTMLCollection { public: - static PassRefPtr<HTMLOptionsCollection> create(Node*, CollectionType); + static PassRefPtrWillBeRawPtr<HTMLOptionsCollection> create(ContainerNode&, CollectionType); - void add(PassRefPtr<HTMLOptionElement>, ExceptionState&); - void add(PassRefPtr<HTMLOptionElement>, int index, ExceptionState&); + void add(PassRefPtrWillBeRawPtr<HTMLOptionElement>, ExceptionState&); + void add(PassRefPtrWillBeRawPtr<HTMLOptionElement>, int index, ExceptionState&); void remove(int index); void remove(HTMLOptionElement*); @@ -45,14 +45,17 @@ public: void setSelectedIndex(int); void setLength(unsigned, ExceptionState&); - void anonymousNamedGetter(const AtomicString& name, bool&, RefPtr<NodeList>&, bool&, RefPtr<Node>&); - bool anonymousIndexedSetter(unsigned, PassRefPtr<HTMLOptionElement>, ExceptionState&); - bool anonymousIndexedSetterRemove(unsigned, ExceptionState&); + void namedGetter(const AtomicString& name, bool&, RefPtrWillBeRawPtr<NodeList>&, bool&, RefPtrWillBeRawPtr<Element>&); + bool anonymousIndexedSetter(unsigned, PassRefPtrWillBeRawPtr<HTMLOptionElement>, ExceptionState&); private: - explicit HTMLOptionsCollection(Node*); + explicit HTMLOptionsCollection(ContainerNode&); + + virtual void supportedPropertyNames(Vector<String>& names) OVERRIDE; }; +DEFINE_TYPE_CASTS(HTMLOptionsCollection, LiveNodeListBase, collection, collection->type() == SelectOptions, collection.type() == SelectOptions); + } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl b/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl index 32c414795d1..a802b20e388 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl @@ -1,7 +1,7 @@ /* * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> - * Copyright (C) 2013 Samsung Electronics. All rights reserved. + * Copyright (C) 2013, 2014 Samsung Electronics. 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 @@ -21,19 +21,17 @@ [ DependentLifetime, - GenerateVisitDOMWrapper=ownerNode, + SetWrapperReferenceFrom=ownerNode, ] interface HTMLOptionsCollection : HTMLCollection { attribute long selectedIndex; [Custom=Setter, RaisesException=Setter] attribute unsigned long length; - [ImplementedAs=item] getter Node(unsigned long index); - [ImplementedAs=anonymousIndexedSetter, RaisesException] setter HTMLOptionElement (unsigned long index, [TreatNullAs=anonymousIndexedSetterRemove, TreatUndefinedAs=anonymousIndexedSetterRemove] HTMLOptionElement value); - [ImplementedAs=anonymousNamedGetter, NotEnumerable] getter (NodeList or Node)(DOMString name); + [ImplementedAs=item] getter Node (unsigned long index); + [RaisesException, TypeChecking=Interface|Nullable] setter HTMLOptionElement (unsigned long index, HTMLOptionElement? value); - [Custom] Node namedItem([Default=Undefined] optional DOMString name); + // FIXME: The spec and firefox return an Element (the first matching Element). + [ImplementedAs=namedGetter] getter (NodeList or Element) namedItem(DOMString name); - [Custom, RaisesException] void add([Default=Undefined] optional HTMLOptionElement option, - optional unsigned long index); + [Custom, RaisesException] void add([Default=Undefined] optional HTMLOptionElement option, optional unsigned long index); void remove(unsigned long index); - void remove(HTMLOptionElement option); // Non standard. + [MeasureAs=HTMLOptionsCollectionRemoveElement] void remove(HTMLOptionElement option); // non-standard }; - diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.cpp index 00d04356f9c..733b6ff38d0 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.cpp @@ -31,24 +31,23 @@ #include "config.h" #include "core/html/HTMLOutputElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" namespace WebCore { inline HTMLOutputElement::HTMLOutputElement(Document& document, HTMLFormElement* form) : HTMLFormControlElement(HTMLNames::outputTag, document, form) , m_isDefaultValueMode(true) - , m_isSetTextContentInProgress(false) , m_defaultValue("") , m_tokens(DOMSettableTokenList::create()) { ScriptWrappable::init(this); } -PassRefPtr<HTMLOutputElement> HTMLOutputElement::create(Document& document, HTMLFormElement* form) +PassRefPtrWillBeRawPtr<HTMLOutputElement> HTMLOutputElement::create(Document& document, HTMLFormElement* form) { - return adoptRef(new HTMLOutputElement(document, form)); + return adoptRefWillBeNoop(new HTMLOutputElement(document, form)); } const AtomicString& HTMLOutputElement::formControlType() const @@ -75,7 +74,7 @@ DOMSettableTokenList* HTMLOutputElement::htmlFor() const return m_tokens.get(); } -void HTMLOutputElement::setFor(const String& value) +void HTMLOutputElement::setFor(const AtomicString& value) { m_tokens->setValue(value); } @@ -84,11 +83,6 @@ void HTMLOutputElement::childrenChanged(bool createdByParser, Node* beforeChange { HTMLFormControlElement::childrenChanged(createdByParser, beforeChange, afterChange, childCountDelta); - if (createdByParser || m_isSetTextContentInProgress) { - m_isSetTextContentInProgress = false; - return; - } - if (m_isDefaultValueMode) m_defaultValue = textContent(); } @@ -98,10 +92,10 @@ void HTMLOutputElement::resetImpl() // The reset algorithm for output elements is to set the element's // value mode flag to "default" and then to set the element's textContent // attribute to the default value. - m_isDefaultValueMode = true; if (m_defaultValue == value()) return; - setTextContentInternal(m_defaultValue); + setTextContent(m_defaultValue); + m_isDefaultValueMode = true; } String HTMLOutputElement::value() const @@ -115,7 +109,7 @@ void HTMLOutputElement::setValue(const String& value) m_isDefaultValueMode = false; if (value == this->value()) return; - setTextContentInternal(value); + setTextContent(value); } String HTMLOutputElement::defaultValue() const @@ -131,14 +125,14 @@ void HTMLOutputElement::setDefaultValue(const String& value) // The spec requires the value attribute set to the default value // when the element's value mode flag to "default". if (m_isDefaultValueMode) - setTextContentInternal(value); + setTextContent(value); } -void HTMLOutputElement::setTextContentInternal(const String& value) + +void HTMLOutputElement::trace(Visitor* visitor) { - ASSERT(!m_isSetTextContentInProgress); - m_isSetTextContentInProgress = true; - setTextContent(value); + visitor->trace(m_tokens); + HTMLFormControlElement::trace(visitor); } } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.h index bf1e469e715..d554341032a 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLOutputElement.h @@ -38,36 +38,35 @@ namespace WebCore { class HTMLOutputElement FINAL : public HTMLFormControlElement { public: - static PassRefPtr<HTMLOutputElement> create(Document&, HTMLFormElement*); + static PassRefPtrWillBeRawPtr<HTMLOutputElement> create(Document&, HTMLFormElement*); - virtual bool willValidate() const { return false; } + virtual bool willValidate() const OVERRIDE { return false; } String value() const; void setValue(const String&); String defaultValue() const; void setDefaultValue(const String&); - void setFor(const String&); + void setFor(const AtomicString&); DOMSettableTokenList* htmlFor() const; - virtual bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE { return false; } + + virtual void trace(Visitor*) OVERRIDE; private: HTMLOutputElement(Document&, HTMLFormElement*); virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - virtual const AtomicString& formControlType() const; - virtual bool isEnumeratable() const { return true; } + virtual const AtomicString& formControlType() const OVERRIDE; + virtual bool isEnumeratable() const OVERRIDE { return true; } virtual bool supportLabels() const OVERRIDE { return true; } - virtual bool supportsFocus() const; - virtual void childrenChanged(bool createdByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual bool supportsFocus() const OVERRIDE; + virtual void childrenChanged(bool createdByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; virtual void resetImpl() OVERRIDE; - void setTextContentInternal(const String&); - bool m_isDefaultValueMode; - bool m_isSetTextContentInProgress; String m_defaultValue; - RefPtr<DOMSettableTokenList> m_tokens; + RefPtrWillBeMember<DOMSettableTokenList> m_tokens; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.cpp index 459800856f9..7cfea938976 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.cpp @@ -23,9 +23,9 @@ #include "config.h" #include "core/html/HTMLParagraphElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -37,17 +37,7 @@ inline HTMLParagraphElement::HTMLParagraphElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLParagraphElement> HTMLParagraphElement::create(Document& document) -{ - return adoptRef(new HTMLParagraphElement(document)); -} - -bool HTMLParagraphElement::isPresentationAttribute(const QualifiedName& name) const -{ - if (name == alignAttr) - return true; - return HTMLElement::isPresentationAttribute(name); -} +DEFINE_NODE_FACTORY(HTMLParagraphElement) void HTMLParagraphElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.h index 4bfbbf64425..43b8d0ead20 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLParagraphElement.h @@ -29,12 +29,11 @@ namespace WebCore { class HTMLParagraphElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLParagraphElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLParagraphElement); private: explicit HTMLParagraphElement(Document&); - virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.cpp index 982d53d993f..63c65aed352 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "core/html/HTMLParamElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" @@ -37,10 +37,7 @@ inline HTMLParamElement::HTMLParamElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLParamElement> HTMLParamElement::create(Document& document) -{ - return adoptRef(new HTMLParamElement(document)); -} +DEFINE_NODE_FACTORY(HTMLParamElement) const AtomicString& HTMLParamElement::name() const { @@ -66,14 +63,4 @@ bool HTMLParamElement::isURLAttribute(const Attribute& attribute) const return HTMLElement::isURLAttribute(attribute); } -void HTMLParamElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLElement::addSubresourceAttributeURLs(urls); - - if (!isURLParameter(name())) - return; - - addSubresourceURL(urls, document().completeURL(value())); -} - } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.h index 991e9595db9..1d04d46b0d8 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLParamElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLParamElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLParamElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLParamElement); const AtomicString& name() const; const AtomicString& value() const; @@ -40,12 +40,8 @@ private: explicit HTMLParamElement(Document&); virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; }; -DEFINE_NODE_TYPE_CASTS(HTMLParamElement, hasTagName(HTMLNames::paramTag)); - } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp new file mode 100644 index 00000000000..d5361777b0b --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/HTMLPictureElement.h" + +#include "core/HTMLNames.h" +#include "core/dom/ElementTraversal.h" +#include "core/html/HTMLImageElement.h" + +namespace WebCore { + +using namespace HTMLNames; + +inline HTMLPictureElement::HTMLPictureElement(Document& document) + : HTMLElement(pictureTag, document) +{ + ScriptWrappable::init(this); +} + +DEFINE_NODE_FACTORY(HTMLPictureElement) + +void HTMLPictureElement::sourceOrMediaChanged() +{ + for (HTMLImageElement* imageElement = Traversal<HTMLImageElement>::firstChild(*this); imageElement; imageElement = Traversal<HTMLImageElement>::nextSibling(*imageElement)) { + imageElement->selectSourceURL(HTMLImageElement::UpdateNormal); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.h new file mode 100644 index 00000000000..c5cb0f501fd --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.h @@ -0,0 +1,24 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HTMLPictureElement_h +#define HTMLPictureElement_h + +#include "core/html/HTMLElement.h" + +namespace WebCore { + +class HTMLPictureElement FINAL : public HTMLElement { +public: + DECLARE_NODE_FACTORY(HTMLPictureElement); + + void sourceOrMediaChanged(); + +protected: + explicit HTMLPictureElement(Document&); +}; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.idl new file mode 100644 index 00000000000..649316cb8a1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPictureElement.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://picture.responsiveimages.org +[ + RuntimeEnabled=Picture +] interface HTMLPictureElement : HTMLElement { +}; + diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp index c4ba8d0a939..7cbceed497d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp @@ -23,19 +23,20 @@ #include "config.h" #include "core/html/HTMLPlugInElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/npruntime_impl.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" -#include "core/dom/PostAttachCallbacks.h" +#include "core/dom/Node.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/events/Event.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/html/HTMLContentElement.h" #include "core/html/HTMLImageLoader.h" #include "core/html/PluginDocument.h" -#include "core/html/shadow/HTMLContentElement.h" #include "core/loader/FrameLoaderClient.h" #include "core/page/EventHandler.h" #include "core/page/Page.h" @@ -59,7 +60,6 @@ HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document& doc , m_isDelayingLoadEvent(false) , m_NPObject(0) , m_isCapturingMouseEvents(false) - , m_inBeforeLoadEventHandler(false) // m_needsWidgetUpdate(!createdByParser) allows HTMLObjectElement to delay // widget updates until after all children are parsed. For HTMLEmbedElement // this delay is unnecessary, but it is simpler to make both classes share @@ -82,6 +82,12 @@ HTMLPlugInElement::~HTMLPlugInElement() } } +void HTMLPlugInElement::trace(Visitor* visitor) +{ + visitor->trace(m_imageLoader); + HTMLFrameOwnerElement::trace(visitor); +} + bool HTMLPlugInElement::canProcessDrag() const { return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->canProcessDrag(); @@ -117,9 +123,10 @@ void HTMLPlugInElement::attach(const AttachContext& context) if (!renderer() || useFallbackContent()) return; + if (isImageType()) { if (!m_imageLoader) - m_imageLoader = adoptPtr(new HTMLImageLoader(this)); + m_imageLoader = HTMLImageLoader::create(this); m_imageLoader->updateFromElement(); } else if (needsWidgetUpdate() && renderEmbeddedObject() @@ -128,12 +135,13 @@ void HTMLPlugInElement::attach(const AttachContext& context) && !m_isDelayingLoadEvent) { m_isDelayingLoadEvent = true; document().incrementLoadEventDelayCount(); + document().loadPluginsSoon(); } } void HTMLPlugInElement::updateWidget() { - RefPtr<HTMLPlugInElement> protector(this); + RefPtrWillBeRawPtr<HTMLPlugInElement> protector(this); updateWidgetInternal(); if (m_isDelayingLoadEvent) { m_isDelayingLoadEvent = false; @@ -141,6 +149,43 @@ void HTMLPlugInElement::updateWidget() } } +void HTMLPlugInElement::requestPluginCreationWithoutRendererIfPossible() +{ + if (m_serviceType.isEmpty()) + return; + + if (!document().frame() + || !document().frame()->loader().client()->canCreatePluginWithoutRenderer(m_serviceType)) + return; + + if (renderer() && renderer()->isWidget()) + return; + + createPluginWithoutRenderer(); +} + +void HTMLPlugInElement::createPluginWithoutRenderer() +{ + ASSERT(document().frame()->loader().client()->canCreatePluginWithoutRenderer(m_serviceType)); + + KURL url; + Vector<String> paramNames; + Vector<String> paramValues; + + paramNames.append("type"); + paramValues.append(m_serviceType); + + bool useFallback = false; + loadPlugin(url, m_serviceType, paramNames, paramValues, useFallback, false); +} + +bool HTMLPlugInElement::shouldAccelerate() const +{ + if (Widget* widget = ownedWidget()) + return widget->isPluginView() && toPluginView(widget)->platformLayer(); + return false; +} + void HTMLPlugInElement::detach(const AttachContext& context) { // Update the widget the next time we attach (detaching destroys the plugin). @@ -152,11 +197,17 @@ void HTMLPlugInElement::detach(const AttachContext& context) document().decrementLoadEventDelayCount(); } + // Only try to persist a plugin widget we actually own. + Widget* plugin = ownedWidget(); + if (plugin && plugin->pluginShouldPersist()) + m_persistedPluginWidget = plugin; resetInstance(); + // FIXME - is this next line necessary? + setWidget(nullptr); if (m_isCapturingMouseEvents) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) + frame->eventHandler().setCapturingMouseEventsNode(nullptr); m_isCapturingMouseEvents = false; } @@ -200,7 +251,7 @@ void HTMLPlugInElement::finishParsingChildren() setNeedsWidgetUpdate(true); if (inDocument()) - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } void HTMLPlugInElement::resetInstance() @@ -210,7 +261,7 @@ void HTMLPlugInElement::resetInstance() SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() { - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) return 0; @@ -218,34 +269,21 @@ SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() // return the cached allocated Bindings::Instance. Not supporting this // edge-case is OK. if (!m_pluginWrapper) { - if (Widget* widget = pluginWidget()) - m_pluginWrapper = frame->script().createPluginWrapper(widget); + Widget* plugin; + + if (m_persistedPluginWidget) + plugin = m_persistedPluginWidget.get(); + else + plugin = pluginWidget(); + + if (plugin) + m_pluginWrapper = frame->script().createPluginWrapper(plugin); } return m_pluginWrapper.get(); } -bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL) -{ - // FIXME: Our current plug-in loading design can't guarantee the following - // assertion is true, since plug-in loading can be initiated during layout, - // and synchronous layout can be initiated in a beforeload event handler! - // See <http://webkit.org/b/71264>. - // ASSERT(!m_inBeforeLoadEventHandler); - m_inBeforeLoadEventHandler = true; - bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent(sourceURL); - m_inBeforeLoadEventHandler = false; - return beforeLoadAllowedLoad; -} - Widget* HTMLPlugInElement::pluginWidget() const { - if (m_inBeforeLoadEventHandler) { - // The plug-in hasn't loaded yet, and it makes no sense to try to load - // if beforeload handler happened to touch the plug-in element. That - // would recursively call beforeload for the same element. - return 0; - } - if (RenderWidget* renderWidget = renderWidgetForJSBindings()) return renderWidget->widget(); return 0; @@ -356,7 +394,7 @@ bool HTMLPlugInElement::isImageType() if (m_serviceType.isEmpty() && protocolIs(m_url, "data")) m_serviceType = mimeTypeFromDataURL(m_url); - if (Frame* frame = document().frame()) { + if (LocalFrame* frame = document().frame()) { KURL completedURL = document().completeURL(m_url); return frame->loader().client()->objectContentType(completedURL, m_serviceType, shouldPreferPlugInsForImages()) == ObjectContentImage; } @@ -364,14 +402,6 @@ bool HTMLPlugInElement::isImageType() return Image::supportsType(m_serviceType); } -const String HTMLPlugInElement::loadedMimeType() const -{ - String mimeType = m_serviceType; - if (mimeType.isEmpty()) - mimeType = mimeTypeFromURL(m_loadedUrl); - return mimeType; -} - RenderEmbeddedObject* HTMLPlugInElement::renderEmbeddedObject() const { // HTMLObjectElement and HTMLEmbedElement may return arbitrary renderers @@ -415,10 +445,13 @@ bool HTMLPlugInElement::requestObject(const String& url, const String& mimeType, return false; KURL completedURL = document().completeURL(url); + if (!pluginIsLoadable(completedURL, mimeType)) + return false; bool useFallback; - if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) - return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFallback); + bool requireRenderer = true; + if (shouldUsePlugin(completedURL, mimeType, hasFallbackContent(), useFallback)) + return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFallback, requireRenderer); // If the plug-in element already contains a subframe, // loadOrRedirectSubframe will re-use it. Otherwise, it will create a new @@ -427,38 +460,43 @@ bool HTMLPlugInElement::requestObject(const String& url, const String& mimeType, return loadOrRedirectSubframe(completedURL, getNameAttribute(), true); } -bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) +bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback, bool requireRenderer) { - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame->loader().allowPlugins(AboutToInstantiatePlugin)) return false; - if (!pluginIsLoadable(url, mimeType)) - return false; - RenderEmbeddedObject* renderer = renderEmbeddedObject(); // FIXME: This code should not depend on renderer! - if (!renderer || useFallback) + if ((!renderer && requireRenderer) || useFallback) return false; WTF_LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data()); WTF_LOG(Plugins, " Loaded URL: %s", url.string().utf8().data()); m_loadedUrl = url; - IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight())); - bool loadManually = document().isPluginDocument() && !document().containsPlugins() && toPluginDocument(document()).shouldLoadPluginManually(); - RefPtr<Widget> widget = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually); + RefPtr<Widget> widget = m_persistedPluginWidget; + if (!widget) { + bool loadManually = document().isPluginDocument() && !document().containsPlugins() && toPluginDocument(document()).shouldLoadPluginManually(); + FrameLoaderClient::DetachedPluginPolicy policy = requireRenderer ? FrameLoaderClient::FailOnDetachedPlugin : FrameLoaderClient::AllowDetachedPlugin; + widget = frame->loader().client()->createPlugin(this, url, paramNames, paramValues, mimeType, loadManually, policy); + } if (!widget) { - if (!renderer->showsUnavailablePluginIndicator()) + if (renderer && !renderer->showsUnavailablePluginIndicator()) renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing); return false; } - renderer->setWidget(widget); + if (renderer) { + setWidget(widget); + m_persistedPluginWidget = nullptr; + } else if (widget != m_persistedPluginWidget) { + m_persistedPluginWidget = widget; + } document().setContainsPlugins(); - setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); + scheduleSVGFilterLayerUpdateHack(); return true; } @@ -482,9 +520,17 @@ bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, } +void HTMLPlugInElement::dispatchErrorEvent() +{ + if (document().isPluginDocument() && document().ownerElement()) + document().ownerElement()->dispatchEvent(Event::create(EventTypeNames::error)); + else + dispatchEvent(Event::create(EventTypeNames::error)); +} + bool HTMLPlugInElement::pluginIsLoadable(const KURL& url, const String& mimeType) { - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); Settings* settings = frame->settings(); if (!settings) return false; @@ -517,10 +563,14 @@ void HTMLPlugInElement::didAddUserAgentShadowRoot(ShadowRoot&) userAgentShadowRoot()->appendChild(HTMLContentElement::create(document())); } -void HTMLPlugInElement::didAddShadowRoot(ShadowRoot& root) +void HTMLPlugInElement::willAddFirstAuthorShadowRoot() +{ + lazyReattachIfAttached(); +} + +bool HTMLPlugInElement::hasFallbackContent() const { - if (root.isOldestAuthorShadowRoot()) - lazyReattachIfAttached(); + return false; } bool HTMLPlugInElement::useFallbackContent() const diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.h index 37d631466b5..9de4531c647 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPlugInElement.h @@ -25,6 +25,7 @@ #include "bindings/v8/SharedPersistent.h" #include "core/html/HTMLFrameOwnerElement.h" +#include <v8.h> struct NPObject; @@ -43,6 +44,7 @@ enum PreferPlugInsForImagesOption { class HTMLPlugInElement : public HTMLFrameOwnerElement { public: virtual ~HTMLPlugInElement(); + virtual void trace(Visitor*) OVERRIDE; void resetInstance(); SharedPersistent<v8::Object>* pluginWrapper(); @@ -56,17 +58,22 @@ public: void setNeedsWidgetUpdate(bool needsWidgetUpdate) { m_needsWidgetUpdate = needsWidgetUpdate; } void updateWidget(); + bool shouldAccelerate() const; + + void requestPluginCreationWithoutRendererIfPossible(); + void createPluginWithoutRenderer(); + protected: HTMLPlugInElement(const QualifiedName& tagName, Document&, bool createdByParser, PreferPlugInsForImagesOption); // Node functions: virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; - virtual bool dispatchBeforeLoadEvent(const String& sourceURL) OVERRIDE; // Element functions: virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; + virtual bool hasFallbackContent() const; virtual bool useFallbackContent() const; // Create or update the RenderWidget and return it, triggering layout if // necessary. @@ -79,10 +86,12 @@ protected: bool requestObject(const String& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues); bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); + void dispatchErrorEvent(); + String m_serviceType; String m_url; KURL m_loadedUrl; - OwnPtr<HTMLImageLoader> m_imageLoader; + OwnPtrWillBeMember<HTMLImageLoader> m_imageLoader; bool m_isDelayingLoadEvent; private: @@ -91,24 +100,24 @@ private: // Node functions: virtual bool canContainRangeEndPoint() const OVERRIDE { return false; } - virtual bool willRespondToMouseClickEvents() OVERRIDE; - virtual void defaultEventHandler(Event*) OVERRIDE; - virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; - virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - virtual void finishParsingChildren() OVERRIDE; - virtual bool isPluginElement() const OVERRIDE; + virtual bool willRespondToMouseClickEvents() OVERRIDE FINAL; + virtual void defaultEventHandler(Event*) OVERRIDE FINAL; + virtual void attach(const AttachContext& = AttachContext()) OVERRIDE FINAL; + virtual void detach(const AttachContext& = AttachContext()) OVERRIDE FINAL; + virtual void finishParsingChildren() OVERRIDE FINAL; // Element functions: virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual void willRecalcStyle(StyleRecalcChange) OVERRIDE FINAL; - virtual bool supportsFocus() const OVERRIDE { return true; }; - virtual bool rendererIsFocusable() const OVERRIDE; - virtual bool isKeyboardFocusable() const OVERRIDE; - virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE; - virtual void didAddShadowRoot(ShadowRoot&) OVERRIDE; + virtual bool supportsFocus() const OVERRIDE FINAL { return true; } + virtual bool rendererIsFocusable() const OVERRIDE FINAL; + virtual bool isKeyboardFocusable() const OVERRIDE FINAL; + virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE FINAL; + virtual void willAddFirstAuthorShadowRoot() OVERRIDE FINAL; // HTMLElement function: virtual bool hasCustomFocusLogic() const OVERRIDE; + virtual bool isPluginElement() const OVERRIDE FINAL; // Return any existing RenderWidget without triggering relayout, or 0 if it // doesn't yet exist. @@ -122,21 +131,36 @@ private: }; DisplayState displayState() const { return m_displayState; } void setDisplayState(DisplayState state) { m_displayState = state; } - const String loadedMimeType() const; - bool loadPlugin(const KURL&, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); + bool loadPlugin(const KURL&, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback, bool requireRenderer); bool pluginIsLoadable(const KURL&, const String& mimeType); bool wouldLoadAsNetscapePlugin(const String& url, const String& serviceType); mutable RefPtr<SharedPersistent<v8::Object> > m_pluginWrapper; NPObject* m_NPObject; bool m_isCapturingMouseEvents; - bool m_inBeforeLoadEventHandler; bool m_needsWidgetUpdate; bool m_shouldPreferPlugInsForImages; DisplayState m_displayState; + + // Normally the Widget is stored in HTMLFrameOwnerElement::m_widget. + // However, plugins can persist even when not rendered. In order to + // prevent confusing code which may assume that widget() != null + // means the frame is active, we save off m_widget here while + // the plugin is persisting but not being displayed. + RefPtr<Widget> m_persistedPluginWidget; }; -DEFINE_NODE_TYPE_CASTS(HTMLPlugInElement, isPluginElement()); +inline bool isHTMLPlugInElement(const Element& element) +{ + return element.isHTMLElement() && toHTMLElement(element).isPluginElement(); +} + +inline bool isHTMLPlugInElement(const HTMLElement& element) +{ + return element.isPluginElement(); +} + +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLPlugInElement); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.cpp index 830f015f841..f8693761312 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.cpp @@ -23,10 +23,11 @@ #include "config.h" #include "core/html/HTMLPreElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/StylePropertySet.h" +#include "core/frame/UseCounter.h" namespace WebCore { @@ -38,10 +39,7 @@ inline HTMLPreElement::HTMLPreElement(const QualifiedName& tagName, Document& do ScriptWrappable::init(this); } -PassRefPtr<HTMLPreElement> HTMLPreElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLPreElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLPreElement) bool HTMLPreElement::isPresentationAttribute(const QualifiedName& name) const { @@ -52,10 +50,12 @@ bool HTMLPreElement::isPresentationAttribute(const QualifiedName& name) const void HTMLPreElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) { - if (name == wrapAttr) + if (name == wrapAttr) { + UseCounter::count(document(), UseCounter::HTMLPreElementWrap); style->setProperty(CSSPropertyWhiteSpace, CSSValuePreWrap); - else + } else { HTMLElement::collectStyleForPresentationAttribute(name, value, style); + } } } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.h index 408475f457d..0ae5a6affb5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLPreElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLPreElement> create(const QualifiedName&, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLPreElement); private: HTMLPreElement(const QualifiedName&, Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.idl index 3d035940d33..6224bc901f2 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLPreElement.idl @@ -19,11 +19,8 @@ */ interface HTMLPreElement : HTMLElement { - // FIXME: DOM spec says that width should be of type DOMString - // see http://bugs.webkit.org/show_bug.cgi?id=8992 [Reflect] attribute long width; // Extensions - [Reflect] attribute boolean wrap; + [Reflect, MeasureAs=HTMLPreElementWrap] attribute boolean wrap; }; - diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp index 3baeb6506a6..e8597d0d273 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp @@ -22,10 +22,10 @@ #include "core/html/HTMLProgressElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/dom/ExceptionCode.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/parser/HTMLParserIdioms.h" @@ -41,7 +41,7 @@ const double HTMLProgressElement::InvalidPosition = -2; HTMLProgressElement::HTMLProgressElement(Document& document) : LabelableElement(progressTag, document) - , m_value(0) + , m_value(nullptr) { ScriptWrappable::init(this); } @@ -50,9 +50,9 @@ HTMLProgressElement::~HTMLProgressElement() { } -PassRefPtr<HTMLProgressElement> HTMLProgressElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLProgressElement> HTMLProgressElement::create(Document& document) { - RefPtr<HTMLProgressElement> progress = adoptRef(new HTMLProgressElement(document)); + RefPtrWillBeRawPtr<HTMLProgressElement> progress = adoptRefWillBeNoop(new HTMLProgressElement(document)); progress->ensureUserAgentShadowRoot(); return progress.release(); } @@ -95,30 +95,30 @@ void HTMLProgressElement::attach(const AttachContext& context) double HTMLProgressElement::value() const { double value = getFloatingPointAttribute(valueAttr); + // Otherwise, if the parsed value was greater than or equal to the maximum + // value, then the current value of the progress bar is the maximum value + // of the progress bar. Otherwise, if parsing the value attribute's value + // resulted in an error, or a number less than or equal to zero, then the + // current value of the progress bar is zero. return !std::isfinite(value) || value < 0 ? 0 : std::min(value, max()); } -void HTMLProgressElement::setValue(double value, ExceptionState& exceptionState) +void HTMLProgressElement::setValue(double value) { - if (!std::isfinite(value)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(value)); - return; - } setFloatingPointAttribute(valueAttr, std::max(value, 0.)); } double HTMLProgressElement::max() const { double max = getFloatingPointAttribute(maxAttr); + // Otherwise, if the element has no max attribute, or if it has one but + // parsing it resulted in an error, or if the parsed value was less than or + // equal to zero, then the maximum value of the progress bar is 1.0. return !std::isfinite(max) || max <= 0 ? 1 : max; } -void HTMLProgressElement::setMax(double max, ExceptionState& exceptionState) +void HTMLProgressElement::setMax(double max) { - if (!std::isfinite(max)) { - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(max)); - return; - } // FIXME: The specification says we should ignore the input value if it is inferior or equal to 0. setFloatingPointAttribute(maxAttr, max > 0 ? max : 1); } @@ -150,15 +150,15 @@ void HTMLProgressElement::didAddUserAgentShadowRoot(ShadowRoot& root) { ASSERT(!m_value); - RefPtr<ProgressInnerElement> inner = ProgressInnerElement::create(document()); - inner->setPseudo(AtomicString("-webkit-progress-inner-element", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<ProgressInnerElement> inner = ProgressInnerElement::create(document()); + inner->setShadowPseudoId(AtomicString("-webkit-progress-inner-element", AtomicString::ConstructFromLiteral)); root.appendChild(inner); - RefPtr<ProgressBarElement> bar = ProgressBarElement::create(document()); - bar->setPseudo(AtomicString("-webkit-progress-bar", AtomicString::ConstructFromLiteral)); - RefPtr<ProgressValueElement> value = ProgressValueElement::create(document()); + RefPtrWillBeRawPtr<ProgressBarElement> bar = ProgressBarElement::create(document()); + bar->setShadowPseudoId(AtomicString("-webkit-progress-bar", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<ProgressValueElement> value = ProgressValueElement::create(document()); m_value = value.get(); - m_value->setPseudo(AtomicString("-webkit-progress-value", AtomicString::ConstructFromLiteral)); + m_value->setShadowPseudoId(AtomicString("-webkit-progress-value", AtomicString::ConstructFromLiteral)); m_value->setWidthPercentage(HTMLProgressElement::IndeterminatePosition * 100); bar->appendChild(m_value); @@ -170,4 +170,10 @@ bool HTMLProgressElement::shouldAppearIndeterminate() const return !isDeterminate(); } +void HTMLProgressElement::trace(Visitor* visitor) +{ + visitor->trace(m_value); + LabelableElement::trace(visitor); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.h index 6162ded1570..cce0dfbbb64 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.h @@ -34,17 +34,19 @@ public: static const double IndeterminatePosition; static const double InvalidPosition; - static PassRefPtr<HTMLProgressElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLProgressElement> create(Document&); double value() const; - void setValue(double, ExceptionState&); + void setValue(double); double max() const; - void setMax(double, ExceptionState&); + void setMax(double); double position() const; - virtual bool canContainRangeEndPoint() const { return false; } + virtual bool canContainRangeEndPoint() const OVERRIDE { return false; } + + virtual void trace(Visitor*) OVERRIDE; private: explicit HTMLProgressElement(Document&); @@ -54,7 +56,7 @@ private: virtual bool shouldAppearIndeterminate() const OVERRIDE; virtual bool supportLabels() const OVERRIDE { return true; } - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; RenderProgress* renderProgress() const; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; @@ -65,17 +67,9 @@ private: virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE; bool isDeterminate() const; - ProgressValueElement* m_value; + RawPtrWillBeMember<ProgressValueElement> m_value; }; -inline bool isHTMLProgressElement(Node* node) -{ - ASSERT(node); - return node->hasTagName(HTMLNames::progressTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLProgressElement, hasTagName(HTMLNames::progressTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.idl index b2f5a9cdbba..a3da90a39e7 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLProgressElement.idl @@ -17,10 +17,13 @@ * Boston, MA 02110-1301, USA. */ -interface HTMLProgressElement : HTMLElement { - [RaisesException=Setter] attribute double value; - [RaisesException=Setter] attribute double max; - readonly attribute double position; - readonly attribute NodeList labels; -}; +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#htmlprogresselement +[ + TypeChecking=Unrestricted, +] interface HTMLProgressElement : HTMLElement { + attribute double value; + attribute double max; + readonly attribute double position; + readonly attribute NodeList labels; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.cpp index ff18c6006e4..228af64484d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "core/html/HTMLQuoteElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/StyleEngine.h" @@ -38,14 +38,21 @@ inline HTMLQuoteElement::HTMLQuoteElement(const QualifiedName& tagName, Document ScriptWrappable::init(this); } -PassRefPtr<HTMLQuoteElement> HTMLQuoteElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLQuoteElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLQuoteElement) bool HTMLQuoteElement::isURLAttribute(const Attribute& attribute) const { return attribute.name() == citeAttr || HTMLElement::isURLAttribute(attribute); } +bool HTMLQuoteElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == citeAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLQuoteElement::subResourceAttributeName() const +{ + return citeAttr; +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.h index bfdc9ee176a..fcf12adcf85 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.h @@ -31,12 +31,14 @@ namespace WebCore { class HTMLQuoteElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLQuoteElement> create(const QualifiedName&, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLQuoteElement); private: HTMLQuoteElement(const QualifiedName&, Document&); virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; }; } //namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.idl index 93a2aff07ea..db0ab9dd9ca 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLQuoteElement.idl @@ -18,5 +18,5 @@ */ interface HTMLQuoteElement : HTMLElement { - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString cite; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString cite; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLRTElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLRTElement.cpp new file mode 100644 index 00000000000..d1fb7c03f22 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLRTElement.cpp @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/HTMLRTElement.h" + +#include "core/HTMLNames.h" +#include "core/rendering/RenderRubyText.h" + +namespace WebCore { + +using namespace HTMLNames; + +inline HTMLRTElement::HTMLRTElement(Document& document) + : HTMLElement(rtTag, document) +{ +} + +DEFINE_NODE_FACTORY(HTMLRTElement) + +RenderObject* HTMLRTElement::createRenderer(RenderStyle* style) +{ + if (style->display() == BLOCK) + return new RenderRubyText(this); + return RenderObject::createObject(this, style); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLRTElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLRTElement.h new file mode 100644 index 00000000000..eea1e94bf30 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLRTElement.h @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HTMLRTElement_h +#define HTMLRTElement_h + +#include "core/html/HTMLElement.h" + +namespace WebCore { + +// <rt> is an HTMLElement in script, but we use a separate interface here +// so HTMLElement's createRenderer doesn't need to know about it. +class HTMLRTElement FINAL : public HTMLElement { +public: + DECLARE_NODE_FACTORY(HTMLRTElement); + +private: + explicit HTMLRTElement(Document&); + + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; +}; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLRubyElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLRubyElement.cpp new file mode 100644 index 00000000000..ab6febd1ecc --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLRubyElement.cpp @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/HTMLRubyElement.h" + +#include "core/HTMLNames.h" +#include "core/rendering/RenderRuby.h" + +namespace WebCore { + +using namespace HTMLNames; + +inline HTMLRubyElement::HTMLRubyElement(Document& document) + : HTMLElement(rubyTag, document) +{ +} + +DEFINE_NODE_FACTORY(HTMLRubyElement) + +RenderObject* HTMLRubyElement::createRenderer(RenderStyle* style) +{ + if (style->display() == INLINE) + return new RenderRubyAsInline(this); + if (style->display() == BLOCK) + return new RenderRubyAsBlock(this); + return RenderObject::createObject(this, style); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLRubyElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLRubyElement.h new file mode 100644 index 00000000000..bf177a6daae --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLRubyElement.h @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HTMLRubyElement_h +#define HTMLRubyElement_h + +#include "core/html/HTMLElement.h" + +namespace WebCore { + +// <ruby> is an HTMLElement in script, but we use a separate interface here +// so HTMLElement's createRenderer doesn't need to know about it. +class HTMLRubyElement FINAL : public HTMLElement { +public: + DECLARE_NODE_FACTORY(HTMLRubyElement); + +private: + explicit HTMLRubyElement(Document&); + + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; +}; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp index fd54cc283c2..ce1adaf24a7 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp @@ -23,15 +23,14 @@ #include "config.h" #include "core/html/HTMLScriptElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "bindings/v8/ScriptEventListener.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" #include "core/dom/ScriptLoader.h" #include "core/dom/Text.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" namespace WebCore { @@ -44,9 +43,9 @@ inline HTMLScriptElement::HTMLScriptElement(Document& document, bool wasInserted ScriptWrappable::init(this); } -PassRefPtr<HTMLScriptElement> HTMLScriptElement::create(Document& document, bool wasInsertedByParser, bool alreadyStarted) +PassRefPtrWillBeRawPtr<HTMLScriptElement> HTMLScriptElement::create(Document& document, bool wasInsertedByParser, bool alreadyStarted) { - return adoptRef(new HTMLScriptElement(document, wasInsertedByParser, alreadyStarted)); + return adoptRefWillBeNoop(new HTMLScriptElement(document, wasInsertedByParser, alreadyStarted)); } bool HTMLScriptElement::isURLAttribute(const Attribute& attribute) const @@ -54,6 +53,16 @@ bool HTMLScriptElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == srcAttr || HTMLElement::isURLAttribute(attribute); } +bool HTMLScriptElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == srcAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLScriptElement::subResourceAttributeName() const +{ + return srcAttr; +} + void HTMLScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); @@ -66,8 +75,6 @@ void HTMLScriptElement::parseAttribute(const QualifiedName& name, const AtomicSt m_loader->handleSourceAttribute(value); else if (name == asyncAttr) m_loader->handleAsyncAttribute(); - else if (name == onbeforeloadAttr) - setAttributeEventListener(EventTypeNames::beforeload, createAttributeEventListener(this, name, value)); else HTMLElement::parseAttribute(name, value); } @@ -85,7 +92,7 @@ void HTMLScriptElement::didNotifySubtreeInsertionsToDocument() void HTMLScriptElement::setText(const String &value) { - RefPtr<Node> protectFromMutationEvents(this); + RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this); if (hasOneTextChild()) { toText(firstChild())->setData(value); @@ -112,13 +119,6 @@ KURL HTMLScriptElement::src() const return document().completeURL(sourceAttributeValue()); } -void HTMLScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, src()); -} - String HTMLScriptElement::sourceAttributeValue() const { return getAttribute(srcAttr).string(); @@ -170,9 +170,9 @@ void HTMLScriptElement::dispatchLoadEvent() dispatchEvent(Event::create(EventTypeNames::load)); } -PassRefPtr<Element> HTMLScriptElement::cloneElementWithoutAttributesAndChildren() +PassRefPtrWillBeRawPtr<Element> HTMLScriptElement::cloneElementWithoutAttributesAndChildren() { - return adoptRef(new HTMLScriptElement(document(), false, m_loader->alreadyStarted())); + return adoptRefWillBeNoop(new HTMLScriptElement(document(), false, m_loader->alreadyStarted())); } } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.h index d4e0efd047e..9dbc0c86fa4 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.h @@ -33,7 +33,7 @@ class ScriptLoader; class HTMLScriptElement FINAL : public HTMLElement, public ScriptLoaderClient { public: - static PassRefPtr<HTMLScriptElement> create(Document&, bool wasInsertedByParser, bool alreadyStarted = false); + static PassRefPtrWillBeRawPtr<HTMLScriptElement> create(Document&, bool wasInsertedByParser, bool alreadyStarted = false); String text() { return textFromChildren(); } void setText(const String&); @@ -51,31 +51,29 @@ private: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; + virtual String sourceAttributeValue() const OVERRIDE; + virtual String charsetAttributeValue() const OVERRIDE; + virtual String typeAttributeValue() const OVERRIDE; + virtual String languageAttributeValue() const OVERRIDE; + virtual String forAttributeValue() const OVERRIDE; + virtual String eventAttributeValue() const OVERRIDE; + virtual bool asyncAttributeValue() const OVERRIDE; + virtual bool deferAttributeValue() const OVERRIDE; + virtual bool hasSourceAttribute() const OVERRIDE; - virtual String sourceAttributeValue() const; - virtual String charsetAttributeValue() const; - virtual String typeAttributeValue() const; - virtual String languageAttributeValue() const; - virtual String forAttributeValue() const; - virtual String eventAttributeValue() const; - virtual bool asyncAttributeValue() const; - virtual bool deferAttributeValue() const; - virtual bool hasSourceAttribute() const; + virtual void dispatchLoadEvent() OVERRIDE; - virtual void dispatchLoadEvent(); - - virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren(); + virtual PassRefPtrWillBeRawPtr<Element> cloneElementWithoutAttributesAndChildren() OVERRIDE; OwnPtr<ScriptLoader> m_loader; }; -DEFINE_NODE_TYPE_CASTS(HTMLScriptElement, hasTagName(HTMLNames::scriptTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.idl index 1f1e260a7f9..71b542261e4 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLScriptElement.idl @@ -24,8 +24,10 @@ interface HTMLScriptElement : HTMLElement { [Reflect] attribute DOMString charset; attribute boolean async; [Reflect] attribute boolean defer; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; [Reflect] attribute DOMString type; - [Reflect] attribute DOMString crossOrigin; + [Reflect, ReflectOnly="anonymous"|"use-credentials", ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString crossOrigin; [Reflect, RuntimeEnabled=ExperimentalContentSecurityPolicyFeatures] attribute DOMString nonce; + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp index 8d8332a3e86..b0dc747ff14 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp @@ -28,24 +28,23 @@ #include "config.h" #include "core/html/HTMLSelectElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/dom/Attribute.h" #include "core/dom/ElementTraversal.h" #include "core/dom/NodeTraversal.h" +#include "core/events/GestureEvent.h" #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/FormDataList.h" #include "core/html/HTMLFormElement.h" -#include "core/html/HTMLOptGroupElement.h" #include "core/html/HTMLOptionElement.h" #include "core/html/forms/FormController.h" #include "core/page/EventHandler.h" -#include "core/frame/Frame.h" #include "core/page/SpatialNavigation.h" #include "core/rendering/RenderListBox.h" #include "core/rendering/RenderMenuList.h" @@ -53,7 +52,6 @@ #include "platform/PlatformMouseEvent.h" #include "platform/text/PlatformLocale.h" -using namespace std; using namespace WTF::Unicode; namespace WebCore { @@ -63,7 +61,7 @@ using namespace HTMLNames; // Upper limit agreed upon with representatives of Opera and Mozilla. static const unsigned maxSelectItems = 10000; -HTMLSelectElement::HTMLSelectElement(Document& document, HTMLFormElement* form, bool createdByParser) +HTMLSelectElement::HTMLSelectElement(Document& document, HTMLFormElement* form) : HTMLFormControlElementWithState(selectTag, document, form) , m_typeAhead(this) , m_size(0) @@ -74,19 +72,20 @@ HTMLSelectElement::HTMLSelectElement(Document& document, HTMLFormElement* form, , m_multiple(false) , m_activeSelectionState(false) , m_shouldRecalcListItems(false) - , m_isParsingInProgress(createdByParser) + , m_suggestedIndex(-1) { ScriptWrappable::init(this); + setHasCustomStyleCallbacks(); } -PassRefPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document) { - return adoptRef(new HTMLSelectElement(document, 0, false)); + return adoptRefWillBeNoop(new HTMLSelectElement(document, 0)); } -PassRefPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document, HTMLFormElement* form, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& document, HTMLFormElement* form) { - return adoptRef(new HTMLSelectElement(document, form, createdByParser)); + return adoptRefWillBeNoop(new HTMLSelectElement(document, form)); } const AtomicString& HTMLSelectElement::formControlType() const @@ -96,12 +95,6 @@ const AtomicString& HTMLSelectElement::formControlType() const return m_multiple ? selectMultiple : selectOne; } -void HTMLSelectElement::deselectItems(HTMLOptionElement* excludeElement) -{ - deselectItemsWithoutValidation(excludeElement); - setNeedsValidityCheck(); -} - void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeNow, bool allowMultipleSelection) { // User interaction such as mousedown events can cause list box select elements to send change events. @@ -121,7 +114,7 @@ void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeN if (optionIndex == selectedIndex()) return; - selectOption(optionIndex, DeselectOtherOptions | (fireOnChangeNow ? DispatchChangeEvent : 0) | UserDriven); + selectOption(optionIndex, DeselectOtherOptions | (fireOnChangeNow ? DispatchInputAndChangeEvent : 0) | UserDriven); } bool HTMLSelectElement::hasPlaceholderLabelOption() const @@ -209,15 +202,21 @@ int HTMLSelectElement::activeSelectionEndListIndex() const void HTMLSelectElement::add(HTMLElement* element, HTMLElement* before, ExceptionState& exceptionState) { // Make sure the element is ref'd and deref'd so we don't leak it. - RefPtr<HTMLElement> protectNewChild(element); + RefPtrWillBeRawPtr<HTMLElement> protectNewChild(element); - if (!element || !(element->hasLocalName(optionTag) || element->hasLocalName(hrTag))) + if (!element || !(isHTMLOptionElement(element) || isHTMLOptGroupElement(element) || isHTMLHRElement(element))) return; insertBefore(element, before, exceptionState); setNeedsValidityCheck(); } +void HTMLSelectElement::addBeforeOptionAtIndex(HTMLElement* element, int beforeIndex, ExceptionState& exceptionState) +{ + HTMLElement* beforeElement = toHTMLElement(options()->item(beforeIndex)); + add(element, beforeElement, exceptionState); +} + void HTMLSelectElement::remove(int optionIndex) { int listIndex = optionToListIndex(optionIndex); @@ -227,46 +226,80 @@ void HTMLSelectElement::remove(int optionIndex) listItems()[listIndex]->remove(IGNORE_EXCEPTION); } -void HTMLSelectElement::remove(HTMLOptionElement* option) -{ - if (option->ownerSelectElement() != this) - return; - - option->remove(IGNORE_EXCEPTION); -} - String HTMLSelectElement::value() const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); i++) { - if (items[i]->hasLocalName(optionTag) && toHTMLOptionElement(items[i])->selected()) + if (isHTMLOptionElement(items[i]) && toHTMLOptionElement(items[i])->selected()) return toHTMLOptionElement(items[i])->value(); } return ""; } -void HTMLSelectElement::setValue(const String &value) +void HTMLSelectElement::setValue(const String &value, bool sendEvents) { // We clear the previously selected option(s) when needed, to guarantee calling setSelectedIndex() only once. + int optionIndex = 0; + if (value.isNull()) { + optionIndex = -1; + } else { + // Find the option with value() matching the given parameter and make it the current selection. + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); + for (unsigned i = 0; i < items.size(); i++) { + if (isHTMLOptionElement(items[i])) { + if (toHTMLOptionElement(items[i])->value() == value) + break; + optionIndex++; + } + } + if (optionIndex >= static_cast<int>(items.size())) + optionIndex = -1; + } + + int previousSelectedIndex = selectedIndex(); + setSuggestedIndex(-1); + setSelectedIndex(optionIndex); + + if (sendEvents && previousSelectedIndex != selectedIndex()) { + if (usesMenuList()) + dispatchInputAndChangeEventForMenuList(false); + else + listBoxOnChange(); + } +} + +String HTMLSelectElement::suggestedValue() const +{ + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); + for (unsigned i = 0; i < items.size(); ++i) { + if (isHTMLOptionElement(items[i]) && m_suggestedIndex >= 0) { + if (i == static_cast<unsigned>(m_suggestedIndex)) + return toHTMLOptionElement(items[i])->value(); + } + } + return ""; +} + +void HTMLSelectElement::setSuggestedValue(const String& value) +{ if (value.isNull()) { - setSelectedIndex(-1); + setSuggestedIndex(-1); return; } - // Find the option with value() matching the given parameter and make it the current selection. - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); unsigned optionIndex = 0; - for (unsigned i = 0; i < items.size(); i++) { - if (items[i]->hasLocalName(optionTag)) { + for (unsigned i = 0; i < items.size(); ++i) { + if (isHTMLOptionElement(items[i])) { if (toHTMLOptionElement(items[i])->value() == value) { - setSelectedIndex(optionIndex); + setSuggestedIndex(optionIndex); return; } optionIndex++; } } - setSelectedIndex(-1); + setSuggestedIndex(-1); } bool HTMLSelectElement::isPresentationAttribute(const QualifiedName& name) const @@ -290,10 +323,10 @@ void HTMLSelectElement::parseAttribute(const QualifiedName& name, const AtomicSt AtomicString attrSize = AtomicString::number(size); if (attrSize != value) { // FIXME: This is horribly factored. - if (Attribute* sizeAttribute = ensureUniqueElementData()->getAttributeItem(sizeAttr)) + if (Attribute* sizeAttribute = ensureUniqueElementData().findAttributeByName(sizeAttr)) sizeAttribute->setValue(attrSize); } - size = max(size, 1); + size = std::max(size, 1); // Ensure that we've determined selectedness of the items at least once prior to changing the size. if (oldSize != size) @@ -310,6 +343,15 @@ void HTMLSelectElement::parseAttribute(const QualifiedName& name, const AtomicSt else if (name == accesskeyAttr) { // FIXME: ignore for the moment. // + } else if (name == disabledAttr) { + HTMLFormControlElementWithState::parseAttribute(name, value); + if (renderer() && renderer()->isMenuList()) { + if (RenderMenuList* menuList = toRenderMenuList(renderer())) { + if (menuList->popupIsVisible()) + menuList->hidePopup(); + } + } + } else HTMLFormControlElementWithState::parseAttribute(name, value); } @@ -331,24 +373,15 @@ RenderObject* HTMLSelectElement::createRenderer(RenderStyle*) return new RenderListBox(this); } -bool HTMLSelectElement::childShouldCreateRenderer(const Node& child) const -{ - if (!HTMLFormControlElementWithState::childShouldCreateRenderer(child)) - return false; - if (!usesMenuList()) - return child.hasTagName(HTMLNames::optionTag) || isHTMLOptGroupElement(&child); - return false; -} - -PassRefPtr<HTMLCollection> HTMLSelectElement::selectedOptions() +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLSelectElement::selectedOptions() { updateListItemSelectedStates(); return ensureCachedHTMLCollection(SelectedOptions); } -PassRefPtr<HTMLOptionsCollection> HTMLSelectElement::options() +PassRefPtrWillBeRawPtr<HTMLOptionsCollection> HTMLSelectElement::options() { - return static_cast<HTMLOptionsCollection*>(ensureCachedHTMLCollection(SelectOptions).get()); + return toHTMLOptionsCollection(ensureCachedHTMLCollection(SelectOptions).get()); } void HTMLSelectElement::updateListItemSelectedStates() @@ -402,12 +435,12 @@ void HTMLSelectElement::setSize(int size) setIntegralAttribute(sizeAttr, size); } -Node* HTMLSelectElement::namedItem(const AtomicString& name) +Element* HTMLSelectElement::namedItem(const AtomicString& name) { return options()->namedItem(name); } -Node* HTMLSelectElement::item(unsigned index) +Element* HTMLSelectElement::item(unsigned index) { return options()->item(index); } @@ -417,7 +450,7 @@ void HTMLSelectElement::setOption(unsigned index, HTMLOptionElement* option, Exc if (index > maxSelectItems - 1) index = maxSelectItems - 1; int diff = index - length(); - RefPtr<HTMLElement> before = 0; + RefPtrWillBeRawPtr<HTMLElement> before = nullptr; // Out of array bounds? First insert empty dummies. if (diff > 0) { setLength(index, exceptionState); @@ -442,22 +475,22 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionState& exceptionStat if (diff < 0) { // Add dummy elements. do { - RefPtr<Element> option = document().createElement(optionTag, false); + RefPtrWillBeRawPtr<Element> option = document().createElement(optionTag, false); ASSERT(option); add(toHTMLElement(option), 0, exceptionState); if (exceptionState.hadException()) break; } while (++diff); } else { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); // Removing children fires mutation events, which might mutate the DOM further, so we first copy out a list // of elements that we intend to remove then attempt to remove them one at a time. - Vector<RefPtr<Element> > itemsToRemove; + WillBeHeapVector<RefPtrWillBeMember<Element> > itemsToRemove; size_t optionIndex = 0; for (size_t i = 0; i < items.size(); ++i) { Element* item = items[i]; - if (item->hasLocalName(optionTag) && optionIndex++ >= newLen) { + if (isHTMLOptionElement(items[i]) && optionIndex++ >= newLen) { ASSERT(item->parentNode()); itemsToRemove.append(item); } @@ -484,16 +517,17 @@ bool HTMLSelectElement::isRequiredFormControl() const int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, int skip) const { ASSERT(direction == -1 || direction == 1); - const Vector<HTMLElement*>& listItems = this->listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems(); int lastGoodIndex = listIndex; int size = listItems.size(); for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) { --skip; - if (!listItems[listIndex]->isDisabledFormControl() && listItems[listIndex]->hasTagName(optionTag)) { - lastGoodIndex = listIndex; - if (skip <= 0) - break; - } + HTMLElement* element = listItems[listIndex]; + if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) + continue; + lastGoodIndex = listIndex; + if (skip <= 0) + break; } return lastGoodIndex; } @@ -512,7 +546,7 @@ int HTMLSelectElement::previousSelectableListIndex(int startIndex) const int HTMLSelectElement::firstSelectableListIndex() const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); int index = nextValidIndex(items.size(), SkipBackwards, INT_MAX); if (static_cast<size_t>(index) == items.size()) return -1; @@ -527,7 +561,7 @@ int HTMLSelectElement::lastSelectableListIndex() const // Returns the index of the next valid item one page away from |startIndex| in direction |direction|. int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirection direction) const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); // Can't use m_size because renderer forces a minimum size. int pageSize = 0; if (renderer()->isListBox()) @@ -568,10 +602,10 @@ void HTMLSelectElement::saveLastSelection() } m_lastOnChangeSelection.clear(); - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - m_lastOnChangeSelection.append(element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected()); + m_lastOnChangeSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()); } } @@ -583,10 +617,10 @@ void HTMLSelectElement::setActiveSelectionAnchorIndex(int index) // selection pivots around this anchor index. m_cachedStateForActiveSelection.clear(); - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - m_cachedStateForActiveSelection.append(element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected()); + m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()); } } @@ -600,13 +634,13 @@ void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); ASSERT(!listItems().size() || m_activeSelectionAnchorIndex >= 0); - unsigned start = min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); - unsigned end = max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); + unsigned start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); + unsigned end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - if (!element->hasTagName(optionTag) || toHTMLOptionElement(element)->isDisabledFormControl()) + if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl() || toHTMLOptionElement(element)->isDisplayNone()) continue; if (i >= start && i <= end) @@ -626,7 +660,7 @@ void HTMLSelectElement::listBoxOnChange() { ASSERT(!usesMenuList() || m_multiple); - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); // If the cached selection list is empty, or the size has changed, then fire // dispatchFormControlChangeEvent, and return early. @@ -640,24 +674,29 @@ void HTMLSelectElement::listBoxOnChange() bool fireOnChange = false; for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - bool selected = element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected(); + bool selected = isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected(); if (selected != m_lastOnChangeSelection[i]) fireOnChange = true; m_lastOnChangeSelection[i] = selected; } - if (fireOnChange) + if (fireOnChange) { + RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); + dispatchInputEvent(); dispatchFormControlChangeEvent(); + } } -void HTMLSelectElement::dispatchChangeEventForMenuList() +void HTMLSelectElement::dispatchInputAndChangeEventForMenuList(bool requiresUserGesture) { ASSERT(usesMenuList()); int selected = selectedIndex(); - if (m_lastOnChangeIndex != selected && m_isProcessingUserDrivenChange) { + if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessingUserDrivenChange)) { m_lastOnChangeIndex = selected; m_isProcessingUserDrivenChange = false; + RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); + dispatchInputEvent(); dispatchFormControlChangeEvent(); } } @@ -681,13 +720,13 @@ void HTMLSelectElement::setOptionsChangedOnRenderer() } } -const Vector<HTMLElement*>& HTMLSelectElement::listItems() const +const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::listItems() const { if (m_shouldRecalcListItems) recalcListItems(); else { -#if !ASSERT_DISABLED - Vector<HTMLElement*> items = m_listItems; +#if ASSERT_ENABLED + WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems; recalcListItems(false); ASSERT(items == m_listItems); #endif @@ -711,7 +750,7 @@ void HTMLSelectElement::setRecalcListItems() // Manual selection anchor is reset when manipulating the select programmatically. m_activeSelectionAnchorIndex = -1; setOptionsChangedOnRenderer(); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); if (!inDocument()) { if (HTMLCollection* collection = cachedHTMLCollection(SelectOptions)) collection->invalidateCache(); @@ -751,7 +790,7 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const } } - if (current.hasTagName(optionTag)) { + if (isHTMLOptionElement(current)) { m_listItems.append(¤t); if (updateSelectedStates && !m_multiple) { @@ -769,7 +808,7 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const } } - if (current.hasTagName(hrTag)) + if (isHTMLHRElement(current)) m_listItems.append(¤t); // In conforming HTML code, only <optgroup> and <option> will be found @@ -790,11 +829,11 @@ int HTMLSelectElement::selectedIndex() const unsigned index = 0; // Return the number of the first option selected. - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (size_t i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - if (element->hasTagName(optionTag)) { - if (toHTMLOptionElement(element)->selected()) + if (isHTMLOptionElement(*element)) { + if (toHTMLOptionElement(*element).selected()) return index; ++index; } @@ -808,6 +847,22 @@ void HTMLSelectElement::setSelectedIndex(int index) selectOption(index, DeselectOtherOptions); } +int HTMLSelectElement::suggestedIndex() const +{ + return m_suggestedIndex; +} + +void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) +{ + m_suggestedIndex = suggestedIndex; + + if (RenderObject* renderer = this->renderer()) { + renderer->updateFromElement(); + if (renderer->isListBox()) + toRenderListBox(renderer)->scrollToRevealElementAtListIndex(suggestedIndex); + } +} + void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, bool optionIsSelected) { ASSERT(option->ownerSelectElement() == this); @@ -823,18 +878,18 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) { bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); int listIndex = optionToListIndex(optionIndex); HTMLElement* element = 0; if (listIndex >= 0) { element = items[listIndex]; - if (element->hasTagName(optionTag)) { + if (isHTMLOptionElement(*element)) { if (m_activeSelectionAnchorIndex < 0 || shouldDeselect) setActiveSelectionAnchorIndex(listIndex); if (m_activeSelectionEndIndex < 0 || shouldDeselect) setActiveSelectionEndIndex(listIndex); - toHTMLOptionElement(element)->setSelectedState(true); + toHTMLOptionElement(*element).setSelectedState(true); } } @@ -847,10 +902,12 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) scrollToSelection(); + setNeedsValidityCheck(); + if (usesMenuList()) { m_isProcessingUserDrivenChange = flags & UserDriven; - if (flags & DispatchChangeEvent) - dispatchChangeEventForMenuList(); + if (flags & DispatchInputAndChangeEvent) + dispatchInputAndChangeEventForMenuList(); if (RenderObject* renderer = this->renderer()) { if (usesMenuList()) toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); @@ -859,20 +916,19 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) } } - setNeedsValidityCheck(); notifyFormStateChanged(); } int HTMLSelectElement::optionToListIndex(int optionIndex) const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); int listSize = static_cast<int>(items.size()); if (optionIndex < 0 || optionIndex >= listSize) return -1; int optionIndex2 = -1; for (int listIndex = 0; listIndex < listSize; ++listIndex) { - if (items[listIndex]->hasTagName(optionTag)) { + if (isHTMLOptionElement(*items[listIndex])) { ++optionIndex2; if (optionIndex2 == optionIndex) return listIndex; @@ -884,27 +940,27 @@ int HTMLSelectElement::optionToListIndex(int optionIndex) const int HTMLSelectElement::listToOptionIndex(int listIndex) const { - const Vector<HTMLElement*>& items = listItems(); - if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !items[listIndex]->hasTagName(optionTag)) + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); + if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLOptionElement(*items[listIndex])) return -1; // Actual index of option not counting OPTGROUP entries that may be in list. int optionIndex = 0; for (int i = 0; i < listIndex; ++i) { - if (items[i]->hasTagName(optionTag)) + if (isHTMLOptionElement(*items[i])) ++optionIndex; } return optionIndex; } -void HTMLSelectElement::dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction) +void HTMLSelectElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType type) { // Save the selection so it can be compared to the new selection when // dispatching change events during blur event dispatch. if (usesMenuList()) saveLastSelection(); - HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, direction); + HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, type); } void HTMLSelectElement::dispatchBlurEvent(Element* newFocusedElement) @@ -913,27 +969,27 @@ void HTMLSelectElement::dispatchBlurEvent(Element* newFocusedElement) // change events for list boxes whenever the selection change is actually made. // This matches other browsers' behavior. if (usesMenuList()) - dispatchChangeEventForMenuList(); + dispatchInputAndChangeEventForMenuList(); HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement); } void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeElement) { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - if (element != excludeElement && element->hasTagName(optionTag)) + if (element != excludeElement && isHTMLOptionElement(*element)) toHTMLOptionElement(element)->setSelectedState(false); } } FormControlState HTMLSelectElement::saveFormControlState() const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); size_t length = items.size(); FormControlState state; for (unsigned i = 0; i < length; ++i) { - if (!items[i]->hasTagName(optionTag)) + if (!isHTMLOptionElement(*items[i])) continue; HTMLOptionElement* option = toHTMLOptionElement(items[i]); if (!option->selected()) @@ -947,10 +1003,10 @@ FormControlState HTMLSelectElement::saveFormControlState() const size_t HTMLSelectElement::searchOptionsForValue(const String& value, size_t listIndexStart, size_t listIndexEnd) const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); size_t loopEndIndex = std::min(items.size(), listIndexEnd); for (size_t i = listIndexStart; i < loopEndIndex; ++i) { - if (!items[i]->hasLocalName(optionTag)) + if (!isHTMLOptionElement(items[i])) continue; if (toHTMLOptionElement(items[i])->value() == value) return i; @@ -962,13 +1018,13 @@ void HTMLSelectElement::restoreFormControlState(const FormControlState& state) { recalcListItems(); - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); size_t itemsSize = items.size(); if (!itemsSize) return; for (size_t i = 0; i < itemsSize; ++i) { - if (!items[i]->hasLocalName(optionTag)) + if (!isHTMLOptionElement(items[i])) continue; toHTMLOptionElement(items[i])->setSelectedState(false); } @@ -1011,12 +1067,12 @@ bool HTMLSelectElement::appendFormData(FormDataList& list, bool) return false; bool successful = false; - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected() && !toHTMLOptionElement(element)->isDisabledFormControl()) { - list.appendData(name, toHTMLOptionElement(element)->value()); + if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selected() && !toHTMLOptionElement(*element).isDisabledFormControl()) { + list.appendData(name, toHTMLOptionElement(*element).value()); successful = true; } } @@ -1032,10 +1088,10 @@ void HTMLSelectElement::resetImpl() HTMLOptionElement* firstOption = 0; HTMLOptionElement* selectedOption = 0; - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { HTMLElement* element = items[i]; - if (!element->hasTagName(optionTag)) + if (!isHTMLOptionElement(*element)) continue; if (items[i]->fastHasAttribute(selectedAttr)) { @@ -1054,7 +1110,7 @@ void HTMLSelectElement::resetImpl() firstOption->setSelectedState(true); setOptionsChangedOnRenderer(); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); setNeedsValidityCheck(); } @@ -1070,7 +1126,7 @@ bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event) // Calling focus() may cause us to lose our renderer. Return true so // that our caller doesn't process the event further, but don't set // the event as handled. - if (!renderer()) + if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) return true; // Save the selection so it can be compared to the new selection @@ -1110,7 +1166,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); bool handled = true; - const Vector<HTMLElement*>& listItems = this->listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems(); int listIndex = optionToListIndex(selectedIndex()); if (keyIdentifier == "Down" || keyIdentifier == "Right") @@ -1129,7 +1185,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) handled = false; if (handled && static_cast<size_t>(listIndex) < listItems.size()) - selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | DispatchChangeEvent | UserDriven); + selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | DispatchInputAndChangeEvent | UserDriven); if (handled) event->setDefaultHandled(); @@ -1157,7 +1213,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) // Calling focus() may remove the renderer or change the // renderer type. - if (!renderer() || !renderer()->isMenuList()) + if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) return; // Save the selection so it can be compared to the new selection @@ -1175,7 +1231,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) // Calling focus() may remove the renderer or change the // renderer type. - if (!renderer() || !renderer()->isMenuList()) + if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) return; // Save the selection so it can be compared to the new selection @@ -1189,7 +1245,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) } else if (keyCode == '\r') { if (form()) form()->submitImplicitly(event, false); - dispatchChangeEventForMenuList(); + dispatchInputAndChangeEventForMenuList(); handled = true; } } @@ -1200,7 +1256,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { focus(); - if (renderer() && renderer()->isMenuList()) { + if (renderer() && renderer()->isMenuList() && !isDisabledFormControl()) { if (RenderMenuList* menuList = toRenderMenuList(renderer())) { if (menuList->popupIsVisible()) menuList->hidePopup(); @@ -1230,6 +1286,11 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif { ASSERT(listIndex >= 0); + HTMLElement* clickedElement = listItems()[listIndex]; + ASSERT(clickedElement); + if (isHTMLOptGroupElement(clickedElement)) + return; + // Save the selection so it can be compared to the new selection when // dispatching change events during mouseup, or after autoscroll finishes. saveLastSelection(); @@ -1239,14 +1300,13 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif bool shiftSelect = m_multiple && shift; bool multiSelect = m_multiple && multi && !shift; - HTMLElement* clickedElement = listItems()[listIndex]; - if (clickedElement->hasTagName(optionTag)) { + if (isHTMLOptionElement(*clickedElement)) { // Keep track of whether an active selection (like during drag // selection), should select or deselect. - if (toHTMLOptionElement(clickedElement)->selected() && multiSelect) + if (toHTMLOptionElement(*clickedElement).selected() && multiSelect) m_activeSelectionState = false; if (!m_activeSelectionState) - toHTMLOptionElement(clickedElement)->setSelectedState(false); + toHTMLOptionElement(*clickedElement).setSelectedState(false); } // If we're not in any special multiple selection mode, then deselect all @@ -1261,8 +1321,8 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif setActiveSelectionAnchorIndex(selectedIndex()); // Set the selection state of the clicked option. - if (clickedElement->hasTagName(optionTag) && !toHTMLOptionElement(clickedElement)->isDisabledFormControl()) - toHTMLOptionElement(clickedElement)->setSelectedState(true); + if (isHTMLOptionElement(*clickedElement) && !toHTMLOptionElement(*clickedElement).isDisabledFormControl()) + toHTMLOptionElement(*clickedElement).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 @@ -1277,12 +1337,26 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) { - const Vector<HTMLElement*>& listItems = this->listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems(); + if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) { + focus(); + // Calling focus() may cause us to lose our renderer or change the render type, in which case do not want to handle the event. + if (!renderer() || !renderer()->isListBox()) + return; - if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { + // Convert to coords relative to the list box if needed. + GestureEvent& gestureEvent = toGestureEvent(*event); + IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(gestureEvent.absoluteLocation(), UseTransforms)); + int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize(localOffset)); + if (listIndex >= 0) { + if (!isDisabledFormControl()) + updateSelectedState(listIndex, true, gestureEvent.shiftKey()); + event->setDefaultHandled(); + } + } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { focus(); // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event. - if (!renderer()) + if (!renderer() || !renderer()->isListBox() || isDisabledFormControl()) return; // Convert to coords relative to the list box if needed. @@ -1297,7 +1371,7 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent->shiftKey()); #endif } - if (Frame* frame = document().frame()) + if (LocalFrame* frame = document().frame()) frame->eventHandler().setMouseDownMayStartAutoscroll(); event->setDefaultHandled(); @@ -1324,15 +1398,11 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) updateListBoxSelection(true); } } - event->setDefaultHandled(); } } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer() && !toRenderBox(renderer())->autoscrollInProgress()) { // We didn't start this click/drag on any options. if (m_lastOnChangeSelection.isEmpty()) return; - // This makes sure we fire dispatchFormControlChangeEvent for a single - // click. For drag selection, onChange will fire when the autoscroll - // timer stops. listBoxOnChange(); } else if (event->type() == EventTypeNames::keydown) { if (!event->isKeyboardEvent()) @@ -1466,10 +1536,10 @@ void HTMLSelectElement::defaultEventHandler(Event* event) int HTMLSelectElement::lastSelectedListIndex() const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (size_t i = items.size(); i;) { HTMLElement* element = items[--i]; - if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected()) + if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()) return i; } return -1; @@ -1487,10 +1557,10 @@ int HTMLSelectElement::optionCount() const String HTMLSelectElement::optionAtIndex(int index) const { - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); HTMLElement* element = items[index]; - if (!element->hasTagName(optionTag) || toHTMLOptionElement(element)->isDisabledFormControl()) + if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl()) return String(); return toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); } @@ -1500,7 +1570,7 @@ void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhead::CycleFirstChar); if (index < 0) return; - selectOption(listToOptionIndex(index), DeselectOtherOptions | DispatchChangeEvent | UserDriven); + selectOption(listToOptionIndex(index), DeselectOtherOptions | DispatchInputAndChangeEvent | UserDriven); if (!usesMenuList()) listBoxOnChange(); } @@ -1522,20 +1592,20 @@ void HTMLSelectElement::accessKeySetSelectedIndex(int index) accessKeyAction(false); // If this index is already selected, unselect. otherwise update the selected index. - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); int listIndex = optionToListIndex(index); if (listIndex >= 0) { HTMLElement* element = items[listIndex]; - if (element->hasTagName(optionTag)) { - if (toHTMLOptionElement(element)->selected()) - toHTMLOptionElement(element)->setSelectedState(false); + if (isHTMLOptionElement(*element)) { + if (toHTMLOptionElement(*element).selected()) + toHTMLOptionElement(*element).setSelectedState(false); else - selectOption(index, DispatchChangeEvent | UserDriven); + selectOption(index, DispatchInputAndChangeEvent | UserDriven); } } if (usesMenuList()) - dispatchChangeEventForMenuList(); + dispatchInputAndChangeEventForMenuList(); else listBoxOnChange(); @@ -1546,9 +1616,9 @@ unsigned HTMLSelectElement::length() const { unsigned options = 0; - const Vector<HTMLElement*>& items = listItems(); + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems(); for (unsigned i = 0; i < items.size(); ++i) { - if (items[i]->hasTagName(optionTag)) + if (isHTMLOptionElement(*items[i])) ++options; } @@ -1558,29 +1628,40 @@ unsigned HTMLSelectElement::length() const void HTMLSelectElement::finishParsingChildren() { HTMLFormControlElementWithState::finishParsingChildren(); - m_isParsingInProgress = false; updateListItemSelectedStates(); } -bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtr<HTMLOptionElement> value, ExceptionState& exceptionState) +bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeRawPtr<HTMLOptionElement> value, ExceptionState& exceptionState) { - if (!value) { - exceptionState.throwTypeError(ExceptionMessages::failedToSet(String::number(index), "HTMLSelectElement", "The value provided was not an HTMLOptionElement.")); - return false; + if (!value) { // undefined or null + remove(index); + return true; } setOption(index, value.get(), exceptionState); return true; } -bool HTMLSelectElement::anonymousIndexedSetterRemove(unsigned index, ExceptionState& exceptionState) +bool HTMLSelectElement::isInteractiveContent() const { - remove(index); return true; } -bool HTMLSelectElement::isInteractiveContent() const +bool HTMLSelectElement::supportsAutofocus() const { return true; } +void HTMLSelectElement::updateListOnRenderer() +{ + setOptionsChangedOnRenderer(); +} + +void HTMLSelectElement::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_listItems); +#endif + HTMLFormControlElementWithState::trace(visitor); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.h index 7564360b5cc..05bf5124376 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.h @@ -39,11 +39,13 @@ class HTMLOptionElement; class HTMLSelectElement FINAL : public HTMLFormControlElementWithState, public TypeAheadDataSource { public: - static PassRefPtr<HTMLSelectElement> create(Document&); - static PassRefPtr<HTMLSelectElement> create(Document&, HTMLFormElement*, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLSelectElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLSelectElement> create(Document&, HTMLFormElement*); int selectedIndex() const; void setSelectedIndex(int); + int suggestedIndex() const; + void setSuggestedIndex(int); void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false); @@ -61,16 +63,18 @@ public: bool usesMenuList() const; void add(HTMLElement*, HTMLElement* beforeElement, ExceptionState&); + void addBeforeOptionAtIndex(HTMLElement*, int beforeIndex, ExceptionState&); using Node::remove; void remove(int index); - void remove(HTMLOptionElement*); String value() const; - void setValue(const String&); + void setValue(const String&, bool sendEvents = false); + String suggestedValue() const; + void setSuggestedValue(const String&); - PassRefPtr<HTMLOptionsCollection> options(); - PassRefPtr<HTMLCollection> selectedOptions(); + PassRefPtrWillBeRawPtr<HTMLOptionsCollection> options(); + PassRefPtrWillBeRawPtr<HTMLCollection> selectedOptions(); void optionElementChildrenChanged(); @@ -78,9 +82,9 @@ public: void invalidateSelectedItems(); void updateListItemSelectedStates(); - const Vector<HTMLElement*>& listItems() const; + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems() const; - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; void accessKeySetSelectedIndex(int); void setMultiple(bool); @@ -90,8 +94,8 @@ public: void setOption(unsigned index, HTMLOptionElement*, ExceptionState&); void setLength(unsigned, ExceptionState&); - Node* namedItem(const AtomicString& name); - Node* item(unsigned index); + Element* namedItem(const AtomicString& name); + Element* item(unsigned index); void scrollToSelection(); @@ -110,25 +114,28 @@ public: // For use in the implementation of HTMLOptionElement. void optionSelectionStateChanged(HTMLOptionElement*, bool optionIsSelected); - bool isParsingInProgress() const { return m_isParsingInProgress; } - bool anonymousIndexedSetter(unsigned, PassRefPtr<HTMLOptionElement>, ExceptionState&); - bool anonymousIndexedSetterRemove(unsigned, ExceptionState&); + bool anonymousIndexedSetter(unsigned, PassRefPtrWillBeRawPtr<HTMLOptionElement>, ExceptionState&); + + void updateListOnRenderer(); + + virtual void trace(Visitor*) OVERRIDE; protected: - HTMLSelectElement(Document&, HTMLFormElement*, bool createdByParser); + HTMLSelectElement(Document&, HTMLFormElement*); private: - virtual const AtomicString& formControlType() const; + virtual const AtomicString& formControlType() const OVERRIDE; virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE; - virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE; + virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusType) OVERRIDE; virtual void dispatchBlurEvent(Element* newFocusedElemnet) OVERRIDE; - virtual bool canStartSelection() const { return false; } + virtual bool canStartSelection() const OVERRIDE { return false; } - virtual bool isEnumeratable() const { return true; } + virtual bool isEnumeratable() const OVERRIDE { return true; } virtual bool isInteractiveContent() const OVERRIDE; + virtual bool supportsAutofocus() const OVERRIDE; virtual bool supportLabels() const OVERRIDE { return true; } virtual FormControlState saveFormControlState() const OVERRIDE; @@ -137,30 +144,28 @@ private: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; - virtual bool childShouldCreateRenderer(const Node& child) const OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle *); - virtual bool appendFormData(FormDataList&, bool); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual bool appendFormData(FormDataList&, bool) OVERRIDE; - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; - void dispatchChangeEventForMenuList(); + void dispatchInputAndChangeEventForMenuList(bool requiresUserGesture = true); void recalcListItems(bool updateSelectedStates = true) const; - void deselectItems(HTMLOptionElement* excludeElement = 0); void typeAheadFind(KeyboardEvent*); void saveLastSelection(); virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; - virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); } - virtual bool isRequiredFormControl() const; + virtual bool isOptionalFormControl() const OVERRIDE { return !isRequiredFormControl(); } + virtual bool isRequiredFormControl() const OVERRIDE; bool hasPlaceholderLabelOption() const; enum SelectOptionFlag { DeselectOtherOptions = 1 << 0, - DispatchChangeEvent = 1 << 1, + DispatchInputAndChangeEvent = 1 << 1, UserDriven = 1 << 2, }; typedef unsigned SelectOptionFlags; @@ -186,7 +191,7 @@ private: int lastSelectableListIndex() const; int nextSelectableListIndexPageAway(int startIndex, SkipDirection) const; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; } virtual void finishParsingChildren() OVERRIDE; @@ -196,7 +201,7 @@ private: virtual String optionAtIndex(int index) const OVERRIDE; // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects. - mutable Vector<HTMLElement*> m_listItems; + mutable WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > m_listItems; Vector<bool> m_lastOnChangeSelection; Vector<bool> m_cachedStateForActiveSelection; TypeAhead m_typeAhead; @@ -208,11 +213,9 @@ private: bool m_multiple; bool m_activeSelectionState; mutable bool m_shouldRecalcListItems; - bool m_isParsingInProgress; + int m_suggestedIndex; }; -DEFINE_NODE_TYPE_CASTS(HTMLSelectElement, hasTagName(HTMLNames::selectTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.idl index b61f5128247..52a124495f9 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSelectElement.idl @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#htmlselectelement + interface HTMLSelectElement : HTMLElement { [Reflect] attribute boolean autofocus; [Reflect] attribute boolean disabled; @@ -33,17 +35,18 @@ interface HTMLSelectElement : HTMLElement { readonly attribute HTMLOptionsCollection options; [RaisesException=Setter] attribute unsigned long length; - getter Node item(unsigned long index); - [ImplementedAs=anonymousIndexedSetter, RaisesException] setter HTMLOptionElement (unsigned long index, [TreatNullAs=anonymousIndexedSetterRemove, TreatUndefinedAs=anonymousIndexedSetterRemove] HTMLOptionElement value); - Node namedItem([Default=Undefined] optional DOMString name); - [RaisesException] void add([Default=Undefined] optional HTMLElement element, - [Default=Undefined] optional HTMLElement before); + getter Element item(unsigned long index); + Element namedItem([Default=Undefined] optional DOMString name); + // FIXME: should be union type http://crbug.com/240176 + [RaisesException, TypeChecking=Interface] void add(HTMLElement element, optional HTMLElement? before = null); + [ImplementedAs=addBeforeOptionAtIndex, RaisesException, TypeChecking=Interface] void add(HTMLElement element, long before); + [RaisesException] void remove(); // ChildNode overload void remove(long index); - void remove(HTMLOptionElement option); // Non standard. - [RaisesException] void remove(); + [RaisesException, TypeChecking=Interface|Nullable] setter HTMLOptionElement (unsigned long index, HTMLOptionElement? value); + readonly attribute HTMLCollection selectedOptions; - attribute long selectedIndex; - attribute DOMString value; + attribute long selectedIndex; + attribute DOMString value; readonly attribute boolean willValidate; readonly attribute ValidityState validity; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLShadowElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.cpp index edfba07e3e1..d44d71b741f 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLShadowElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "core/html/shadow/HTMLShadowElement.h" +#include "core/html/HTMLShadowElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/shadow/ShadowRoot.h" namespace WebCore { @@ -44,10 +44,7 @@ inline HTMLShadowElement::HTMLShadowElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLShadowElement> HTMLShadowElement::create(Document& document) -{ - return adoptRef(new HTMLShadowElement(document)); -} +DEFINE_NODE_FACTORY(HTMLShadowElement) HTMLShadowElement::~HTMLShadowElement() { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.h index 70833399beb..5f0f02695b1 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.h @@ -1,2 +1,53 @@ -// FIXME: Move HTMLShadowElement.h here. -#include "core/html/shadow/HTMLShadowElement.h" +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLShadowElement_h +#define HTMLShadowElement_h + +#include "core/dom/shadow/InsertionPoint.h" +#include "wtf/Forward.h" + +namespace WebCore { + +class HTMLShadowElement FINAL : public InsertionPoint { +public: + DECLARE_NODE_FACTORY(HTMLShadowElement); + virtual ~HTMLShadowElement(); + + ShadowRoot* olderShadowRoot(); + +private: + explicit HTMLShadowElement(Document&); + virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint) OVERRIDE; +}; + +} // namespace WebCore + +#endif // HTMLShadowElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLShadowElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.idl index faceace1458..86532b18888 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLShadowElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLShadowElement.idl @@ -29,7 +29,5 @@ */ interface HTMLShadowElement : HTMLElement { - attribute boolean resetStyleInheritance; - [DeprecateAs=HTMLShadowElementOlderShadowRoot] readonly attribute ShadowRoot olderShadowRoot; - [RuntimeEnabled=ShadowDOM] NodeList getDistributedNodes(); + NodeList getDistributedNodes(); }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp index 75daceb07a4..6364f84b11d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp @@ -26,37 +26,45 @@ #include "config.h" #include "core/html/HTMLSourceElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/events/EventSender.h" #include "core/html/HTMLMediaElement.h" +#include "core/html/HTMLPictureElement.h" #include "platform/Logging.h" -using namespace std; - namespace WebCore { using namespace HTMLNames; +static SourceEventSender& sourceErrorEventSender() +{ + DEFINE_STATIC_LOCAL(SourceEventSender, sharedErrorEventSender, (EventTypeNames::error)); + return sharedErrorEventSender; +} + inline HTMLSourceElement::HTMLSourceElement(Document& document) : HTMLElement(sourceTag, document) - , m_errorEventTimer(this, &HTMLSourceElement::errorEventTimerFired) { WTF_LOG(Media, "HTMLSourceElement::HTMLSourceElement - %p", this); ScriptWrappable::init(this); } -PassRefPtr<HTMLSourceElement> HTMLSourceElement::create(Document& document) +DEFINE_NODE_FACTORY(HTMLSourceElement) + +HTMLSourceElement::~HTMLSourceElement() { - return adoptRef(new HTMLSourceElement(document)); + sourceErrorEventSender().cancelEvent(this); } Node::InsertionNotificationRequest HTMLSourceElement::insertedInto(ContainerNode* insertionPoint) { HTMLElement::insertedInto(insertionPoint); Element* parent = parentElement(); - if (parent && parent->isMediaElement()) - toHTMLMediaElement(parentNode())->sourceWasAdded(this); + if (isHTMLMediaElement(parent)) + toHTMLMediaElement(parent)->sourceWasAdded(this); + if (isHTMLPictureElement(parent)) + toHTMLPictureElement(parent)->sourceOrMediaChanged(); return InsertionDone; } @@ -65,8 +73,10 @@ void HTMLSourceElement::removedFrom(ContainerNode* removalRoot) Element* parent = parentElement(); if (!parent && removalRoot->isElementNode()) parent = toElement(removalRoot); - if (parent && parent->isMediaElement()) + if (isHTMLMediaElement(parent)) toHTMLMediaElement(parent)->sourceWasRemoved(this); + if (isHTMLPictureElement(parent)) + toHTMLPictureElement(parent)->sourceOrMediaChanged(); HTMLElement::removedFrom(removalRoot); } @@ -75,16 +85,6 @@ void HTMLSourceElement::setSrc(const String& url) setAttribute(srcAttr, AtomicString(url)); } -const AtomicString& HTMLSourceElement::media() const -{ - return getAttribute(mediaAttr); -} - -void HTMLSourceElement::setMedia(const AtomicString& media) -{ - setAttribute(mediaAttr, media); -} - const AtomicString& HTMLSourceElement::type() const { return getAttribute(typeAttr); @@ -98,21 +98,19 @@ void HTMLSourceElement::setType(const AtomicString& type) void HTMLSourceElement::scheduleErrorEvent() { WTF_LOG(Media, "HTMLSourceElement::scheduleErrorEvent - %p", this); - if (m_errorEventTimer.isActive()) - return; - - m_errorEventTimer.startOneShot(0); + sourceErrorEventSender().dispatchEventSoon(this); } void HTMLSourceElement::cancelPendingErrorEvent() { WTF_LOG(Media, "HTMLSourceElement::cancelPendingErrorEvent - %p", this); - m_errorEventTimer.stop(); + sourceErrorEventSender().cancelEvent(this); } -void HTMLSourceElement::errorEventTimerFired(Timer<HTMLSourceElement>*) +void HTMLSourceElement::dispatchPendingEvent(SourceEventSender* eventSender) { - WTF_LOG(Media, "HTMLSourceElement::errorEventTimerFired - %p", this); + ASSERT_UNUSED(eventSender, eventSender == &sourceErrorEventSender()); + WTF_LOG(Media, "HTMLSourceElement::dispatchPendingEvent - %p", this); dispatchEvent(Event::createCancelable(EventTypeNames::error)); } @@ -121,4 +119,14 @@ bool HTMLSourceElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == srcAttr || HTMLElement::isURLAttribute(attribute); } +void HTMLSourceElement::parseAttribute(const QualifiedName& name, const AtomicString& value) +{ + HTMLElement::parseAttribute(name, value); + if (name == srcsetAttr || name == sizesAttr || name == mediaAttr || name == typeAttr) { + Element* parent = parentElement(); + if (isHTMLPictureElement(parent)) + toHTMLPictureElement(parent)->sourceOrMediaChanged(); + } +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.h index 0002d210706..339c12a99af 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.h @@ -31,33 +31,32 @@ namespace WebCore { +template<typename T> class EventSender; +typedef EventSender<HTMLSourceElement> SourceEventSender; + class HTMLSourceElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLSourceElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLSourceElement); + virtual ~HTMLSourceElement(); - const AtomicString& media() const; const AtomicString& type() const; void setSrc(const String&); - void setMedia(const AtomicString&); void setType(const AtomicString&); void scheduleErrorEvent(); void cancelPendingErrorEvent(); + void dispatchPendingEvent(SourceEventSender*); + private: explicit HTMLSourceElement(Document&); virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - - void errorEventTimerFired(Timer<HTMLSourceElement>*); - - Timer<HTMLSourceElement> m_errorEventTimer; + virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLSourceElement, hasTagName(HTMLNames::sourceTag)); - } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.idl index 4e10349051e..45f76b93977 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSourceElement.idl @@ -26,7 +26,12 @@ [ RuntimeEnabled=Media ] interface HTMLSourceElement : HTMLElement { - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; attribute DOMString type; - attribute DOMString media; + + [Reflect, RuntimeEnabled=Picture] attribute DOMString srcset; + [Reflect, RuntimeEnabled=Picture] attribute DOMString sizes; + [Reflect, RuntimeEnabled=Picture] attribute DOMString media; + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.cpp index 193c659b84d..840377e2aa2 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/html/HTMLSpanElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -38,9 +38,6 @@ HTMLSpanElement::HTMLSpanElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLSpanElement> HTMLSpanElement::create(Document& document) -{ - return adoptRef(new HTMLSpanElement(document)); -} +DEFINE_NODE_FACTORY(HTMLSpanElement) } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.h index ca77b867cfb..69e0e049b2e 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSpanElement.h @@ -32,7 +32,7 @@ namespace WebCore { class HTMLSpanElement : public HTMLElement { public: - static PassRefPtr<HTMLSpanElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLSpanElement); protected: explicit HTMLSpanElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp index c3d7e1c31aa..3076436827d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp @@ -24,7 +24,7 @@ #include "config.h" #include "core/html/HTMLStyleElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/css/MediaList.h" #include "core/css/StyleSheetContents.h" #include "core/dom/ContextFeatures.h" @@ -49,135 +49,48 @@ inline HTMLStyleElement::HTMLStyleElement(Document& document, bool createdByPars , StyleElement(&document, createdByParser) , m_firedLoad(false) , m_loadedSheet(false) - , m_scopedStyleRegistrationState(NotRegistered) { ScriptWrappable::init(this); } HTMLStyleElement::~HTMLStyleElement() { - // During tear-down, willRemove isn't called, so m_scopedStyleRegistrationState may still be RegisteredAsScoped or RegisteredInShadowRoot here. - // Therefore we can't ASSERT(m_scopedStyleRegistrationState == NotRegistered). +#if !ENABLE(OILPAN) StyleElement::clearDocumentData(document(), this); +#endif styleLoadEventSender().cancelEvent(this); } -PassRefPtr<HTMLStyleElement> HTMLStyleElement::create(Document& document, bool createdByParser) +PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& document, bool createdByParser) { - return adoptRef(new HTMLStyleElement(document, createdByParser)); + return adoptRefWillBeNoop(new HTMLStyleElement(document, createdByParser)); } void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (name == titleAttr && m_sheet) { m_sheet->setTitle(value); - } else if (name == scopedAttr && ContextFeatures::styleScopedEnabled(&document())) { - scopedAttributeChanged(!value.isNull()); } else if (name == mediaAttr && inDocument() && document().isActive() && m_sheet) { m_sheet->setMediaQueries(MediaQuerySet::create(value)); - // FIXME: This shold be RecalcStyleDeferred. - document().modifiedStyleSheet(m_sheet.get(), RecalcStyleImmediately); + document().modifiedStyleSheet(m_sheet.get()); } else { HTMLElement::parseAttribute(name, value); } } -void HTMLStyleElement::scopedAttributeChanged(bool scoped) -{ - ASSERT(ContextFeatures::styleScopedEnabled(&document())); - - if (!inDocument()) - return; - - if (scoped) { - if (m_scopedStyleRegistrationState == RegisteredAsScoped) - return; - - // As any <style> in a shadow tree is treated as "scoped", - // need to remove the <style> from its shadow root. - ContainerNode* scopingNode = 0; - if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) { - scopingNode = containingShadowRoot(); - unregisterWithScopingNode(scopingNode); - } - document().styleEngine()->removeStyleSheetCandidateNode(this, scopingNode); - registerWithScopingNode(true); - - document().styleEngine()->addStyleSheetCandidateNode(this, false); - document().modifiedStyleSheet(sheet()); - return; - } - - // If the <style> was scoped, need to remove the <style> from the scoping - // element, i.e. the parent node. - if (m_scopedStyleRegistrationState != RegisteredAsScoped) - return; - - unregisterWithScopingNode(parentNode()); - document().styleEngine()->removeStyleSheetCandidateNode(this, parentNode()); - - // As any <style> in a shadow tree is treated as "scoped", - // need to add the <style> to its shadow root. - if (isInShadowTree()) - registerWithScopingNode(false); - - document().styleEngine()->addStyleSheetCandidateNode(this, false); - // FIXME: currently need to use FullStyleUpdate here. - // Because ShadowTreeStyleSheetCollection doesn't know old scoping node. - // So setNeedsStyleRecalc for old scoping node is not invoked. - document().modifiedStyleSheet(sheet()); -} - void HTMLStyleElement::finishParsingChildren() { StyleElement::finishParsingChildren(this); HTMLElement::finishParsingChildren(); } -void HTMLStyleElement::registerWithScopingNode(bool scoped) -{ - // Note: We cannot rely on the 'scoped' element already being present when this method is invoked. - // Therefore we cannot rely on scoped()! - ASSERT(m_scopedStyleRegistrationState == NotRegistered); - ASSERT(inDocument()); - if (m_scopedStyleRegistrationState != NotRegistered) - return; - - ContainerNode* scope = scoped ? parentNode() : containingShadowRoot(); - if (!scope) - return; - if (!scope->isElementNode() && !scope->isShadowRoot()) { - // DocumentFragment nodes should never be inDocument, - // <style> should not be a child of Document, PI or some such. - ASSERT_NOT_REACHED(); - return; - } - scope->registerScopedHTMLStyleChild(); - m_scopedStyleRegistrationState = scoped ? RegisteredAsScoped : RegisteredInShadowRoot; -} - -void HTMLStyleElement::unregisterWithScopingNode(ContainerNode* scope) -{ - ASSERT(m_scopedStyleRegistrationState != NotRegistered || !ContextFeatures::styleScopedEnabled(&document())); - if (!isRegisteredAsScoped()) - return; - - ASSERT(scope); - if (scope) { - ASSERT(scope->hasScopedHTMLStyleChild()); - scope->unregisterScopedHTMLStyleChild(); - } - - m_scopedStyleRegistrationState = NotRegistered; -} - Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode* insertionPoint) { HTMLElement::insertedInto(insertionPoint); - if (insertionPoint->inDocument()) { - if (m_scopedStyleRegistrationState == NotRegistered && (scoped() || isInShadowTree())) - registerWithScopingNode(scoped()); + if (insertionPoint->inDocument() && isInShadowTree()) { + if (ShadowRoot* scope = containingShadowRoot()) + scope->registerScopedHTMLStyleChild(); } return InsertionShouldCallDidNotifySubtreeInsertions; } @@ -186,23 +99,18 @@ void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) { HTMLElement::removedFrom(insertionPoint); - // In the current implementation, <style scoped> is only registered if the node is in the document. - // That is, because willRemove() is also called if an ancestor is removed from the document. - // Now, if we want to register <style scoped> even if it's not inDocument, - // we'd need to find a way to discern whether that is the case, or whether <style scoped> itself is about to be removed. - ContainerNode* scope = 0; - if (m_scopedStyleRegistrationState != NotRegistered) { - if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) { - scope = containingShadowRoot(); - if (!scope) - scope = insertionPoint->containingShadowRoot(); - } else - scope = parentNode() ? parentNode() : insertionPoint; - unregisterWithScopingNode(scope); - } + if (!insertionPoint->inDocument()) + return; + + ShadowRoot* scopingNode = containingShadowRoot(); + if (!scopingNode) + scopingNode = insertionPoint->containingShadowRoot(); + + if (scopingNode) + scopingNode->unregisterScopedHTMLStyleChild(); - if (insertionPoint->inDocument()) - StyleElement::removedFromDocument(document(), this, scope); + TreeScope* containingScope = containingShadowRoot(); + StyleElement::removedFromDocument(document(), this, scopingNode, containingScope ? *containingScope : insertionPoint->treeScope()); } void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() @@ -226,28 +134,15 @@ const AtomicString& HTMLStyleElement::type() const return getAttribute(typeAttr); } -bool HTMLStyleElement::scoped() const -{ - return fastHasAttribute(scopedAttr) && ContextFeatures::styleScopedEnabled(&document()); -} - -void HTMLStyleElement::setScoped(bool scopedValue) -{ - setBooleanAttribute(scopedAttr, scopedValue); -} - ContainerNode* HTMLStyleElement::scopingNode() { if (!inDocument()) return 0; - if (!isRegisteredAsScoped()) - return &document(); - - if (isRegisteredInShadowRoot()) + if (isInShadowTree()) return containingShadowRoot(); - return parentNode(); + return &document(); } void HTMLStyleElement::dispatchPendingLoadEvents() @@ -270,14 +165,6 @@ void HTMLStyleElement::notifyLoadedSheetAndAllCriticalSubresources(bool errorOcc m_firedLoad = true; } -void HTMLStyleElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLElement::addSubresourceAttributeURLs(urls); - - if (CSSStyleSheet* styleSheet = const_cast<HTMLStyleElement*>(this)->sheet()) - styleSheet->contents()->addSubresourceStyleURLs(urls); -} - bool HTMLStyleElement::disabled() const { if (!m_sheet) @@ -292,4 +179,10 @@ void HTMLStyleElement::setDisabled(bool setDisabled) styleSheet->setDisabled(setDisabled); } +void HTMLStyleElement::trace(Visitor* visitor) +{ + StyleElement::trace(visitor); + HTMLElement::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.h index 3ab95c6c0ee..71da210804c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.h @@ -35,28 +35,14 @@ template<typename T> class EventSender; typedef EventSender<HTMLStyleElement> StyleEventSender; class HTMLStyleElement FINAL : public HTMLElement, private StyleElement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLStyleElement); public: - static PassRefPtr<HTMLStyleElement> create(Document&, bool createdByParser); + static PassRefPtrWillBeRawPtr<HTMLStyleElement> create(Document&, bool createdByParser); virtual ~HTMLStyleElement(); void setType(const AtomicString&); - bool scoped() const; - void setScoped(bool); ContainerNode* scopingNode(); - bool isRegisteredAsScoped() const - { - // Note: We cannot rely on the 'scoped' attribute still being present when this method is invoked. - // Therefore we cannot rely on scoped()! - if (m_scopedStyleRegistrationState == NotRegistered) - return false; - return true; - } - - bool isRegisteredInShadowRoot() const - { - return m_scopedStyleRegistrationState == RegisteredInShadowRoot; - } using StyleElement::sheet; @@ -66,6 +52,8 @@ public: void dispatchPendingEvent(StyleEventSender*); static void dispatchPendingLoadEvents(); + virtual void trace(Visitor*) OVERRIDE; + private: HTMLStyleElement(Document&, bool createdByParser); @@ -74,43 +62,21 @@ private: virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void didNotifySubtreeInsertionsToDocument() OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - - virtual void finishParsingChildren(); - - virtual bool isLoading() const { return StyleElement::isLoading(); } - virtual bool sheetLoaded() { return StyleElement::sheetLoaded(document()); } - virtual void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred); - virtual void startLoadingDynamicSheet() { StyleElement::startLoadingDynamicSheet(document()); } + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; + virtual void finishParsingChildren() OVERRIDE; - virtual const AtomicString& media() const; - virtual const AtomicString& type() const; + virtual bool sheetLoaded() OVERRIDE { return StyleElement::sheetLoaded(document()); } + virtual void notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred) OVERRIDE; + virtual void startLoadingDynamicSheet() OVERRIDE { StyleElement::startLoadingDynamicSheet(document()); } - void scopedAttributeChanged(bool); - void registerWithScopingNode(bool); - void unregisterWithScopingNode(ContainerNode*); + virtual const AtomicString& media() const OVERRIDE; + virtual const AtomicString& type() const OVERRIDE; bool m_firedLoad; bool m_loadedSheet; - - enum ScopedStyleRegistrationState { - NotRegistered, - RegisteredAsScoped, - RegisteredInShadowRoot - }; - ScopedStyleRegistrationState m_scopedStyleRegistrationState; }; -inline bool isHTMLStyleElement(Node* node) -{ - ASSERT(node); - return node->hasTagName(HTMLNames::styleTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLStyleElement, hasTagName(HTMLNames::styleTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.idl index 42a38de99d4..ecc6b2bd57d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLStyleElement.idl @@ -20,7 +20,6 @@ interface HTMLStyleElement : HTMLElement { attribute boolean disabled; - [RuntimeEnabled=StyleScoped] attribute boolean scoped; [Reflect] attribute DOMString media; [Reflect] attribute DOMString type; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp index 7f13462137e..821b37a8e99 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp @@ -21,23 +21,23 @@ #include "config.h" #include "core/html/HTMLSummaryElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/events/KeyboardEvent.h" #include "core/dom/NodeRenderingTraversal.h" #include "core/dom/shadow/ShadowRoot.h" +#include "core/html/HTMLContentElement.h" #include "core/html/HTMLDetailsElement.h" #include "core/html/shadow/DetailsMarkerControl.h" -#include "core/html/shadow/HTMLContentElement.h" #include "core/rendering/RenderBlockFlow.h" namespace WebCore { using namespace HTMLNames; -PassRefPtr<HTMLSummaryElement> HTMLSummaryElement::create(Document& document) +PassRefPtrWillBeRawPtr<HTMLSummaryElement> HTMLSummaryElement::create(Document& document) { - RefPtr<HTMLSummaryElement> summary = adoptRef(new HTMLSummaryElement(document)); + RefPtrWillBeRawPtr<HTMLSummaryElement> summary = adoptRefWillBeNoop(new HTMLSummaryElement(document)); summary->ensureUserAgentShadowRoot(); return summary.release(); } @@ -61,7 +61,7 @@ void HTMLSummaryElement::didAddUserAgentShadowRoot(ShadowRoot& root) HTMLDetailsElement* HTMLSummaryElement::detailsElement() const { Node* parent = NodeRenderingTraversal::parent(this); - if (parent && isHTMLDetailsElement(parent)) + if (isHTMLDetailsElement(parent)) return toHTMLDetailsElement(parent); return 0; } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.h index 45f14630a86..1a05da725ae 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLSummaryElement.h @@ -29,23 +29,21 @@ class HTMLDetailsElement; class HTMLSummaryElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLSummaryElement> create(Document&); + static PassRefPtrWillBeRawPtr<HTMLSummaryElement> create(Document&); bool isMainSummary() const; virtual bool willRespondToMouseClickEvents() OVERRIDE; private: explicit HTMLSummaryElement(Document&); - virtual RenderObject* createRenderer(RenderStyle*); - virtual void defaultEventHandler(Event*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual void defaultEventHandler(Event*) OVERRIDE; virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE; HTMLDetailsElement* detailsElement() const; - bool supportsFocus() const OVERRIDE; + virtual bool supportsFocus() const OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLSummaryElement, hasTagName(HTMLNames::summaryTag)); - } #endif // HTMLSummaryElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.cpp index 0212e3249e4..872845f736f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.cpp @@ -25,8 +25,8 @@ #include "config.h" #include "core/html/HTMLTableCaptionElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" namespace WebCore { @@ -38,17 +38,7 @@ inline HTMLTableCaptionElement::HTMLTableCaptionElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLTableCaptionElement> HTMLTableCaptionElement::create(Document& document) -{ - return adoptRef(new HTMLTableCaptionElement(document)); -} - -bool HTMLTableCaptionElement::isPresentationAttribute(const QualifiedName& name) const -{ - if (name == alignAttr) - return true; - return HTMLElement::isPresentationAttribute(name); -} +DEFINE_NODE_FACTORY(HTMLTableCaptionElement) void HTMLTableCaptionElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.h index 33315acfdb0..ce8b6c11d91 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.h @@ -32,17 +32,14 @@ namespace WebCore { class HTMLTableCaptionElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLTableCaptionElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLTableCaptionElement); private: HTMLTableCaptionElement(Document&); - virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; }; -DEFINE_NODE_TYPE_CASTS(HTMLTableCaptionElement, hasTagName(HTMLNames::captionTag)); - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp index 01b712585fc..2f6d5d5418f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.cpp @@ -25,9 +25,9 @@ #include "config.h" #include "core/html/HTMLTableCellElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/html/HTMLTableElement.h" #include "core/rendering/RenderTableCell.h" @@ -48,10 +48,7 @@ inline HTMLTableCellElement::HTMLTableCellElement(const QualifiedName& tagName, ScriptWrappable::init(this); } -PassRefPtr<HTMLTableCellElement> HTMLTableCellElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLTableCellElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLTableCellElement) int HTMLTableCellElement::colSpan() const { @@ -67,14 +64,12 @@ int HTMLTableCellElement::rowSpan() const int HTMLTableCellElement::cellIndex() const { - int index = 0; - if (!parentElement() || !parentElement()->hasTagName(trTag)) + if (!isHTMLTableRowElement(parentElement())) return -1; - for (const Node * node = previousSibling(); node; node = node->previousSibling()) { - if (node->hasTagName(tdTag) || node->hasTagName(thTag)) - index++; - } + int index = 0; + for (const HTMLTableCellElement* element = Traversal<HTMLTableCellElement>::previousSibling(*this); element; element = Traversal<HTMLTableCellElement>::previousSibling(*element)) + ++index; return index; } @@ -130,14 +125,24 @@ bool HTMLTableCellElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == backgroundAttr || HTMLTablePartElement::isURLAttribute(attribute); } +bool HTMLTableCellElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return (hasLocalName(tdTag) && name == backgroundAttr) || HTMLTablePartElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLTableCellElement::subResourceAttributeName() const +{ + return hasLocalName(tdTag) ? backgroundAttr : HTMLTablePartElement::subResourceAttributeName(); +} + const AtomicString& HTMLTableCellElement::abbr() const { - return getAttribute(abbrAttr); + return fastGetAttribute(abbrAttr); } const AtomicString& HTMLTableCellElement::axis() const { - return getAttribute(axisAttr); + return fastGetAttribute(axisAttr); } void HTMLTableCellElement::setColSpan(int n) @@ -147,7 +152,7 @@ void HTMLTableCellElement::setColSpan(int n) const AtomicString& HTMLTableCellElement::headers() const { - return getAttribute(headersAttr); + return fastGetAttribute(headersAttr); } void HTMLTableCellElement::setRowSpan(int n) @@ -157,14 +162,7 @@ void HTMLTableCellElement::setRowSpan(int n) const AtomicString& HTMLTableCellElement::scope() const { - return getAttribute(scopeAttr); -} - -void HTMLTableCellElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const -{ - HTMLTablePartElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, document().completeURL(getAttribute(backgroundAttr))); + return fastGetAttribute(scopeAttr); } HTMLTableCellElement* HTMLTableCellElement::cellAbove() const diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.h index 8c22cccfb38..55cbd5f4b6b 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableCellElement.h @@ -32,7 +32,7 @@ namespace WebCore { class HTMLTableCellElement FINAL : public HTMLTablePartElement { public: - static PassRefPtr<HTMLTableCellElement> create(const QualifiedName&, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLTableCellElement); int cellIndex() const; @@ -59,16 +59,21 @@ private: virtual const StylePropertySet* additionalPresentationAttributeStyle() OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; - - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; }; -inline bool isHTMLTableCellElement(const Node& node) +inline bool isHTMLTableCellElement(const Element& element) +{ + return element.hasTagName(HTMLNames::tdTag) || element.hasTagName(HTMLNames::thTag); +} + +inline bool isHTMLTableCellElement(const HTMLElement& element) { - return node.hasTagName(HTMLNames::tdTag) || node.hasTagName(HTMLNames::thTag); + return element.hasLocalName(HTMLNames::tdTag) || element.hasLocalName(HTMLNames::thTag); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLTableCellElement); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLTableCellElement); } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.cpp index 19e301d95c0..5094868e388 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.cpp @@ -25,8 +25,8 @@ #include "config.h" #include "core/html/HTMLTableColElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLTableElement.h" #include "core/rendering/RenderTableCol.h" @@ -41,10 +41,7 @@ inline HTMLTableColElement::HTMLTableColElement(const QualifiedName& tagName, Do ScriptWrappable::init(this); } -PassRefPtr<HTMLTableColElement> HTMLTableColElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLTableColElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLTableColElement) bool HTMLTableColElement::isPresentationAttribute(const QualifiedName& name) const { @@ -64,7 +61,10 @@ void HTMLTableColElement::collectStyleForPresentationAttribute(const QualifiedNa void HTMLTableColElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (name == spanAttr) { - m_span = !value.isNull() ? value.toInt() : 1; + int newSpan = value.toInt(); + // If the value of span is not a valid non-negative integer greater than zero, + // set it to 1. + m_span = newSpan ? newSpan : 1; if (renderer() && renderer()->isRenderTableCol()) renderer()->updateFromElement(); } else if (name == widthAttr) { @@ -73,7 +73,7 @@ void HTMLTableColElement::parseAttribute(const QualifiedName& name, const Atomic RenderTableCol* col = toRenderTableCol(renderer()); int newWidth = width().toInt(); if (newWidth != col->width()) - col->setNeedsLayoutAndPrefWidthsRecalc(); + col->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } } } else diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.h index ecd3f73f241..72e859673ec 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableColElement.h @@ -32,7 +32,7 @@ namespace WebCore { class HTMLTableColElement FINAL : public HTMLTablePartElement { public: - static PassRefPtr<HTMLTableColElement> create(const QualifiedName& tagName, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLTableColElement); int span() const { return m_span; } void setSpan(int); @@ -50,12 +50,17 @@ private: int m_span; }; -inline bool isHTMLTableColElement(const Node& node) +inline bool isHTMLTableColElement(const Element& element) { - return node.hasTagName(HTMLNames::colTag) || node.hasTagName(HTMLNames::colgroupTag); + return element.hasTagName(HTMLNames::colTag) || element.hasTagName(HTMLNames::colgroupTag); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLTableColElement); +inline bool isHTMLTableColElement(const HTMLElement& element) +{ + return element.hasLocalName(HTMLNames::colTag) || element.hasLocalName(HTMLNames::colgroupTag); +} + +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLTableColElement); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.cpp index c963c1f65a0..cebf9c3d6ea 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.cpp @@ -25,29 +25,33 @@ #include "config.h" #include "core/html/HTMLTableElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSValuePool.h" #include "core/css/StylePropertySet.h" #include "core/dom/Attribute.h" +#include "core/dom/ElementTraversal.h" #include "core/dom/ExceptionCode.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLTableCaptionElement.h" +#include "core/html/HTMLTableCellElement.h" #include "core/html/HTMLTableRowElement.h" #include "core/html/HTMLTableRowsCollection.h" #include "core/html/HTMLTableSectionElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/rendering/RenderTable.h" +#include "platform/weborigin/Referrer.h" #include "wtf/StdLibExtras.h" namespace WebCore { using namespace HTMLNames; -HTMLTableElement::HTMLTableElement(Document& document) +inline HTMLTableElement::HTMLTableElement(Document& document) : HTMLElement(tableTag, document) , m_borderAttr(false) , m_borderColorAttr(false) @@ -58,21 +62,14 @@ HTMLTableElement::HTMLTableElement(Document& document) ScriptWrappable::init(this); } -PassRefPtr<HTMLTableElement> HTMLTableElement::create(Document& document) -{ - return adoptRef(new HTMLTableElement(document)); -} +DEFINE_NODE_FACTORY(HTMLTableElement) HTMLTableCaptionElement* HTMLTableElement::caption() const { - for (Node* child = firstChild(); child; child = child->nextSibling()) { - if (child->hasTagName(captionTag)) - return toHTMLTableCaptionElement(child); - } - return 0; + return Traversal<HTMLTableCaptionElement>::firstChild(*this); } -void HTMLTableElement::setCaption(PassRefPtr<HTMLTableCaptionElement> newCaption, ExceptionState& exceptionState) +void HTMLTableElement::setCaption(PassRefPtrWillBeRawPtr<HTMLTableCaptionElement> newCaption, ExceptionState& exceptionState) { deleteCaption(); insertBefore(newCaption, firstChild(), exceptionState); @@ -80,51 +77,53 @@ void HTMLTableElement::setCaption(PassRefPtr<HTMLTableCaptionElement> newCaption HTMLTableSectionElement* HTMLTableElement::tHead() const { - for (Node* child = firstChild(); child; child = child->nextSibling()) { + for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) { if (child->hasTagName(theadTag)) return toHTMLTableSectionElement(child); } return 0; } -void HTMLTableElement::setTHead(PassRefPtr<HTMLTableSectionElement> newHead, ExceptionState& exceptionState) +void HTMLTableElement::setTHead(PassRefPtrWillBeRawPtr<HTMLTableSectionElement> newHead, ExceptionState& exceptionState) { deleteTHead(); - Node* child; - for (child = firstChild(); child; child = child->nextSibling()) - if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag)) + Element* child; + for (child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) { + if (!child->hasTagName(captionTag) && !child->hasTagName(colgroupTag)) break; + } insertBefore(newHead, child, exceptionState); } HTMLTableSectionElement* HTMLTableElement::tFoot() const { - for (Node* child = firstChild(); child; child = child->nextSibling()) { + for (Element* child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) { if (child->hasTagName(tfootTag)) return toHTMLTableSectionElement(child); } return 0; } -void HTMLTableElement::setTFoot(PassRefPtr<HTMLTableSectionElement> newFoot, ExceptionState& exceptionState) +void HTMLTableElement::setTFoot(PassRefPtrWillBeRawPtr<HTMLTableSectionElement> newFoot, ExceptionState& exceptionState) { deleteTFoot(); - Node* child; - for (child = firstChild(); child; child = child->nextSibling()) - if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag)) + Element* child; + for (child = ElementTraversal::firstWithin(*this); child; child = ElementTraversal::nextSibling(*child)) { + if (!child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag)) break; + } insertBefore(newFoot, child, exceptionState); } -PassRefPtr<HTMLElement> HTMLTableElement::createTHead() +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTHead() { if (HTMLTableSectionElement* existingHead = tHead()) return existingHead; - RefPtr<HTMLTableSectionElement> head = HTMLTableSectionElement::create(theadTag, document()); + RefPtrWillBeRawPtr<HTMLTableSectionElement> head = HTMLTableSectionElement::create(theadTag, document()); setTHead(head, IGNORE_EXCEPTION); return head.release(); } @@ -134,11 +133,11 @@ void HTMLTableElement::deleteTHead() removeChild(tHead(), IGNORE_EXCEPTION); } -PassRefPtr<HTMLElement> HTMLTableElement::createTFoot() +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTFoot() { if (HTMLTableSectionElement* existingFoot = tFoot()) return existingFoot; - RefPtr<HTMLTableSectionElement> foot = HTMLTableSectionElement::create(tfootTag, document()); + RefPtrWillBeRawPtr<HTMLTableSectionElement> foot = HTMLTableSectionElement::create(tfootTag, document()); setTFoot(foot, IGNORE_EXCEPTION); return foot.release(); } @@ -148,20 +147,20 @@ void HTMLTableElement::deleteTFoot() removeChild(tFoot(), IGNORE_EXCEPTION); } -PassRefPtr<HTMLElement> HTMLTableElement::createTBody() +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createTBody() { - RefPtr<HTMLTableSectionElement> body = HTMLTableSectionElement::create(tbodyTag, document()); + RefPtrWillBeRawPtr<HTMLTableSectionElement> body = HTMLTableSectionElement::create(tbodyTag, document()); Node* referenceElement = lastBody() ? lastBody()->nextSibling() : 0; insertBefore(body, referenceElement); return body.release(); } -PassRefPtr<HTMLElement> HTMLTableElement::createCaption() +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::createCaption() { if (HTMLTableCaptionElement* existingCaption = caption()) return existingCaption; - RefPtr<HTMLTableCaptionElement> caption = HTMLTableCaptionElement::create(document()); + RefPtrWillBeRawPtr<HTMLTableCaptionElement> caption = HTMLTableCaptionElement::create(document()); setCaption(caption, IGNORE_EXCEPTION); return caption.release(); } @@ -180,26 +179,32 @@ HTMLTableSectionElement* HTMLTableElement::lastBody() const return 0; } -PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::insertRow(ExceptionState& exceptionState) +{ + // The default 'index' argument value is -1. + return insertRow(-1, exceptionState); +} + +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionState& exceptionState) { if (index < -1) { exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1."); - return 0; + return nullptr; } - RefPtr<Node> protectFromMutationEvents(this); + RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this); - RefPtr<HTMLTableRowElement> lastRow = 0; - RefPtr<HTMLTableRowElement> row = 0; + RefPtrWillBeRawPtr<HTMLTableRowElement> lastRow = nullptr; + RefPtrWillBeRawPtr<HTMLTableRowElement> row = nullptr; if (index == -1) - lastRow = HTMLTableRowsCollection::lastRow(this); + lastRow = HTMLTableRowsCollection::lastRow(*this); else { for (int i = 0; i <= index; ++i) { - row = HTMLTableRowsCollection::rowAfter(this, lastRow.get()); + row = HTMLTableRowsCollection::rowAfter(*this, lastRow.get()); if (!row) { if (i != index) { exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is greater than the number of rows in the table (" + String::number(i) + ")."); - return 0; + return nullptr; } break; } @@ -207,21 +212,21 @@ PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionState& e } } - RefPtr<ContainerNode> parent; + RefPtrWillBeRawPtr<ContainerNode> parent; if (lastRow) parent = row ? row->parentNode() : lastRow->parentNode(); else { parent = lastBody(); if (!parent) { - RefPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document()); - RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); + RefPtrWillBeRawPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document()); + RefPtrWillBeRawPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); newBody->appendChild(newRow, exceptionState); appendChild(newBody.release(), exceptionState); return newRow.release(); } } - RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); + RefPtrWillBeRawPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); parent->insertBefore(newRow, row.get(), exceptionState); return newRow.release(); } @@ -236,10 +241,10 @@ void HTMLTableElement::deleteRow(int index, ExceptionState& exceptionState) HTMLTableRowElement* row = 0; int i = 0; if (index == -1) - row = HTMLTableRowsCollection::lastRow(this); + row = HTMLTableRowsCollection::lastRow(*this); else { for (i = 0; i <= index; ++i) { - row = HTMLTableRowsCollection::rowAfter(this, row); + row = HTMLTableRowsCollection::rowAfter(*this, row); if (!row) break; } @@ -251,29 +256,16 @@ void HTMLTableElement::deleteRow(int index, ExceptionState& exceptionState) row->remove(exceptionState); } -static inline bool isTableCellAncestor(Node* n) -{ - return n->hasTagName(theadTag) || n->hasTagName(tbodyTag) || - n->hasTagName(tfootTag) || n->hasTagName(trTag) || - n->hasTagName(thTag); -} - -static bool setTableCellsChanged(Node* n) +void HTMLTableElement::setNeedsTableStyleRecalc() const { - ASSERT(n); - bool cellChanged = false; - - if (n->hasTagName(tdTag)) - cellChanged = true; - else if (isTableCellAncestor(n)) { - for (Node* child = n->firstChild(); child; child = child->nextSibling()) - cellChanged |= setTableCellsChanged(child); + Element* element = ElementTraversal::next(*this, this); + while (element) { + element->setNeedsStyleRecalc(LocalStyleChange); + if (isHTMLTableCellElement(*element)) + element = ElementTraversal::nextSkippingChildren(*element, this); + else + element = ElementTraversal::next(*element, this); } - - if (cellChanged) - n->setNeedsStyleRecalc(); - - return cellChanged; } static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& borderTop, bool& borderRight, bool& borderBottom, bool& borderLeft) @@ -317,8 +309,11 @@ void HTMLTableElement::collectStyleForPresentationAttribute(const QualifiedName& addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value); else if (name == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(value); - if (!url.isEmpty()) - style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document().completeURL(url).string()))); + if (!url.isEmpty()) { + RefPtrWillBeRawPtr<CSSImageValue> imageValue = CSSImageValue::create(url, document().completeURL(url)); + imageValue->setReferrer(Referrer(document().outgoingReferrer(), document().referrerPolicy())); + style->setProperty(CSSProperty(CSSPropertyBackgroundImage, imageValue.release())); + } } else if (name == valignAttr) { if (!value.isEmpty()) addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, value); @@ -326,9 +321,11 @@ void HTMLTableElement::collectStyleForPresentationAttribute(const QualifiedName& if (!value.isEmpty()) addHTMLLengthToStyle(style, CSSPropertyBorderSpacing, value); } else if (name == vspaceAttr) { + UseCounter::count(document(), UseCounter::HTMLTableElementVspace); addHTMLLengthToStyle(style, CSSPropertyMarginTop, value); addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value); } else if (name == hspaceAttr) { + UseCounter::count(document(), UseCounter::HTMLTableElementHspace); addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value); addHTMLLengthToStyle(style, CSSPropertyMarginRight, value); } else if (name == alignAttr) { @@ -406,18 +403,14 @@ void HTMLTableElement::parseAttribute(const QualifiedName& name, const AtomicStr HTMLElement::parseAttribute(name, value); if (bordersBefore != cellBorders() || oldPadding != m_padding) { - m_sharedCellStyle = 0; - bool cellChanged = false; - for (Node* child = firstChild(); child; child = child->nextSibling()) - cellChanged |= setTableCellsChanged(child); - if (cellChanged) - setNeedsStyleRecalc(); + m_sharedCellStyle = nullptr; + setNeedsTableStyleRecalc(); } } static PassRefPtr<StylePropertySet> createBorderStyle(CSSValueID value) { - RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); + RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); style->setProperty(CSSPropertyBorderTopStyle, value); style->setProperty(CSSPropertyBorderBottomStyle, value); style->setProperty(CSSPropertyBorderLeftStyle, value); @@ -471,9 +464,9 @@ HTMLTableElement::CellBorders HTMLTableElement::cellBorders() const return NoBorders; } -PassRefPtr<StylePropertySet> HTMLTableElement::createSharedCellStyle() +PassRefPtrWillBeRawPtr<StylePropertySet> HTMLTableElement::createSharedCellStyle() { - RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); + RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); switch (cellBorders()) { case SolidBordersColsOnly: @@ -518,9 +511,9 @@ const StylePropertySet* HTMLTableElement::additionalCellStyle() return m_sharedCellStyle.get(); } -static PassRefPtr<StylePropertySet> createGroupBorderStyle(int rows) +static PassRefPtrWillBeRawPtr<StylePropertySet> createGroupBorderStyle(int rows) { - RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); + RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); if (rows) { style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin); style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin); @@ -553,12 +546,22 @@ bool HTMLTableElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute); } -PassRefPtr<HTMLCollection> HTMLTableElement::rows() +bool HTMLTableElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == backgroundAttr || HTMLElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLTableElement::subResourceAttributeName() const +{ + return backgroundAttr; +} + +PassRefPtrWillBeRawPtr<HTMLTableRowsCollection> HTMLTableElement::rows() { - return ensureCachedHTMLCollection(TableRows); + return toHTMLTableRowsCollection(ensureCachedHTMLCollection(TableRows).get()); } -PassRefPtr<HTMLCollection> HTMLTableElement::tBodies() +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLTableElement::tBodies() { return ensureCachedHTMLCollection(TableTBodies); } @@ -573,11 +576,10 @@ const AtomicString& HTMLTableElement::summary() const return getAttribute(summaryAttr); } -void HTMLTableElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const +void HTMLTableElement::trace(Visitor* visitor) { - HTMLElement::addSubresourceAttributeURLs(urls); - - addSubresourceURL(urls, document().completeURL(getAttribute(backgroundAttr))); + visitor->trace(m_sharedCellStyle); + HTMLElement::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.h index d25a23c59bf..c8b2dbcf35a 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.h @@ -38,29 +38,30 @@ class HTMLTableSectionElement; class HTMLTableElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLTableElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLTableElement); HTMLTableCaptionElement* caption() const; - void setCaption(PassRefPtr<HTMLTableCaptionElement>, ExceptionState&); + void setCaption(PassRefPtrWillBeRawPtr<HTMLTableCaptionElement>, ExceptionState&); HTMLTableSectionElement* tHead() const; - void setTHead(PassRefPtr<HTMLTableSectionElement>, ExceptionState&); + void setTHead(PassRefPtrWillBeRawPtr<HTMLTableSectionElement>, ExceptionState&); HTMLTableSectionElement* tFoot() const; - void setTFoot(PassRefPtr<HTMLTableSectionElement>, ExceptionState&); + void setTFoot(PassRefPtrWillBeRawPtr<HTMLTableSectionElement>, ExceptionState&); - PassRefPtr<HTMLElement> createTHead(); + PassRefPtrWillBeRawPtr<HTMLElement> createTHead(); void deleteTHead(); - PassRefPtr<HTMLElement> createTFoot(); + PassRefPtrWillBeRawPtr<HTMLElement> createTFoot(); void deleteTFoot(); - PassRefPtr<HTMLElement> createTBody(); - PassRefPtr<HTMLElement> createCaption(); + PassRefPtrWillBeRawPtr<HTMLElement> createTBody(); + PassRefPtrWillBeRawPtr<HTMLElement> createCaption(); void deleteCaption(); - PassRefPtr<HTMLElement> insertRow(int index, ExceptionState&); + PassRefPtrWillBeRawPtr<HTMLElement> insertRow(ExceptionState&); + PassRefPtrWillBeRawPtr<HTMLElement> insertRow(int index, ExceptionState&); void deleteRow(int index, ExceptionState&); - PassRefPtr<HTMLCollection> rows(); - PassRefPtr<HTMLCollection> tBodies(); + PassRefPtrWillBeRawPtr<HTMLTableRowsCollection> rows(); + PassRefPtrWillBeRawPtr<HTMLCollection> tBodies(); const AtomicString& rules() const; const AtomicString& summary() const; @@ -68,6 +69,8 @@ public: const StylePropertySet* additionalCellStyle(); const StylePropertySet* additionalGroupStyle(bool rows); + virtual void trace(Visitor*) OVERRIDE; + private: explicit HTMLTableElement(Document&); @@ -75,21 +78,23 @@ private: virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; // Used to obtain either a solid or outset border decl and to deal with the frame and rules attributes. virtual const StylePropertySet* additionalPresentationAttributeStyle() OVERRIDE; - virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; - enum TableRules { UnsetRules, NoneRules, GroupsRules, RowsRules, ColsRules, AllRules }; enum CellBorders { NoBorders, SolidBorders, InsetBorders, SolidBordersColsOnly, SolidBordersRowsOnly }; CellBorders cellBorders() const; - PassRefPtr<StylePropertySet> createSharedCellStyle(); + PassRefPtrWillBeRawPtr<StylePropertySet> createSharedCellStyle(); HTMLTableSectionElement* lastBody() const; + void setNeedsTableStyleRecalc() const; + bool m_borderAttr; // Sets a precise border width and creates an outset border for the table and for its cells. bool m_borderColorAttr; // Overrides the outset border and makes it solid for the table and cells instead. bool m_frameAttr; // Implies a thin border width if no border is set and then a certain set of solid/hidden borders based off the value. @@ -97,21 +102,9 @@ private: // are present, to none otherwise). unsigned short m_padding; - RefPtr<StylePropertySet> m_sharedCellStyle; + RefPtrWillBeMember<StylePropertySet> m_sharedCellStyle; }; -inline bool isHTMLTableElement(const Node* node) -{ - return node->hasTagName(HTMLNames::tableTag); -} - -inline bool isHTMLTableElement(const Element* element) -{ - return element->hasTagName(HTMLNames::tableTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLTableElement, hasTagName(HTMLNames::tableTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.idl index 4cd6d6f573b..3072583711c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableElement.idl @@ -45,6 +45,6 @@ interface HTMLTableElement : HTMLElement { HTMLElement createCaption(); void deleteCaption(); - [RaisesException] HTMLElement insertRow([Default=Undefined] optional long index); + [RaisesException] HTMLElement insertRow(optional long index); [RaisesException] void deleteRow([Default=Undefined] optional long index); }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp index 79b2b6c1138..4483de09ecc 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp @@ -25,15 +25,16 @@ #include "config.h" #include "core/html/HTMLTablePartElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/CSSImageValue.h" #include "core/css/StylePropertySet.h" #include "core/dom/Document.h" #include "core/dom/NodeRenderingTraversal.h" #include "core/html/HTMLTableElement.h" #include "core/html/parser/HTMLParserIdioms.h" +#include "platform/weborigin/Referrer.h" namespace WebCore { @@ -52,8 +53,11 @@ void HTMLTablePartElement::collectStyleForPresentationAttribute(const QualifiedN addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value); else if (name == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(value); - if (!url.isEmpty()) - style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document().completeURL(url).string()))); + if (!url.isEmpty()) { + RefPtrWillBeRawPtr<CSSImageValue> imageValue = CSSImageValue::create(url, document().completeURL(url)); + imageValue->setReferrer(Referrer(document().outgoingReferrer(), document().referrerPolicy())); + style->setProperty(CSSProperty(CSSPropertyBackgroundImage, imageValue.release())); + } } else if (name == valignAttr) { if (equalIgnoringCase(value, "top")) addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, CSSValueTop); @@ -86,7 +90,7 @@ void HTMLTablePartElement::collectStyleForPresentationAttribute(const QualifiedN HTMLTableElement* HTMLTablePartElement::findParentTable() const { ContainerNode* parent = NodeRenderingTraversal::parent(this); - while (parent && !isHTMLTableElement(parent)) + while (parent && !isHTMLTableElement(*parent)) parent = NodeRenderingTraversal::parent(parent); return toHTMLTableElement(parent); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp index b643924cf72..2aadf0ba3e3 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.cpp @@ -25,8 +25,9 @@ #include "config.h" #include "core/html/HTMLTableRowElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/HTMLNames.h" +#include "core/dom/ElementTraversal.h" #include "core/dom/ExceptionCode.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLTableCellElement.h" @@ -37,15 +38,22 @@ namespace WebCore { using namespace HTMLNames; -HTMLTableRowElement::HTMLTableRowElement(Document& document) +inline HTMLTableRowElement::HTMLTableRowElement(Document& document) : HTMLTablePartElement(trTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLTableRowElement> HTMLTableRowElement::create(Document& document) +DEFINE_NODE_FACTORY(HTMLTableRowElement) + +bool HTMLTableRowElement::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == backgroundAttr || HTMLTablePartElement::hasLegalLinkAttribute(name); +} + +const QualifiedName& HTMLTableRowElement::subResourceAttributeName() const { - return adoptRef(new HTMLTableRowElement(document)); + return backgroundAttr; } int HTMLTableRowElement::rowIndex() const @@ -54,7 +62,7 @@ int HTMLTableRowElement::rowIndex() const if (!table) return -1; table = table->parentNode(); - if (!table || !isHTMLTableElement(table)) + if (!isHTMLTableElement(table)) return -1; // To match Firefox, the row indices work like this: @@ -65,32 +73,29 @@ int HTMLTableRowElement::rowIndex() const int rIndex = 0; if (HTMLTableSectionElement* head = toHTMLTableElement(table)->tHead()) { - for (Node *row = head->firstChild(); row; row = row->nextSibling()) { + for (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*head); row; row = Traversal<HTMLTableRowElement>::nextSibling(*row)) { if (row == this) return rIndex; - if (row->hasTagName(trTag)) - ++rIndex; + ++rIndex; } } - for (Node *node = table->firstChild(); node; node = node->nextSibling()) { - if (node->hasTagName(tbodyTag)) { - HTMLTableSectionElement* section = toHTMLTableSectionElement(node); - for (Node* row = section->firstChild(); row; row = row->nextSibling()) { + for (Element* child = ElementTraversal::firstWithin(*table); child; child = ElementTraversal::nextSibling(*child)) { + if (child->hasTagName(tbodyTag)) { + HTMLTableSectionElement* section = toHTMLTableSectionElement(child); + for (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*section); row; row = Traversal<HTMLTableRowElement>::nextSibling(*row)) { if (row == this) return rIndex; - if (row->hasTagName(trTag)) - ++rIndex; + ++rIndex; } } } if (HTMLTableSectionElement* foot = toHTMLTableElement(table)->tFoot()) { - for (Node *row = foot->firstChild(); row; row = row->nextSibling()) { + for (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*foot); row; row = Traversal<HTMLTableRowElement>::nextSibling(*row)) { if (row == this) return rIndex; - if (row->hasTagName(trTag)) - ++rIndex; + ++rIndex; } } @@ -101,55 +106,54 @@ int HTMLTableRowElement::rowIndex() const int HTMLTableRowElement::sectionRowIndex() const { int rIndex = 0; - const Node *n = this; + const Node* n = this; do { n = n->previousSibling(); - if (n && n->hasTagName(trTag)) - rIndex++; - } - while (n); + if (n && isHTMLTableRowElement(*n)) + ++rIndex; + } while (n); return rIndex; } -PassRefPtr<HTMLElement> HTMLTableRowElement::insertCell(int index, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableRowElement::insertCell(ExceptionState& exceptionState) +{ + // The default 'index' argument value is -1. + return insertCell(-1, exceptionState); +} + +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableRowElement::insertCell(int index, ExceptionState& exceptionState) { - RefPtr<HTMLCollection> children = cells(); + RefPtrWillBeRawPtr<HTMLCollection> children = cells(); int numCells = children ? children->length() : 0; if (index < -1 || index > numCells) { exceptionState.throwDOMException(IndexSizeError, "The value provided (" + String::number(index) + ") is outside the range [-1, " + String::number(numCells) + "]."); - return 0; + return nullptr; } - RefPtr<HTMLTableCellElement> cell = HTMLTableCellElement::create(tdTag, document()); - if (index < 0 || index >= numCells) + RefPtrWillBeRawPtr<HTMLTableCellElement> cell = HTMLTableCellElement::create(tdTag, document()); + if (numCells == index || index == -1) appendChild(cell, exceptionState); - else { - Node* n; - if (index < 1) - n = firstChild(); - else - n = children->item(index); - insertBefore(cell, n, exceptionState); - } + else + insertBefore(cell, children->item(index), exceptionState); return cell.release(); } void HTMLTableRowElement::deleteCell(int index, ExceptionState& exceptionState) { - RefPtr<HTMLCollection> children = cells(); + RefPtrWillBeRawPtr<HTMLCollection> children = cells(); int numCells = children ? children->length() : 0; if (index == -1) index = numCells-1; if (index >= 0 && index < numCells) { - RefPtr<Node> cell = children->item(index); + RefPtrWillBeRawPtr<Element> cell = children->item(index); HTMLElement::removeChild(cell.get(), exceptionState); } else { exceptionState.throwDOMException(IndexSizeError, "The value provided (" + String::number(index) + ") is outside the range [0, " + String::number(numCells) + ")."); } } -PassRefPtr<HTMLCollection> HTMLTableRowElement::cells() +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLTableRowElement::cells() { return ensureCachedHTMLCollection(TRCells); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.h index 1fe3867218b..539856ef5d5 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.h @@ -34,27 +34,24 @@ class ExceptionState; class HTMLTableRowElement FINAL : public HTMLTablePartElement { public: - static PassRefPtr<HTMLTableRowElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLTableRowElement); int rowIndex() const; int sectionRowIndex() const; - PassRefPtr<HTMLElement> insertCell(int index, ExceptionState&); + PassRefPtrWillBeRawPtr<HTMLElement> insertCell(ExceptionState&); + PassRefPtrWillBeRawPtr<HTMLElement> insertCell(int index, ExceptionState&); void deleteCell(int index, ExceptionState&); - PassRefPtr<HTMLCollection> cells(); + PassRefPtrWillBeRawPtr<HTMLCollection> cells(); private: explicit HTMLTableRowElement(Document&); -}; - -inline bool isHTMLTableRowElement(const Node* node) -{ - return node->hasTagName(HTMLNames::trTag); -} -DEFINE_NODE_TYPE_CASTS(HTMLTableRowElement, hasTagName(HTMLNames::trTag)); + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; +}; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.idl index aa7b9cae5bd..e38f999ef53 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowElement.idl @@ -27,6 +27,6 @@ interface HTMLTableRowElement : HTMLElement { [Reflect=char] attribute DOMString ch; [Reflect=charoff] attribute DOMString chOff; [Reflect] attribute DOMString vAlign; - [RaisesException] HTMLElement insertCell([Default=Undefined] optional long index); + [RaisesException] HTMLElement insertCell(optional long index); [RaisesException] void deleteCell([Default=Undefined] optional long index); }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp index 3037aff1c61..dbf5e04e827 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.cpp @@ -29,7 +29,8 @@ #include "config.h" #include "core/html/HTMLTableRowsCollection.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/dom/ElementTraversal.h" #include "core/html/HTMLTableElement.h" #include "core/html/HTMLTableRowElement.h" @@ -52,96 +53,81 @@ static bool isInFoot(Element* row) return row->parentNode() && toElement(row->parentNode())->hasLocalName(tfootTag); } -HTMLTableRowElement* HTMLTableRowsCollection::rowAfter(HTMLTableElement* table, HTMLTableRowElement* previous) +HTMLTableRowElement* HTMLTableRowsCollection::rowAfter(HTMLTableElement& table, HTMLTableRowElement* previous) { - Node* child = 0; - // Start by looking for the next row in this section. // Continue only if there is none. if (previous && previous->parentNode() != table) { - for (child = previous->nextSibling(); child; child = child->nextSibling()) { - if (isHTMLTableRowElement(child)) - return toHTMLTableRowElement(child); - } + if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::nextSibling(*previous)) + return row; } // If still looking at head sections, find the first row in the next head section. + HTMLElement* child = 0; if (!previous) - child = table->firstChild(); + child = Traversal<HTMLElement>::firstChild(table); else if (isInHead(previous)) - child = previous->parentNode()->nextSibling(); - for (; child; child = child->nextSibling()) { - if (child->hasTagName(theadTag)) { - for (Node* grandchild = child->firstChild(); grandchild; grandchild = grandchild->nextSibling()) { - if (isHTMLTableRowElement(grandchild)) - return toHTMLTableRowElement(grandchild); - } + child = Traversal<HTMLElement>::nextSibling(*previous->parentNode()); + for (; child; child = Traversal<HTMLElement>::nextSibling(*child)) { + if (child->hasLocalName(theadTag)) { + if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*child)) + return row; } } // If still looking at top level and bodies, find the next row in top level or the first in the next body section. if (!previous || isInHead(previous)) - child = table->firstChild(); + child = Traversal<HTMLElement>::firstChild(table); else if (previous->parentNode() == table) - child = previous->nextSibling(); + child = Traversal<HTMLElement>::nextSibling(*previous); else if (isInBody(previous)) - child = previous->parentNode()->nextSibling(); - for (; child; child = child->nextSibling()) { + child = Traversal<HTMLElement>::nextSibling(*previous->parentNode()); + for (; child; child = Traversal<HTMLElement>::nextSibling(*child)) { if (isHTMLTableRowElement(child)) return toHTMLTableRowElement(child); - if (child->hasTagName(tbodyTag)) { - for (Node* grandchild = child->firstChild(); grandchild; grandchild = grandchild->nextSibling()) { - if (isHTMLTableRowElement(grandchild)) - return toHTMLTableRowElement(grandchild); - } + if (child->hasLocalName(tbodyTag)) { + if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*child)) + return row; } } // Find the first row in the next foot section. if (!previous || !isInFoot(previous)) - child = table->firstChild(); + child = Traversal<HTMLElement>::firstChild(table); else - child = previous->parentNode()->nextSibling(); - for (; child; child = child->nextSibling()) { - if (child->hasTagName(tfootTag)) { - for (Node* grandchild = child->firstChild(); grandchild; grandchild = grandchild->nextSibling()) { - if (isHTMLTableRowElement(grandchild)) - return toHTMLTableRowElement(grandchild); - } + child = Traversal<HTMLElement>::nextSibling(*previous->parentNode()); + for (; child; child = Traversal<HTMLElement>::nextSibling(*child)) { + if (child->hasLocalName(tfootTag)) { + if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*child)) + return row; } } return 0; } -HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement* table) +HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement& table) { - for (Node* child = table->lastChild(); child; child = child->previousSibling()) { - if (child->hasTagName(tfootTag)) { - for (Node* grandchild = child->lastChild(); grandchild; grandchild = grandchild->previousSibling()) { - if (isHTMLTableRowElement(grandchild)) - return toHTMLTableRowElement(grandchild); - } + for (HTMLElement* child = Traversal<HTMLElement>::lastChild(table); child; child = Traversal<HTMLElement>::previousSibling(*child)) { + if (child->hasLocalName(tfootTag)) { + if (HTMLTableRowElement* lastRow = Traversal<HTMLTableRowElement>::lastChild(*child)) + return lastRow; } } - for (Node* child = table->lastChild(); child; child = child->previousSibling()) { + for (HTMLElement* child = Traversal<HTMLElement>::lastChild(table); child; child = Traversal<HTMLElement>::previousSibling(*child)) { if (isHTMLTableRowElement(child)) return toHTMLTableRowElement(child); - if (child->hasTagName(tbodyTag)) { - for (Node* grandchild = child->lastChild(); grandchild; grandchild = grandchild->previousSibling()) { - if (isHTMLTableRowElement(grandchild)) - return toHTMLTableRowElement(grandchild); - } + if (child->hasLocalName(tbodyTag)) { + if (HTMLTableRowElement* lastRow = Traversal<HTMLTableRowElement>::lastChild(*child)) + return lastRow; } } - for (Node* child = table->lastChild(); child; child = child->previousSibling()) { - if (child->hasTagName(theadTag)) { - for (Node* grandchild = child->lastChild(); grandchild; grandchild = grandchild->previousSibling()) { - if (isHTMLTableRowElement(grandchild)) - return toHTMLTableRowElement(grandchild); - } + for (HTMLElement* child = Traversal<HTMLElement>::lastChild(table); child; child = Traversal<HTMLElement>::previousSibling(*child)) { + if (child->hasLocalName(theadTag)) { + if (HTMLTableRowElement* lastRow = Traversal<HTMLTableRowElement>::lastChild(*child)) + return lastRow; } } @@ -151,20 +137,20 @@ HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement* table) // Must call get() on the table in case that argument is compiled before dereferencing the // table to get at the collection cache. Order of argument evaluation is undefined and can // differ between compilers. -HTMLTableRowsCollection::HTMLTableRowsCollection(Node* table) +HTMLTableRowsCollection::HTMLTableRowsCollection(ContainerNode& table) : HTMLCollection(table, TableRows, OverridesItemAfter) { ASSERT(isHTMLTableElement(table)); } -PassRefPtr<HTMLTableRowsCollection> HTMLTableRowsCollection::create(Node* table, CollectionType) +PassRefPtrWillBeRawPtr<HTMLTableRowsCollection> HTMLTableRowsCollection::create(ContainerNode& table, CollectionType type) { - return adoptRef(new HTMLTableRowsCollection(table)); + ASSERT_UNUSED(type, type == TableRows); + return adoptRefWillBeNoop(new HTMLTableRowsCollection(table)); } -Element* HTMLTableRowsCollection::virtualItemAfter(unsigned& offsetInArray, Element* previous) const +Element* HTMLTableRowsCollection::virtualItemAfter(Element* previous) const { - ASSERT_UNUSED(offsetInArray, !offsetInArray); return rowAfter(toHTMLTableElement(ownerNode()), toHTMLTableRowElement(previous)); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.h index d643d430de4..653328e7305 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableRowsCollection.h @@ -38,17 +38,19 @@ class HTMLTableRowElement; class HTMLTableRowsCollection FINAL : public HTMLCollection { public: - static PassRefPtr<HTMLTableRowsCollection> create(Node*, CollectionType); + static PassRefPtrWillBeRawPtr<HTMLTableRowsCollection> create(ContainerNode&, CollectionType); - static HTMLTableRowElement* rowAfter(HTMLTableElement*, HTMLTableRowElement*); - static HTMLTableRowElement* lastRow(HTMLTableElement*); + static HTMLTableRowElement* rowAfter(HTMLTableElement&, HTMLTableRowElement*); + static HTMLTableRowElement* lastRow(HTMLTableElement&); private: - explicit HTMLTableRowsCollection(Node*); + explicit HTMLTableRowsCollection(ContainerNode&); - virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE; + virtual Element* virtualItemAfter(Element*) const OVERRIDE; }; +DEFINE_TYPE_CASTS(HTMLTableRowsCollection, LiveNodeListBase, collection, collection->type() == TableRows, collection.type() == TableRows); + } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.cpp index 01ec777a27f..e4b42660287 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.cpp @@ -25,8 +25,9 @@ #include "config.h" #include "core/html/HTMLTableSectionElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/HTMLNames.h" +#include "core/dom/ElementTraversal.h" #include "core/dom/ExceptionCode.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLTableElement.h" @@ -42,10 +43,7 @@ inline HTMLTableSectionElement::HTMLTableSectionElement(const QualifiedName& tag ScriptWrappable::init(this); } -PassRefPtr<HTMLTableSectionElement> HTMLTableSectionElement::create(const QualifiedName& tagName, Document& document) -{ - return adoptRef(new HTMLTableSectionElement(tagName, document)); -} +DEFINE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLTableSectionElement) const StylePropertySet* HTMLTableSectionElement::additionalPresentationAttributeStyle() { @@ -54,99 +52,54 @@ const StylePropertySet* HTMLTableSectionElement::additionalPresentationAttribute return 0; } +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableSectionElement::insertRow(ExceptionState& exceptionState) +{ + // The default 'index' argument value is -1. + return insertRow(-1, exceptionState); +} + // these functions are rather slow, since we need to get the row at // the index... but they aren't used during usual HTML parsing anyway -PassRefPtr<HTMLElement> HTMLTableSectionElement::insertRow(int index, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<HTMLElement> HTMLTableSectionElement::insertRow(int index, ExceptionState& exceptionState) { - RefPtr<HTMLTableRowElement> row; - RefPtr<HTMLCollection> children = rows(); - int numRows = children ? (int)children->length() : 0; - if (index < -1 || index > numRows) - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); // per the DOM - else { - row = HTMLTableRowElement::create(document()); - if (numRows == index || index == -1) - appendChild(row, exceptionState); - else { - Node* n; - if (index < 1) - n = firstChild(); - else - n = children->item(index); - insertBefore(row, n, exceptionState); - } + RefPtrWillBeRawPtr<HTMLCollection> children = rows(); + int numRows = children ? static_cast<int>(children->length()) : 0; + if (index < -1 || index > numRows) { + exceptionState.throwDOMException(IndexSizeError, "The provided index (" + String::number(index) + " is outside the range [-1, " + String::number(numRows) + "]."); + return nullptr; } + + RefPtrWillBeRawPtr<HTMLTableRowElement> row = HTMLTableRowElement::create(document()); + if (numRows == index || index == -1) + appendChild(row, exceptionState); + else + insertBefore(row, children->item(index), exceptionState); return row.release(); } void HTMLTableSectionElement::deleteRow(int index, ExceptionState& exceptionState) { - RefPtr<HTMLCollection> children = rows(); + RefPtrWillBeRawPtr<HTMLCollection> children = rows(); int numRows = children ? (int)children->length() : 0; if (index == -1) index = numRows - 1; if (index >= 0 && index < numRows) { - RefPtr<Node> row = children->item(index); + RefPtrWillBeRawPtr<Element> row = children->item(index); HTMLElement::removeChild(row.get(), exceptionState); } else { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided index (" + String::number(index) + " is outside the range [-1, " + String::number(numRows) + "]."); } } int HTMLTableSectionElement::numRows() const { - int rows = 0; - const Node *n = firstChild(); - while (n) { - if (n->hasTagName(trTag)) - rows++; - n = n->nextSibling(); - } - - return rows; -} - -const AtomicString& HTMLTableSectionElement::align() const -{ - return getAttribute(alignAttr); -} - -void HTMLTableSectionElement::setAlign(const AtomicString& value) -{ - setAttribute(alignAttr, value); -} - -const AtomicString& HTMLTableSectionElement::ch() const -{ - return getAttribute(charAttr); -} - -void HTMLTableSectionElement::setCh(const AtomicString& value) -{ - setAttribute(charAttr, value); -} - -const AtomicString& HTMLTableSectionElement::chOff() const -{ - return getAttribute(charoffAttr); -} - -void HTMLTableSectionElement::setChOff(const AtomicString& value) -{ - setAttribute(charoffAttr, value); -} - -const AtomicString& HTMLTableSectionElement::vAlign() const -{ - return getAttribute(valignAttr); -} - -void HTMLTableSectionElement::setVAlign(const AtomicString& value) -{ - setAttribute(valignAttr, value); + int rowCount = 0; + for (const HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*this); row; row = Traversal<HTMLTableRowElement>::nextSibling(*row)) + ++rowCount; + return rowCount; } -PassRefPtr<HTMLCollection> HTMLTableSectionElement::rows() +PassRefPtrWillBeRawPtr<HTMLCollection> HTMLTableSectionElement::rows() { return ensureCachedHTMLCollection(TSectionRows); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.h index 02d55167adb..4fa633b2b4c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.h @@ -34,26 +34,15 @@ class ExceptionState; class HTMLTableSectionElement FINAL : public HTMLTablePartElement { public: - static PassRefPtr<HTMLTableSectionElement> create(const QualifiedName&, Document&); + DECLARE_ELEMENT_FACTORY_WITH_TAGNAME(HTMLTableSectionElement); - PassRefPtr<HTMLElement> insertRow(int index, ExceptionState&); + PassRefPtrWillBeRawPtr<HTMLElement> insertRow(ExceptionState&); + PassRefPtrWillBeRawPtr<HTMLElement> insertRow(int index, ExceptionState&); void deleteRow(int index, ExceptionState&); int numRows() const; - const AtomicString& align() const; - void setAlign(const AtomicString&); - - const AtomicString& ch() const; - void setCh(const AtomicString&); - - const AtomicString& chOff() const; - void setChOff(const AtomicString&); - - const AtomicString& vAlign() const; - void setVAlign(const AtomicString&); - - PassRefPtr<HTMLCollection> rows(); + PassRefPtrWillBeRawPtr<HTMLCollection> rows(); private: HTMLTableSectionElement(const QualifiedName& tagName, Document&); @@ -61,12 +50,17 @@ private: virtual const StylePropertySet* additionalPresentationAttributeStyle() OVERRIDE; }; -inline bool isHTMLTableSectionElement(const Node& node) +inline bool isHTMLTableSectionElement(const Element& element) +{ + return element.hasTagName(HTMLNames::tbodyTag) || element.hasTagName(HTMLNames::tfootTag) || element.hasTagName(HTMLNames::theadTag); +} + +inline bool isHTMLTableSectionElement(const HTMLElement& element) { - return node.hasTagName(HTMLNames::tbodyTag) || node.hasTagName(HTMLNames::tfootTag) || node.hasTagName(HTMLNames::theadTag); + return element.hasLocalName(HTMLNames::tbodyTag) || element.hasLocalName(HTMLNames::tfootTag) || element.hasLocalName(HTMLNames::theadTag); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLTableSectionElement); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLTableSectionElement); } //namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.idl index 836b712c43e..a8f0b894191 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTableSectionElement.idl @@ -24,6 +24,6 @@ interface HTMLTableSectionElement : HTMLElement { [Reflect=charoff] attribute DOMString chOff; [Reflect] attribute DOMString vAlign; readonly attribute HTMLCollection rows; - [RaisesException] HTMLElement insertRow([Default=Undefined] optional long index); + [RaisesException] HTMLElement insertRow(optional long index); [RaisesException] void deleteRow([Default=Undefined] optional long index); }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTagNames.in b/chromium/third_party/WebKit/Source/core/html/HTMLTagNames.in index ee8c92f89f3..9e349119186 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTagNames.in +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTagNames.in @@ -11,7 +11,7 @@ applet constructorNeedsCreatedByParser area article interfaceName=HTMLElement aside interfaceName=HTMLElement -audio runtimeEnabled=media, constructorNeedsCreatedByParser +audio runtimeEnabled=media b interfaceName=HTMLElement base basefont interfaceName=HTMLElement @@ -66,10 +66,9 @@ html i interfaceName=HTMLElement iframe interfaceName=HTMLIFrameElement image interfaceName=HTMLUnknownElement -img interfaceName=HTMLImageElement, constructorNeedsFormElement +img interfaceName=HTMLImageElement, constructorNeedsFormElement, constructorNeedsCreatedByParser input constructorNeedsFormElement, constructorNeedsCreatedByParser ins interfaceName=HTMLModElement -isindex interfaceName=HTMLUnknownElement kbd interfaceName=HTMLElement keygen constructorNeedsFormElement label @@ -87,7 +86,7 @@ meta meter interfaceName=HTMLMeterElement nav interfaceName=HTMLElement nobr interfaceName=HTMLElement -noembed interfaceName=HTMLElement +noembed interfaceName=HTMLNoEmbedElement, JSInterfaceName=HTMLElement noframes interfaceName=HTMLElement nolayer interfaceName=HTMLElement object constructorNeedsFormElement, constructorNeedsCreatedByParser @@ -98,18 +97,19 @@ output constructorNeedsFormElement shadow interfaceName=HTMLShadowElement p interfaceName=HTMLParagraphElement param +picture interfaceName=HTMLPictureElement, runtimeEnabled=picture plaintext interfaceName=HTMLElement pre progress interfaceName=HTMLProgressElement q interfaceName=HTMLQuoteElement rp interfaceName=HTMLElement -rt interfaceName=HTMLElement -ruby interfaceName=HTMLElement +rt interfaceName=HTMLRTElement, JSInterfaceName=HTMLElement +ruby interfaceName=HTMLRubyElement, JSInterfaceName=HTMLElement s interfaceName=HTMLElement samp interfaceName=HTMLElement script constructorNeedsCreatedByParser section interfaceName=HTMLElement -select constructorNeedsFormElement, constructorNeedsCreatedByParser +select constructorNeedsFormElement small interfaceName=HTMLElement source runtimeEnabled=media span @@ -129,12 +129,12 @@ th interfaceName=HTMLTableCellElement thead interfaceName=HTMLTableSectionElement title tr interfaceName=HTMLTableRowElement -track runtimeEnabled=videoTrack +track tt interfaceName=HTMLElement u interfaceName=HTMLElement ul interfaceName=HTMLUListElement var interfaceName=HTMLElement -video runtimeEnabled=media, constructorNeedsCreatedByParser -wbr interfaceName=HTMLElement +video runtimeEnabled=media +wbr interfaceName=HTMLWBRElement, JSInterfaceName=HTMLElement xmp interfaceName=HTMLPreElement -noscript interfaceName=HTMLElement +noscript interfaceName=HTMLNoScriptElement, JSInterfaceName=HTMLElement diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp index 2990838c707..3d24f522f91 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp @@ -32,6 +32,7 @@ #include "core/html/HTMLTemplateElement.h" +#include "core/dom/Document.h" #include "core/dom/DocumentFragment.h" #include "core/dom/TemplateContentDocumentFragment.h" @@ -45,15 +46,14 @@ inline HTMLTemplateElement::HTMLTemplateElement(Document& document) ScriptWrappable::init(this); } +DEFINE_NODE_FACTORY(HTMLTemplateElement) + HTMLTemplateElement::~HTMLTemplateElement() { +#if !ENABLE(OILPAN) if (m_content) m_content->clearHost(); -} - -PassRefPtr<HTMLTemplateElement> HTMLTemplateElement::create(Document& document) -{ - return adoptRef(new HTMLTemplateElement(document)); +#endif } DocumentFragment* HTMLTemplateElement::content() const @@ -64,12 +64,12 @@ DocumentFragment* HTMLTemplateElement::content() const return m_content.get(); } -PassRefPtr<Node> HTMLTemplateElement::cloneNode(bool deep) +PassRefPtrWillBeRawPtr<Node> HTMLTemplateElement::cloneNode(bool deep) { if (!deep) return cloneElementWithoutChildren(); - RefPtr<Node> clone = cloneElementWithChildren(); + RefPtrWillBeRawPtr<Node> clone = cloneElementWithChildren(); if (m_content) content()->cloneChildNodes(toHTMLTemplateElement(clone.get())->content()); return clone.release(); @@ -83,4 +83,10 @@ void HTMLTemplateElement::didMoveToNewDocument(Document& oldDocument) document().ensureTemplateDocument().adoptIfNeeded(*m_content); } +void HTMLTemplateElement::trace(Visitor* visitor) +{ + visitor->trace(m_content); + HTMLElement::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.h index b27958dafb1..78467973f94 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTemplateElement.h @@ -40,22 +40,21 @@ class TemplateContentDocumentFragment; class HTMLTemplateElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLTemplateElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLTemplateElement); virtual ~HTMLTemplateElement(); + virtual void trace(Visitor*) OVERRIDE; DocumentFragment* content() const; private: - virtual PassRefPtr<Node> cloneNode(bool deep = true) OVERRIDE; + virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = true) OVERRIDE; virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; explicit HTMLTemplateElement(Document&); - mutable RefPtr<TemplateContentDocumentFragment> m_content; + mutable RefPtrWillBeMember<TemplateContentDocumentFragment> m_content; }; -DEFINE_NODE_TYPE_CASTS(HTMLTemplateElement, hasTagName(HTMLNames::templateTag)); - } // namespace WebCore #endif // HTMLTemplateElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp index ca7494e2af6..5b4fde76b34 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp @@ -26,10 +26,10 @@ #include "config.h" #include "core/html/HTMLTextAreaElement.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/Text.h" @@ -39,12 +39,14 @@ #include "core/editing/TextIterator.h" #include "core/events/BeforeTextInsertedEvent.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/html/FormDataList.h" #include "core/html/forms/FormController.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/html/shadow/TextControlInnerElements.h" -#include "core/frame/Frame.h" +#include "core/page/Chrome.h" +#include "core/page/ChromeClient.h" #include "core/rendering/RenderTextControlMultiLine.h" #include "platform/text/PlatformLocale.h" #include "wtf/StdLibExtras.h" @@ -81,21 +83,21 @@ HTMLTextAreaElement::HTMLTextAreaElement(Document& document, HTMLFormElement* fo , m_cols(defaultCols) , m_wrap(SoftWrap) , m_isDirty(false) + , m_valueIsUpToDate(true) { - setFormControlValueMatchesRenderer(true); ScriptWrappable::init(this); } -PassRefPtr<HTMLTextAreaElement> HTMLTextAreaElement::create(Document& document, HTMLFormElement* form) +PassRefPtrWillBeRawPtr<HTMLTextAreaElement> HTMLTextAreaElement::create(Document& document, HTMLFormElement* form) { - RefPtr<HTMLTextAreaElement> textArea = adoptRef(new HTMLTextAreaElement(document, form)); + RefPtrWillBeRawPtr<HTMLTextAreaElement> textArea = adoptRefWillBeNoop(new HTMLTextAreaElement(document, form)); textArea->ensureUserAgentShadowRoot(); return textArea.release(); } void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot& root) { - root.appendChild(TextControlInnerTextElement::create(document())); + root.appendChild(TextControlInnerEditorElement::create(document())); } const AtomicString& HTMLTextAreaElement::formControlType() const @@ -119,7 +121,7 @@ void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChan HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); setLastChangeWasNotUserEdit(); if (m_isDirty) - setInnerTextValue(value()); + setInnerEditorValue(value()); else setNonDirtyValue(defaultValue()); } @@ -160,7 +162,7 @@ void HTMLTextAreaElement::parseAttribute(const QualifiedName& name, const Atomic if (m_rows != rows) { m_rows = rows; if (renderer()) - renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } } else if (name == colsAttr) { int cols = value.toInt(); @@ -169,7 +171,7 @@ void HTMLTextAreaElement::parseAttribute(const QualifiedName& name, const Atomic if (m_cols != cols) { m_cols = cols; if (renderer()) - renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } } else if (name == wrapAttr) { // The virtual/physical values were a Netscape extension of HTML 3.0, now deprecated. @@ -184,7 +186,7 @@ void HTMLTextAreaElement::parseAttribute(const QualifiedName& name, const Atomic if (wrap != m_wrap) { m_wrap = wrap; if (renderer()) - renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } } else if (name == accesskeyAttr) { // ignore for the moment @@ -238,12 +240,9 @@ bool HTMLTextAreaElement::shouldShowFocusRingOnMouseFocus() const void HTMLTextAreaElement::updateFocusAppearance(bool restorePreviousSelection) { - if (!restorePreviousSelection || !hasCachedSelection()) { - // If this is the first focus, set a caret at the beginning of the text. - // This matches some browsers' behavior; see bug 11746 Comment #15. - // http://bugs.webkit.org/show_bug.cgi?id=11746#c15 + if (!restorePreviousSelection) setSelectionRange(0, 0); - } else + else restoreCachedSelection(); if (document().frame()) @@ -260,16 +259,16 @@ void HTMLTextAreaElement::defaultEventHandler(Event* event) HTMLTextFormControlElement::defaultEventHandler(event); } -void HTMLTextAreaElement::handleFocusEvent(Element*, FocusDirection) +void HTMLTextAreaElement::handleFocusEvent(Element*, FocusType) { - if (Frame* frame = document().frame()) + if (LocalFrame* frame = document().frame()) frame->spellChecker().didBeginEditing(this); } void HTMLTextAreaElement::subtreeHasChanged() { setChangedSinceLastFormControlChangeEvent(true); - setFormControlValueMatchesRenderer(false); + m_valueIsUpToDate = false; setNeedsValidityCheck(); if (!focused()) @@ -277,6 +276,9 @@ void HTMLTextAreaElement::subtreeHasChanged() // When typing in a textarea, childrenChanged is not called, so we need to force the directionality check. calculateAndAdjustDirectionality(); + + ASSERT(document().isActive()); + document().frameHost()->chrome().client().didChangeValueInTextField(*this); } void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event) const @@ -288,7 +290,7 @@ void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* return; unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength); - const String& currentValue = innerTextValue(); + const String& currentValue = innerEditorValue(); unsigned currentLength = computeLengthForSubmission(currentValue); if (currentLength + computeLengthForSubmission(event->text()) < unsignedMaxLength) return; @@ -312,19 +314,14 @@ String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, return proposedValue.left(maxLength); } -void HTMLTextAreaElement::rendererWillBeDestroyed() -{ - updateValue(); -} - void HTMLTextAreaElement::updateValue() const { - if (formControlValueMatchesRenderer()) + if (m_valueIsUpToDate) return; ASSERT(renderer()); - m_value = innerTextValue(); - const_cast<HTMLTextAreaElement*>(this)->setFormControlValueMatchesRenderer(true); + m_value = innerEditorValue(); + const_cast<HTMLTextAreaElement*>(this)->m_valueIsUpToDate = true; const_cast<HTMLTextAreaElement*>(this)->notifyFormStateChanged(); m_isDirty = true; const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility(false); @@ -336,21 +333,24 @@ String HTMLTextAreaElement::value() const return m_value; } -void HTMLTextAreaElement::setValue(const String& value) +void HTMLTextAreaElement::setValue(const String& value, TextFieldEventBehavior eventBehavior) { - setValueCommon(value); + RefPtrWillBeRawPtr<HTMLTextAreaElement> protector(this); + setValueCommon(value, eventBehavior); m_isDirty = true; setNeedsValidityCheck(); + if (document().focusedElement() == this) + document().frameHost()->chrome().client().didUpdateTextOfFocusedElementByNonUserInput(); } void HTMLTextAreaElement::setNonDirtyValue(const String& value) { - setValueCommon(value); + setValueCommon(value, DispatchNoEvent); m_isDirty = false; setNeedsValidityCheck(); } -void HTMLTextAreaElement::setValueCommon(const String& newValue) +void HTMLTextAreaElement::setValueCommon(const String& newValue, TextFieldEventBehavior eventBehavior) { // Code elsewhere normalizes line endings added by the user via the keyboard or pasting. // We normalize line endings coming from JavaScript here. @@ -364,11 +364,12 @@ void HTMLTextAreaElement::setValueCommon(const String& newValue) return; m_value = normalizedValue; - setInnerTextValue(m_value); - setLastChangeWasNotUserEdit(); + setInnerEditorValue(m_value); + if (eventBehavior == DispatchNoEvent) + setLastChangeWasNotUserEdit(); updatePlaceholderVisibility(false); - setNeedsStyleRecalc(); - setFormControlValueMatchesRenderer(true); + setNeedsStyleRecalc(SubtreeStyleChange); + m_suggestedValue = String(); // Set the caret to the end of the text value. if (document().focusedElement() == this) { @@ -377,7 +378,19 @@ void HTMLTextAreaElement::setValueCommon(const String& newValue) } notifyFormStateChanged(); - setTextAsOfLastFormControlChangeEvent(normalizedValue); + if (eventBehavior == DispatchNoEvent) { + setTextAsOfLastFormControlChangeEvent(normalizedValue); + } else { + if (eventBehavior == DispatchInputAndChangeEvent) + dispatchFormControlInputEvent(); + dispatchFormControlChangeEvent(); + } +} + +void HTMLTextAreaElement::setInnerEditorValue(const String& value) +{ + HTMLTextFormControlElement::setInnerEditorValue(value); + m_valueIsUpToDate = true; } String HTMLTextAreaElement::defaultValue() const @@ -395,10 +408,10 @@ String HTMLTextAreaElement::defaultValue() const void HTMLTextAreaElement::setDefaultValue(const String& defaultValue) { - RefPtr<Node> protectFromMutationEvents(this); + RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this); // To preserve comments, remove only the text nodes, then add a single text node. - Vector<RefPtr<Node> > textNodes; + WillBeHeapVector<RefPtrWillBeMember<Node> > textNodes; for (Node* n = firstChild(); n; n = n->nextSibling()) { if (n->isTextNode()) textNodes.append(n); @@ -433,6 +446,23 @@ void HTMLTextAreaElement::setMaxLength(int newValue, ExceptionState& exceptionSt setIntegralAttribute(maxlengthAttr, newValue); } +String HTMLTextAreaElement::suggestedValue() const +{ + return m_suggestedValue; +} + +void HTMLTextAreaElement::setSuggestedValue(const String& value) +{ + m_suggestedValue = value; + + if (!value.isNull()) + setInnerEditorValue(m_suggestedValue); + else + setInnerEditorValue(m_value); + updatePlaceholderVisibility(false); + setNeedsStyleRecalc(SubtreeStyleChange); +} + String HTMLTextAreaElement::validationMessage() const { if (!willValidate()) @@ -511,18 +541,18 @@ bool HTMLTextAreaElement::matchesReadWritePseudoClass() const void HTMLTextAreaElement::updatePlaceholderText() { HTMLElement* placeholder = placeholderElement(); - String placeholderText = strippedPlaceholder(); + const AtomicString& placeholderText = fastGetAttribute(placeholderAttr); if (placeholderText.isEmpty()) { if (placeholder) userAgentShadowRoot()->removeChild(placeholder); return; } if (!placeholder) { - RefPtr<HTMLDivElement> newElement = HTMLDivElement::create(document()); + RefPtrWillBeRawPtr<HTMLDivElement> newElement = HTMLDivElement::create(document()); placeholder = newElement.get(); - placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral)); + placeholder->setShadowPseudoId(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral)); placeholder->setAttribute(idAttr, ShadowElementNames::placeholder()); - userAgentShadowRoot()->insertBefore(placeholder, innerTextElement()->nextSibling()); + userAgentShadowRoot()->insertBefore(placeholder, innerEditorElement()->nextSibling()); } placeholder->setTextContent(placeholderText); } @@ -532,4 +562,9 @@ bool HTMLTextAreaElement::isInteractiveContent() const return true; } +bool HTMLTextAreaElement::supportsAutofocus() const +{ + return true; +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h index a5693348c08..57b3b4e52b8 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.h @@ -34,28 +34,30 @@ class VisibleSelection; class HTMLTextAreaElement FINAL : public HTMLTextFormControlElement { public: - static PassRefPtr<HTMLTextAreaElement> create(Document&, HTMLFormElement*); + static PassRefPtrWillBeRawPtr<HTMLTextAreaElement> create(Document&, HTMLFormElement*); int cols() const { return m_cols; } int rows() const { return m_rows; } bool shouldWrapText() const { return m_wrap != NoWrap; } - virtual String value() const; - void setValue(const String&); + virtual String value() const OVERRIDE; + void setValue(const String&, TextFieldEventBehavior = DispatchNoEvent); String defaultValue() const; void setDefaultValue(const String&); int textLength() const { return value().length(); } - virtual int maxLength() const; + int maxLength() const; void setMaxLength(int, ExceptionState&); + + String suggestedValue() const; + void setSuggestedValue(const String&); + // For ValidityState virtual String validationMessage() const OVERRIDE; virtual bool valueMissing() const OVERRIDE; virtual bool tooLong() const OVERRIDE; bool isValidValue(const String&) const; - void rendererWillBeDestroyed(); - void setCols(int); void setRows(int); @@ -72,47 +74,50 @@ private: void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) const; static String sanitizeUserInputValue(const String&, unsigned maxLength); void updateValue() const; + virtual void setInnerEditorValue(const String&) OVERRIDE; void setNonDirtyValue(const String&); - void setValueCommon(const String&); + void setValueCommon(const String&, TextFieldEventBehavior); - virtual bool supportsPlaceholder() const { return true; } - virtual void updatePlaceholderText(); - virtual bool isEmptyValue() const { return value().isEmpty(); } + virtual bool supportsPlaceholder() const OVERRIDE { return true; } + virtual void updatePlaceholderText() OVERRIDE; + virtual bool isEmptyValue() const OVERRIDE { return value().isEmpty(); } + virtual bool isEmptySuggestedValue() const OVERRIDE FINAL { return suggestedValue().isEmpty(); } - virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); } - virtual bool isRequiredFormControl() const { return isRequired(); } + virtual bool isOptionalFormControl() const OVERRIDE { return !isRequiredFormControl(); } + virtual bool isRequiredFormControl() const OVERRIDE { return isRequired(); } - virtual void defaultEventHandler(Event*); - virtual void handleFocusEvent(Element* oldFocusedNode, FocusDirection) OVERRIDE; + virtual void defaultEventHandler(Event*) OVERRIDE; + virtual void handleFocusEvent(Element* oldFocusedNode, FocusType) OVERRIDE; - virtual void subtreeHasChanged(); + virtual void subtreeHasChanged() OVERRIDE; - virtual bool isEnumeratable() const { return true; } + virtual bool isEnumeratable() const OVERRIDE { return true; } virtual bool isInteractiveContent() const OVERRIDE; + virtual bool supportsAutofocus() const OVERRIDE; virtual bool supportLabels() const OVERRIDE { return true; } - virtual const AtomicString& formControlType() const; + virtual const AtomicString& formControlType() const OVERRIDE; virtual FormControlState saveFormControlState() const OVERRIDE; virtual void restoreFormControlState(const FormControlState&) OVERRIDE; - virtual bool isTextFormControl() const { return true; } + virtual bool isTextFormControl() const OVERRIDE { return true; } - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*); - virtual bool appendFormData(FormDataList&, bool); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual bool appendFormData(FormDataList&, bool) OVERRIDE; virtual void resetImpl() OVERRIDE; virtual bool hasCustomFocusLogic() const OVERRIDE; virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE; virtual bool isKeyboardFocusable() const OVERRIDE; - virtual void updateFocusAppearance(bool restorePreviousSelection); + virtual void updateFocusAppearance(bool restorePreviousSelection) OVERRIDE; - virtual void accessKeyAction(bool sendMouseEvents); + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; - virtual bool shouldUseInputMethod(); + virtual bool shouldUseInputMethod() OVERRIDE; virtual bool matchesReadOnlyPseudoClass() const OVERRIDE; virtual bool matchesReadWritePseudoClass() const OVERRIDE; @@ -124,20 +129,10 @@ private: WrapMethod m_wrap; mutable String m_value; mutable bool m_isDirty; + bool m_valueIsUpToDate; + String m_suggestedValue; }; -inline bool isHTMLTextAreaElement(const Node* node) -{ - return node->hasTagName(HTMLNames::textareaTag); -} - -inline bool isHTMLTextAreaElement(const Element* element) -{ - return element->hasTagName(HTMLNames::textareaTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLTextAreaElement, hasTagName(HTMLNames::textareaTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.idl index e5d79264392..937c8c94193 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTextAreaElement.idl @@ -56,7 +56,7 @@ interface HTMLTextAreaElement : HTMLElement { [RaisesException] void setRangeText(DOMString replacement, unsigned long start, unsigned long end, - [Default=NullString] optional DOMString selectionMode); + optional DOMString selectionMode = null); void setSelectionRange([Default=Undefined] optional long start, [Default=Undefined] optional long end, diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.cpp index d4b83cb03d8..06a5579087d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.cpp @@ -25,9 +25,9 @@ #include "config.h" #include "core/html/HTMLTextFormControlElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/dom/Document.h" #include "core/dom/NodeTraversal.h" @@ -36,25 +36,24 @@ #include "core/editing/FrameSelection.h" #include "core/editing/TextIterator.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLBRElement.h" #include "core/html/shadow/ShadowElementNames.h" -#include "core/frame/Frame.h" -#include "core/frame/UseCounter.h" #include "core/rendering/RenderBlock.h" #include "core/rendering/RenderTheme.h" +#include "platform/heap/Handle.h" #include "wtf/text/StringBuilder.h" namespace WebCore { using namespace HTMLNames; -using namespace std; HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& doc, HTMLFormElement* form) : HTMLFormControlElementWithState(tagName, doc, form) , m_lastChangeWasUserEdit(false) - , m_cachedSelectionStart(-1) - , m_cachedSelectionEnd(-1) + , m_cachedSelectionStart(0) + , m_cachedSelectionEnd(0) , m_cachedSelectionDirection(SelectionHasNoDirection) { } @@ -73,12 +72,12 @@ Node::InsertionNotificationRequest HTMLTextFormControlElement::insertedInto(Cont return InsertionDone; } -void HTMLTextFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction) +void HTMLTextFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType type) { if (supportsPlaceholder()) updatePlaceholderVisibility(false); - handleFocusEvent(oldFocusedElement, direction); - HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, direction); + handleFocusEvent(oldFocusedElement, type); + HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, type); } void HTMLTextFormControlElement::dispatchBlurEvent(Element* newFocusedElement) @@ -104,7 +103,7 @@ void HTMLTextFormControlElement::forwardEvent(Event* event) { if (event->type() == EventTypeNames::blur || event->type() == EventTypeNames::focus) return; - innerTextElement()->defaultEventHandler(event); + innerEditorElement()->defaultEventHandler(event); } String HTMLTextFormControlElement::strippedPlaceholder() const @@ -164,12 +163,12 @@ void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderVal void HTMLTextFormControlElement::setSelectionStart(int start) { - setSelectionRange(start, max(start, selectionEnd()), selectionDirection()); + setSelectionRange(start, std::max(start, selectionEnd()), selectionDirection()); } void HTMLTextFormControlElement::setSelectionEnd(int end) { - setSelectionRange(min(end, selectionStart()), end, selectionDirection()); + setSelectionRange(std::min(end, selectionStart()), end, selectionDirection()); } void HTMLTextFormControlElement::setSelectionDirection(const String& direction) @@ -179,21 +178,20 @@ void HTMLTextFormControlElement::setSelectionDirection(const String& direction) void HTMLTextFormControlElement::select() { - setSelectionRange(0, numeric_limits<int>::max(), SelectionHasNoDirection); + setSelectionRange(0, std::numeric_limits<int>::max(), SelectionHasNoDirection); } -String HTMLTextFormControlElement::selectedText() const +bool HTMLTextFormControlElement::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue) { - if (!isTextFormControl()) - return String(); - return value().substring(selectionStart(), selectionEnd() - selectionStart()); + return !equalIgnoringNullity(oldValue, newValue); } void HTMLTextFormControlElement::dispatchFormControlChangeEvent() { - if (m_textAsOfLastFormControlChangeEvent != value()) { - HTMLElement::dispatchChangeEvent(); - setTextAsOfLastFormControlChangeEvent(value()); + String newValue = value(); + if (shouldDispatchFormControlChangeEvent(m_textAsOfLastFormControlChangeEvent, newValue)) { + setTextAsOfLastFormControlChangeEvent(newValue); + dispatchChangeEvent(); } setChangedSinceLastFormControlChangeEvent(false); } @@ -216,8 +214,10 @@ void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigne exceptionState.throwDOMException(IndexSizeError, "The provided start value (" + String::number(start) + ") is larger than the provided end value (" + String::number(end) + ")."); return; } + if (hasAuthorShadowRoot()) + return; - String text = innerTextValue(); + String text = innerEditorValue(); unsigned textLength = text.length(); unsigned replacementLength = replacement.length(); unsigned newSelectionStart = selectionStart(); @@ -231,7 +231,7 @@ void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigne else text.insert(replacement, start); - setInnerTextValue(text); + setInnerEditorValue(text); // FIXME: What should happen to the value (as in value()) if there's no renderer? if (!renderer()) @@ -282,10 +282,10 @@ void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField if (!renderer() || !renderer()->isTextControl()) return; - end = max(end, 0); - start = min(max(start, 0), end); + end = std::max(end, 0); + start = std::min(std::max(start, 0), end); - if (!hasVisibleTextArea(renderer(), innerTextElement())) { + if (!hasVisibleTextArea(renderer(), innerEditorElement())) { cacheSelection(start, end, direction); return; } @@ -309,16 +309,16 @@ void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField newSelection = VisibleSelection(startPosition, endPosition); newSelection.setIsDirectional(direction != SelectionHasNoDirection); - if (Frame* frame = document().frame()) + if (LocalFrame* frame = document().frame()) frame->selection().setSelection(newSelection); } VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const { if (index <= 0) - return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTREAM); - RefPtr<Range> range = Range::create(document()); - range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION); + return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNSTREAM); + RefPtrWillBeRawPtr<Range> range = Range::create(document()); + range->selectNodeContents(innerEditorElement(), ASSERT_NO_EXCEPTION); CharacterIterator it(range.get()); it.advance(index - 1); return VisiblePosition(it.range()->endPosition(), UPSTREAM); @@ -330,8 +330,8 @@ int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& p if (enclosingTextFormControl(indexPosition) != this) return 0; ASSERT(indexPosition.document()); - RefPtr<Range> range = Range::create(*indexPosition.document()); - range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION); + RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document()); + range->setStart(innerEditorElement(), 0, ASSERT_NO_EXCEPTION); range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION); return TextIterator::rangeLength(range.get()); } @@ -340,7 +340,7 @@ int HTMLTextFormControlElement::selectionStart() const { if (!isTextFormControl()) return 0; - if (document().focusedElement() != this && hasCachedSelection()) + if (document().focusedElement() != this) return m_cachedSelectionStart; return computeSelectionStart(); @@ -349,18 +349,18 @@ int HTMLTextFormControlElement::selectionStart() const int HTMLTextFormControlElement::computeSelectionStart() const { ASSERT(isTextFormControl()); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) return 0; - return indexForVisiblePosition(frame->selection().start()); + return indexForVisiblePosition(VisiblePosition(frame->selection().start())); } int HTMLTextFormControlElement::selectionEnd() const { if (!isTextFormControl()) return 0; - if (document().focusedElement() != this && hasCachedSelection()) + if (document().focusedElement() != this) return m_cachedSelectionEnd; return computeSelectionEnd(); } @@ -368,11 +368,11 @@ int HTMLTextFormControlElement::selectionEnd() const int HTMLTextFormControlElement::computeSelectionEnd() const { ASSERT(isTextFormControl()); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) return 0; - return indexForVisiblePosition(frame->selection().end()); + return indexForVisiblePosition(VisiblePosition(frame->selection().end())); } static const AtomicString& directionString(TextFieldSelectionDirection direction) @@ -398,7 +398,7 @@ const AtomicString& HTMLTextFormControlElement::selectionDirection() const { if (!isTextFormControl()) return directionString(SelectionHasNoDirection); - if (document().focusedElement() != this && hasCachedSelection()) + if (document().focusedElement() != this) return directionString(m_cachedSelectionDirection); return directionString(computeSelectionDirection()); @@ -407,7 +407,7 @@ const AtomicString& HTMLTextFormControlElement::selectionDirection() const TextFieldSelectionDirection HTMLTextFormControlElement::computeSelectionDirection() const { ASSERT(isTextFormControl()); - Frame* frame = document().frame(); + LocalFrame* frame = document().frame(); if (!frame) return SelectionHasNoDirection; @@ -426,18 +426,18 @@ static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& } } -PassRefPtr<Range> HTMLTextFormControlElement::selection() const +PassRefPtrWillBeRawPtr<Range> HTMLTextFormControlElement::selection() const { - if (!renderer() || !isTextFormControl() || !hasCachedSelection()) - return 0; + if (!renderer() || !isTextFormControl()) + return nullptr; int start = m_cachedSelectionStart; int end = m_cachedSelectionEnd; ASSERT(start <= end); - HTMLElement* innerText = innerTextElement(); + HTMLElement* innerText = innerEditorElement(); if (!innerText) - return 0; + return nullptr; if (!innerText->firstChild()) return Range::create(document(), innerText, 0, innerText, 0); @@ -447,7 +447,7 @@ PassRefPtr<Range> HTMLTextFormControlElement::selection() const Node* endNode = 0; for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) { ASSERT(!node->firstChild()); - ASSERT(node->isTextNode() || node->hasTagName(brTag)); + ASSERT(node->isTextNode() || isHTMLBRElement(*node)); int length = node->isTextNode() ? lastOffsetInNode(node) : 1; if (offset <= start && start <= offset + length) @@ -462,7 +462,7 @@ PassRefPtr<Range> HTMLTextFormControlElement::selection() const } if (!startNode || !endNode) - return 0; + return nullptr; return Range::create(document(), startNode, start, endNode, end); } @@ -480,7 +480,7 @@ void HTMLTextFormControlElement::selectionChanged(bool userTriggered) // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelectionDirection()); - if (Frame* frame = document().frame()) { + if (LocalFrame* frame = document().frame()) { if (frame->selection().isRange() && userTriggered) dispatchEvent(Event::createBubble(EventTypeNames::select)); } @@ -502,24 +502,23 @@ bool HTMLTextFormControlElement::lastChangeWasUserEdit() const return m_lastChangeWasUserEdit; } -void HTMLTextFormControlElement::setInnerTextValue(const String& value) +void HTMLTextFormControlElement::setInnerEditorValue(const String& value) { - if (!isTextFormControl()) + ASSERT(!hasAuthorShadowRoot()); + if (!isTextFormControl() || hasAuthorShadowRoot()) return; - bool textIsChanged = value != innerTextValue(); - if (textIsChanged || !innerTextElement()->hasChildNodes()) { + bool textIsChanged = value != innerEditorValue(); + if (textIsChanged || !innerEditorElement()->hasChildren()) { if (textIsChanged && renderer()) { if (AXObjectCache* cache = document().existingAXObjectCache()) cache->postNotification(this, AXObjectCache::AXValueChanged, false); } - innerTextElement()->setInnerText(value, ASSERT_NO_EXCEPTION); + innerEditorElement()->setInnerText(value, ASSERT_NO_EXCEPTION); if (value.endsWith('\n') || value.endsWith('\r')) - innerTextElement()->appendChild(HTMLBRElement::create(document())); + innerEditorElement()->appendChild(HTMLBRElement::create(document())); } - - setFormControlValueMatchesRenderer(true); } static String finishText(StringBuilder& result) @@ -531,15 +530,16 @@ static String finishText(StringBuilder& result) return result.toString(); } -String HTMLTextFormControlElement::innerTextValue() const +String HTMLTextFormControlElement::innerEditorValue() const { - HTMLElement* innerText = innerTextElement(); - if (!innerText || !isTextFormControl()) + ASSERT(!hasAuthorShadowRoot()); + HTMLElement* innerEditor = innerEditorElement(); + if (!innerEditor || !isTextFormControl()) return emptyString(); StringBuilder result; - for (Node* node = innerText; node; node = NodeTraversal::next(*node, innerText)) { - if (node->hasTagName(brTag)) + for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, innerEditor)) { + if (isHTMLBRElement(*node)) result.append(newlineCharacter); else if (node->isTextNode()) result.append(toText(node)->data()); @@ -568,7 +568,7 @@ String HTMLTextFormControlElement::valueWithHardLineBreaks() const { // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer. // While we have no evidence this has ever been a practical problem, it would be best to fix it some day. - HTMLElement* innerText = innerTextElement(); + HTMLElement* innerText = innerEditorElement(); if (!innerText || !isTextFormControl()) return value(); @@ -586,7 +586,7 @@ String HTMLTextFormControlElement::valueWithHardLineBreaks() const StringBuilder result; for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) { - if (node->hasTagName(brTag)) + if (isHTMLBRElement(*node)) result.append(newlineCharacter); else if (node->isTextNode()) { String data = toText(node)->data(); @@ -613,12 +613,15 @@ HTMLTextFormControlElement* enclosingTextFormControl(const Position& position) ASSERT(position.isNull() || position.anchorType() == Position::PositionIsOffsetInAnchor || position.containerNode() || !position.anchorNode()->shadowHost() || (position.anchorNode()->parentNode() && position.anchorNode()->parentNode()->isShadowRoot())); + return enclosingTextFormControl(position.containerNode()); +} - Node* container = position.containerNode(); +HTMLTextFormControlElement* enclosingTextFormControl(Node* container) +{ if (!container) return 0; Element* ancestor = container->shadowHost(); - return ancestor && isHTMLTextFormControlElement(ancestor) ? toHTMLTextFormControlElement(ancestor) : 0; + return ancestor && isHTMLTextFormControlElement(*ancestor) && container->containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot ? toHTMLTextFormControlElement(ancestor) : 0; } static const HTMLElement* parentHTMLElement(const Element* element) @@ -651,7 +654,7 @@ String HTMLTextFormControlElement::directionForFormData() const return "ltr"; } -HTMLElement* HTMLTextFormControlElement::innerTextElement() const +HTMLElement* HTMLTextFormControlElement::innerEditorElement() const { return toHTMLElement(userAgentShadowRoot()->getElementById(ShadowElementNames::innerEditor())); } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.h index 2c7a9bf8895..6d1c5921f2f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElement.h @@ -31,6 +31,7 @@ namespace WebCore { class ExceptionState; class Position; +class Range; class RenderTextControl; class VisiblePosition; @@ -69,20 +70,18 @@ public: virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&); void setSelectionRange(int start, int end, const String& direction); void setSelectionRange(int start, int end, TextFieldSelectionDirection = SelectionHasNoDirection); - PassRefPtr<Range> selection() const; - String selectedText() const; + PassRefPtrWillBeRawPtr<Range> selection() const; - virtual void dispatchFormControlChangeEvent(); + virtual void dispatchFormControlChangeEvent() OVERRIDE FINAL; - virtual int maxLength() const = 0; virtual String value() const = 0; - HTMLElement* innerTextElement() const; + HTMLElement* innerEditorElement() const; void selectionChanged(bool userTriggered); bool lastChangeWasUserEdit() const; - void setInnerTextValue(const String&); - String innerTextValue() const; + virtual void setInnerEditorValue(const String&); + String innerEditorValue() const; String directionForFormData() const; @@ -97,35 +96,37 @@ protected: void cacheSelection(int start, int end, TextFieldSelectionDirection direction) { + ASSERT(start >= 0); m_cachedSelectionStart = start; m_cachedSelectionEnd = end; m_cachedSelectionDirection = direction; } void restoreCachedSelection(); - bool hasCachedSelection() const { return m_cachedSelectionStart >= 0; } - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; virtual void subtreeHasChanged() = 0; void setLastChangeWasNotUserEdit() { m_lastChangeWasUserEdit = false; } String valueWithHardLineBreaks() const; + virtual bool shouldDispatchFormControlChangeEvent(String&, String&); + private: int computeSelectionStart() const; int computeSelectionEnd() const; TextFieldSelectionDirection computeSelectionDirection() const; - virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE; - virtual void dispatchBlurEvent(Element* newFocusedElement) OVERRIDE; + virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusType) OVERRIDE FINAL; + virtual void dispatchBlurEvent(Element* newFocusedElement) OVERRIDE FINAL; // Returns true if user-editable value is empty. Used to check placeholder visibility. virtual bool isEmptyValue() const = 0; // Returns true if suggested value is empty. Used to check placeholder visibility. virtual bool isEmptySuggestedValue() const { return true; } // Called in dispatchFocusEvent(), after placeholder process, before calling parent's dispatchFocusEvent(). - virtual void handleFocusEvent(Element* /* oldFocusedNode */, FocusDirection) { } + virtual void handleFocusEvent(Element* /* oldFocusedNode */, FocusType) { } // Called in dispatchBlurEvent(), after placeholder process, before calling parent's dispatchBlurEvent(). virtual void handleBlurEvent() { } @@ -137,19 +138,15 @@ private: TextFieldSelectionDirection m_cachedSelectionDirection; }; -inline bool isHTMLTextFormControlElement(const Node* node) -{ - return node->isElementNode() && toElement(node)->isTextFormControl(); -} - -inline bool isHTMLTextFormControlElement(const Node& node) +inline bool isHTMLTextFormControlElement(const Element& element) { - return node.isElementNode() && toElement(node).isTextFormControl(); + return element.isTextFormControl(); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLTextFormControlElement); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLTextFormControlElement); HTMLTextFormControlElement* enclosingTextFormControl(const Position&); +HTMLTextFormControlElement* enclosingTextFormControl(Node*); } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElementTest.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElementTest.cpp new file mode 100644 index 00000000000..1134854814f --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTextFormControlElementTest.cpp @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/HTMLTextFormControlElement.h" + +#include "core/frame/FrameView.h" +#include "core/html/HTMLDocument.h" +#include "core/testing/DummyPageHolder.h" +#include "wtf/OwnPtr.h" +#include <gtest/gtest.h> + +using namespace WebCore; + +namespace { + +class HTMLTextFormControlElementTest : public ::testing::Test { +protected: + virtual void SetUp() OVERRIDE; + + HTMLTextFormControlElement& textControl() const { return *m_textControl; } + +private: + OwnPtr<DummyPageHolder> m_dummyPageHolder; + + RefPtrWillBePersistent<HTMLTextFormControlElement> m_textControl; +}; + +void HTMLTextFormControlElementTest::SetUp() +{ + m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); + HTMLDocument& document = toHTMLDocument(m_dummyPageHolder->document()); + document.documentElement()->setInnerHTML("<body><textarea id=textarea></textarea></body>", ASSERT_NO_EXCEPTION); + document.view()->updateLayoutAndStyleIfNeededRecursive(); + m_textControl = toHTMLTextFormControlElement(document.getElementById("textarea")); + m_textControl->focus(); +} + +TEST_F(HTMLTextFormControlElementTest, SetSelectionRange) +{ + EXPECT_EQ(0, textControl().selectionStart()); + EXPECT_EQ(0, textControl().selectionEnd()); + + textControl().setInnerEditorValue("Hello, text form."); + EXPECT_EQ(0, textControl().selectionStart()); + EXPECT_EQ(0, textControl().selectionEnd()); + + textControl().setSelectionRange(1, 3); + EXPECT_EQ(1, textControl().selectionStart()); + EXPECT_EQ(3, textControl().selectionEnd()); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp index c9fdaedc0f2..33060e20b43 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp @@ -23,8 +23,9 @@ #include "config.h" #include "core/html/HTMLTitleElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" +#include "core/dom/ChildListMutationScope.h" #include "core/dom/Document.h" #include "core/dom/Text.h" #include "core/rendering/style/RenderStyle.h" @@ -37,15 +38,13 @@ using namespace HTMLNames; inline HTMLTitleElement::HTMLTitleElement(Document& document) : HTMLElement(titleTag, document) + , m_ignoreTitleUpdatesWhenChildrenChange(false) { setHasCustomStyleCallbacks(); ScriptWrappable::init(this); } -PassRefPtr<HTMLTitleElement> HTMLTitleElement::create(Document& document) -{ - return adoptRef(new HTMLTitleElement(document)); -} +DEFINE_NODE_FACTORY(HTMLTitleElement) Node::InsertionNotificationRequest HTMLTitleElement::insertedInto(ContainerNode* insertionPoint) { @@ -65,7 +64,7 @@ void HTMLTitleElement::removedFrom(ContainerNode* insertionPoint) void HTMLTitleElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (inDocument() && !isInShadowTree()) + if (inDocument() && !isInShadowTree() && !m_ignoreTitleUpdatesWhenChildrenChange) document().setTitleElement(text(), this); } @@ -83,23 +82,16 @@ String HTMLTitleElement::text() const void HTMLTitleElement::setText(const String &value) { - RefPtr<Node> protectFromMutationEvents(this); + RefPtrWillBeRawPtr<Node> protectFromMutationEvents(this); + ChildListMutationScope mutation(*this); - int numChildren = childNodeCount(); + // Avoid calling Document::setTitleElement() during intermediate steps. + m_ignoreTitleUpdatesWhenChildrenChange = !value.isEmpty(); + removeChildren(); + m_ignoreTitleUpdatesWhenChildrenChange = false; - if (numChildren == 1 && firstChild()->isTextNode()) - toText(firstChild())->setData(value); - else { - // We make a copy here because entity of "value" argument can be Document::m_title, - // which goes empty during removeChildren() invocation below, - // which causes HTMLTitleElement::childrenChanged(), which ends up Document::setTitle(). - String valueCopy(value); - - if (numChildren > 0) - removeChildren(); - - appendChild(document().createTextNode(valueCopy.impl()), IGNORE_EXCEPTION); - } + if (!value.isEmpty()) + appendChild(document().createTextNode(value.impl()), IGNORE_EXCEPTION); } } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.h index 988f77ac96e..76f2e6bfb9f 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTitleElement.h @@ -28,7 +28,7 @@ namespace WebCore { class HTMLTitleElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLTitleElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLTitleElement); String text() const; void setText(const String&); @@ -38,20 +38,10 @@ private: virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; virtual void removedFrom(ContainerNode*) OVERRIDE; - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); -}; - -inline bool isHTMLTitleElement(const Node* node) -{ - return node->hasTagName(HTMLNames::titleTag); -} + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; -inline bool isHTMLTitleElement(const Element* element) -{ - return element->hasTagName(HTMLNames::titleTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLTitleElement, hasTagName(HTMLNames::titleTag)); + bool m_ignoreTitleUpdatesWhenChildrenChange; +}; } //namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp index 0182bcef28f..0c1bae6eeb0 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp @@ -26,15 +26,13 @@ #include "config.h" #include "core/html/HTMLTrackElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/events/Event.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLMediaElement.h" -#include "core/frame/ContentSecurityPolicy.h" #include "platform/Logging.h" -using namespace std; - namespace WebCore { using namespace HTMLNames; @@ -58,15 +56,14 @@ inline HTMLTrackElement::HTMLTrackElement(Document& document) ScriptWrappable::init(this); } +DEFINE_NODE_FACTORY(HTMLTrackElement) + HTMLTrackElement::~HTMLTrackElement() { +#if !ENABLE(OILPAN) if (m_track) - m_track->clearClient(); -} - -PassRefPtr<HTMLTrackElement> HTMLTrackElement::create(Document& document) -{ - return adoptRef(new HTMLTrackElement(document)); + m_track->clearTrackElement(); +#endif } Node::InsertionNotificationRequest HTMLTrackElement::insertedInto(ContainerNode* insertionPoint) @@ -79,14 +76,14 @@ Node::InsertionNotificationRequest HTMLTrackElement::insertedInto(ContainerNode* HTMLElement::insertedInto(insertionPoint); HTMLMediaElement* parent = mediaElement(); if (insertionPoint == parent) - parent->didAddTrack(this); + parent->didAddTrackElement(this); return InsertionDone; } void HTMLTrackElement::removedFrom(ContainerNode* insertionPoint) { - if (!parentNode() && isHTMLMediaElement(insertionPoint)) - toHTMLMediaElement(insertionPoint)->didRemoveTrack(this); + if (!parentNode() && isHTMLMediaElement(*insertionPoint)) + toHTMLMediaElement(insertionPoint)->didRemoveTrackElement(this); HTMLElement::removedFrom(insertionPoint); } @@ -162,7 +159,7 @@ void HTMLTrackElement::scheduleLoad() return; // 4. Run the remainder of these steps asynchronously, allowing whatever caused these steps to run to continue. - m_loadTimer.startOneShot(0); + m_loadTimer.startOneShot(0, FROM_HERE); } void HTMLTrackElement::loadTimerFired(Timer<HTMLTrackElement>*) @@ -207,7 +204,7 @@ bool HTMLTrackElement::canLoadUrl(const KURL& url) return false; } - return dispatchBeforeLoadEvent(url.string()); + return true; } void HTMLTrackElement::didCompleteLoad(LoadStatus status) @@ -264,53 +261,18 @@ const AtomicString& HTMLTrackElement::mediaElementCrossOriginAttribute() const return nullAtom; } -void HTMLTrackElement::textTrackKindChanged(TextTrack* track) -{ - if (HTMLMediaElement* parent = mediaElement()) - return parent->textTrackKindChanged(track); -} - -void HTMLTrackElement::textTrackModeChanged(TextTrack* track) -{ - // Since we've moved to a new parent, we may now be able to load. - if (readyState() == HTMLTrackElement::NONE) - scheduleLoad(); - - if (HTMLMediaElement* parent = mediaElement()) - return parent->textTrackModeChanged(track); -} - -void HTMLTrackElement::textTrackAddCues(TextTrack* track, const TextTrackCueList* cues) -{ - if (HTMLMediaElement* parent = mediaElement()) - return parent->textTrackAddCues(track, cues); -} - -void HTMLTrackElement::textTrackRemoveCues(TextTrack* track, const TextTrackCueList* cues) -{ - if (HTMLMediaElement* parent = mediaElement()) - return parent->textTrackRemoveCues(track, cues); -} - -void HTMLTrackElement::textTrackAddCue(TextTrack* track, PassRefPtr<TextTrackCue> cue) -{ - if (HTMLMediaElement* parent = mediaElement()) - return parent->textTrackAddCue(track, cue); -} - -void HTMLTrackElement::textTrackRemoveCue(TextTrack* track, PassRefPtr<TextTrackCue> cue) -{ - if (HTMLMediaElement* parent = mediaElement()) - return parent->textTrackRemoveCue(track, cue); -} - HTMLMediaElement* HTMLTrackElement::mediaElement() const { Element* parent = parentElement(); - if (parent && parent->isMediaElement()) - return toHTMLMediaElement(parentNode()); + if (isHTMLMediaElement(parent)) + return toHTMLMediaElement(parent); return 0; } +void HTMLTrackElement::trace(Visitor* visitor) +{ + visitor->trace(m_track); + HTMLElement::trace(visitor); } +} diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.h index 9e70146d56d..6657fd51f8d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.h @@ -29,14 +29,15 @@ #include "core/html/HTMLElement.h" #include "core/html/track/LoadableTextTrack.h" #include "core/html/track/TextTrack.h" +#include "platform/heap/Handle.h" namespace WebCore { class HTMLMediaElement; -class HTMLTrackElement FINAL : public HTMLElement, public TextTrackClient { +class HTMLTrackElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLTrackElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLTrackElement); const AtomicString& kind(); void setKind(const AtomicString&); @@ -54,6 +55,8 @@ public: const AtomicString& mediaElementCrossOriginAttribute() const; + virtual void trace(Visitor*) OVERRIDE; + private: explicit HTMLTrackElement(Document&); virtual ~HTMLTrackElement(); @@ -69,23 +72,13 @@ private: HTMLMediaElement* mediaElement() const; - // TextTrackClient - virtual void textTrackModeChanged(TextTrack*) OVERRIDE; - virtual void textTrackKindChanged(TextTrack*) OVERRIDE; - virtual void textTrackAddCues(TextTrack*, const TextTrackCueList*) OVERRIDE; - virtual void textTrackRemoveCues(TextTrack*, const TextTrackCueList*) OVERRIDE; - virtual void textTrackAddCue(TextTrack*, PassRefPtr<TextTrackCue>) OVERRIDE; - virtual void textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue>) OVERRIDE; - LoadableTextTrack* ensureTrack(); bool canLoadUrl(const KURL&); - RefPtr<LoadableTextTrack> m_track; + RefPtrWillBeMember<LoadableTextTrack> m_track; Timer<HTMLTrackElement> m_loadTimer; }; -DEFINE_NODE_TYPE_CASTS(HTMLTrackElement, hasTagName(HTMLNames::trackTag)); - } #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.idl index da7e22e9e64..7ad3e606e3d 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLTrackElement.idl @@ -23,11 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -[ - RuntimeEnabled=VideoTrack -] interface HTMLTrackElement : HTMLElement { +interface HTMLTrackElement : HTMLElement { attribute DOMString kind; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString src; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString src; [Reflect] attribute DOMString srclang; [Reflect] attribute DOMString label; [Reflect] attribute boolean default; @@ -40,4 +38,6 @@ readonly attribute unsigned short readyState; readonly attribute TextTrack track; + + [Reflect, RuntimeEnabled=SubresourceIntegrity] attribute DOMString integrity; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.cpp index 9eb6e55e679..0261d0f7d78 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.cpp @@ -23,23 +23,20 @@ #include "config.h" #include "core/html/HTMLUListElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" namespace WebCore { using namespace HTMLNames; -HTMLUListElement::HTMLUListElement(Document& document) +inline HTMLUListElement::HTMLUListElement(Document& document) : HTMLElement(ulTag, document) { ScriptWrappable::init(this); } -PassRefPtr<HTMLUListElement> HTMLUListElement::create(Document& document) -{ - return adoptRef(new HTMLUListElement(document)); -} +DEFINE_NODE_FACTORY(HTMLUListElement) bool HTMLUListElement::isPresentationAttribute(const QualifiedName& name) const { diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.h index 899467c4945..9a7c238fb38 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLUListElement.h @@ -29,7 +29,7 @@ namespace WebCore { class HTMLUListElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLUListElement> create(Document&); + DECLARE_NODE_FACTORY(HTMLUListElement); private: explicit HTMLUListElement(Document&); diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLUnknownElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLUnknownElement.h index 1c1794c0ed5..09d87365f01 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLUnknownElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLUnknownElement.h @@ -36,9 +36,9 @@ namespace WebCore { class HTMLUnknownElement FINAL : public HTMLElement { public: - static PassRefPtr<HTMLUnknownElement> create(const QualifiedName& tagName, Document& document) + static PassRefPtrWillBeRawPtr<HTMLUnknownElement> create(const QualifiedName& tagName, Document& document) { - return adoptRef(new HTMLUnknownElement(tagName, document)); + return adoptRefWillBeNoop(new HTMLUnknownElement(tagName, document)); } virtual bool isHTMLUnknownElement() const OVERRIDE { return true; } @@ -51,12 +51,17 @@ private: } }; -inline bool isHTMLUnknownElement(const Node& node) +inline bool isHTMLUnknownElement(const Element& element) { - return node.isElementNode() && toHTMLElement(node).isHTMLUnknownElement(); + return element.isHTMLElement() && toHTMLElement(element).isHTMLUnknownElement(); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLUnknownElement); +inline bool isHTMLUnknownElement(const HTMLElement& element) +{ + return element.isHTMLUnknownElement(); +} + +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLUnknownElement); } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp index b5c1c00ebb4..c03e09716cf 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp @@ -26,15 +26,17 @@ #include "config.h" #include "core/html/HTMLVideoElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/dom/Attribute.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/shadow/ShadowRoot.h" +#include "core/frame/Settings.h" #include "core/html/HTMLImageLoader.h" +#include "core/html/canvas/CanvasRenderingContext.h" #include "core/html/parser/HTMLParserIdioms.h" -#include "core/frame/Settings.h" #include "core/rendering/RenderImage.h" #include "core/rendering/RenderVideo.h" #include "platform/UserGestureIndicator.h" @@ -43,19 +45,26 @@ namespace WebCore { using namespace HTMLNames; -inline HTMLVideoElement::HTMLVideoElement(Document& document, bool createdByParser) - : HTMLMediaElement(videoTag, document, createdByParser) +inline HTMLVideoElement::HTMLVideoElement(Document& document) + : HTMLMediaElement(videoTag, document) { ScriptWrappable::init(this); if (document.settings()) - m_defaultPosterURL = document.settings()->defaultVideoPosterURL(); + m_defaultPosterURL = AtomicString(document.settings()->defaultVideoPosterURL()); +} + +PassRefPtrWillBeRawPtr<HTMLVideoElement> HTMLVideoElement::create(Document& document) +{ + RefPtrWillBeRawPtr<HTMLVideoElement> video = adoptRefWillBeNoop(new HTMLVideoElement(document)); + video->ensureUserAgentShadowRoot(); + video->suspendIfNeeded(); + return video.release(); } -PassRefPtr<HTMLVideoElement> HTMLVideoElement::create(Document& document, bool createdByParser) +void HTMLVideoElement::trace(Visitor* visitor) { - RefPtr<HTMLVideoElement> videoElement(adoptRef(new HTMLVideoElement(document, createdByParser))); - videoElement->suspendIfNeeded(); - return videoElement.release(); + visitor->trace(m_imageLoader); + HTMLMediaElement::trace(visitor); } bool HTMLVideoElement::rendererIsNeeded(const RenderStyle& style) @@ -75,7 +84,7 @@ void HTMLVideoElement::attach(const AttachContext& context) updateDisplayState(); if (shouldDisplayPosterImage()) { if (!m_imageLoader) - m_imageLoader = adoptPtr(new HTMLImageLoader(this)); + m_imageLoader = HTMLImageLoader::create(this); m_imageLoader->updateFromElement(); if (renderer()) toRenderImage(renderer())->imageResource()->setImageResource(m_imageLoader->image()); @@ -107,12 +116,15 @@ void HTMLVideoElement::parseAttribute(const QualifiedName& name, const AtomicStr updateDisplayState(); if (shouldDisplayPosterImage()) { if (!m_imageLoader) - m_imageLoader = adoptPtr(new HTMLImageLoader(this)); + m_imageLoader = HTMLImageLoader::create(this); m_imageLoader->updateFromElementIgnoringPreviousError(); } else { if (renderer()) toRenderImage(renderer())->imageResource()->setImageResource(0); } + // Notify the player when the poster image URL changes. + if (player()) + player()->setPoster(posterImageURL()); } else HTMLMediaElement::parseAttribute(name, value); } @@ -122,7 +134,7 @@ bool HTMLVideoElement::supportsFullscreen() const if (!document().page()) return false; - if (!player() || !player()->supportsFullscreen()) + if (!player()) return false; return true; @@ -130,16 +142,16 @@ bool HTMLVideoElement::supportsFullscreen() const unsigned HTMLVideoElement::videoWidth() const { - if (!player()) + if (!webMediaPlayer()) return 0; - return player()->naturalSize().width(); + return webMediaPlayer()->naturalSize().width; } unsigned HTMLVideoElement::videoHeight() const { - if (!player()) + if (!webMediaPlayer()) return 0; - return player()->naturalSize().height(); + return webMediaPlayer()->naturalSize().height; } bool HTMLVideoElement::isURLAttribute(const Attribute& attribute) const @@ -163,7 +175,9 @@ void HTMLVideoElement::setDisplayMode(DisplayMode mode) if (!poster.isEmpty()) { // We have a poster path, but only show it until the user triggers display by playing or seeking and the // media engine has something to display. - if (mode == Video && !hasAvailableVideoFrame()) + // Don't show the poster if there is a seek operation or + // the video has restarted because of loop attribute + if (mode == Video && oldMode == Poster && !hasAvailableVideoFrame()) mode = PosterWaitingForVideo; } @@ -181,7 +195,7 @@ void HTMLVideoElement::updateDisplayState() setDisplayMode(Poster); } -void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect) +void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect) const { MediaPlayer* player = HTMLMediaElement::player(); if (!player) @@ -189,7 +203,7 @@ void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, cons player->paint(context, destRect); } -bool HTMLVideoElement::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY) +bool HTMLVideoElement::copyVideoTextureToPlatformTexture(blink::WebGraphicsContext3D* context, Platform3DObject texture, GLint level, GLenum type, GLenum internalFormat, bool premultiplyAlpha, bool flipY) { if (!player()) return false; @@ -198,10 +212,10 @@ bool HTMLVideoElement::copyVideoTextureToPlatformTexture(GraphicsContext3D* cont bool HTMLVideoElement::hasAvailableVideoFrame() const { - if (!player()) + if (!webMediaPlayer()) return false; - return player()->hasVideo() && player()->readyState() >= MediaPlayer::HaveCurrentData; + return webMediaPlayer()->hasVideo() && webMediaPlayer()->readyState() >= blink::WebMediaPlayer::ReadyStateHaveCurrentData; } void HTMLVideoElement::webkitEnterFullscreen(ExceptionState& exceptionState) @@ -209,12 +223,6 @@ void HTMLVideoElement::webkitEnterFullscreen(ExceptionState& exceptionState) if (isFullscreen()) return; - // Generate an exception if this isn't called in response to a user gesture, or if the - // element does not support fullscreen. - if (userGestureRequiredForFullscreen() && !UserGestureIndicator::processingUserGesture()) { - exceptionState.throwDOMException(InvalidStateError, "This element may only enter fullscreen mode in response to a user gesture ('click', for example)."); - return; - } if (!supportsFullscreen()) { exceptionState.throwDOMException(InvalidStateError, "This element does not support fullscreen mode."); return; @@ -248,18 +256,18 @@ void HTMLVideoElement::didMoveToNewDocument(Document& oldDocument) unsigned HTMLVideoElement::webkitDecodedFrameCount() const { - if (!player()) + if (!webMediaPlayer()) return 0; - return player()->decodedFrameCount(); + return webMediaPlayer()->decodedFrameCount(); } unsigned HTMLVideoElement::webkitDroppedFrameCount() const { - if (!player()) + if (!webMediaPlayer()) return 0; - return player()->droppedFrameCount(); + return webMediaPlayer()->droppedFrameCount(); } KURL HTMLVideoElement::posterImageURL() const @@ -270,4 +278,39 @@ KURL HTMLVideoElement::posterImageURL() const return document().completeURL(url); } +KURL HTMLVideoElement::mediaPlayerPosterURL() +{ + return posterImageURL(); +} + +PassRefPtr<Image> HTMLVideoElement::getSourceImageForCanvas(SourceImageMode mode, SourceImageStatus* status) const +{ + if (!hasAvailableVideoFrame()) { + *status = InvalidSourceImageStatus; + return nullptr; + } + + IntSize intrinsicSize(videoWidth(), videoHeight()); + OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(intrinsicSize); + if (!imageBuffer) { + *status = InvalidSourceImageStatus; + return nullptr; + } + + paintCurrentFrameInContext(imageBuffer->context(), IntRect(IntPoint(0, 0), intrinsicSize)); + + *status = NormalSourceImageStatus; + return imageBuffer->copyImage(mode == CopySourceImageIfVolatile ? CopyBackingStore : DontCopyBackingStore, Unscaled); +} + +bool HTMLVideoElement::wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const +{ + return !hasSingleSecurityOrigin() || (!(webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) && destinationSecurityOrigin->taintsCanvas(currentSrc())); +} + +FloatSize HTMLVideoElement::sourceSize() const +{ + return FloatSize(videoWidth(), videoHeight()); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.h b/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.h index 4d729f39fa5..fa8f5fe1984 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.h @@ -27,15 +27,21 @@ #define HTMLVideoElement_h #include "core/html/HTMLMediaElement.h" +#include "core/html/canvas/CanvasImageSource.h" + +namespace blink { +class WebGraphicsContext3D; +} namespace WebCore { class ExceptionState; class HTMLImageLoader; -class HTMLVideoElement FINAL : public HTMLMediaElement { +class HTMLVideoElement FINAL : public HTMLMediaElement, public CanvasImageSource { public: - static PassRefPtr<HTMLVideoElement> create(Document&, bool createdByParser = false); + static PassRefPtrWillBeRawPtr<HTMLVideoElement> create(Document&); + virtual void trace(Visitor*) OVERRIDE; unsigned videoWidth() const; unsigned videoHeight() const; @@ -51,18 +57,28 @@ public: unsigned webkitDroppedFrameCount() const; // Used by canvas to gain raw pixel access - void paintCurrentFrameInContext(GraphicsContext*, const IntRect&); + void paintCurrentFrameInContext(GraphicsContext*, const IntRect&) const; // Used by WebGL to do GPU-GPU textures copy if possible. // See more details at MediaPlayer::copyVideoTextureToPlatformTexture() defined in Source/WebCore/platform/graphics/MediaPlayer.h. - bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY); + bool copyVideoTextureToPlatformTexture(blink::WebGraphicsContext3D*, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY); bool shouldDisplayPosterImage() const { return displayMode() == Poster || displayMode() == PosterWaitingForVideo; } KURL posterImageURL() const; + // FIXME: Remove this when WebMediaPlayerClientImpl::loadInternal does not depend on it. + virtual KURL mediaPlayerPosterURL() OVERRIDE; + + // CanvasImageSource implementation + virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus*) const OVERRIDE; + virtual bool isVideoElement() const OVERRIDE { return true; } + virtual bool wouldTaintOrigin(SecurityOrigin*) const OVERRIDE; + virtual FloatSize sourceSize() const OVERRIDE; + virtual const KURL& sourceURL() const OVERRIDE { return currentSrc(); } + private: - HTMLVideoElement(Document&, bool); + HTMLVideoElement(Document&); virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; @@ -70,9 +86,8 @@ private: virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE; virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; - virtual bool isVideo() const OVERRIDE { return true; } - virtual bool hasVideo() const OVERRIDE { return player() && player()->hasVideo(); } - virtual bool supportsFullscreen() const OVERRIDE; + virtual bool hasVideo() const OVERRIDE { return webMediaPlayer() && webMediaPlayer()->hasVideo(); } + bool supportsFullscreen() const; virtual bool isURLAttribute(const Attribute&) const OVERRIDE; virtual const AtomicString imageSourceURL() const OVERRIDE; @@ -81,23 +96,11 @@ private: virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE; virtual void setDisplayMode(DisplayMode) OVERRIDE; - OwnPtr<HTMLImageLoader> m_imageLoader; + OwnPtrWillBeMember<HTMLImageLoader> m_imageLoader; AtomicString m_defaultPosterURL; }; -inline bool isHTMLVideoElement(const Node* node) -{ - return node->hasTagName(HTMLNames::videoTag); -} - -inline bool isHTMLVideoElement(const Element* element) -{ - return element->hasTagName(HTMLNames::videoTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLVideoElement, hasTagName(HTMLNames::videoTag)); - } //namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.idl b/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.idl index 4448cd23542..30825e5b91c 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLVideoElement.idl @@ -30,17 +30,17 @@ [Reflect] attribute unsigned long height; readonly attribute unsigned long videoWidth; readonly attribute unsigned long videoHeight; - [Reflect, URL, PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute DOMString poster; + [Reflect, URL, LogActivity=SetterOnly] attribute DOMString poster; - [MeasureAs=PrefixedVideoSupportsFullscreen] readonly attribute boolean webkitSupportsFullscreen; - [MeasureAs=PrefixedVideoDisplayingFullscreen] readonly attribute boolean webkitDisplayingFullscreen; + [RuntimeEnabled=PrefixedVideoFullscreen, DeprecateAs=PrefixedVideoSupportsFullscreen] readonly attribute boolean webkitSupportsFullscreen; + [RuntimeEnabled=PrefixedVideoFullscreen, DeprecateAs=PrefixedVideoDisplayingFullscreen] readonly attribute boolean webkitDisplayingFullscreen; - [MeasureAs=PrefixedVideoEnterFullscreen, RaisesException, PerWorldBindings, ActivityLogging=ForAllWorlds] void webkitEnterFullscreen(); - [MeasureAs=PrefixedVideoExitFullscreen] void webkitExitFullscreen(); + [RuntimeEnabled=PrefixedVideoFullscreen, DeprecateAs=PrefixedVideoEnterFullscreen, RaisesException, LogActivity, LogAllWorlds] void webkitEnterFullscreen(); + [RuntimeEnabled=PrefixedVideoFullscreen, DeprecateAs=PrefixedVideoExitFullscreen] void webkitExitFullscreen(); // Note the different capitalization of the "S" in FullScreen. - [MeasureAs=PrefixedVideoEnterFullScreen, ImplementedAs=webkitEnterFullscreen, RaisesException, PerWorldBindings, ActivityLogging=ForAllWorlds] void webkitEnterFullScreen(); - [MeasureAs=PrefixedVideoExitFullScreen, ImplementedAs=webkitExitFullscreen] void webkitExitFullScreen(); + [RuntimeEnabled=PrefixedVideoFullscreen, DeprecateAs=PrefixedVideoEnterFullScreen, ImplementedAs=webkitEnterFullscreen, RaisesException, LogActivity, LogAllWorlds] void webkitEnterFullScreen(); + [RuntimeEnabled=PrefixedVideoFullscreen, DeprecateAs=PrefixedVideoExitFullScreen, ImplementedAs=webkitExitFullscreen] void webkitExitFullScreen(); // The number of frames that have been decoded and made available for // playback. diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp b/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp index 4a55226d0b4..80bfd5cf740 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp +++ b/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "core/html/HTMLViewSourceDocument.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/StyleEngine.h" #include "core/dom/Text.h" #include "core/html/HTMLAnchorElement.h" @@ -47,6 +47,12 @@ namespace WebCore { using namespace HTMLNames; +namespace { + +const char kXSSDetected[] = "Token contains a reflected XSS vector"; + +} // namespace + HTMLViewSourceDocument::HTMLViewSourceDocument(const DocumentInit& initializer, const String& mimeType) : HTMLDocument(initializer) , m_type(mimeType) @@ -58,27 +64,27 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(const DocumentInit& initializer, lockCompatibilityMode(); } -PassRefPtr<DocumentParser> HTMLViewSourceDocument::createParser() +PassRefPtrWillBeRawPtr<DocumentParser> HTMLViewSourceDocument::createParser() { - return HTMLViewSourceParser::create(this, m_type); + return HTMLViewSourceParser::create(*this, m_type); } void HTMLViewSourceDocument::createContainingTable() { - RefPtr<HTMLHtmlElement> html = HTMLHtmlElement::create(*this); + RefPtrWillBeRawPtr<HTMLHtmlElement> html = HTMLHtmlElement::create(*this); parserAppendChild(html); - RefPtr<HTMLHeadElement> head = HTMLHeadElement::create(*this); + RefPtrWillBeRawPtr<HTMLHeadElement> head = HTMLHeadElement::create(*this); html->parserAppendChild(head); - RefPtr<HTMLBodyElement> body = HTMLBodyElement::create(*this); + RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*this); html->parserAppendChild(body); // Create a line gutter div that can be used to make sure the gutter extends down the height of the whole // document. - RefPtr<HTMLDivElement> div = HTMLDivElement::create(*this); + RefPtrWillBeRawPtr<HTMLDivElement> div = HTMLDivElement::create(*this); div->setAttribute(classAttr, "webkit-line-gutter-backdrop"); body->parserAppendChild(div); - RefPtr<HTMLTableElement> table = HTMLTableElement::create(*this); + RefPtrWillBeRawPtr<HTMLTableElement> table = HTMLTableElement::create(*this); body->parserAppendChild(table); m_tbody = HTMLTableSectionElement::create(tbodyTag, *this); table->parserAppendChild(m_tbody); @@ -86,7 +92,7 @@ void HTMLViewSourceDocument::createContainingTable() m_lineNumber = 0; } -void HTMLViewSourceDocument::addSource(const String& source, HTMLToken& token) +void HTMLViewSourceDocument::addSource(const String& source, HTMLToken& token, SourceAnnotation annotation) { if (!m_current) createContainingTable(); @@ -103,13 +109,13 @@ void HTMLViewSourceDocument::addSource(const String& source, HTMLToken& token) break; case HTMLToken::StartTag: case HTMLToken::EndTag: - processTagToken(source, token); + processTagToken(source, token, annotation); break; case HTMLToken::Comment: processCommentToken(source, token); break; case HTMLToken::Character: - processCharacterToken(source, token); + processCharacterToken(source, token, annotation); break; } } @@ -128,8 +134,9 @@ void HTMLViewSourceDocument::processEndOfFileToken(const String& source, HTMLTok m_current = m_td; } -void HTMLViewSourceDocument::processTagToken(const String& source, HTMLToken& token) +void HTMLViewSourceDocument::processTagToken(const String& source, HTMLToken& token, SourceAnnotation annotation) { + maybeAddSpanForAnnotation(annotation); m_current = addSpanWithClassName("webkit-html-tag"); AtomicString tagName(token.name()); @@ -139,21 +146,21 @@ void HTMLViewSourceDocument::processTagToken(const String& source, HTMLToken& to while (index < source.length()) { if (iter == token.attributes().end()) { // We want to show the remaining characters in the token. - index = addRange(source, index, source.length(), ""); + index = addRange(source, index, source.length(), emptyAtom); ASSERT(index == source.length()); break; } AtomicString name(iter->name); - String value = StringImpl::create8BitIfPossible(iter->value); + AtomicString value(StringImpl::create8BitIfPossible(iter->value)); - index = addRange(source, index, iter->nameRange.start - token.startIndex(), ""); + index = addRange(source, index, iter->nameRange.start - token.startIndex(), emptyAtom); index = addRange(source, index, iter->nameRange.end - token.startIndex(), "webkit-html-attribute-name"); if (tagName == baseTag && name == hrefAttr) addBase(value); - index = addRange(source, index, iter->valueRange.start - token.startIndex(), ""); + index = addRange(source, index, iter->valueRange.start - token.startIndex(), emptyAtom); bool isLink = name == srcAttr || name == hrefAttr; index = addRange(source, index, iter->valueRange.end - token.startIndex(), "webkit-html-attribute-value", isLink, tagName == aTag, value); @@ -170,19 +177,19 @@ void HTMLViewSourceDocument::processCommentToken(const String& source, HTMLToken m_current = m_td; } -void HTMLViewSourceDocument::processCharacterToken(const String& source, HTMLToken&) +void HTMLViewSourceDocument::processCharacterToken(const String& source, HTMLToken&, SourceAnnotation annotation) { - addText(source, ""); + addText(source, "", annotation); } -PassRefPtr<Element> HTMLViewSourceDocument::addSpanWithClassName(const AtomicString& className) +PassRefPtrWillBeRawPtr<Element> HTMLViewSourceDocument::addSpanWithClassName(const AtomicString& className) { if (m_current == m_tbody) { addLine(className); return m_current; } - RefPtr<HTMLSpanElement> span = HTMLSpanElement::create(*this); + RefPtrWillBeRawPtr<HTMLSpanElement> span = HTMLSpanElement::create(*this); span->setAttribute(classAttr, className); m_current->parserAppendChild(span); return span.release(); @@ -191,11 +198,11 @@ PassRefPtr<Element> HTMLViewSourceDocument::addSpanWithClassName(const AtomicStr void HTMLViewSourceDocument::addLine(const AtomicString& className) { // Create a table row. - RefPtr<HTMLTableRowElement> trow = HTMLTableRowElement::create(*this); + RefPtrWillBeRawPtr<HTMLTableRowElement> trow = HTMLTableRowElement::create(*this); m_tbody->parserAppendChild(trow); // Create a cell that will hold the line number (it is generated in the stylesheet using counters). - RefPtr<HTMLTableCellElement> td = HTMLTableCellElement::create(tdTag, *this); + RefPtrWillBeRawPtr<HTMLTableCellElement> td = HTMLTableCellElement::create(tdTag, *this); td->setAttribute(classAttr, "webkit-line-number"); td->setIntegralAttribute(valueAttr, ++m_lineNumber); trow->parserAppendChild(td); @@ -216,14 +223,14 @@ void HTMLViewSourceDocument::addLine(const AtomicString& className) void HTMLViewSourceDocument::finishLine() { - if (!m_current->hasChildNodes()) { - RefPtr<HTMLBRElement> br = HTMLBRElement::create(*this); + if (!m_current->hasChildren()) { + RefPtrWillBeRawPtr<HTMLBRElement> br = HTMLBRElement::create(*this); m_current->parserAppendChild(br); } m_current = m_tbody; } -void HTMLViewSourceDocument::addText(const String& text, const AtomicString& className) +void HTMLViewSourceDocument::addText(const String& text, const AtomicString& className, SourceAnnotation annotation) { if (text.isEmpty()) return; @@ -242,14 +249,16 @@ void HTMLViewSourceDocument::addText(const String& text, const AtomicString& cla finishLine(); continue; } - RefPtr<Text> t = Text::create(*this, substring); - m_current->parserAppendChild(t); + RefPtrWillBeRawPtr<Element> oldElement = m_current; + maybeAddSpanForAnnotation(annotation); + m_current->parserAppendChild(Text::create(*this, substring)); + m_current = oldElement; if (i < size - 1) finishLine(); } } -int HTMLViewSourceDocument::addRange(const String& source, int start, int end, const String& className, bool isLink, bool isAnchor, const String& link) +int HTMLViewSourceDocument::addRange(const String& source, int start, int end, const AtomicString& className, bool isLink, bool isAnchor, const AtomicString& link) { ASSERT(start <= end); if (start == end) @@ -268,21 +277,21 @@ int HTMLViewSourceDocument::addRange(const String& source, int start, int end, c return end; } -PassRefPtr<Element> HTMLViewSourceDocument::addBase(const AtomicString& href) +PassRefPtrWillBeRawPtr<Element> HTMLViewSourceDocument::addBase(const AtomicString& href) { - RefPtr<HTMLBaseElement> base = HTMLBaseElement::create(*this); + RefPtrWillBeRawPtr<HTMLBaseElement> base = HTMLBaseElement::create(*this); base->setAttribute(hrefAttr, href); m_current->parserAppendChild(base); return base.release(); } -PassRefPtr<Element> HTMLViewSourceDocument::addLink(const AtomicString& url, bool isAnchor) +PassRefPtrWillBeRawPtr<Element> HTMLViewSourceDocument::addLink(const AtomicString& url, bool isAnchor) { if (m_current == m_tbody) addLine("webkit-html-tag"); // Now create a link for the attribute value instead of a span. - RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::create(*this); + RefPtrWillBeRawPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::create(*this); const char* classValue; if (isAnchor) classValue = "webkit-html-attribute-value webkit-html-external-link"; @@ -295,4 +304,20 @@ PassRefPtr<Element> HTMLViewSourceDocument::addLink(const AtomicString& url, boo return anchor.release(); } +void HTMLViewSourceDocument::maybeAddSpanForAnnotation(SourceAnnotation annotation) +{ + if (annotation == AnnotateSourceAsXSS) { + m_current = addSpanWithClassName("webkit-highlight"); + m_current->setAttribute(titleAttr, kXSSDetected); + } +} + +void HTMLViewSourceDocument::trace(Visitor* visitor) +{ + visitor->trace(m_current); + visitor->trace(m_tbody); + visitor->trace(m_td); + HTMLDocument::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h b/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h index a1988cc7e2c..29e44ae7a98 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLViewSourceDocument.h @@ -35,37 +35,46 @@ class HTMLToken; class HTMLViewSourceDocument FINAL : public HTMLDocument { public: - static PassRefPtr<HTMLViewSourceDocument> create(const DocumentInit& initializer, const String& mimeType) + enum SourceAnnotation { + AnnotateSourceAsSafe, + AnnotateSourceAsXSS + }; + + static PassRefPtrWillBeRawPtr<HTMLViewSourceDocument> create(const DocumentInit& initializer, const String& mimeType) { - return adoptRef(new HTMLViewSourceDocument(initializer, mimeType)); + return adoptRefWillBeNoop(new HTMLViewSourceDocument(initializer, mimeType)); } - void addSource(const String&, HTMLToken&); + void addSource(const String&, HTMLToken&, SourceAnnotation); + + virtual void trace(Visitor*) OVERRIDE; private: HTMLViewSourceDocument(const DocumentInit&, const String& mimeType); - virtual PassRefPtr<DocumentParser> createParser() OVERRIDE; + virtual PassRefPtrWillBeRawPtr<DocumentParser> createParser() OVERRIDE; void processDoctypeToken(const String& source, HTMLToken&); void processEndOfFileToken(const String& source, HTMLToken&); - void processTagToken(const String& source, HTMLToken&); + void processTagToken(const String& source, HTMLToken&, SourceAnnotation); void processCommentToken(const String& source, HTMLToken&); - void processCharacterToken(const String& source, HTMLToken&); + void processCharacterToken(const String& source, HTMLToken&, SourceAnnotation); void createContainingTable(); - PassRefPtr<Element> addSpanWithClassName(const AtomicString&); + PassRefPtrWillBeRawPtr<Element> addSpanWithClassName(const AtomicString&); void addLine(const AtomicString& className); void finishLine(); - void addText(const String& text, const AtomicString& className); - int addRange(const String& source, int start, int end, const String& className, bool isLink = false, bool isAnchor = false, const String& link = String()); - PassRefPtr<Element> addLink(const AtomicString& url, bool isAnchor); - PassRefPtr<Element> addBase(const AtomicString& href); + void addText(const String& text, const AtomicString& className, SourceAnnotation = AnnotateSourceAsSafe); + int addRange(const String& source, int start, int end, const AtomicString& className, bool isLink = false, bool isAnchor = false, const AtomicString& link = nullAtom); + void maybeAddSpanForAnnotation(SourceAnnotation); + + PassRefPtrWillBeRawPtr<Element> addLink(const AtomicString& url, bool isAnchor); + PassRefPtrWillBeRawPtr<Element> addBase(const AtomicString& href); String m_type; - RefPtr<Element> m_current; - RefPtr<HTMLTableSectionElement> m_tbody; - RefPtr<HTMLTableCellElement> m_td; + RefPtrWillBeMember<Element> m_current; + RefPtrWillBeMember<HTMLTableSectionElement> m_tbody; + RefPtrWillBeMember<HTMLTableCellElement> m_td; int m_lineNumber; }; diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportLoaderClient.h b/chromium/third_party/WebKit/Source/core/html/HTMLWBRElement.cpp index 5d510d1248b..74e06d30b05 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportLoaderClient.h +++ b/chromium/third_party/WebKit/Source/core/html/HTMLWBRElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -28,17 +28,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HTMLImportLoaderClient_h -#define HTMLImportLoaderClient_h +#include "config.h" +#include "core/html/HTMLWBRElement.h" + +#include "core/HTMLNames.h" +#include "core/rendering/RenderWordBreak.h" namespace WebCore { -class HTMLImportLoaderClient { -public: - virtual ~HTMLImportLoaderClient() { } - virtual void didFinish() = 0; -}; +using namespace HTMLNames; +inline HTMLWBRElement::HTMLWBRElement(Document& document) + : HTMLElement(wbrTag, document) +{ } -#endif // HTMLImportLoaderClient_h +DEFINE_NODE_FACTORY(HTMLWBRElement) + +RenderObject* HTMLWBRElement::createRenderer(RenderStyle* style) +{ + return new RenderWordBreak(this); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/ime/Composition.idl b/chromium/third_party/WebKit/Source/core/html/HTMLWBRElement.h index 494d2a06b75..0f187e2e309 100644 --- a/chromium/third_party/WebKit/Source/core/html/ime/Composition.idl +++ b/chromium/third_party/WebKit/Source/core/html/HTMLWBRElement.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -28,12 +28,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.w3.org/TR/ime-api/ -[ - NoInterfaceObject -] interface Composition { - readonly attribute DOMString text; - readonly attribute long selectionStart; - readonly attribute long selectionEnd; - sequence<unsigned long> getSegments(); +#ifndef HTMLWBRElement_h +#define HTMLWBRElement_h + +#include "core/html/HTMLElement.h" + +namespace WebCore { + +// <wbr> is an HTMLElement in script, but we use a separate interface here +// so HTMLElement's createRenderer doesn't need to know about it. +class HTMLWBRElement FINAL : public HTMLElement { +public: + DECLARE_NODE_FACTORY(HTMLWBRElement); + +private: + explicit HTMLWBRElement(Document&); + + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; }; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/ImageData.cpp b/chromium/third_party/WebKit/Source/core/html/ImageData.cpp index 64c86c931b6..14b6fbed3ba 100644 --- a/chromium/third_party/WebKit/Source/core/html/ImageData.cpp +++ b/chromium/third_party/WebKit/Source/core/html/ImageData.cpp @@ -29,37 +29,104 @@ #include "config.h" #include "core/html/ImageData.h" +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" +#include "platform/RuntimeEnabledFeatures.h" + namespace WebCore { -PassRefPtr<ImageData> ImageData::create(const IntSize& size) +PassRefPtrWillBeRawPtr<ImageData> ImageData::create(const IntSize& size) { Checked<int, RecordOverflow> dataSize = 4; dataSize *= size.width(); dataSize *= size.height(); if (dataSize.hasOverflowed()) - return 0; + return nullptr; - return adoptRef(new ImageData(size)); + return adoptRefWillBeNoop(new ImageData(size)); } -PassRefPtr<ImageData> ImageData::create(const IntSize& size, PassRefPtr<Uint8ClampedArray> byteArray) +PassRefPtrWillBeRawPtr<ImageData> ImageData::create(const IntSize& size, PassRefPtr<Uint8ClampedArray> byteArray) { Checked<int, RecordOverflow> dataSize = 4; dataSize *= size.width(); dataSize *= size.height(); if (dataSize.hasOverflowed()) - return 0; + return nullptr; if (dataSize.unsafeGet() < 0 || static_cast<unsigned>(dataSize.unsafeGet()) > byteArray->length()) - return 0; + return nullptr; + + return adoptRefWillBeNoop(new ImageData(size, byteArray)); +} + +PassRefPtrWillBeRawPtr<ImageData> ImageData::create(unsigned width, unsigned height, ExceptionState& exceptionState) +{ + if (!RuntimeEnabledFeatures::imageDataConstructorEnabled()) { + exceptionState.throwTypeError("Illegal constructor"); + return nullptr; + } + if (!width || !height) { + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is zero or not a number.", width ? "height" : "width")); + return nullptr; + } + + Checked<unsigned, RecordOverflow> dataSize = 4; + dataSize *= width; + dataSize *= height; + if (dataSize.hasOverflowed()) { + exceptionState.throwDOMException(IndexSizeError, "The requested image size exceeds the supported range."); + return nullptr; + } + + RefPtrWillBeRawPtr<ImageData> imageData = adoptRefWillBeNoop(new ImageData(IntSize(width, height))); + imageData->data()->zeroFill(); + return imageData.release(); +} + +PassRefPtrWillBeRawPtr<ImageData> ImageData::create(Uint8ClampedArray* data, unsigned width, unsigned height, ExceptionState& exceptionState) +{ + if (!RuntimeEnabledFeatures::imageDataConstructorEnabled()) { + exceptionState.throwTypeError("Illegal constructor"); + return nullptr; + } + if (!data) { + exceptionState.throwTypeError("Expected a Uint8ClampedArray as first argument."); + return nullptr; + } + if (!width) { + exceptionState.throwDOMException(IndexSizeError, "The source width is zero or not a number."); + return nullptr; + } + + unsigned length = data->length(); + if (!length) { + exceptionState.throwDOMException(IndexSizeError, "The input data has a zero byte length."); + return nullptr; + } + if (length % 4) { + exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not a multiple of 4."); + return nullptr; + } + length /= 4; + if (length % width) { + exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not a multiple of (4 * width)."); + return nullptr; + } + if (!height) { + height = length / width; + } else if (height != length / width) { + exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not equal to (4 * width * height)."); + return nullptr; + } - return adoptRef(new ImageData(size, byteArray)); + return adoptRefWillBeNoop(new ImageData(IntSize(width, height), data)); } ImageData::ImageData(const IntSize& size) : m_size(size) - , m_data(Uint8ClampedArray::createUninitialized(size.width() * size.height() * 4)) + , m_data(Uint8ClampedArray::create(size.width() * size.height() * 4)) { ScriptWrappable::init(this); } diff --git a/chromium/third_party/WebKit/Source/core/html/ImageData.h b/chromium/third_party/WebKit/Source/core/html/ImageData.h index 5015885998b..94fbaa10c72 100644 --- a/chromium/third_party/WebKit/Source/core/html/ImageData.h +++ b/chromium/third_party/WebKit/Source/core/html/ImageData.h @@ -31,24 +31,31 @@ #include "bindings/v8/ScriptWrappable.h" #include "platform/geometry/IntSize.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/Uint8ClampedArray.h" namespace WebCore { -class ImageData : public RefCounted<ImageData>, public ScriptWrappable { +class ExceptionState; + +class ImageData FINAL : public RefCountedWillBeGarbageCollectedFinalized<ImageData>, public ScriptWrappable { public: - static PassRefPtr<ImageData> create(const IntSize&); - static PassRefPtr<ImageData> create(const IntSize&, PassRefPtr<Uint8ClampedArray>); + static PassRefPtrWillBeRawPtr<ImageData> create(const IntSize&); + static PassRefPtrWillBeRawPtr<ImageData> create(const IntSize&, PassRefPtr<Uint8ClampedArray>); + static PassRefPtrWillBeRawPtr<ImageData> create(unsigned width, unsigned height, ExceptionState&); + static PassRefPtrWillBeRawPtr<ImageData> create(Uint8ClampedArray*, unsigned width, unsigned height, ExceptionState&); IntSize size() const { return m_size; } int width() const { return m_size.width(); } int height() const { return m_size.height(); } Uint8ClampedArray* data() const { return m_data.get(); } + void trace(Visitor*) { } + private: - ImageData(const IntSize&); + explicit ImageData(const IntSize&); ImageData(const IntSize&, PassRefPtr<Uint8ClampedArray>); IntSize m_size; diff --git a/chromium/third_party/WebKit/Source/core/html/ImageData.idl b/chromium/third_party/WebKit/Source/core/html/ImageData.idl index 06847999097..18ed72f2478 100644 --- a/chromium/third_party/WebKit/Source/core/html/ImageData.idl +++ b/chromium/third_party/WebKit/Source/core/html/ImageData.idl @@ -26,10 +26,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata + [ + Constructor(unsigned long width, unsigned long height), + Constructor(Uint8ClampedArray data, unsigned long width, [Default=Undefined] optional unsigned long height), Custom=Wrap, + Exposed=Window&Worker, + RaisesException=Constructor, + WillBeGarbageCollected, ] interface ImageData { readonly attribute long width; readonly attribute long height; }; - diff --git a/chromium/third_party/WebKit/Source/core/html/ImageDocument.cpp b/chromium/third_party/WebKit/Source/core/html/ImageDocument.cpp index aaeff99d644..62903c2344c 100644 --- a/chromium/third_party/WebKit/Source/core/html/ImageDocument.cpp +++ b/chromium/third_party/WebKit/Source/core/html/ImageDocument.cpp @@ -25,13 +25,15 @@ #include "config.h" #include "core/html/ImageDocument.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/dom/RawDataDocumentParser.h" #include "core/events/EventListener.h" #include "core/events/MouseEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/fetch/ImageResource.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" #include "core/html/HTMLBodyElement.h" #include "core/html/HTMLHeadElement.h" #include "core/html/HTMLHtmlElement.h" @@ -40,9 +42,6 @@ #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" -#include "core/frame/Settings.h" #include "wtf/text/StringBuilder.h" using std::min; @@ -77,9 +76,9 @@ private: class ImageDocumentParser : public RawDataDocumentParser { public: - static PassRefPtr<ImageDocumentParser> create(ImageDocument* document) + static PassRefPtrWillBeRawPtr<ImageDocumentParser> create(ImageDocument* document) { - return adoptRef(new ImageDocumentParser(document)); + return adoptRefWillBeNoop(new ImageDocumentParser(document)); } ImageDocument* document() const @@ -101,7 +100,7 @@ private: static float pageZoomFactor(const Document* document) { - Frame* frame = document->frame(); + LocalFrame* frame = document->frame(); return frame ? frame->pageZoomFactor() : 1; } @@ -124,18 +123,22 @@ void ImageDocumentParser::appendBytes(const char* data, size_t length) if (!length) return; - Frame* frame = document()->frame(); + LocalFrame* frame = document()->frame(); Settings* settings = frame->settings(); if (!frame->loader().client()->allowImage(!settings || settings->imagesEnabled(), document()->url())) return; - document()->cachedImage()->appendData(data, length); + if (document()->cachedImage()) + document()->cachedImage()->appendData(data, length); + // Make sure the image renderer gets created because we need the renderer + // to read the aspect ratio. See crbug.com/320244 + document()->updateRenderTreeIfNeeded(); document()->imageUpdated(); } void ImageDocumentParser::finish() { - if (!isStopped() && document()->imageElement()) { + if (!isStopped() && document()->imageElement() && document()->cachedImage()) { ImageResource* cachedImage = document()->cachedImage(); cachedImage->finish(); cachedImage->setResponse(document()->frame()->loader().documentLoader()->response()); @@ -162,7 +165,7 @@ void ImageDocumentParser::finish() ImageDocument::ImageDocument(const DocumentInit& initializer) : HTMLDocument(initializer, ImageDocumentClass) - , m_imageElement(0) + , m_imageElement(nullptr) , m_imageSizeIsKnown(false) , m_didShrinkImage(false) , m_shouldShrinkImage(shouldShrinkToFit()) @@ -171,27 +174,27 @@ ImageDocument::ImageDocument(const DocumentInit& initializer) lockCompatibilityMode(); } -PassRefPtr<DocumentParser> ImageDocument::createParser() +PassRefPtrWillBeRawPtr<DocumentParser> ImageDocument::createParser() { return ImageDocumentParser::create(this); } void ImageDocument::createDocumentStructure() { - RefPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*this); + RefPtrWillBeRawPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*this); appendChild(rootElement); rootElement->insertedByParser(); if (frame()) frame()->loader().dispatchDocumentElementAvailable(); - RefPtr<HTMLHeadElement> head = HTMLHeadElement::create(*this); - RefPtr<HTMLMetaElement> meta = HTMLMetaElement::create(*this); + RefPtrWillBeRawPtr<HTMLHeadElement> head = HTMLHeadElement::create(*this); + RefPtrWillBeRawPtr<HTMLMetaElement> meta = HTMLMetaElement::create(*this); meta->setAttribute(nameAttr, "viewport"); - meta->setAttribute(contentAttr, "width=device-width"); + meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1"); head->appendChild(meta); - RefPtr<HTMLBodyElement> body = HTMLBodyElement::create(*this); + RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*this); body->setAttribute(styleAttr, "margin: 0px;"); m_imageElement = HTMLImageElement::create(*this); @@ -203,7 +206,7 @@ void ImageDocument::createDocumentStructure() if (shouldShrinkToFit()) { // Add event listeners RefPtr<EventListener> listener = ImageEventListener::create(this); - if (DOMWindow* domWindow = this->domWindow()) + if (LocalDOMWindow* domWindow = this->domWindow()) domWindow->addEventListener("resize", listener, false); m_imageElement->addEventListener("click", listener.release(), false); } @@ -224,15 +227,15 @@ float ImageDocument::scale() const LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this)); LayoutSize windowSize = LayoutSize(view->width(), view->height()); - float widthScale = (float)windowSize.width() / imageSize.width(); - float heightScale = (float)windowSize.height() / imageSize.height(); + float widthScale = windowSize.width().toFloat() / imageSize.width().toFloat(); + float heightScale = windowSize.height().toFloat() / imageSize.height().toFloat(); return min(widthScale, heightScale); } -void ImageDocument::resizeImageToFit() +void ImageDocument::resizeImageToFit(ScaleType type) { - if (!m_imageElement || m_imageElement->document() != this || pageZoomFactor(this) > 1) + if (!m_imageElement || m_imageElement->document() != this || (pageZoomFactor(this) > 1 && type == ScaleOnlyUnzoomedDocument)) return; LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this)); @@ -241,7 +244,7 @@ void ImageDocument::resizeImageToFit() m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale)); m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale)); - m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueWebkitZoomIn); + m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomIn); } void ImageDocument::imageClicked(int x, int y) @@ -252,9 +255,9 @@ void ImageDocument::imageClicked(int x, int y) m_shouldShrinkImage = !m_shouldShrinkImage; if (m_shouldShrinkImage) - windowSizeChanged(); + windowSizeChanged(ScaleZoomedDocument); else { - restoreImageSize(); + restoreImageSize(ScaleZoomedDocument); updateLayout(); @@ -281,13 +284,13 @@ void ImageDocument::imageUpdated() if (shouldShrinkToFit()) { // Force resizing of the image - windowSizeChanged(); + windowSizeChanged(ScaleOnlyUnzoomedDocument); } } -void ImageDocument::restoreImageSize() +void ImageDocument::restoreImageSize(ScaleType type) { - if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() != this || pageZoomFactor(this) < 1) + if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() != this || (pageZoomFactor(this) < 1 && type == ScaleOnlyUnzoomedDocument)) return; LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), 1.0f); @@ -297,7 +300,7 @@ void ImageDocument::restoreImageSize() if (imageFitsInWindow()) m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); else - m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueWebkitZoomOut); + m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomOut); m_didShrinkImage = false; } @@ -317,7 +320,7 @@ bool ImageDocument::imageFitsInWindow() const return imageSize.width() <= windowSize.width() && imageSize.height() <= windowSize.height(); } -void ImageDocument::windowSizeChanged() +void ImageDocument::windowSizeChanged(ScaleType type) { if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() != this) return; @@ -330,7 +333,7 @@ void ImageDocument::windowSizeChanged() if (fitsInWindow) m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); else - m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueWebkitZoomOut); + m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomOut); return; } @@ -338,13 +341,13 @@ void ImageDocument::windowSizeChanged() // If the window has been resized so that the image fits, restore the image size // otherwise update the restored image size. if (fitsInWindow) - restoreImageSize(); + restoreImageSize(type); else - resizeImageToFit(); + resizeImageToFit(type); } else { // If the image isn't resized but needs to be, then resize it. if (!fitsInWindow) { - resizeImageToFit(); + resizeImageToFit(type); m_didShrinkImage = true; } } @@ -363,18 +366,26 @@ bool ImageDocument::shouldShrinkToFit() const return frame()->settings()->shrinksStandaloneImagesToFit() && frame()->isMainFrame(); } +#if !ENABLE(OILPAN) void ImageDocument::dispose() { - m_imageElement = 0; + m_imageElement = nullptr; HTMLDocument::dispose(); } +#endif + +void ImageDocument::trace(Visitor* visitor) +{ + visitor->trace(m_imageElement); + HTMLDocument::trace(visitor); +} // -------- void ImageEventListener::handleEvent(ExecutionContext*, Event* event) { if (event->type() == EventTypeNames::resize) - m_doc->windowSizeChanged(); + m_doc->windowSizeChanged(ImageDocument::ScaleOnlyUnzoomedDocument); else if (event->type() == EventTypeNames::click && event->isMouseEvent()) { MouseEvent* mouseEvent = toMouseEvent(event); m_doc->imageClicked(mouseEvent->x(), mouseEvent->y()); diff --git a/chromium/third_party/WebKit/Source/core/html/ImageDocument.h b/chromium/third_party/WebKit/Source/core/html/ImageDocument.h index 896a46261da..b52f08f34e4 100644 --- a/chromium/third_party/WebKit/Source/core/html/ImageDocument.h +++ b/chromium/third_party/WebKit/Source/core/html/ImageDocument.h @@ -35,32 +35,41 @@ class HTMLImageElement; class ImageDocument FINAL : public HTMLDocument { public: - static PassRefPtr<ImageDocument> create(const DocumentInit& initializer = DocumentInit()) + static PassRefPtrWillBeRawPtr<ImageDocument> create(const DocumentInit& initializer = DocumentInit()) { - return adoptRef(new ImageDocument(initializer)); + return adoptRefWillBeNoop(new ImageDocument(initializer)); } + enum ScaleType { + ScaleZoomedDocument, + ScaleOnlyUnzoomedDocument + }; + ImageResource* cachedImage(); HTMLImageElement* imageElement() const { return m_imageElement.get(); } - void windowSizeChanged(); + void windowSizeChanged(ScaleType); void imageUpdated(); void imageClicked(int x, int y); + virtual void trace(Visitor*) OVERRIDE; + private: - ImageDocument(const DocumentInit&); + explicit ImageDocument(const DocumentInit&); - virtual PassRefPtr<DocumentParser> createParser() OVERRIDE; + virtual PassRefPtrWillBeRawPtr<DocumentParser> createParser() OVERRIDE; +#if !ENABLE(OILPAN) virtual void dispose() OVERRIDE; +#endif void createDocumentStructure(); - void resizeImageToFit(); - void restoreImageSize(); + void resizeImageToFit(ScaleType); + void restoreImageSize(ScaleType); bool imageFitsInWindow() const; bool shouldShrinkToFit() const; float scale() const; - RefPtr<HTMLImageElement> m_imageElement; + RefPtrWillBeMember<HTMLImageElement> m_imageElement; // Whether enough of the image has been loaded to determine its size bool m_imageSizeIsKnown; diff --git a/chromium/third_party/WebKit/Source/core/html/LabelableElement.cpp b/chromium/third_party/WebKit/Source/core/html/LabelableElement.cpp index ad302516baf..5233425facd 100644 --- a/chromium/third_party/WebKit/Source/core/html/LabelableElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/LabelableElement.cpp @@ -39,12 +39,17 @@ LabelableElement::~LabelableElement() { } -PassRefPtr<NodeList> LabelableElement::labels() +PassRefPtrWillBeRawPtr<LabelsNodeList> LabelableElement::labels() { if (!supportLabels()) - return 0; + return nullptr; - return ensureRareData().ensureNodeLists().addCacheWithAtomicName<LabelsNodeList>(this, LabelsNodeListType, starAtom); + return ensureRareData().ensureNodeLists().addCache<LabelsNodeList>(*this, LabelsNodeListType); +} + +void LabelableElement::trace(Visitor* visitor) +{ + HTMLElement::trace(visitor); } } // namespace Webcore diff --git a/chromium/third_party/WebKit/Source/core/html/LabelableElement.h b/chromium/third_party/WebKit/Source/core/html/LabelableElement.h index f3d2188dbfb..b633b8ab5a5 100644 --- a/chromium/third_party/WebKit/Source/core/html/LabelableElement.h +++ b/chromium/third_party/WebKit/Source/core/html/LabelableElement.h @@ -35,14 +35,18 @@ namespace WebCore { +class LabelsNodeList; + // LabelableElement represents "labelable element" defined in the HTML // specification, and provides the implementation of the "labels" attribute. class LabelableElement : public HTMLElement { public: virtual ~LabelableElement(); - PassRefPtr<NodeList> labels(); + PassRefPtrWillBeRawPtr<LabelsNodeList> labels(); virtual bool supportLabels() const { return false; } + virtual void trace(Visitor*) OVERRIDE; + protected: LabelableElement(const QualifiedName& tagName, Document&); @@ -50,12 +54,17 @@ private: virtual bool isLabelable() const OVERRIDE FINAL { return true; } }; -inline bool isLabelableElement(const Node& node) +inline bool isLabelableElement(const Element& element) +{ + return element.isHTMLElement() && toHTMLElement(element).isLabelable(); +} + +inline bool isLabelableElement(const HTMLElement& element) { - return node.isHTMLElement() && toHTMLElement(node).isLabelable(); + return element.isLabelable(); } -DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(LabelableElement); +DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(LabelableElement); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.cpp b/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.cpp index a3a6579370f..389af27af5f 100644 --- a/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.cpp @@ -24,7 +24,7 @@ #include "config.h" #include "core/html/LabelsNodeList.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Element.h" #include "core/dom/NodeRareData.h" #include "core/html/HTMLLabelElement.h" @@ -33,19 +33,21 @@ namespace WebCore { using namespace HTMLNames; -LabelsNodeList::LabelsNodeList(Node* ownerNode) +LabelsNodeList::LabelsNodeList(ContainerNode& ownerNode) : LiveNodeList(ownerNode, LabelsNodeListType, InvalidateOnForAttrChange, NodeListIsRootedAtDocument) { } LabelsNodeList::~LabelsNodeList() { - ownerNode()->nodeLists()->removeCacheWithAtomicName(this, LabelsNodeListType, starAtom); +#if !ENABLE(OILPAN) + ownerNode().nodeLists()->removeCache(this, LabelsNodeListType); +#endif } -bool LabelsNodeList::nodeMatches(Element* testNode) const +bool LabelsNodeList::elementMatches(const Element& element) const { - return isHTMLLabelElement(testNode) && toHTMLLabelElement(testNode)->control() == ownerNode(); + return isHTMLLabelElement(element) && toHTMLLabelElement(element).control() == ownerNode(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.h b/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.h index 0e5b125ca69..4a8a485be33 100644 --- a/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.h +++ b/chromium/third_party/WebKit/Source/core/html/LabelsNodeList.h @@ -32,18 +32,18 @@ namespace WebCore { class LabelsNodeList FINAL : public LiveNodeList { public: - static PassRefPtr<LabelsNodeList> create(Node* ownerNode, CollectionType type, const AtomicString&) + static PassRefPtrWillBeRawPtr<LabelsNodeList> create(ContainerNode& ownerNode, CollectionType type) { ASSERT_UNUSED(type, type == LabelsNodeListType); - return adoptRef(new LabelsNodeList(ownerNode)); + return adoptRefWillBeNoop(new LabelsNodeList(ownerNode)); } virtual ~LabelsNodeList(); protected: - explicit LabelsNodeList(Node*); + explicit LabelsNodeList(ContainerNode&); - virtual bool nodeMatches(Element*) const; + virtual bool elementMatches(const Element&) const OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/LinkManifest.cpp b/chromium/third_party/WebKit/Source/core/html/LinkManifest.cpp new file mode 100644 index 00000000000..09153932596 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/LinkManifest.cpp @@ -0,0 +1,47 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/LinkManifest.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" +#include "core/html/HTMLLinkElement.h" +#include "core/loader/FrameLoaderClient.h" + +namespace WebCore { + +PassOwnPtrWillBeRawPtr<LinkManifest> LinkManifest::create(HTMLLinkElement* owner) +{ + return adoptPtrWillBeNoop(new LinkManifest(owner)); +} + +LinkManifest::LinkManifest(HTMLLinkElement* owner) + : LinkResource(owner) +{ +} + +LinkManifest::~LinkManifest() +{ +} + +void LinkManifest::process() +{ + if (!m_owner || !m_owner->document().frame()) + return; + + m_owner->document().frame()->loader().client()->dispatchDidChangeManifest(); +} + +bool LinkManifest::hasLoaded() const +{ + return false; +} + +void LinkManifest::ownerRemoved() +{ + process(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/LinkManifest.h b/chromium/third_party/WebKit/Source/core/html/LinkManifest.h new file mode 100644 index 00000000000..c89b449818e --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/LinkManifest.h @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LinkManifest_h +#define LinkManifest_h + +#include "core/html/LinkResource.h" +#include "wtf/FastAllocBase.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +class HTMLLinkElement; + +class LinkManifest FINAL : public LinkResource { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; +public: + + static PassOwnPtrWillBeRawPtr<LinkManifest> create(HTMLLinkElement* owner); + + virtual ~LinkManifest(); + + // LinkResource + virtual void process() OVERRIDE; + virtual Type type() const OVERRIDE { return Manifest; } + virtual bool hasLoaded() const OVERRIDE; + virtual void ownerRemoved() OVERRIDE; + +private: + explicit LinkManifest(HTMLLinkElement* owner); +}; + +} + +#endif // LinkManifest_h diff --git a/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp b/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp index 0c2f32be4ca..bc2d746167e 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp +++ b/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.cpp @@ -32,22 +32,10 @@ #include "config.h" #include "core/html/LinkRelAttribute.h" -#include "wtf/text/WTFString.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { -LinkRelAttribute::LinkRelAttribute() - : m_iconType(InvalidIcon) - , m_isStyleSheet(false) - , m_isAlternate(false) - , m_isDNSPrefetch(false) - , m_isLinkPrefetch(false) - , m_isLinkSubresource(false) - , m_isLinkPrerender(false) - , m_isImport(false) -{ -} - LinkRelAttribute::LinkRelAttribute(const String& rel) : m_iconType(InvalidIcon) , m_isStyleSheet(false) @@ -56,51 +44,53 @@ LinkRelAttribute::LinkRelAttribute(const String& rel) , m_isLinkPrefetch(false) , m_isLinkSubresource(false) , m_isLinkPrerender(false) + , m_isLinkNext(false) , m_isImport(false) + , m_isManifest(false) + , m_isTransitionExitingStylesheet(false) { - if (equalIgnoringCase(rel, "stylesheet")) - m_isStyleSheet = true; - else if (equalIgnoringCase(rel, "icon") || equalIgnoringCase(rel, "shortcut icon")) - m_iconType = Favicon; -#if ENABLE(TOUCH_ICON_LOADING) - else if (equalIgnoringCase(rel, "apple-touch-icon")) - m_iconType = TouchIcon; - else if (equalIgnoringCase(rel, "apple-touch-icon-precomposed")) - m_iconType = TouchPrecomposedIcon; -#endif - else if (equalIgnoringCase(rel, "dns-prefetch")) - m_isDNSPrefetch = true; - else if (equalIgnoringCase(rel, "alternate stylesheet") || equalIgnoringCase(rel, "stylesheet alternate")) { - m_isStyleSheet = true; - m_isAlternate = true; - } else if (equalIgnoringCase(rel, "import")) { - m_isImport = true; - } else { - // Tokenize the rel attribute and set bits based on specific keywords that we find. - String relCopy = rel; - relCopy.replace('\n', ' '); - Vector<String> list; - relCopy.split(' ', list); - Vector<String>::const_iterator end = list.end(); - for (Vector<String>::const_iterator it = list.begin(); it != end; ++it) { - if (equalIgnoringCase(*it, "stylesheet")) + if (rel.isEmpty()) + return; + String relCopy = rel; + relCopy.replace('\n', ' '); + Vector<String> list; + relCopy.split(' ', list); + Vector<String>::const_iterator end = list.end(); + for (Vector<String>::const_iterator it = list.begin(); it != end; ++it) { + if (equalIgnoringCase(*it, "stylesheet")) { + if (!m_isImport) m_isStyleSheet = true; - else if (equalIgnoringCase(*it, "alternate")) - m_isAlternate = true; - else if (equalIgnoringCase(*it, "icon")) - m_iconType = Favicon; -#if ENABLE(TOUCH_ICON_LOADING) - else if (equalIgnoringCase(*it, "apple-touch-icon")) + } else if (equalIgnoringCase(*it, "import")) { + if (!m_isStyleSheet) + m_isImport = true; + } else if (equalIgnoringCase(*it, "alternate")) { + m_isAlternate = true; + } else if (equalIgnoringCase(*it, "icon")) { + // This also allows "shortcut icon" since we just ignore the non-standard "shortcut" token. + // FIXME: This doesn't really follow the spec that requires "shortcut icon" to be the + // entire string http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#rel-icon + m_iconType = Favicon; + } else if (equalIgnoringCase(*it, "prefetch")) { + m_isLinkPrefetch = true; + } else if (equalIgnoringCase(*it, "dns-prefetch")) { + m_isDNSPrefetch = true; + } else if (equalIgnoringCase(*it, "subresource")) { + m_isLinkSubresource = true; + } else if (equalIgnoringCase(*it, "prerender")) { + m_isLinkPrerender = true; + } else if (equalIgnoringCase(*it, "next")) { + m_isLinkNext = true; + } else if (equalIgnoringCase(*it, "apple-touch-icon")) { + if (RuntimeEnabledFeatures::touchIconLoadingEnabled()) m_iconType = TouchIcon; - else if (equalIgnoringCase(*it, "apple-touch-icon-precomposed")) + } else if (equalIgnoringCase(*it, "apple-touch-icon-precomposed")) { + if (RuntimeEnabledFeatures::touchIconLoadingEnabled()) m_iconType = TouchPrecomposedIcon; -#endif - else if (equalIgnoringCase(*it, "prefetch")) - m_isLinkPrefetch = true; - else if (equalIgnoringCase(*it, "subresource")) - m_isLinkSubresource = true; - else if (equalIgnoringCase(*it, "prerender")) - m_isLinkPrerender = true; + } else if (equalIgnoringCase(*it, "manifest")) { + m_isManifest = true; + } else if (equalIgnoringCase(rel, "transition-exiting-stylesheet")) { + if (RuntimeEnabledFeatures::navigationTransitionsEnabled()) + m_isTransitionExitingStylesheet = true; } } } diff --git a/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.h b/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.h index a124012055d..d4424100e93 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.h +++ b/chromium/third_party/WebKit/Source/core/html/LinkRelAttribute.h @@ -33,17 +33,13 @@ #define LinkRelAttribute_h #include "core/dom/IconURL.h" - -namespace WTF { -class String; -} +#include "wtf/text/WTFString.h" namespace WebCore { class LinkRelAttribute { public: - LinkRelAttribute(); - explicit LinkRelAttribute(const String&); + explicit LinkRelAttribute(const String& = ""); bool isStyleSheet() const { return m_isStyleSheet; } IconType iconType() const { return m_iconType; } @@ -52,7 +48,10 @@ public: bool isLinkPrefetch() const { return m_isLinkPrefetch; } bool isLinkSubresource() const { return m_isLinkSubresource; } bool isLinkPrerender() const { return m_isLinkPrerender; } + bool isLinkNext() const { return m_isLinkNext; } bool isImport() const { return m_isImport; } + bool isManifest() const { return m_isManifest; } + bool isTransitionExitingStylesheet() const { return m_isTransitionExitingStylesheet; } private: IconType m_iconType; @@ -62,7 +61,10 @@ private: bool m_isLinkPrefetch : 1; bool m_isLinkSubresource : 1; bool m_isLinkPrerender : 1; + bool m_isLinkNext : 1; bool m_isImport : 1; + bool m_isManifest : 1; + bool m_isTransitionExitingStylesheet : 1; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/LinkRelAttributeTest.cpp b/chromium/third_party/WebKit/Source/core/html/LinkRelAttributeTest.cpp index beac0e64066..e75ea4d97eb 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkRelAttributeTest.cpp +++ b/chromium/third_party/WebKit/Source/core/html/LinkRelAttributeTest.cpp @@ -30,6 +30,7 @@ #include "config.h" #include "core/html/LinkRelAttribute.h" +#include "platform/RuntimeEnabledFeatures.h" #include "wtf/text/CString.h" #include <gtest/gtest.h> @@ -38,6 +39,22 @@ using namespace WebCore; namespace { +class LinkRelAttributeTest : public testing::Test { +protected: + virtual void SetUp() + { + m_touchIconLoadingEnabled = RuntimeEnabledFeatures::touchIconLoadingEnabled(); + } + + virtual void TearDown() + { + RuntimeEnabledFeatures::setTouchIconLoadingEnabled(m_touchIconLoadingEnabled); + } + +private: + bool m_touchIconLoadingEnabled; +}; + static inline void testLinkRelAttribute(String value, bool isStyleSheet, IconType iconType, bool isAlternate, bool isDNSPrefetch, bool isLinkSubresource, bool isLinkPrerender, bool isImport = false) { LinkRelAttribute linkRelAttribute(value); @@ -50,8 +67,10 @@ static inline void testLinkRelAttribute(String value, bool isStyleSheet, IconTyp ASSERT_EQ(isImport, linkRelAttribute.isImport()) << value.utf8().data(); } -TEST(CoreLinkRelAttribute, Constructor) +TEST_F(LinkRelAttributeTest, Constructor) { + RuntimeEnabledFeatures::setTouchIconLoadingEnabled(false); + testLinkRelAttribute("stylesheet", true, InvalidIcon, false, false, false, false); testLinkRelAttribute("sTyLeShEeT", true, InvalidIcon, false, false, false, false); @@ -60,16 +79,48 @@ TEST(CoreLinkRelAttribute, Constructor) testLinkRelAttribute("shortcut icon", false, Favicon, false, false, false, false); testLinkRelAttribute("sHoRtCuT iCoN", false, Favicon, false, false, false, false); -#if ENABLE(TOUCH_ICON_LOADING) - testLinkRelAttribute("apple-touch-icon", false, TouchIcon, false, false, false, false); - testLinkRelAttribute("aPpLe-tOuCh-IcOn", false, TouchIcon, false, false, false, false); + testLinkRelAttribute("dns-prefetch", false, InvalidIcon, false, true, false, false); + testLinkRelAttribute("dNs-pReFeTcH", false, InvalidIcon, false, true, false, false); - testLinkRelAttribute("apple-touch-icon-precomposed", false, TouchPrecomposedIcon, false, false, false, false); - testLinkRelAttribute("aPpLe-tOuCh-IcOn-pReCoMpOsEd", false, TouchPrecomposedIcon, false, false, false, false); -#endif + testLinkRelAttribute("apple-touch-icon", false, InvalidIcon, false, false, false, false); + testLinkRelAttribute("aPpLe-tOuCh-IcOn", false, InvalidIcon, false, false, false, false); + testLinkRelAttribute("apple-touch-icon-precomposed", false, InvalidIcon, false, false, false, false); + testLinkRelAttribute("aPpLe-tOuCh-IcOn-pReCoMpOsEd", false, InvalidIcon, false, false, false, false); + + testLinkRelAttribute("alternate stylesheet", true, InvalidIcon, true, false, false, false); + testLinkRelAttribute("stylesheet alternate", true, InvalidIcon, true, false, false, false); + testLinkRelAttribute("aLtErNaTe sTyLeShEeT", true, InvalidIcon, true, false, false, false); + testLinkRelAttribute("sTyLeShEeT aLtErNaTe", true, InvalidIcon, true, false, false, false); + + testLinkRelAttribute("stylesheet icon prerender aLtErNaTe", true, Favicon, true, false, false, true); + testLinkRelAttribute("alternate subresource", false, InvalidIcon, true, false, true, false); + testLinkRelAttribute("alternate icon stylesheet", true, Favicon, true, false, false, false); + + testLinkRelAttribute("import", false, InvalidIcon, false, false, false, false, true); + // "import" is mutually exclusive and "stylesheet" wins when they conflict. + testLinkRelAttribute("stylesheet import", true, InvalidIcon, false, false, false, false, false); +} + +TEST_F(LinkRelAttributeTest, ConstructorTouchIconLoadingEnabled) +{ + RuntimeEnabledFeatures::setTouchIconLoadingEnabled(true); + + testLinkRelAttribute("stylesheet", true, InvalidIcon, false, false, false, false); + testLinkRelAttribute("sTyLeShEeT", true, InvalidIcon, false, false, false, false); + + testLinkRelAttribute("icon", false, Favicon, false, false, false, false); + testLinkRelAttribute("iCoN", false, Favicon, false, false, false, false); + testLinkRelAttribute("shortcut icon", false, Favicon, false, false, false, false); + testLinkRelAttribute("sHoRtCuT iCoN", false, Favicon, false, false, false, false); testLinkRelAttribute("dns-prefetch", false, InvalidIcon, false, true, false, false); testLinkRelAttribute("dNs-pReFeTcH", false, InvalidIcon, false, true, false, false); + testLinkRelAttribute("alternate dNs-pReFeTcH", false, InvalidIcon, true, true, false, false); + + testLinkRelAttribute("apple-touch-icon", false, TouchIcon, false, false, false, false); + testLinkRelAttribute("aPpLe-tOuCh-IcOn", false, TouchIcon, false, false, false, false); + testLinkRelAttribute("apple-touch-icon-precomposed", false, TouchPrecomposedIcon, false, false, false, false); + testLinkRelAttribute("aPpLe-tOuCh-IcOn-pReCoMpOsEd", false, TouchPrecomposedIcon, false, false, false, false); testLinkRelAttribute("alternate stylesheet", true, InvalidIcon, true, false, false, false); testLinkRelAttribute("stylesheet alternate", true, InvalidIcon, true, false, false, false); @@ -81,7 +132,7 @@ TEST(CoreLinkRelAttribute, Constructor) testLinkRelAttribute("alternate icon stylesheet", true, Favicon, true, false, false, false); testLinkRelAttribute("import", false, InvalidIcon, false, false, false, false, true); - // "import" is mutually exclusive and "stylesheet" wins when they conflict. + testLinkRelAttribute("alternate import", false, InvalidIcon, true, false, false, false, true); testLinkRelAttribute("stylesheet import", true, InvalidIcon, false, false, false, false, false); } diff --git a/chromium/third_party/WebKit/Source/core/html/LinkResource.cpp b/chromium/third_party/WebKit/Source/core/html/LinkResource.cpp index ef239527a14..850fbd40d6d 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkResource.cpp +++ b/chromium/third_party/WebKit/Source/core/html/LinkResource.cpp @@ -31,9 +31,10 @@ #include "config.h" #include "core/html/LinkResource.h" -#include "HTMLNames.h" -#include "core/html/HTMLImport.h" +#include "core/HTMLNames.h" +#include "core/dom/Document.h" #include "core/html/HTMLLinkElement.h" +#include "core/html/imports/HTMLImportsController.h" namespace WebCore { @@ -50,15 +51,20 @@ LinkResource::~LinkResource() bool LinkResource::shouldLoadResource() const { - return m_owner->document().frame() || m_owner->document().import(); + return m_owner->document().frame() || m_owner->document().importsController(); } -Frame* LinkResource::loadingFrame() const +LocalFrame* LinkResource::loadingFrame() const { - HTMLImport* import = m_owner->document().import(); - if (!import) + HTMLImportsController* importsController = m_owner->document().importsController(); + if (!importsController) return m_owner->document().frame(); - return import->master()->document().frame(); + return importsController->master()->frame(); +} + +void LinkResource::trace(Visitor* visitor) +{ + visitor->trace(m_owner); } LinkRequestBuilder::LinkRequestBuilder(HTMLLinkElement* owner) diff --git a/chromium/third_party/WebKit/Source/core/html/LinkResource.h b/chromium/third_party/WebKit/Source/core/html/LinkResource.h index a922639d216..93815b08526 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkResource.h +++ b/chromium/third_party/WebKit/Source/core/html/LinkResource.h @@ -32,6 +32,7 @@ #define LinkResource_h #include "core/fetch/FetchRequest.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "wtf/text/WTFString.h" @@ -39,30 +40,35 @@ namespace WebCore { class HTMLLinkElement; -class LinkResource { - WTF_MAKE_NONCOPYABLE(LinkResource); WTF_MAKE_FAST_ALLOCATED; +class LinkResource : public NoBaseWillBeGarbageCollectedFinalized<LinkResource> { + WTF_MAKE_NONCOPYABLE(LinkResource); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: enum Type { Style, - Import + Import, + Manifest }; explicit LinkResource(HTMLLinkElement*); virtual ~LinkResource(); bool shouldLoadResource() const; - Frame* loadingFrame() const; + LocalFrame* loadingFrame() const; virtual Type type() const = 0; virtual void process() = 0; - virtual void ownerRemoved() = 0; + virtual void ownerRemoved() { } + virtual void ownerInserted() { } virtual bool hasLoaded() const = 0; + virtual void trace(Visitor*); + protected: - HTMLLinkElement* m_owner; + RawPtrWillBeMember<HTMLLinkElement> m_owner; }; class LinkRequestBuilder { + STACK_ALLOCATED(); public: explicit LinkRequestBuilder(HTMLLinkElement* owner); @@ -72,7 +78,7 @@ public: FetchRequest build(bool blocking) const; private: - HTMLLinkElement* m_owner; + RawPtrWillBeMember<HTMLLinkElement> m_owner; KURL m_url; AtomicString m_charset; }; diff --git a/chromium/third_party/WebKit/Source/core/html/MediaController.cpp b/chromium/third_party/WebKit/Source/core/html/MediaController.cpp index e93bbc1df30..2cf4b0a9863 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaController.cpp +++ b/chromium/third_party/WebKit/Source/core/html/MediaController.cpp @@ -30,6 +30,9 @@ #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" +#include "core/events/Event.h" +#include "core/events/GenericEventQueue.h" #include "core/html/HTMLMediaElement.h" #include "core/html/TimeRanges.h" #include "platform/Clock.h" @@ -37,12 +40,11 @@ #include "wtf/StdLibExtras.h" #include "wtf/text/AtomicString.h" -using namespace WebCore; -using namespace std; +namespace WebCore { -PassRefPtr<MediaController> MediaController::create(ExecutionContext* context) +PassRefPtrWillBeRawPtr<MediaController> MediaController::create(ExecutionContext* context) { - return adoptRef(new MediaController(context)); + return adoptRefWillBeRefCountedGarbageCollected(new MediaController(context)); } MediaController::MediaController(ExecutionContext* context) @@ -51,11 +53,10 @@ MediaController::MediaController(ExecutionContext* context) , m_volume(1) , m_position(MediaPlayer::invalidTime()) , m_muted(false) - , m_readyState(HAVE_NOTHING) + , m_readyState(HTMLMediaElement::HAVE_NOTHING) , m_playbackState(WAITING) - , m_asyncEventTimer(this, &MediaController::asyncEventTimerFired) + , m_pendingEventsQueue(GenericEventQueue::create(this)) , m_clearPositionTimer(this, &MediaController::clearPositionTimerFired) - , m_closedCaptionsVisible(false) , m_clock(Clock::create()) , m_executionContext(context) , m_timeupdateTimer(this, &MediaController::timeupdateTimerFired) @@ -73,7 +74,7 @@ void MediaController::addMediaElement(HTMLMediaElement* element) ASSERT(element); ASSERT(!m_mediaElements.contains(element)); - m_mediaElements.append(element); + m_mediaElements.add(element); bringElementUpToSpeed(element); } @@ -84,11 +85,6 @@ void MediaController::removeMediaElement(HTMLMediaElement* element) m_mediaElements.remove(m_mediaElements.find(element)); } -bool MediaController::containsMediaElement(HTMLMediaElement* element) const -{ - return m_mediaElements.contains(element); -} - PassRefPtr<TimeRanges> MediaController::buffered() const { if (m_mediaElements.isEmpty()) @@ -97,9 +93,10 @@ PassRefPtr<TimeRanges> MediaController::buffered() const // The buffered attribute must return a new static normalized TimeRanges object that represents // the intersection of the ranges of the media resources of the slaved media elements that the // user agent has buffered, at the time the attribute is evaluated. - RefPtr<TimeRanges> bufferedRanges = m_mediaElements.first()->buffered(); - for (size_t index = 1; index < m_mediaElements.size(); ++index) - bufferedRanges->intersectWith(m_mediaElements[index]->buffered().get()); + MediaElementSequence::const_iterator it = m_mediaElements.begin(); + RefPtr<TimeRanges> bufferedRanges = (*it)->buffered(); + for (++it; it != m_mediaElements.end(); ++it) + bufferedRanges->intersectWith((*it)->buffered().get()); return bufferedRanges; } @@ -111,9 +108,10 @@ PassRefPtr<TimeRanges> MediaController::seekable() const // The seekable attribute must return a new static normalized TimeRanges object that represents // the intersection of the ranges of the media resources of the slaved media elements that the // user agent is able to seek to, at the time the attribute is evaluated. - RefPtr<TimeRanges> seekableRanges = m_mediaElements.first()->seekable(); - for (size_t index = 1; index < m_mediaElements.size(); ++index) - seekableRanges->intersectWith(m_mediaElements[index]->seekable().get()); + MediaElementSequence::const_iterator it = m_mediaElements.begin(); + RefPtr<TimeRanges> seekableRanges = (*it)->seekable(); + for (++it; it != m_mediaElements.end(); ++it) + seekableRanges->intersectWith((*it)->seekable().get()); return seekableRanges; } @@ -125,9 +123,10 @@ PassRefPtr<TimeRanges> MediaController::played() // The played attribute must return a new static normalized TimeRanges object that represents // the union of the ranges of the media resources of the slaved media elements that the // user agent has so far rendered, at the time the attribute is evaluated. - RefPtr<TimeRanges> playedRanges = m_mediaElements.first()->played(); - for (size_t index = 1; index < m_mediaElements.size(); ++index) - playedRanges->unionWith(m_mediaElements[index]->played().get()); + MediaElementSequence::const_iterator it = m_mediaElements.begin(); + RefPtr<TimeRanges> playedRanges = (*it)->played(); + for (++it; it != m_mediaElements.end(); ++it) + playedRanges->unionWith((*it)->played().get()); return playedRanges; } @@ -136,11 +135,11 @@ double MediaController::duration() const // FIXME: Investigate caching the maximum duration and only updating the cached value // when the slaved media elements' durations change. double maxDuration = 0; - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - double duration = m_mediaElements[index]->duration(); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) { + double duration = (*it)->duration(); if (std::isnan(duration)) continue; - maxDuration = max(maxDuration, duration); + maxDuration = std::max(maxDuration, duration); } return maxDuration; } @@ -152,8 +151,8 @@ double MediaController::currentTime() const if (m_position == MediaPlayer::invalidTime()) { // Some clocks may return times outside the range of [0..duration]. - m_position = max(0.0, min(duration(), m_clock->currentTime())); - m_clearPositionTimer.startOneShot(0); + m_position = std::max(0.0, std::min(duration(), m_clock->currentTime())); + m_clearPositionTimer.startOneShot(0, FROM_HERE); } return m_position; @@ -164,18 +163,19 @@ void MediaController::setCurrentTime(double time, ExceptionState& exceptionState // When the user agent is to seek the media controller to a particular new playback position, // it must follow these steps: // If the new playback position is less than zero, then set it to zero. - time = max(0.0, time); + time = std::max(0.0, time); // If the new playback position is greater than the media controller duration, then set it // to the media controller duration. - time = min(time, duration()); + time = std::min(time, duration()); // Set the media controller position to the new playback position. + m_position = time; m_clock->setCurrentTime(time); // Seek each slaved media element to the new playback position relative to the media element timeline. - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->seek(time, exceptionState); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) + (*it)->seek(time, exceptionState); scheduleTimeupdateEvent(); } @@ -198,8 +198,8 @@ void MediaController::play() { // When the play() method is invoked, the user agent must invoke the play method of each // slaved media element in turn, - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->play(); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) + (*it)->play(); // and then invoke the unpause method of the MediaController. unpause(); @@ -246,8 +246,8 @@ void MediaController::setPlaybackRate(double rate) // playback rate to the new value, m_clock->setPlayRate(rate); - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->updatePlaybackRate(); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) + (*it)->updatePlaybackRate(); // then queue a task to fire a simple event named ratechange at the MediaController. scheduleEvent(EventTypeNames::ratechange); @@ -261,7 +261,7 @@ void MediaController::setVolume(double level, ExceptionState& exceptionState) // If the new value is outside the range 0.0 to 1.0 inclusive, then, on setting, an // IndexSizeError exception must be raised instead. if (level < 0 || level > 1) { - exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::failedToSet("volume", "MediaController", "The value provided (" + String::number(level) + ") is not in the range [0.0, 1.0].")); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexOutsideRange("volume", level, 0.0, ExceptionMessages::InclusiveBound, 1.0, ExceptionMessages::InclusiveBound)); return; } @@ -272,8 +272,8 @@ void MediaController::setVolume(double level, ExceptionState& exceptionState) // and queue a task to fire a simple event named volumechange at the MediaController. scheduleEvent(EventTypeNames::volumechange); - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->updateVolume(); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) + (*it)->updateVolume(); } void MediaController::setMuted(bool flag) @@ -288,8 +288,8 @@ void MediaController::setMuted(bool flag) // and queue a task to fire a simple event named volumechange at the MediaController. scheduleEvent(EventTypeNames::volumechange); - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->updateVolume(); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) + (*it)->updateVolume(); } static const AtomicString& playbackStateWaiting() @@ -331,18 +331,18 @@ void MediaController::reportControllerState() updatePlaybackState(); } -static AtomicString eventNameForReadyState(MediaControllerInterface::ReadyState state) +static const AtomicString& eventNameForReadyState(HTMLMediaElement::ReadyState state) { switch (state) { - case MediaControllerInterface::HAVE_NOTHING: + case HTMLMediaElement::HAVE_NOTHING: return EventTypeNames::emptied; - case MediaControllerInterface::HAVE_METADATA: + case HTMLMediaElement::HAVE_METADATA: return EventTypeNames::loadedmetadata; - case MediaControllerInterface::HAVE_CURRENT_DATA: + case HTMLMediaElement::HAVE_CURRENT_DATA: return EventTypeNames::loadeddata; - case MediaControllerInterface::HAVE_FUTURE_DATA: + case HTMLMediaElement::HAVE_FUTURE_DATA: return EventTypeNames::canplay; - case MediaControllerInterface::HAVE_ENOUGH_DATA: + case HTMLMediaElement::HAVE_ENOUGH_DATA: return EventTypeNames::canplaythrough; default: ASSERT_NOT_REACHED(); @@ -357,13 +357,14 @@ void MediaController::updateReadyState() if (m_mediaElements.isEmpty()) { // If the MediaController has no slaved media elements, let new readiness state be 0. - newReadyState = HAVE_NOTHING; + newReadyState = HTMLMediaElement::HAVE_NOTHING; } else { // Otherwise, let it have the lowest value of the readyState IDL attributes of all of its // slaved media elements. - newReadyState = m_mediaElements.first()->readyState(); - for (size_t index = 1; index < m_mediaElements.size(); ++index) - newReadyState = min(newReadyState, m_mediaElements[index]->readyState()); + MediaElementSequence::const_iterator it = m_mediaElements.begin(); + newReadyState = (*it)->readyState(); + for (++it; it != m_mediaElements.end(); ++it) + newReadyState = std::min(newReadyState, (*it)->readyState()); } if (newReadyState == oldReadyState) @@ -471,8 +472,8 @@ void MediaController::updatePlaybackState() void MediaController::updateMediaElements() { - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->updatePlayState(); + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) + (*it)->updatePlayState(); } void MediaController::bringElementUpToSpeed(HTMLMediaElement* element) @@ -486,20 +487,51 @@ void MediaController::bringElementUpToSpeed(HTMLMediaElement* element) element->seek(currentTime(), IGNORE_EXCEPTION); } +bool MediaController::isRestrained() const +{ + ASSERT(!m_mediaElements.isEmpty()); + + // A MediaController is a restrained media controller if the MediaController is a playing media + // controller, + if (m_paused) + return false; + + bool anyAutoplayingAndPaused = false; + bool allPaused = true; + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) { + HTMLMediaElement* element = *it; + + // and none of its slaved media elements are blocked media elements, + if (element->isBlocked()) + return false; + + if (element->isAutoplaying() && element->paused()) + anyAutoplayingAndPaused = true; + + if (!element->paused()) + allPaused = false; + } + + // but either at least one of its slaved media elements whose autoplaying flag is true still has + // its paused attribute set to true, or, all of its slaved media elements have their paused + // attribute set to true. + return anyAutoplayingAndPaused || allPaused; +} + bool MediaController::isBlocked() const { + ASSERT(!m_mediaElements.isEmpty()); + // A MediaController is a blocked media controller if the MediaController is a paused media // controller, if (m_paused) return true; - if (m_mediaElements.isEmpty()) - return false; - bool allPaused = true; - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - HTMLMediaElement* element = m_mediaElements[index]; - // or if any of its slaved media elements are blocked media elements, + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) { + HTMLMediaElement* element = *it; + + // or if any of its slaved media elements are blocked media elements, if (element->isBlocked()) return true; @@ -528,8 +560,8 @@ bool MediaController::hasEnded() const return false; bool allHaveEnded = true; - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - if (!m_mediaElements[index]->ended()) + for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) { + if (!(*it)->ended()) allHaveEnded = false; } return allHaveEnded; @@ -537,19 +569,7 @@ bool MediaController::hasEnded() const void MediaController::scheduleEvent(const AtomicString& eventName) { - m_pendingEvents.append(Event::createCancelable(eventName)); - if (!m_asyncEventTimer.isActive()) - m_asyncEventTimer.startOneShot(0); -} - -void MediaController::asyncEventTimerFired(Timer<MediaController>*) -{ - Vector<RefPtr<Event> > pendingEvents; - - m_pendingEvents.swap(pendingEvents); - size_t count = pendingEvents.size(); - for (size_t index = 0; index < count; ++index) - dispatchEvent(pendingEvents[index].release(), IGNORE_EXCEPTION); + m_pendingEventsQueue->enqueueEvent(Event::createCancelable(eventName)); } void MediaController::clearPositionTimerFired(Timer<MediaController>*) @@ -557,77 +577,6 @@ void MediaController::clearPositionTimerFired(Timer<MediaController>*) m_position = MediaPlayer::invalidTime(); } -bool MediaController::hasAudio() const -{ - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - if (m_mediaElements[index]->hasAudio()) - return true; - } - return false; -} - -bool MediaController::hasVideo() const -{ - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - if (m_mediaElements[index]->hasVideo()) - return true; - } - return false; -} - -bool MediaController::hasClosedCaptions() const -{ - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - if (m_mediaElements[index]->hasClosedCaptions()) - return true; - } - return false; -} - -void MediaController::setClosedCaptionsVisible(bool visible) -{ - m_closedCaptionsVisible = visible; - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->setClosedCaptionsVisible(visible); -} - -void MediaController::beginScrubbing() -{ - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->beginScrubbing(); - if (m_playbackState == PLAYING) - m_clock->stop(); -} - -void MediaController::endScrubbing() -{ - for (size_t index = 0; index < m_mediaElements.size(); ++index) - m_mediaElements[index]->endScrubbing(); - if (m_playbackState == PLAYING) - m_clock->start(); -} - -bool MediaController::canPlay() const -{ - if (m_paused) - return true; - - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - if (!m_mediaElements[index]->canPlay()) - return false; - } - return true; -} - -bool MediaController::hasCurrentSrc() const -{ - for (size_t index = 0; index < m_mediaElements.size(); ++index) { - if (!m_mediaElements[index]->hasCurrentSrc()) - return false; - } - return true; -} - const AtomicString& MediaController::interfaceName() const { return EventTargetNames::MediaController; @@ -642,7 +591,7 @@ void MediaController::startTimeupdateTimer() if (m_timeupdateTimer.isActive()) return; - m_timeupdateTimer.startRepeating(maxTimeupdateEventFrequency); + m_timeupdateTimer.startRepeating(maxTimeupdateEventFrequency, FROM_HERE); } void MediaController::timeupdateTimerFired(Timer<MediaController>*) @@ -661,3 +610,13 @@ void MediaController::scheduleTimeupdateEvent() scheduleEvent(EventTypeNames::timeupdate); m_previousTimeupdateTime = now; } + +void MediaController::trace(Visitor* visitor) +{ + visitor->trace(m_mediaElements); + visitor->trace(m_pendingEventsQueue); + visitor->trace(m_executionContext); + EventTargetWithInlineData::trace(visitor); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/MediaController.h b/chromium/third_party/WebKit/Source/core/html/MediaController.h index 5b31cc24e18..c9311a906d7 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaController.h +++ b/chromium/third_party/WebKit/Source/core/html/MediaController.h @@ -27,84 +27,68 @@ #define MediaController_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/Event.h" #include "core/events/EventTarget.h" -#include "core/html/MediaControllerInterface.h" -#include "platform/Timer.h" +#include "core/html/HTMLMediaElement.h" +#include "wtf/LinkedHashSet.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" -#include "wtf/Vector.h" namespace WebCore { class Clock; -class Event; class ExceptionState; -class HTMLMediaElement; class ExecutionContext; +class GenericEventQueue; -class MediaController : public RefCounted<MediaController>, public ScriptWrappable, public MediaControllerInterface, public EventTargetWithInlineData { +class MediaController FINAL : public RefCountedWillBeRefCountedGarbageCollected<MediaController>, public ScriptWrappable, public EventTargetWithInlineData { REFCOUNTED_EVENT_TARGET(MediaController); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaController); public: - static PassRefPtr<MediaController> create(ExecutionContext*); + static PassRefPtrWillBeRawPtr<MediaController> create(ExecutionContext*); virtual ~MediaController(); void addMediaElement(HTMLMediaElement*); void removeMediaElement(HTMLMediaElement*); - bool containsMediaElement(HTMLMediaElement*) const; - const String& mediaGroup() const { return m_mediaGroup; } + PassRefPtr<TimeRanges> buffered() const; + PassRefPtr<TimeRanges> seekable() const; + PassRefPtr<TimeRanges> played(); - virtual PassRefPtr<TimeRanges> buffered() const; - virtual PassRefPtr<TimeRanges> seekable() const; - virtual PassRefPtr<TimeRanges> played(); + double duration() const; + double currentTime() const; + void setCurrentTime(double, ExceptionState&); - virtual double duration() const; - virtual double currentTime() const; - virtual void setCurrentTime(double, ExceptionState&); - - virtual bool paused() const { return m_paused; } - virtual void play(); - virtual void pause(); + bool paused() const { return m_paused; } + void play(); + void pause(); void unpause(); - virtual double defaultPlaybackRate() const { return m_defaultPlaybackRate; } - virtual void setDefaultPlaybackRate(double); + double defaultPlaybackRate() const { return m_defaultPlaybackRate; } + void setDefaultPlaybackRate(double); - virtual double playbackRate() const; - virtual void setPlaybackRate(double); + double playbackRate() const; + void setPlaybackRate(double); - virtual double volume() const { return m_volume; } - virtual void setVolume(double, ExceptionState&); + double volume() const { return m_volume; } + void setVolume(double, ExceptionState&); - virtual bool muted() const { return m_muted; } - virtual void setMuted(bool); + bool muted() const { return m_muted; } + void setMuted(bool); - virtual ReadyState readyState() const { return m_readyState; } + typedef HTMLMediaElement::ReadyState ReadyState; + ReadyState readyState() const { return m_readyState; } enum PlaybackState { WAITING, PLAYING, ENDED }; const AtomicString& playbackState() const; - virtual bool supportsFullscreen() const { return false; } - virtual bool isFullscreen() const { return false; } - virtual void enterFullscreen() { } - - virtual bool hasAudio() const; - virtual bool hasVideo() const; - virtual bool hasClosedCaptions() const; - virtual void setClosedCaptionsVisible(bool); - virtual bool closedCaptionsVisible() const { return m_closedCaptionsVisible; } - - virtual void beginScrubbing(); - virtual void endScrubbing(); - - virtual bool canPlay() const; - - virtual bool hasCurrentSrc() const; - + bool isRestrained() const; bool isBlocked() const; - void clearExecutionContext() { m_executionContext = 0; } +#if !ENABLE(OILPAN) + void clearExecutionContext() { m_executionContext = nullptr; } +#endif + + virtual void trace(Visitor*) OVERRIDE; private: MediaController(ExecutionContext*); @@ -114,7 +98,6 @@ private: void updateMediaElements(); void bringElementUpToSpeed(HTMLMediaElement*); void scheduleEvent(const AtomicString& eventName); - void asyncEventTimerFired(Timer<MediaController>*); void clearPositionTimerFired(Timer<MediaController>*); bool hasEnded() const; void scheduleTimeupdateEvent(); @@ -127,7 +110,12 @@ private: friend class HTMLMediaElement; friend class MediaControllerEventListener; - Vector<HTMLMediaElement*> m_mediaElements; + // FIXME: A MediaController should ideally keep an otherwise + // unreferenced slaved media element alive. When Oilpan is + // enabled by default, consider making the hash set references + // strong to accomplish that. crbug.com/383072 + typedef WillBeHeapLinkedHashSet<RawPtrWillBeWeakMember<HTMLMediaElement> > MediaElementSequence; + MediaElementSequence m_mediaElements; bool m_paused; double m_defaultPlaybackRate; double m_volume; @@ -135,13 +123,10 @@ private: bool m_muted; ReadyState m_readyState; PlaybackState m_playbackState; - Vector<RefPtr<Event> > m_pendingEvents; - Timer<MediaController> m_asyncEventTimer; + OwnPtrWillBeMember<GenericEventQueue> m_pendingEventsQueue; mutable Timer<MediaController> m_clearPositionTimer; - String m_mediaGroup; - bool m_closedCaptionsVisible; OwnPtr<Clock> m_clock; - ExecutionContext* m_executionContext; + RawPtrWillBeWeakMember<ExecutionContext> m_executionContext; Timer<MediaController> m_timeupdateTimer; double m_previousTimeupdateTime; }; diff --git a/chromium/third_party/WebKit/Source/core/html/MediaController.idl b/chromium/third_party/WebKit/Source/core/html/MediaController.idl index ad46115d889..8e70a8b0531 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaController.idl +++ b/chromium/third_party/WebKit/Source/core/html/MediaController.idl @@ -23,15 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#mediacontroller + [ Constructor, ConstructorCallWith=ExecutionContext, - RuntimeEnabled=Media, + RuntimeEnabled=MediaController, + TypeChecking=Unrestricted, ] interface MediaController : EventTarget { readonly attribute TimeRanges buffered; readonly attribute TimeRanges seekable; - readonly attribute double duration; + readonly attribute unrestricted double duration; [RaisesException=Setter] attribute double currentTime; readonly attribute boolean paused; diff --git a/chromium/third_party/WebKit/Source/core/html/MediaControllerInterface.h b/chromium/third_party/WebKit/Source/core/html/MediaControllerInterface.h deleted file mode 100644 index 9f8f7042f39..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/MediaControllerInterface.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MediaControllerInterface_h -#define MediaControllerInterface_h - -#include "wtf/PassRefPtr.h" - -namespace WebCore { - -class ExceptionState; -class TimeRanges; - -class MediaControllerInterface { -public: - virtual ~MediaControllerInterface() { }; - - // MediaController IDL: - virtual PassRefPtr<TimeRanges> buffered() const = 0; - virtual PassRefPtr<TimeRanges> seekable() const = 0; - virtual PassRefPtr<TimeRanges> played() = 0; - - virtual double duration() const = 0; - virtual double currentTime() const = 0; - virtual void setCurrentTime(double, ExceptionState&) = 0; - - virtual bool paused() const = 0; - virtual void play() = 0; - virtual void pause() = 0; - - virtual double defaultPlaybackRate() const = 0; - virtual void setDefaultPlaybackRate(double) = 0; - - virtual double playbackRate() const = 0; - virtual void setPlaybackRate(double) = 0; - - virtual double volume() const = 0; - virtual void setVolume(double, ExceptionState&) = 0; - - virtual bool muted() const = 0; - virtual void setMuted(bool) = 0; - - enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA }; - virtual ReadyState readyState() const = 0; - - // MediaControlElements: - virtual bool supportsFullscreen() const = 0; - virtual bool isFullscreen() const = 0; - virtual void enterFullscreen() = 0; - - virtual bool hasAudio() const = 0; - virtual bool hasVideo() const = 0; - virtual bool hasClosedCaptions() const = 0; - virtual void setClosedCaptionsVisible(bool) = 0; - virtual bool closedCaptionsVisible() const = 0; - - virtual void beginScrubbing() = 0; - virtual void endScrubbing() = 0; - - virtual bool canPlay() const = 0; - - virtual bool hasCurrentSrc() const = 0; -}; - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/html/MediaDocument.cpp b/chromium/third_party/WebKit/Source/core/html/MediaDocument.cpp index ef6207470d6..1a9235d6546 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaDocument.cpp +++ b/chromium/third_party/WebKit/Source/core/html/MediaDocument.cpp @@ -27,12 +27,12 @@ #include "core/html/MediaDocument.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" -#include "core/dom/NodeTraversal.h" +#include "core/HTMLNames.h" +#include "core/dom/ElementTraversal.h" #include "core/dom/RawDataDocumentParser.h" #include "core/events/KeyboardEvent.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLBodyElement.h" #include "core/html/HTMLHeadElement.h" #include "core/html/HTMLHtmlElement.h" @@ -41,7 +41,6 @@ #include "core/html/HTMLVideoElement.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" -#include "core/frame/Frame.h" #include "platform/KeyboardCodes.h" namespace WebCore { @@ -51,9 +50,9 @@ using namespace HTMLNames; // FIXME: Share more code with PluginDocumentParser. class MediaDocumentParser : public RawDataDocumentParser { public: - static PassRefPtr<MediaDocumentParser> create(MediaDocument* document) + static PassRefPtrWillBeRawPtr<MediaDocumentParser> create(MediaDocument* document) { - return adoptRef(new MediaDocumentParser(document)); + return adoptRefWillBeNoop(new MediaDocumentParser(document)); } private: @@ -73,25 +72,25 @@ private: void MediaDocumentParser::createDocumentStructure() { ASSERT(document()); - RefPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*document()); + RefPtrWillBeRawPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*document()); rootElement->insertedByParser(); document()->appendChild(rootElement); if (document()->frame()) document()->frame()->loader().dispatchDocumentElementAvailable(); - RefPtr<HTMLHeadElement> head = HTMLHeadElement::create(*document()); - RefPtr<HTMLMetaElement> meta = HTMLMetaElement::create(*document()); + RefPtrWillBeRawPtr<HTMLHeadElement> head = HTMLHeadElement::create(*document()); + RefPtrWillBeRawPtr<HTMLMetaElement> meta = HTMLMetaElement::create(*document()); meta->setAttribute(nameAttr, "viewport"); meta->setAttribute(contentAttr, "width=device-width"); head->appendChild(meta.release()); - RefPtr<HTMLVideoElement> media = HTMLVideoElement::create(*document()); + RefPtrWillBeRawPtr<HTMLVideoElement> media = HTMLVideoElement::create(*document()); media->setAttribute(controlsAttr, ""); media->setAttribute(autoplayAttr, ""); media->setAttribute(nameAttr, "media"); - RefPtr<HTMLSourceElement> source = HTMLSourceElement::create(*document()); + RefPtrWillBeRawPtr<HTMLSourceElement> source = HTMLSourceElement::create(*document()); source->setSrc(document()->url()); if (DocumentLoader* loader = document()->loader()) @@ -99,7 +98,7 @@ void MediaDocumentParser::createDocumentStructure() media->appendChild(source.release()); - RefPtr<HTMLBodyElement> body = HTMLBodyElement::create(*document()); + RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*document()); body->appendChild(media.release()); rootElement->appendChild(head.release()); @@ -124,23 +123,11 @@ MediaDocument::MediaDocument(const DocumentInit& initializer) lockCompatibilityMode(); } -PassRefPtr<DocumentParser> MediaDocument::createParser() +PassRefPtrWillBeRawPtr<DocumentParser> MediaDocument::createParser() { return MediaDocumentParser::create(this); } -static inline HTMLVideoElement* descendentVideoElement(Node* root) -{ - ASSERT(root); - - for (Node* node = root; node; node = NodeTraversal::next(*node, root)) { - if (isHTMLVideoElement(node)) - return toHTMLVideoElement(node); - } - - return 0; -} - void MediaDocument::defaultEventHandler(Event* event) { Node* targetNode = event->target()->toNode(); @@ -148,18 +135,14 @@ void MediaDocument::defaultEventHandler(Event* event) return; if (event->type() == EventTypeNames::keydown && event->isKeyboardEvent()) { - HTMLVideoElement* video = descendentVideoElement(targetNode); + HTMLVideoElement* video = Traversal<HTMLVideoElement>::firstWithin(*targetNode); if (!video) return; KeyboardEvent* keyboardEvent = toKeyboardEvent(event); if (keyboardEvent->keyIdentifier() == "U+0020" || keyboardEvent->keyCode() == VKEY_MEDIA_PLAY_PAUSE) { // space or media key (play/pause) - if (video->paused()) { - if (video->canPlay()) - video->play(); - } else - video->pause(); + video->togglePlayState(); event->setDefaultHandled(); } } diff --git a/chromium/third_party/WebKit/Source/core/html/MediaDocument.h b/chromium/third_party/WebKit/Source/core/html/MediaDocument.h index b5d264ec976..a2b55c5c385 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaDocument.h +++ b/chromium/third_party/WebKit/Source/core/html/MediaDocument.h @@ -32,15 +32,15 @@ namespace WebCore { class MediaDocument FINAL : public HTMLDocument { public: - static PassRefPtr<MediaDocument> create(const DocumentInit& initializer = DocumentInit()) + static PassRefPtrWillBeRawPtr<MediaDocument> create(const DocumentInit& initializer = DocumentInit()) { - return adoptRef(new MediaDocument(initializer)); + return adoptRefWillBeNoop(new MediaDocument(initializer)); } private: MediaDocument(const DocumentInit&); - virtual PassRefPtr<DocumentParser> createParser() OVERRIDE; + virtual PassRefPtrWillBeRawPtr<DocumentParser> createParser() OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; }; diff --git a/chromium/third_party/WebKit/Source/core/html/MediaError.h b/chromium/third_party/WebKit/Source/core/html/MediaError.h index 86ace1108bf..0169c759713 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaError.h +++ b/chromium/third_party/WebKit/Source/core/html/MediaError.h @@ -32,7 +32,7 @@ namespace WebCore { -class MediaError : public RefCounted<MediaError>, public ScriptWrappable { +class MediaError FINAL : public RefCountedWillBeGarbageCollectedFinalized<MediaError>, public ScriptWrappable { public: enum Code { MEDIA_ERR_ABORTED = 1, @@ -42,10 +42,15 @@ public: MEDIA_ERR_ENCRYPTED }; - static PassRefPtr<MediaError> create(Code code) { return adoptRef(new MediaError(code)); } + static PassRefPtrWillBeRawPtr<MediaError> create(Code code) + { + return adoptRefWillBeNoop(new MediaError(code)); + } Code code() const { return m_code; } + void trace(Visitor*) { } + private: MediaError(Code code) : m_code(code) { diff --git a/chromium/third_party/WebKit/Source/core/html/MediaError.idl b/chromium/third_party/WebKit/Source/core/html/MediaError.idl index 4cf13edcef5..aaffbc230d9 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaError.idl +++ b/chromium/third_party/WebKit/Source/core/html/MediaError.idl @@ -24,12 +24,13 @@ */ [ - RuntimeEnabled=Media + RuntimeEnabled=Media, + WillBeGarbageCollected, ] interface MediaError { const unsigned short MEDIA_ERR_ABORTED = 1; const unsigned short MEDIA_ERR_NETWORK = 2; const unsigned short MEDIA_ERR_DECODE = 3; const unsigned short MEDIA_ERR_SRC_NOT_SUPPORTED = 4; - [RuntimeEnabled=EncryptedMediaAnyVersion] const unsigned short MEDIA_ERR_ENCRYPTED = 5; + [RuntimeEnabled=EncryptedMediaAnyVersion, DeprecateAs=MediaErrorEncrypted] const unsigned short MEDIA_ERR_ENCRYPTED = 5; readonly attribute unsigned short code; }; diff --git a/chromium/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp b/chromium/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp index f887a05f163..70cd27fe98f 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp @@ -134,11 +134,11 @@ void MediaFragmentURIParser::parseFragments() // name or value are not valid UTF-8 strings, then remove the name-value pair from the list. bool validUTF8 = true; if (!name.isEmpty()) { - name = name.utf8(String::StrictConversion).data(); + name = name.utf8(StrictUTF8Conversion).data(); validUTF8 = !name.isEmpty(); } if (validUTF8 && !value.isEmpty()) { - value = value.utf8(String::StrictConversion).data(); + value = value.utf8(StrictUTF8Conversion).data(); validUTF8 = !value.isEmpty(); } diff --git a/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.cpp b/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.cpp index 38f02b701bd..270236ec6c0 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.cpp +++ b/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "core/html/MediaKeyEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "wtf/Uint8Array.h" namespace WebCore { @@ -63,4 +62,9 @@ const AtomicString& MediaKeyEvent::interfaceName() const return EventNames::MediaKeyEvent; } +void MediaKeyEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.h b/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.h index 370abafce6b..cf95046f657 100644 --- a/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.h +++ b/chromium/third_party/WebKit/Source/core/html/MediaKeyEvent.h @@ -43,21 +43,21 @@ struct MediaKeyEventInit : public EventInit { unsigned short systemCode; }; -class MediaKeyEvent : public Event { +class MediaKeyEvent FINAL : public Event { public: virtual ~MediaKeyEvent(); - static PassRefPtr<MediaKeyEvent> create() + static PassRefPtrWillBeRawPtr<MediaKeyEvent> create() { - return adoptRef(new MediaKeyEvent); + return adoptRefWillBeNoop(new MediaKeyEvent); } - static PassRefPtr<MediaKeyEvent> create(const AtomicString& type, const MediaKeyEventInit& initializer) + static PassRefPtrWillBeRawPtr<MediaKeyEvent> create(const AtomicString& type, const MediaKeyEventInit& initializer) { - return adoptRef(new MediaKeyEvent(type, initializer)); + return adoptRefWillBeNoop(new MediaKeyEvent(type, initializer)); } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; String keySystem() const { return m_keySystem; } String sessionId() const { return m_sessionId; } @@ -68,6 +68,8 @@ public: MediaKeyError* errorCode(bool& isNull) const { isNull = !m_errorCode; return m_errorCode.get(); } unsigned short systemCode() const { return m_systemCode; } + virtual void trace(Visitor*) OVERRIDE; + private: MediaKeyEvent(); MediaKeyEvent(const AtomicString& type, const MediaKeyEventInit& initializer); diff --git a/chromium/third_party/WebKit/Source/core/html/PluginDocument.cpp b/chromium/third_party/WebKit/Source/core/html/PluginDocument.cpp index 366ee643ba3..15e112713f0 100644 --- a/chromium/third_party/WebKit/Source/core/html/PluginDocument.cpp +++ b/chromium/third_party/WebKit/Source/core/html/PluginDocument.cpp @@ -25,17 +25,17 @@ #include "config.h" #include "core/html/PluginDocument.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" #include "core/dom/RawDataDocumentParser.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLBodyElement.h" #include "core/html/HTMLEmbedElement.h" #include "core/html/HTMLHtmlElement.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" #include "core/plugins/PluginView.h" #include "core/rendering/RenderEmbeddedObject.h" @@ -46,15 +46,21 @@ using namespace HTMLNames; // FIXME: Share more code with MediaDocumentParser. class PluginDocumentParser : public RawDataDocumentParser { public: - static PassRefPtr<PluginDocumentParser> create(PluginDocument* document) + static PassRefPtrWillBeRawPtr<PluginDocumentParser> create(PluginDocument* document) { - return adoptRef(new PluginDocumentParser(document)); + return adoptRefWillBeNoop(new PluginDocumentParser(document)); + } + + virtual void trace(Visitor* visitor) OVERRIDE + { + visitor->trace(m_embedElement); + RawDataDocumentParser::trace(visitor); } private: PluginDocumentParser(Document* document) : RawDataDocumentParser(document) - , m_embedElement(0) + , m_embedElement(nullptr) { } @@ -66,7 +72,7 @@ private: PluginView* pluginView() const; - RefPtr<HTMLEmbedElement> m_embedElement; + RefPtrWillBeMember<HTMLEmbedElement> m_embedElement; }; void PluginDocumentParser::createDocumentStructure() @@ -76,7 +82,7 @@ void PluginDocumentParser::createDocumentStructure() ASSERT(document()); RELEASE_ASSERT(document()->loader()); - Frame* frame = document()->frame(); + LocalFrame* frame = document()->frame(); if (!frame) return; @@ -84,12 +90,12 @@ void PluginDocumentParser::createDocumentStructure() if (!frame->settings() || !frame->loader().allowPlugins(NotAboutToInstantiatePlugin)) return; - RefPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*document()); + RefPtrWillBeRawPtr<HTMLHtmlElement> rootElement = HTMLHtmlElement::create(*document()); rootElement->insertedByParser(); document()->appendChild(rootElement); frame->loader().dispatchDocumentElementAvailable(); - RefPtr<HTMLBodyElement> body = HTMLBodyElement::create(*document()); + RefPtrWillBeRawPtr<HTMLBodyElement> body = HTMLBodyElement::create(*document()); body->setAttribute(marginwidthAttr, "0"); body->setAttribute(marginheightAttr, "0"); body->setAttribute(styleAttr, "background-color: rgb(38,38,38)"); @@ -134,7 +140,7 @@ void PluginDocumentParser::finish() view->didFinishLoading(); else view->didFailLoading(error); - m_embedElement = 0; + m_embedElement = nullptr; } RawDataDocumentParser::finish(); } @@ -156,7 +162,7 @@ PluginDocument::PluginDocument(const DocumentInit& initializer) lockCompatibilityMode(); } -PassRefPtr<DocumentParser> PluginDocument::createParser() +PassRefPtrWillBeRawPtr<DocumentParser> PluginDocument::createParser() { return PluginDocumentParser::create(this); } @@ -178,20 +184,14 @@ Node* PluginDocument::pluginNode() void PluginDocument::detach(const AttachContext& context) { // Release the plugin node so that we don't have a circular reference. - m_pluginNode = 0; + m_pluginNode = nullptr; HTMLDocument::detach(context); } -void PluginDocument::cancelManualPluginLoad() +void PluginDocument::trace(Visitor* visitor) { - // PluginDocument::cancelManualPluginLoad should only be called once, but there are issues - // with how many times we call beforeload on object elements. <rdar://problem/8441094>. - if (!shouldLoadPluginManually()) - return; - - DocumentLoader* documentLoader = frame()->loader().activeDocumentLoader(); - documentLoader->cancelMainResourceLoad(ResourceError::cancelledError(documentLoader->request().url())); - setShouldLoadPluginManually(false); + visitor->trace(m_pluginNode); + HTMLDocument::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/core/html/PluginDocument.h b/chromium/third_party/WebKit/Source/core/html/PluginDocument.h index 590cb30303f..021e5c100ec 100644 --- a/chromium/third_party/WebKit/Source/core/html/PluginDocument.h +++ b/chromium/third_party/WebKit/Source/core/html/PluginDocument.h @@ -34,9 +34,9 @@ class Widget; class PluginDocument FINAL : public HTMLDocument { public: - static PassRefPtr<PluginDocument> create(const DocumentInit& initializer = DocumentInit()) + static PassRefPtrWillBeRawPtr<PluginDocument> create(const DocumentInit& initializer = DocumentInit()) { - return adoptRef(new PluginDocument(initializer)); + return adoptRefWillBeNoop(new PluginDocument(initializer)); } void setPluginNode(Node* pluginNode) { m_pluginNode = pluginNode; } @@ -46,19 +46,19 @@ public: virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - void cancelManualPluginLoad(); - bool shouldLoadPluginManually() { return m_shouldLoadPluginManually; } + virtual void trace(Visitor*) OVERRIDE; + private: - PluginDocument(const DocumentInit&); + explicit PluginDocument(const DocumentInit&); - virtual PassRefPtr<DocumentParser> createParser() OVERRIDE; + virtual PassRefPtrWillBeRawPtr<DocumentParser> createParser() OVERRIDE; void setShouldLoadPluginManually(bool loadManually) { m_shouldLoadPluginManually = loadManually; } bool m_shouldLoadPluginManually; - RefPtr<Node> m_pluginNode; + RefPtrWillBeMember<Node> m_pluginNode; }; DEFINE_DOCUMENT_TYPE_CASTS(PluginDocument); diff --git a/chromium/third_party/WebKit/Source/core/html/PublicURLManager.cpp b/chromium/third_party/WebKit/Source/core/html/PublicURLManager.cpp index 09157de9df7..f084b7cae8a 100644 --- a/chromium/third_party/WebKit/Source/core/html/PublicURLManager.cpp +++ b/chromium/third_party/WebKit/Source/core/html/PublicURLManager.cpp @@ -27,8 +27,10 @@ #include "config.h" #include "core/html/PublicURLManager.h" +#include "core/fetch/MemoryCache.h" #include "core/html/URLRegistry.h" #include "platform/weborigin/KURL.h" +#include "wtf/Vector.h" #include "wtf/text/StringHash.h" namespace WebCore { @@ -46,14 +48,14 @@ PublicURLManager::PublicURLManager(ExecutionContext* context) { } -void PublicURLManager::registerURL(SecurityOrigin* origin, const KURL& url, URLRegistrable* registrable) +void PublicURLManager::registerURL(SecurityOrigin* origin, const KURL& url, URLRegistrable* registrable, const String& uuid) { if (m_isStopped) return; - RegistryURLMap::iterator found = m_registryToURL.add(®istrable->registry(), URLSet()).iterator; + RegistryURLMap::ValueType* found = m_registryToURL.add(®istrable->registry(), URLMap()).storedValue; found->key->registerURL(origin, url, registrable); - found->value.add(url.string()); + found->value.add(url.string(), uuid); } void PublicURLManager::revoke(const KURL& url) @@ -67,6 +69,27 @@ void PublicURLManager::revoke(const KURL& url) } } +void PublicURLManager::revoke(const String& uuid) +{ + // A linear scan; revoking by UUID is assumed rare. + Vector<String> urlsToRemove; + for (RegistryURLMap::iterator i = m_registryToURL.begin(); i != m_registryToURL.end(); ++i) { + URLRegistry* registry = i->key; + URLMap& registeredURLs = i->value; + for (URLMap::iterator j = registeredURLs.begin(); j != registeredURLs.end(); ++j) { + if (uuid == j->value) { + KURL url(ParsedURLString, j->key); + MemoryCache::removeURLFromCache(executionContext(), url); + registry->unregisterURL(url); + urlsToRemove.append(j->key); + } + } + for (unsigned j = 0; j < urlsToRemove.size(); j++) + registeredURLs.remove(urlsToRemove[j]); + urlsToRemove.clear(); + } +} + void PublicURLManager::stop() { if (m_isStopped) @@ -74,8 +97,8 @@ void PublicURLManager::stop() m_isStopped = true; for (RegistryURLMap::iterator i = m_registryToURL.begin(); i != m_registryToURL.end(); ++i) { - for (URLSet::iterator j = i->value.begin(); j != i->value.end(); ++j) - i->key->unregisterURL(KURL(ParsedURLString, *j)); + for (URLMap::iterator j = i->value.begin(); j != i->value.end(); ++j) + i->key->unregisterURL(KURL(ParsedURLString, j->key)); } m_registryToURL.clear(); diff --git a/chromium/third_party/WebKit/Source/core/html/PublicURLManager.h b/chromium/third_party/WebKit/Source/core/html/PublicURLManager.h index 08848772701..094d42b4204 100644 --- a/chromium/third_party/WebKit/Source/core/html/PublicURLManager.h +++ b/chromium/third_party/WebKit/Source/core/html/PublicURLManager.h @@ -40,13 +40,14 @@ class SecurityOrigin; class URLRegistry; class URLRegistrable; -class PublicURLManager : public ActiveDOMObject { +class PublicURLManager FINAL : public ActiveDOMObject { WTF_MAKE_FAST_ALLOCATED; public: static PassOwnPtr<PublicURLManager> create(ExecutionContext*); - void registerURL(SecurityOrigin*, const KURL&, URLRegistrable*); + void registerURL(SecurityOrigin*, const KURL&, URLRegistrable*, const String& uuid = String()); void revoke(const KURL&); + void revoke(const String& uuid); // ActiveDOMObject interface. virtual void stop() OVERRIDE; @@ -54,12 +55,16 @@ public: private: PublicURLManager(ExecutionContext*); - typedef HashSet<String> URLSet; - typedef HashMap<URLRegistry*, URLSet > RegistryURLMap; + // One or more URLs can be associated with the same unique ID. + // Objects need be revoked by unique ID in some cases. + typedef String URLString; + typedef HashMap<URLString, String> URLMap; + typedef HashMap<URLRegistry*, URLMap> RegistryURLMap; + RegistryURLMap m_registryToURL; bool m_isStopped; }; } // namespace WebCore -#endif // PUBLICURLMANAGER_h +#endif // PublicURLManager_h diff --git a/chromium/third_party/WebKit/Source/core/html/RadioNodeList.cpp b/chromium/third_party/WebKit/Source/core/html/RadioNodeList.cpp index f7cbfa982a2..423badc97c1 100644 --- a/chromium/third_party/WebKit/Source/core/html/RadioNodeList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/RadioNodeList.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/html/RadioNodeList.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Element.h" #include "core/dom/NodeRareData.h" #include "core/html/HTMLFormElement.h" @@ -37,34 +37,38 @@ namespace WebCore { using namespace HTMLNames; -RadioNodeList::RadioNodeList(Node* rootNode, const AtomicString& name) - : LiveNodeList(rootNode, RadioNodeListType, InvalidateForFormControls, rootNode->hasTagName(formTag) ? NodeListIsRootedAtDocument : NodeListIsRootedAtNode) +RadioNodeList::RadioNodeList(ContainerNode& rootNode, const AtomicString& name, CollectionType type) + : LiveNodeList(rootNode, type, InvalidateForFormControls, isHTMLFormElement(rootNode) ? NodeListIsRootedAtDocument : NodeListIsRootedAtNode) , m_name(name) + , m_onlyMatchImgElements(type == RadioImgNodeListType) { ScriptWrappable::init(this); } RadioNodeList::~RadioNodeList() { - ownerNode()->nodeLists()->removeCacheWithAtomicName(this, RadioNodeListType, m_name); +#if !ENABLE(OILPAN) + ownerNode().nodeLists()->removeCache(this, m_onlyMatchImgElements ? RadioImgNodeListType : RadioNodeListType, m_name); +#endif } -static inline HTMLInputElement* toRadioButtonInputElement(Node* node) +static inline HTMLInputElement* toRadioButtonInputElement(Element& element) { - ASSERT(node->isElementNode()); - if (!node->hasTagName(inputTag)) + if (!isHTMLInputElement(element)) return 0; - HTMLInputElement* inputElement = toHTMLInputElement(node); - if (!inputElement->isRadioButton() || inputElement->value().isEmpty()) + HTMLInputElement& inputElement = toHTMLInputElement(element); + if (!inputElement.isRadioButton() || inputElement.value().isEmpty()) return 0; - return inputElement; + return &inputElement; } String RadioNodeList::value() const { - for (unsigned i = 0; i < length(); ++i) { - Node* node = item(i); - const HTMLInputElement* inputElement = toRadioButtonInputElement(node); + if (m_onlyMatchImgElements) + return String(); + unsigned length = this->length(); + for (unsigned i = 0; i < length; ++i) { + const HTMLInputElement* inputElement = toRadioButtonInputElement(*item(i)); if (!inputElement || !inputElement->checked()) continue; return inputElement->value(); @@ -74,9 +78,11 @@ String RadioNodeList::value() const void RadioNodeList::setValue(const String& value) { - for (unsigned i = 0; i < length(); ++i) { - Node* node = item(i); - HTMLInputElement* inputElement = toRadioButtonInputElement(node); + if (m_onlyMatchImgElements) + return; + unsigned length = this->length(); + for (unsigned i = 0; i < length; ++i) { + HTMLInputElement* inputElement = toRadioButtonInputElement(*item(i)); if (!inputElement || inputElement->value() != value) continue; inputElement->setChecked(true); @@ -84,28 +90,43 @@ void RadioNodeList::setValue(const String& value) } } -bool RadioNodeList::checkElementMatchesRadioNodeListFilter(Element* testElement) const +bool RadioNodeList::matchesByIdOrName(const Element& testElement) const +{ + return testElement.getIdAttribute() == m_name || testElement.getNameAttribute() == m_name; +} + +bool RadioNodeList::checkElementMatchesRadioNodeListFilter(const Element& testElement) const { - ASSERT(testElement->hasTagName(objectTag) || testElement->isFormControlElement()); - if (ownerNode()->hasTagName(formTag)) { - HTMLFormElement* formElement = toHTMLElement(testElement)->formOwner(); + ASSERT(!m_onlyMatchImgElements); + ASSERT(isHTMLObjectElement(testElement) || testElement.isFormControlElement()); + if (isHTMLFormElement(ownerNode())) { + HTMLFormElement* formElement = toHTMLElement(testElement).formOwner(); if (!formElement || formElement != ownerNode()) return false; } - return testElement->getIdAttribute() == m_name || testElement->getNameAttribute() == m_name; + return matchesByIdOrName(testElement); } -bool RadioNodeList::nodeMatches(Element* testElement) const +bool RadioNodeList::elementMatches(const Element& element) const { - if (!testElement->hasTagName(objectTag) && !testElement->isFormControlElement()) + if (m_onlyMatchImgElements) { + if (!isHTMLImageElement(element)) + return false; + + if (toHTMLElement(element).formOwner() != ownerNode()) + return false; + + return matchesByIdOrName(element); + } + + if (!isHTMLObjectElement(element) && !element.isFormControlElement()) return false; - if (testElement->hasTagName(inputTag) && toHTMLInputElement(testElement)->isImageButton()) + if (isHTMLInputElement(element) && toHTMLInputElement(element).isImageButton()) return false; - return checkElementMatchesRadioNodeListFilter(testElement); + return checkElementMatchesRadioNodeListFilter(element); } -} // namspace - +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/RadioNodeList.h b/chromium/third_party/WebKit/Source/core/html/RadioNodeList.h index b735b0c3377..5dbd7b6ce6b 100644 --- a/chromium/third_party/WebKit/Source/core/html/RadioNodeList.h +++ b/chromium/third_party/WebKit/Source/core/html/RadioNodeList.h @@ -34,10 +34,10 @@ namespace WebCore { class RadioNodeList FINAL : public LiveNodeList { public: - static PassRefPtr<RadioNodeList> create(Node* ownerNode, CollectionType type, const AtomicString& name) + static PassRefPtrWillBeRawPtr<RadioNodeList> create(ContainerNode& ownerNode, CollectionType type, const AtomicString& name) { - ASSERT_UNUSED(type, type == RadioNodeListType); - return adoptRef(new RadioNodeList(ownerNode, name)); + ASSERT_UNUSED(type, type == RadioNodeListType || type == RadioImgNodeListType); + return adoptRefWillBeNoop(new RadioNodeList(ownerNode, name, type)); } virtual ~RadioNodeList(); @@ -46,15 +46,18 @@ public: void setValue(const String&); private: - RadioNodeList(Node*, const AtomicString& name); - bool checkElementMatchesRadioNodeListFilter(Element*) const; + RadioNodeList(ContainerNode&, const AtomicString& name, CollectionType); - virtual bool nodeMatches(Element*) const OVERRIDE; + bool checkElementMatchesRadioNodeListFilter(const Element&) const; + + bool matchesByIdOrName(const Element&) const; + + virtual bool elementMatches(const Element&) const OVERRIDE; AtomicString m_name; + const bool m_onlyMatchImgElements; }; -} // namepsace +} // namespace #endif - diff --git a/chromium/third_party/WebKit/Source/core/html/RadioNodeList.idl b/chromium/third_party/WebKit/Source/core/html/RadioNodeList.idl index 47beea06be2..057ad06c0ba 100644 --- a/chromium/third_party/WebKit/Source/core/html/RadioNodeList.idl +++ b/chromium/third_party/WebKit/Source/core/html/RadioNodeList.idl @@ -24,8 +24,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, ] interface RadioNodeList : NodeList { attribute DOMString value; - [ImplementedAs=item] getter Node(unsigned long index); + [ImplementedAs=item] getter Node (unsigned long index); }; diff --git a/chromium/third_party/WebKit/Source/core/html/TextDocument.cpp b/chromium/third_party/WebKit/Source/core/html/TextDocument.cpp index acff1d92f70..742339679db 100644 --- a/chromium/third_party/WebKit/Source/core/html/TextDocument.cpp +++ b/chromium/third_party/WebKit/Source/core/html/TextDocument.cpp @@ -36,9 +36,9 @@ TextDocument::TextDocument(const DocumentInit& initializer) lockCompatibilityMode(); } -PassRefPtr<DocumentParser> TextDocument::createParser() +PassRefPtrWillBeRawPtr<DocumentParser> TextDocument::createParser() { - return TextDocumentParser::create(this); + return TextDocumentParser::create(*this); } } diff --git a/chromium/third_party/WebKit/Source/core/html/TextDocument.h b/chromium/third_party/WebKit/Source/core/html/TextDocument.h index a36617db0bf..a7961f6fc8c 100644 --- a/chromium/third_party/WebKit/Source/core/html/TextDocument.h +++ b/chromium/third_party/WebKit/Source/core/html/TextDocument.h @@ -31,15 +31,15 @@ namespace WebCore { class TextDocument FINAL : public HTMLDocument { public: - static PassRefPtr<TextDocument> create(const DocumentInit& initializer = DocumentInit()) + static PassRefPtrWillBeRawPtr<TextDocument> create(const DocumentInit& initializer = DocumentInit()) { - return adoptRef(new TextDocument(initializer)); + return adoptRefWillBeNoop(new TextDocument(initializer)); } private: TextDocument(const DocumentInit&); - virtual PassRefPtr<DocumentParser> createParser(); + virtual PassRefPtrWillBeRawPtr<DocumentParser> createParser() OVERRIDE; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/TextMetrics.h b/chromium/third_party/WebKit/Source/core/html/TextMetrics.h index 9925831e009..f936067b7e4 100644 --- a/chromium/third_party/WebKit/Source/core/html/TextMetrics.h +++ b/chromium/third_party/WebKit/Source/core/html/TextMetrics.h @@ -39,14 +39,72 @@ public: float width() const { return m_width; } void setWidth(float w) { m_width = w; } + float actualBoundingBoxLeft() const { return m_actualBoundingBoxLeft; } + void setActualBoundingBoxLeft(float actualBoundingBoxLeft) { m_actualBoundingBoxLeft = actualBoundingBoxLeft; } + + float actualBoundingBoxRight() const { return m_actualBoundingBoxRight; } + void setActualBoundingBoxRight(float actualBoundingBoxRight) { m_actualBoundingBoxRight = actualBoundingBoxRight; } + + float fontBoundingBoxAscent() const { return m_fontBoundingBoxAscent; } + void setFontBoundingBoxAscent(float fontBoundingBoxAscent) { m_fontBoundingBoxAscent = fontBoundingBoxAscent; } + + float fontBoundingBoxDescent() const { return m_fontBoundingBoxDescent; } + void setFontBoundingBoxDescent(float fontBoundingBoxDescent) { m_fontBoundingBoxDescent = fontBoundingBoxDescent; } + + float actualBoundingBoxAscent() const { return m_actualBoundingBoxAscent; } + void setActualBoundingBoxAscent(float actualBoundingBoxAscent) { m_actualBoundingBoxAscent = actualBoundingBoxAscent; } + + float actualBoundingBoxDescent() const { return m_actualBoundingBoxDescent; } + void setActualBoundingBoxDescent(float actualBoundingBoxDescent) { m_actualBoundingBoxDescent = actualBoundingBoxDescent; } + + float emHeightAscent() const { return m_emHeightAscent; } + void setEmHeightAscent(float emHeightAscent) { m_emHeightAscent = emHeightAscent; } + + float emHeightDescent() const { return m_emHeightDescent; } + void setEmHeightDescent(float emHeightDescent) { m_emHeightDescent = emHeightDescent; } + + float hangingBaseline() const { return m_hangingBaseline; } + void setHangingBaseline(float hangingBaseline) { m_hangingBaseline = hangingBaseline; } + + float alphabeticBaseline() const { return m_alphabeticBaseline; } + void setAlphabeticBaseline(float alphabeticBaseline) { m_alphabeticBaseline = alphabeticBaseline; } + + float ideographicBaseline() const { return m_ideographicBaseline; } + void setIdeographicBaseline(float ideographicBaseline) { m_ideographicBaseline = ideographicBaseline; } + private: TextMetrics() : m_width(0) + , m_actualBoundingBoxLeft(0) + , m_actualBoundingBoxRight(0) + , m_fontBoundingBoxAscent(0) + , m_fontBoundingBoxDescent(0) + , m_actualBoundingBoxAscent(0) + , m_actualBoundingBoxDescent(0) + , m_emHeightAscent(0) + , m_emHeightDescent(0) + , m_hangingBaseline(0) + , m_alphabeticBaseline(0) + , m_ideographicBaseline(0) { ScriptWrappable::init(this); } + // x-direction float m_width; + float m_actualBoundingBoxLeft; + float m_actualBoundingBoxRight; + + // y-direction + float m_fontBoundingBoxAscent; + float m_fontBoundingBoxDescent; + float m_actualBoundingBoxAscent; + float m_actualBoundingBoxDescent; + float m_emHeightAscent; + float m_emHeightDescent; + float m_hangingBaseline; + float m_alphabeticBaseline; + float m_ideographicBaseline; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/TextMetrics.idl b/chromium/third_party/WebKit/Source/core/html/TextMetrics.idl index fc37998bda6..14f11483dd2 100644 --- a/chromium/third_party/WebKit/Source/core/html/TextMetrics.idl +++ b/chromium/third_party/WebKit/Source/core/html/TextMetrics.idl @@ -24,6 +24,20 @@ */ [ ] interface TextMetrics { + // x-direction readonly attribute float width; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float actualBoundingBoxLeft; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float actualBoundingBoxRight; + + // y-direction + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float fontBoundingBoxAscent; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float fontBoundingBoxDescent; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float actualBoundingBoxAscent; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float actualBoundingBoxDescent; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float emHeightAscent; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float emHeightDescent; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float hangingBaseline; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float alphabeticBaseline; + [RuntimeEnabled=ExperimentalCanvasFeatures] readonly attribute float ideographicBaseline; }; diff --git a/chromium/third_party/WebKit/Source/core/html/TimeRanges.cpp b/chromium/third_party/WebKit/Source/core/html/TimeRanges.cpp index 407ff32353b..c8fa279edad 100644 --- a/chromium/third_party/WebKit/Source/core/html/TimeRanges.cpp +++ b/chromium/third_party/WebKit/Source/core/html/TimeRanges.cpp @@ -26,13 +26,13 @@ #include "config.h" #include "core/html/TimeRanges.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/dom/ExceptionCode.h" #include <math.h> using namespace WebCore; -using namespace std; TimeRanges::TimeRanges(double start, double end) { @@ -116,7 +116,7 @@ void TimeRanges::unionWith(const TimeRanges* other) double TimeRanges::start(unsigned index, ExceptionState& exceptionState) const { if (index >= length()) { - exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is not less than the object's length (" + String::number(length()) + ")."); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexExceedsMaximumBound("index", index, length())); return 0; } return m_ranges[index].m_start; @@ -125,7 +125,7 @@ double TimeRanges::start(unsigned index, ExceptionState& exceptionState) const double TimeRanges::end(unsigned index, ExceptionState& exceptionState) const { if (index >= length()) { - exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is not less than the object's length (" + String::number(length()) + ")."); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexExceedsMaximumBound("index", index, length())); return 0; } return m_ranges[index].m_end; @@ -134,7 +134,7 @@ double TimeRanges::end(unsigned index, ExceptionState& exceptionState) const void TimeRanges::add(double start, double end) { ASSERT(start <= end); - unsigned int overlappingArcIndex; + unsigned overlappingArcIndex; Range addedRange(start, end); // For each present range check if we need to: @@ -193,9 +193,9 @@ double TimeRanges::nearest(double time) const if (time >= startTime && time <= endTime) return time; if (fabs(startTime - time) < closest) - closest = fabsf(startTime - time); + closest = fabs(startTime - time); else if (fabs(endTime - time) < closest) - closest = fabsf(endTime - time); + closest = fabs(endTime - time); } return closest; } diff --git a/chromium/third_party/WebKit/Source/core/html/URLRegistry.h b/chromium/third_party/WebKit/Source/core/html/URLRegistry.h index 660acb92852..f6f2c3bcbf0 100644 --- a/chromium/third_party/WebKit/Source/core/html/URLRegistry.h +++ b/chromium/third_party/WebKit/Source/core/html/URLRegistry.h @@ -52,8 +52,9 @@ public: virtual void registerURL(SecurityOrigin*, const KURL&, URLRegistrable*) = 0; virtual void unregisterURL(const KURL&) = 0; - // This is an optional API + // These are optional APIs virtual URLRegistrable* lookup(const String&) { ASSERT_NOT_REACHED(); return 0; } + virtual bool contains(const String&) { ASSERT_NOT_REACHED(); return false; } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/ValidityState.h b/chromium/third_party/WebKit/Source/core/html/ValidityState.h index 44d05b8cc8c..829cc4e97a4 100644 --- a/chromium/third_party/WebKit/Source/core/html/ValidityState.h +++ b/chromium/third_party/WebKit/Source/core/html/ValidityState.h @@ -30,16 +30,20 @@ namespace WebCore { -class ValidityState : public ScriptWrappable { - WTF_MAKE_NONCOPYABLE(ValidityState); WTF_MAKE_FAST_ALLOCATED; +class ValidityState : public NoBaseWillBeGarbageCollectedFinalized<ValidityState>, public ScriptWrappable { + WTF_MAKE_NONCOPYABLE(ValidityState); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<ValidityState> create(FormAssociatedElement* control) + static PassOwnPtrWillBeRawPtr<ValidityState> create(FormAssociatedElement* control) { - return adoptPtr(new ValidityState(control)); + return adoptPtrWillBeNoop(new ValidityState(control)); } + void trace(Visitor* visitor) { visitor->trace(m_control); } +#if !ENABLE(OILPAN) void ref() { m_control->ref(); } void deref() { m_control->deref(); } +#endif String validationMessage() const; @@ -57,12 +61,12 @@ public: bool valid() const; private: - ValidityState(FormAssociatedElement* control) : m_control(control) + explicit ValidityState(FormAssociatedElement* control) : m_control(control) { ScriptWrappable::init(this); } - FormAssociatedElement* m_control; + RawPtrWillBeMember<FormAssociatedElement> m_control; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/ValidityState.idl b/chromium/third_party/WebKit/Source/core/html/ValidityState.idl index 582baf9a4a3..d4f72538d3a 100644 --- a/chromium/third_party/WebKit/Source/core/html/ValidityState.idl +++ b/chromium/third_party/WebKit/Source/core/html/ValidityState.idl @@ -21,6 +21,7 @@ */ [ + WillBeGarbageCollected ] interface ValidityState { readonly attribute boolean valueMissing; readonly attribute boolean typeMismatch; diff --git a/chromium/third_party/WebKit/Source/core/html/WindowNameCollection.cpp b/chromium/third_party/WebKit/Source/core/html/WindowNameCollection.cpp new file mode 100644 index 00000000000..7321f853f29 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/WindowNameCollection.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/WindowNameCollection.h" + +#include "core/html/HTMLImageElement.h" + +namespace WebCore { + +WindowNameCollection::WindowNameCollection(ContainerNode& document, const AtomicString& name) + : HTMLNameCollection(document, WindowNamedItems, name) +{ +} + +bool WindowNameCollection::elementMatches(const Element& element) const +{ + // Match only images, forms, applets, embeds and objects by name, + // but anything by id + if (isHTMLImageElement(element) + || isHTMLFormElement(element) + || isHTMLAppletElement(element) + || isHTMLEmbedElement(element) + || isHTMLObjectElement(element)) { + if (element.getNameAttribute() == m_name) + return true; + } + return element.getIdAttribute() == m_name; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/WindowNameCollection.h b/chromium/third_party/WebKit/Source/core/html/WindowNameCollection.h new file mode 100644 index 00000000000..fc9408707c1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/WindowNameCollection.h @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WindowNameCollection_h +#define WindowNameCollection_h + +#include "core/html/HTMLNameCollection.h" + +namespace WebCore { + +class WindowNameCollection FINAL : public HTMLNameCollection { +public: + static PassRefPtrWillBeRawPtr<WindowNameCollection> create(ContainerNode& document, CollectionType type, const AtomicString& name) + { + ASSERT_UNUSED(type, type == WindowNamedItems); + return adoptRefWillBeNoop(new WindowNameCollection(document, name)); + } + + bool elementMatches(const Element&) const; + +private: + WindowNameCollection(ContainerNode& document, const AtomicString& name); +}; + +DEFINE_TYPE_CASTS(WindowNameCollection, LiveNodeListBase, collection, collection->type() == WindowNamedItems, collection.type() == WindowNamedItems); + +} // namespace WebCore + +#endif // WindowNameCollection_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp index c7e5c9301b6..bc7f5932d0f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp @@ -32,36 +32,34 @@ #include "core/html/canvas/ANGLEInstancedArrays.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContext* context) +ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_ANGLE_instanced_arrays"); + context->extensionsUtil()->ensureExtensionEnabled("GL_ANGLE_instanced_arrays"); } ANGLEInstancedArrays::~ANGLEInstancedArrays() { } -WebGLExtension::ExtensionName ANGLEInstancedArrays::name() const +WebGLExtensionName ANGLEInstancedArrays::name() const { return ANGLEInstancedArraysName; } -PassRefPtr<ANGLEInstancedArrays> ANGLEInstancedArrays::create(WebGLRenderingContext* context) +PassRefPtr<ANGLEInstancedArrays> ANGLEInstancedArrays::create(WebGLRenderingContextBase* context) { return adoptRef(new ANGLEInstancedArrays(context)); } -bool ANGLEInstancedArrays::supported(WebGLRenderingContext* context) +bool ANGLEInstancedArrays::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_ANGLE_instanced_arrays"); + return context->extensionsUtil()->supportsExtension("GL_ANGLE_instanced_arrays"); } const char* ANGLEInstancedArrays::extensionName() @@ -69,7 +67,7 @@ const char* ANGLEInstancedArrays::extensionName() return "ANGLE_instanced_arrays"; } -void ANGLEInstancedArrays::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +void ANGLEInstancedArrays::drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { if (isLost()) return; @@ -77,7 +75,7 @@ void ANGLEInstancedArrays::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first m_context->drawArraysInstancedANGLE(mode, first, count, primcount); } -void ANGLEInstancedArrays::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) +void ANGLEInstancedArrays::drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount) { if (isLost()) return; @@ -85,7 +83,7 @@ void ANGLEInstancedArrays::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei c m_context->drawElementsInstancedANGLE(mode, count, type, offset, primcount); } -void ANGLEInstancedArrays::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor) +void ANGLEInstancedArrays::vertexAttribDivisorANGLE(GLuint index, GLuint divisor) { if (isLost()) return; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h index 0b9f53119e0..7141e82de09 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h @@ -32,28 +32,27 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/WebGLExtension.h" -#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; -class ANGLEInstancedArrays : public WebGLExtension, public ScriptWrappable { +class ANGLEInstancedArrays FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<ANGLEInstancedArrays> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<ANGLEInstancedArrays> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~ANGLEInstancedArrays(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; - void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); - void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount); - void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor); + void drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); + void drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount); + void vertexAttribDivisorANGLE(GLuint index, GLuint divisor); private: - ANGLEInstancedArrays(WebGLRenderingContext*); + ANGLEInstancedArrays(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl index 2d257cce1b9..4e63430ade0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl @@ -29,12 +29,13 @@ */ [ + DoNotCheckConstants, NoInterfaceObject, - DoNotCheckConstants + TypeChecking=Interface|Nullable, ] interface ANGLEInstancedArrays { const unsigned long VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE; - [StrictTypeChecking] void drawArraysInstancedANGLE(unsigned long mode, long first, long count, long primcount); - [StrictTypeChecking] void drawElementsInstancedANGLE(unsigned long mode, long count, unsigned long type, long long offset, long primcount); - [StrictTypeChecking] void vertexAttribDivisorANGLE(unsigned long index, long divisor); + void drawArraysInstancedANGLE(unsigned long mode, long first, long count, long primcount); + void drawElementsInstancedANGLE(unsigned long mode, long count, unsigned long type, long long offset, long primcount); + void vertexAttribDivisorANGLE(unsigned long index, long divisor); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp index 66429f5af14..3ff9b1ac9ee 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp @@ -26,12 +26,15 @@ #include "config.h" -#include "Canvas2DContextAttributes.h" +#include "core/html/canvas/Canvas2DContextAttributes.h" + +#include "wtf/text/WTFString.h" namespace WebCore { Canvas2DContextAttributes::Canvas2DContextAttributes() : m_alpha(true) + , m_storage(PersistentStorage) { ScriptWrappable::init(this); } @@ -55,4 +58,22 @@ void Canvas2DContextAttributes::setAlpha(bool alpha) m_alpha = alpha; } +String Canvas2DContextAttributes::storage() const +{ + return m_storage == PersistentStorage ? "persistent" : "discardable"; +} + +void Canvas2DContextAttributes::setStorage(const String& storage) +{ + if (storage == "persistent") + m_storage = PersistentStorage; + else if (storage == "discardable") + m_storage = DiscardableStorage; +} + +Canvas2DContextStorage Canvas2DContextAttributes::parsedStorage() const +{ + return m_storage; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h index e777ef80778..dab44564297 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h @@ -33,6 +33,11 @@ namespace WebCore { +enum Canvas2DContextStorage { + PersistentStorage, + DiscardableStorage +}; + class Canvas2DContextAttributes : public CanvasContextAttributes, public ScriptWrappable { public: virtual ~Canvas2DContextAttributes(); @@ -44,10 +49,15 @@ public: bool alpha() const; void setAlpha(bool); + String storage() const; + void setStorage(const String&); + Canvas2DContextStorage parsedStorage() const; + protected: Canvas2DContextAttributes(); bool m_alpha; + Canvas2DContextStorage m_storage; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl index 72e01914f14..f6017b3c86f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl @@ -28,4 +28,5 @@ NoInterfaceObject ] interface Canvas2DContextAttributes { attribute boolean alpha; + [RuntimeEnabled=ExperimentalCanvasFeatures] attribute DOMString storage; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp index 07e62a07e10..c63aa7d85b0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp @@ -49,13 +49,13 @@ CanvasGradient::CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& void CanvasGradient::addColorStop(float value, const String& color, ExceptionState& exceptionState) { if (!(value >= 0 && value <= 1.0f)) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided value (" + String::number(value) + ") is outside the range (0.0, 1.0)."); return; } RGBA32 rgba = 0; if (!parseColorOrCurrentColor(rgba, color, 0 /*canvas*/)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The value provided ('" + color + "') could not be parsed as a color."); return; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl index 35a4e2a31d0..3da025a744c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ [ + TypeChecking=Unrestricted, ] interface CanvasGradient { [RaisesException] void addColorStop(float offset, DOMString color); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h new file mode 100644 index 00000000000..10e3b958b6c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * + * 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 CanvasImageSource_h +#define CanvasImageSource_h + +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class Image; +class SecurityOrigin; + +enum SourceImageMode { + CopySourceImageIfVolatile, + DontCopySourceImage +}; + +enum SourceImageStatus { + NormalSourceImageStatus, + ExternalSourceImageStatus, // Shared with another GPU context + UndecodableSourceImageStatus, // Image element with a 'broken' image + ZeroSizeCanvasSourceImageStatus, // Source is a canvas with width or heigh of zero + IncompleteSourceImageStatus, // Image element with no source media + InvalidSourceImageStatus, +}; + +class CanvasImageSource { +public: + virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus* = 0) const = 0; + + // IMPORTANT: Result must be independent of whether destinationContext is + // already tainted because this function may be used to determine whether + // a CanvasPattern is "origin clean", and that pattern may be used on + // another canvas, which may not be already tainted. + virtual bool wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const = 0; + + virtual bool isVideoElement() const { return false; } + + // Adjusts the source and destination rectangles for cases where the actual + // source image is a subregion of the image returned by getSourceImageForCanvas. + virtual void adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const { } + + virtual FloatSize sourceSize() const = 0; + virtual FloatSize defaultDestinationSize() const { return sourceSize(); } + virtual const KURL& sourceURL() const { return blankURL(); } + +protected: + virtual ~CanvasImageSource() { } +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp index 66a1ac99fa4..879487b14d3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp @@ -113,7 +113,7 @@ void CanvasPathMethods::arcTo(float x1, float y1, float x2, float y2, float r, E return; if (r < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The radius provided (" + String::number(r) + ") is negative."); return; } @@ -135,7 +135,6 @@ namespace { float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise) { - float twoPi = 2 * piFloat; float newEndAngle = endAngle; /* http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc * If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2pi, or, @@ -143,10 +142,10 @@ float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise) * then the arc is the whole circumference of this ellipse, and the point at startAngle along this circle's circumference, * measured in radians clockwise from the ellipse's semi-major axis, acts as both the start point and the end point. */ - if (!anticlockwise && endAngle - startAngle >= twoPi) - newEndAngle = startAngle + twoPi; - else if (anticlockwise && startAngle - endAngle >= twoPi) - newEndAngle = startAngle - twoPi; + if (!anticlockwise && endAngle - startAngle >= twoPiFloat) + newEndAngle = startAngle + twoPiFloat; + else if (anticlockwise && startAngle - endAngle >= twoPiFloat) + newEndAngle = startAngle - twoPiFloat; /* * Otherwise, the arc is the path along the circumference of this ellipse from the start point to the end point, @@ -159,9 +158,9 @@ float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise) * We preserve backward-compatibility. */ else if (!anticlockwise && startAngle > endAngle) - newEndAngle = startAngle + (twoPi - fmodf(startAngle - endAngle, twoPi)); + newEndAngle = startAngle + (twoPiFloat - fmodf(startAngle - endAngle, twoPiFloat)); else if (anticlockwise && startAngle < endAngle) - newEndAngle = startAngle - (twoPi - fmodf(endAngle - startAngle, twoPi)); + newEndAngle = startAngle - (twoPiFloat - fmodf(endAngle - startAngle, twoPiFloat)); ASSERT(ellipseIsRenderable(startAngle, newEndAngle)); return newEndAngle; @@ -180,17 +179,16 @@ inline FloatPoint getPointOnEllipse(float radiusX, float radiusY, float theta) void canonicalizeAngle(float* startAngle, float* endAngle) { // Make 0 <= startAngle < 2*PI - float twoPi = 2 * piFloat; float newStartAngle = *startAngle; if (newStartAngle < 0) - newStartAngle = twoPi + fmodf(newStartAngle, -twoPi); + newStartAngle = twoPiFloat + fmodf(newStartAngle, -twoPiFloat); else - newStartAngle = fmodf(newStartAngle, twoPi); + newStartAngle = fmodf(newStartAngle, twoPiFloat); float delta = newStartAngle - *startAngle; *startAngle = newStartAngle; *endAngle = *endAngle + delta; - ASSERT(newStartAngle >= 0 && newStartAngle < twoPi); + ASSERT(newStartAngle >= 0 && newStartAngle < twoPiFloat); } /* @@ -227,25 +225,24 @@ void canonicalizeAngle(float* startAngle, float* endAngle) void degenerateEllipse(CanvasPathMethods* path, float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise) { ASSERT(ellipseIsRenderable(startAngle, endAngle)); - ASSERT(startAngle >= 0 && startAngle < 2 * piFloat); + ASSERT(startAngle >= 0 && startAngle < twoPiFloat); ASSERT((anticlockwise && (startAngle - endAngle) >= 0) || (!anticlockwise && (endAngle - startAngle) >= 0)); FloatPoint center(x, y); AffineTransform rotationMatrix; - rotationMatrix.rotate(rad2deg(rotation)); + rotationMatrix.rotateRadians(rotation); // First, if the object's path has any subpaths, then the method must add a straight line from the last point in the subpath to the start point of the arc. lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(radiusX, radiusY, startAngle))); if ((!radiusX && !radiusY) || startAngle == endAngle) return; - float halfPiFloat = piFloat * 0.5; if (!anticlockwise) { - // startAngle - fmodf(startAngle, halfPiFloat) + halfPiFloat is the one of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) + // startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat is the one of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) // that is the closest to startAngle on the clockwise direction. - for (float angle = startAngle - fmodf(startAngle, halfPiFloat) + halfPiFloat; angle < endAngle; angle += halfPiFloat) + for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat; angle < endAngle; angle += piOverTwoFloat) lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(radiusX, radiusY, angle))); } else { - for (float angle = startAngle - fmodf(startAngle, halfPiFloat); angle > endAngle; angle -= halfPiFloat) + for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat); angle > endAngle; angle -= piOverTwoFloat) lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(radiusX, radiusY, angle))); } @@ -260,7 +257,7 @@ void CanvasPathMethods::arc(float x, float y, float radius, float startAngle, fl return; if (radius < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The radius provided (" + String::number(radius) + ") is negative."); return; } @@ -283,8 +280,12 @@ void CanvasPathMethods::ellipse(float x, float y, float radiusX, float radiusY, if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !std::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) || !std::isfinite(endAngle)) return; - if (radiusX < 0 || radiusY < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + if (radiusX < 0) { + exceptionState.throwDOMException(IndexSizeError, "The major-axis radius provided (" + String::number(radiusX) + ") is negative."); + return; + } + if (radiusY < 0) { + exceptionState.throwDOMException(IndexSizeError, "The minor-axis radius provided (" + String::number(radiusY) + ") is negative."); return; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h index 100f95cf055..2f0160ea1bf 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h @@ -54,6 +54,7 @@ public: protected: CanvasPathMethods() { } + CanvasPathMethods(const Path& path) : m_path(path) { } Path m_path; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.idl new file mode 100644 index 00000000000..2c37810cef7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.idl @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspathmethods + +[ + NoInterfaceObject, // Always used on target of 'implements' +] interface CanvasPathMethods { + // shared path API methods + void closePath(); + void moveTo(unrestricted float x, unrestricted float y); + void lineTo(unrestricted float x, unrestricted float y); + void quadraticCurveTo(unrestricted float cpx, unrestricted float cpy, unrestricted float x, unrestricted float y); + void bezierCurveTo(unrestricted float cp1x, unrestricted float cp1y, unrestricted float cp2x, unrestricted float cp2y, unrestricted float x, unrestricted float y); + [RaisesException] void arcTo(unrestricted float x1, unrestricted float y1, unrestricted float x2, unrestricted float y2, unrestricted float radius); + void rect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void arc(unrestricted float x, unrestricted float y, unrestricted float radius, unrestricted float startAngle, unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise); + [RaisesException] void ellipse(unrestricted float x, unrestricted float y, unrestricted float radiusX, unrestricted float radiusY, unrestricted float rotation, unrestricted float startAngle, unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise); +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp index f7ee0da4388..e011ff082a3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp @@ -54,7 +54,7 @@ void CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool& repeatY = true; return; } - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The provided type ('" + type + "') is not one of 'repeat', 'no-repeat', 'repeat-x', or 'repeat-y'."); } CanvasPattern::CanvasPattern(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp index 47a0e616efb..9e5dd350d8f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp @@ -26,10 +26,7 @@ #include "config.h" #include "core/html/canvas/CanvasRenderingContext.h" -#include "core/fetch/ImageResource.h" -#include "core/html/HTMLImageElement.h" -#include "core/html/HTMLVideoElement.h" -#include "core/html/canvas/CanvasPattern.h" +#include "core/html/canvas/CanvasImageSource.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { @@ -37,72 +34,30 @@ namespace WebCore { CanvasRenderingContext::CanvasRenderingContext(HTMLCanvasElement* canvas) : m_canvas(canvas) { - ScriptWrappable::init(this); -} - -bool CanvasRenderingContext::wouldTaintOrigin(const CanvasPattern* pattern) -{ - if (canvas()->originClean() && pattern && !pattern->originClean()) - return true; - return false; -} - -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLCanvasElement* sourceCanvas) -{ - if (canvas()->originClean() && sourceCanvas && !sourceCanvas->originClean()) - return true; - return false; -} - -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLImageElement* image) -{ - if (!image || !canvas()->originClean()) - return false; - - ImageResource* cachedImage = image->cachedImage(); - if (!cachedImage->image()->currentFrameHasSingleSecurityOrigin()) - return true; - - return wouldTaintOrigin(cachedImage->response().url()) && !cachedImage->passesAccessControlCheck(canvas()->securityOrigin()); -} - -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLVideoElement* video) -{ - // FIXME: This check is likely wrong when a redirect is involved. We need - // to test the finalURL. Please be careful when fixing this issue not to - // make currentSrc be the final URL because then the - // HTMLMediaElement.currentSrc DOM API would leak redirect destinations! - if (!video || !canvas()->originClean()) - return false; - - if (!video->hasSingleSecurityOrigin()) - return true; - - if (!(video->player() && video->player()->didPassCORSAccessCheck()) && wouldTaintOrigin(video->currentSrc())) - return true; - - return false; -} - -bool CanvasRenderingContext::wouldTaintOrigin(const KURL& url) -{ - if (!canvas()->originClean() || m_cleanURLs.contains(url.string())) - return false; - - if (canvas()->securityOrigin()->taintsCanvas(url)) - return true; - - if (url.protocolIsData()) - return false; - m_cleanURLs.add(url.string()); - return false; } -void CanvasRenderingContext::checkOrigin(const KURL& url) +bool CanvasRenderingContext::wouldTaintOrigin(CanvasImageSource* imageSource) { - if (wouldTaintOrigin(url)) - canvas()->setOriginTainted(); + const KURL& sourceURL = imageSource->sourceURL(); + bool hasURL = (sourceURL.isValid() && !sourceURL.isAboutBlankURL()); + + if (hasURL) { + if (sourceURL.protocolIsData() || m_cleanURLs.contains(sourceURL.string())) + return false; + if (m_dirtyURLs.contains(sourceURL.string())) + return true; + } + + bool taintOrigin = imageSource->wouldTaintOrigin(canvas()->securityOrigin()); + + if (hasURL) { + if (taintOrigin) + m_dirtyURLs.add(sourceURL.string()); + else + m_cleanURLs.add(sourceURL.string()); + } + return taintOrigin; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h index 2f5cd637991..0999d334bf7 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h @@ -26,8 +26,8 @@ #ifndef CanvasRenderingContext_h #define CanvasRenderingContext_h -#include "bindings/v8/ScriptWrappable.h" #include "core/html/HTMLCanvasElement.h" +#include "platform/heap/Handle.h" #include "wtf/HashSet.h" #include "wtf/Noncopyable.h" #include "wtf/text/StringHash.h" @@ -36,20 +36,22 @@ namespace blink { class WebLayer; } namespace WebCore { -class CanvasPattern; +class CanvasImageSource; class HTMLCanvasElement; -class HTMLImageElement; -class HTMLVideoElement; class KURL; class WebGLObject; -class CanvasRenderingContext : public ScriptWrappable { - WTF_MAKE_NONCOPYABLE(CanvasRenderingContext); WTF_MAKE_FAST_ALLOCATED; +class CanvasRenderingContext : public NoBaseWillBeGarbageCollectedFinalized<CanvasRenderingContext> { + WTF_MAKE_NONCOPYABLE(CanvasRenderingContext); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: virtual ~CanvasRenderingContext() { } +#if !ENABLE(OILPAN) void ref() { m_canvas->ref(); } void deref() { m_canvas->deref(); } +#endif + HTMLCanvasElement* canvas() const { return m_canvas; } virtual bool is2d() const { return false; } @@ -61,24 +63,17 @@ public: virtual blink::WebLayer* platformLayer() const { return 0; } + virtual void trace(Visitor* visitor) { visitor->trace(m_canvas); } + + bool wouldTaintOrigin(CanvasImageSource*); + protected: CanvasRenderingContext(HTMLCanvasElement*); - bool wouldTaintOrigin(const CanvasPattern*); - bool wouldTaintOrigin(const HTMLCanvasElement*); - bool wouldTaintOrigin(const HTMLImageElement*); - bool wouldTaintOrigin(const HTMLVideoElement*); - bool wouldTaintOrigin(const KURL&); - - template<class T> void checkOrigin(const T* arg) - { - if (wouldTaintOrigin(arg)) - canvas()->setOriginTainted(); - } - void checkOrigin(const KURL&); private: - HTMLCanvasElement* m_canvas; + RawPtrWillBeMember<HTMLCanvasElement> m_canvas; HashSet<String> m_cleanURLs; + HashSet<String> m_dirtyURLs; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.idl deleted file mode 100644 index ae89a5fcd56..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.idl +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - Custom=Wrap, - NoInterfaceObject, -] interface CanvasRenderingContext { - readonly attribute HTMLCanvasElement canvas; -}; - diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp index 68f213b18ae..ccca4ddd03f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp @@ -33,16 +33,18 @@ #include "config.h" #include "core/html/canvas/CanvasRenderingContext2D.h" -#include "CSSPropertyNames.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSPropertyNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/css/CSSFontSelector.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/StylePropertySet.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/ExceptionCode.h" #include "core/fetch/ImageResource.h" +#include "core/frame/ImageBitmap.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLMediaElement.h" @@ -52,46 +54,52 @@ #include "core/html/canvas/CanvasGradient.h" #include "core/html/canvas/CanvasPattern.h" #include "core/html/canvas/CanvasStyle.h" -#include "core/html/canvas/DOMPath.h" -#include "core/frame/ImageBitmap.h" +#include "core/html/canvas/Path2D.h" #include "core/rendering/RenderImage.h" #include "core/rendering/RenderLayer.h" #include "core/rendering/RenderTheme.h" #include "platform/fonts/FontCache.h" #include "platform/geometry/FloatQuad.h" +#include "platform/graphics/DrawLooperBuilder.h" #include "platform/graphics/GraphicsContextStateSaver.h" -#include "platform/graphics/DrawLooper.h" #include "platform/text/TextRun.h" -#include "platform/weborigin/SecurityOrigin.h" #include "wtf/CheckedArithmetic.h" #include "wtf/MathExtras.h" #include "wtf/OwnPtr.h" #include "wtf/Uint8ClampedArray.h" #include "wtf/text/StringBuilder.h" -using namespace std; - namespace WebCore { static const int defaultFontSize = 10; static const char defaultFontFamily[] = "sans-serif"; static const char defaultFont[] = "10px sans-serif"; +static const double TryRestoreContextInterval = 0.5; +static const unsigned MaxTryRestoreContextAttempts = 4; + +static bool contextLostRestoredEventsEnabled() +{ + return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); +} CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) : CanvasRenderingContext(canvas) - , m_stateStack(1) - , m_unrealizedSaveCount(0) , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) , m_hasAlpha(!attrs || attrs->alpha()) -{ + , m_isContextLost(false) + , m_contextRestorable(true) + , m_storageMode(!attrs ? PersistentStorage : attrs->parsedStorage()) + , m_tryRestoreContextAttemptCount(0) + , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchContextLostEvent) + , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispatchContextRestoredEvent) + , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreContextEvent) +{ + m_stateStack.append(adoptPtrWillBeNoop(new State())); ScriptWrappable::init(this); } void CanvasRenderingContext2D::unwindStateStack() { - // Ensure that the state stack in the ImageBuffer's context - // is cleared before destruction, to avoid assertions in the - // GraphicsContext dtor. if (size_t stackSize = m_stateStack.size()) { if (GraphicsContext* context = canvas()->existingDrawingContext()) { while (--stackSize) @@ -102,8 +110,14 @@ void CanvasRenderingContext2D::unwindStateStack() CanvasRenderingContext2D::~CanvasRenderingContext2D() { -#if !ASSERT_DISABLED - unwindStateStack(); +} + +void CanvasRenderingContext2D::validateStateStack() +{ +#if ASSERT_ENABLED + GraphicsContext* context = canvas()->existingDrawingContext(); + if (context && !context->contextDisabled()) + ASSERT(context->saveCount() == m_stateStack.size()); #endif } @@ -115,13 +129,108 @@ bool CanvasRenderingContext2D::isAccelerated() const return context && context->isAccelerated(); } +bool CanvasRenderingContext2D::isContextLost() const +{ + return m_isContextLost; +} + +void CanvasRenderingContext2D::loseContext() +{ + if (m_isContextLost) + return; + m_isContextLost = true; + m_dispatchContextLostEventTimer.startOneShot(0, FROM_HERE); +} + +void CanvasRenderingContext2D::restoreContext() +{ + if (!m_contextRestorable) + return; + // This code path is for restoring from an eviction + // Restoring from surface failure is handled internally + ASSERT(m_isContextLost && !canvas()->hasImageBuffer()); + + if (canvas()->buffer()) { + if (contextLostRestoredEventsEnabled()) { + m_dispatchContextRestoredEventTimer.startOneShot(0, FROM_HERE); + } else { + // legacy synchronous context restoration. + reset(); + m_isContextLost = false; + } + } +} + +void CanvasRenderingContext2D::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_stateStack); + visitor->trace(m_fetchedFonts); +#endif + CanvasRenderingContext::trace(visitor); +} + +void CanvasRenderingContext2D::dispatchContextLostEvent(Timer<CanvasRenderingContext2D>*) +{ + if (contextLostRestoredEventsEnabled()) { + RefPtrWillBeRawPtr<Event> event = Event::createCancelable(EventTypeNames::contextlost); + canvas()->dispatchEvent(event); + if (event->defaultPrevented()) { + m_contextRestorable = false; + } + } + + // If an image buffer is present, it means the context was not lost due to + // an eviction, but rather due to a surface failure (gpu context lost?) + if (m_contextRestorable && canvas()->hasImageBuffer()) { + m_tryRestoreContextAttemptCount = 0; + m_tryRestoreContextEventTimer.startRepeating(TryRestoreContextInterval, FROM_HERE); + } +} + +void CanvasRenderingContext2D::tryRestoreContextEvent(Timer<CanvasRenderingContext2D>* timer) +{ + if (!m_isContextLost) { + // Canvas was already restored (possibly thanks to a resize), so stop trying. + m_tryRestoreContextEventTimer.stop(); + return; + } + if (canvas()->hasImageBuffer() && canvas()->buffer()->restoreSurface()) { + m_tryRestoreContextEventTimer.stop(); + dispatchContextRestoredEvent(0); + } + + if (++m_tryRestoreContextAttemptCount > MaxTryRestoreContextAttempts) + canvas()->discardImageBuffer(); + + if (!canvas()->hasImageBuffer()) { + // final attempt: allocate a brand new image buffer instead of restoring + timer->stop(); + if (canvas()->buffer()) + dispatchContextRestoredEvent(0); + } +} + +void CanvasRenderingContext2D::dispatchContextRestoredEvent(Timer<CanvasRenderingContext2D>*) +{ + if (!m_isContextLost) + return; + reset(); + m_isContextLost = false; + if (contextLostRestoredEventsEnabled()) { + RefPtrWillBeRawPtr<Event> event(Event::create(EventTypeNames::contextrestored)); + canvas()->dispatchEvent(event); + } +} + void CanvasRenderingContext2D::reset() { + validateStateStack(); unwindStateStack(); m_stateStack.resize(1); - m_stateStack.first() = State(); + m_stateStack.first() = adoptPtrWillBeNoop(new State()); m_path.clear(); - m_unrealizedSaveCount = 0; + validateStateStack(); } // Important: Several of these properties are also stored in GraphicsContext's @@ -129,7 +238,8 @@ void CanvasRenderingContext2D::reset() // that the canvas 2d spec specifies. Make sure to sync the initial state of the // GraphicsContext in HTMLCanvasElement::createImageBuffer()! CanvasRenderingContext2D::State::State() - : m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) + : m_unrealizedSaveCount(0) + , m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) , m_fillStyle(CanvasStyle::createFromRGBA(Color::black)) , m_lineWidth(1) , m_lineCap(ButtCap) @@ -151,7 +261,8 @@ CanvasRenderingContext2D::State::State() } CanvasRenderingContext2D::State::State(const State& other) - : FontSelectorClient() + : CSSFontSelectorClient() + , m_unrealizedSaveCount(other.m_unrealizedSaveCount) , m_unparsedStrokeColor(other.m_unparsedStrokeColor) , m_unparsedFillColor(other.m_unparsedFillColor) , m_strokeStyle(other.m_strokeStyle) @@ -177,7 +288,7 @@ CanvasRenderingContext2D::State::State(const State& other) , m_realizedFont(other.m_realizedFont) { if (m_realizedFont) - m_font.fontSelector()->registerForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalidationCallbacks(this); } CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(const State& other) @@ -185,9 +296,12 @@ CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons if (this == &other) return *this; +#if !ENABLE(OILPAN) if (m_realizedFont) - m_font.fontSelector()->unregisterForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->unregisterForInvalidationCallbacks(this); +#endif + m_unrealizedSaveCount = other.m_unrealizedSaveCount; m_unparsedStrokeColor = other.m_unparsedStrokeColor; m_unparsedFillColor = other.m_unparsedFillColor; m_strokeStyle = other.m_strokeStyle; @@ -212,18 +326,20 @@ CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons m_realizedFont = other.m_realizedFont; if (m_realizedFont) - m_font.fontSelector()->registerForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalidationCallbacks(this); return *this; } CanvasRenderingContext2D::State::~State() { +#if !ENABLE(OILPAN) if (m_realizedFont) - m_font.fontSelector()->unregisterForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->unregisterForInvalidationCallbacks(this); +#endif } -void CanvasRenderingContext2D::State::fontsNeedUpdate(FontSelector* fontSelector) +void CanvasRenderingContext2D::State::fontsNeedUpdate(CSSFontSelector* fontSelector) { ASSERT_ARG(fontSelector, fontSelector == m_font.fontSelector()); ASSERT(m_realizedFont); @@ -231,22 +347,33 @@ void CanvasRenderingContext2D::State::fontsNeedUpdate(FontSelector* fontSelector m_font.update(fontSelector); } -void CanvasRenderingContext2D::realizeSavesLoop() -{ - ASSERT(m_unrealizedSaveCount); - ASSERT(m_stateStack.size() >= 1); - GraphicsContext* context = drawingContext(); - do { - m_stateStack.append(state()); +void CanvasRenderingContext2D::realizeSaves() +{ + validateStateStack(); + if (state().m_unrealizedSaveCount) { + ASSERT(m_stateStack.size() >= 1); + // Reduce the current state's unrealized count by one now, + // to reflect the fact we are saving one state. + m_stateStack.last()->m_unrealizedSaveCount--; + m_stateStack.append(adoptPtrWillBeNoop(new State(state()))); + // Set the new state's unrealized count to 0, because it has no outstanding saves. + // We need to do this explicitly because the copy constructor and operator= used + // by the Vector operations copy the unrealized count from the previous state (in + // turn necessary to support correct resizing and unwinding of the stack). + m_stateStack.last()->m_unrealizedSaveCount = 0; + GraphicsContext* context = drawingContext(); if (context) context->save(); - } while (--m_unrealizedSaveCount); + validateStateStack(); + } } void CanvasRenderingContext2D::restore() { - if (m_unrealizedSaveCount) { - --m_unrealizedSaveCount; + validateStateStack(); + if (state().m_unrealizedSaveCount) { + // We never realized the save, so just record that it was unnecessary. + --m_stateStack.last()->m_unrealizedSaveCount; return; } ASSERT(m_stateStack.size() >= 1); @@ -256,9 +383,9 @@ void CanvasRenderingContext2D::restore() m_stateStack.removeLast(); m_path.transform(state().m_transform.inverse()); GraphicsContext* c = drawingContext(); - if (!c) - return; - c->restore(); + if (c) + c->restore(); + validateStateStack(); } CanvasStyle* CanvasRenderingContext2D::strokeStyle() const @@ -281,8 +408,9 @@ void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> prpStyle) style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha())); else style = CanvasStyle::createFromRGBA(currentColor(canvas())); - } else - checkOrigin(style->canvasPattern()); + } else if (canvas()->originClean() && style->canvasPattern() && !style->canvasPattern()->originClean()) { + canvas()->setOriginTainted(); + } realizeSaves(); modifiableState().m_strokeStyle = style.release(); @@ -313,8 +441,9 @@ void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> prpStyle) style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha())); else style = CanvasStyle::createFromRGBA(currentColor(canvas())); - } else - checkOrigin(style->canvasPattern()); + } else if (canvas()->originClean() && style->canvasPattern() && !style->canvasPattern()->originClean()) { + canvas()->setOriginTainted(); + } realizeSaves(); modifiableState().m_fillStyle = style.release(); @@ -492,18 +621,7 @@ void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash) // Spec requires the concatenation of two copies the dash list when the // number of elements is odd if (dash.size() % 2) - modifiableState().m_lineDash.append(dash); - - applyLineDash(); -} - -void CanvasRenderingContext2D::setWebkitLineDash(const Vector<float>& dash) -{ - if (!lineDashSequenceIsValid(dash)) - return; - - realizeSaves(); - modifiableState().m_lineDash = dash; + modifiableState().m_lineDash.appendVector(dash); applyLineDash(); } @@ -523,16 +641,6 @@ void CanvasRenderingContext2D::setLineDashOffset(float offset) applyLineDash(); } -float CanvasRenderingContext2D::webkitLineDashOffset() const -{ - return lineDashOffset(); -} - -void CanvasRenderingContext2D::setWebkitLineDashOffset(float offset) -{ - setLineDashOffset(offset); -} - void CanvasRenderingContext2D::applyLineDash() const { GraphicsContext* c = drawingContext(); @@ -560,7 +668,7 @@ void CanvasRenderingContext2D::setGlobalAlpha(float alpha) GraphicsContext* c = drawingContext(); if (!c) return; - c->setAlpha(alpha); + c->setAlphaAsFloat(alpha); } String CanvasRenderingContext2D::globalCompositeOperation() const @@ -585,9 +693,11 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati c->setCompositeOperation(op, blendMode); } -void CanvasRenderingContext2D::setCurrentTransform(const SVGMatrix& matrix) +void CanvasRenderingContext2D::setCurrentTransform(PassRefPtr<SVGMatrixTearOff> passMatrixTearOff) { - setTransform(matrix.a(), matrix.b(), matrix.c(), matrix.d(), matrix.e(), matrix.f()); + RefPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff; + const AffineTransform& transform = matrixTearOff->value(); + setTransform(transform.a(), transform.b(), transform.c(), transform.d(), transform.e(), transform.f()); } void CanvasRenderingContext2D::scale(float sx, float sy) @@ -614,7 +724,7 @@ void CanvasRenderingContext2D::scale(float sx, float sy) } modifiableState().m_transform = newTransform; - c->scale(FloatSize(sx, sy)); + c->scale(sx, sy); m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); } @@ -630,7 +740,7 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) return; AffineTransform newTransform = state().m_transform; - newTransform.rotate(angleInRadians / piDouble * 180.0); + newTransform.rotateRadians(angleInRadians); if (state().m_transform == newTransform) return; @@ -643,7 +753,7 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) modifiableState().m_transform = newTransform; c->rotate(angleInRadians); - m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0)); + m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); } void CanvasRenderingContext2D::translate(float tx, float ty) @@ -745,7 +855,7 @@ void CanvasRenderingContext2D::setStrokeColor(const String& color) if (color == state().m_unparsedStrokeColor) return; realizeSaves(); - setStrokeStyle(CanvasStyle::createFromString(color, &canvas()->document())); + setStrokeStyle(CanvasStyle::createFromString(color)); modifiableState().m_unparsedStrokeColor = color; } @@ -787,7 +897,7 @@ void CanvasRenderingContext2D::setFillColor(const String& color) if (color == state().m_unparsedFillColor) return; realizeSaves(); - setFillStyle(CanvasStyle::createFromString(color, &canvas()->document())); + setFillStyle(CanvasStyle::createFromString(color)); modifiableState().m_unparsedFillColor = color; } @@ -829,18 +939,6 @@ void CanvasRenderingContext2D::beginPath() m_path.clear(); } -PassRefPtr<DOMPath> CanvasRenderingContext2D::currentPath() -{ - return DOMPath::create(m_path); -} - -void CanvasRenderingContext2D::setCurrentPath(DOMPath* path) -{ - if (!path) - return; - m_path = path->path(); -} - static bool validateRectForCanvas(float& x, float& y, float& width, float& height) { if (!std::isfinite(x) | !std::isfinite(y) | !std::isfinite(width) | !std::isfinite(height)) @@ -870,102 +968,157 @@ static bool isFullCanvasCompositeMode(CompositeOperator op) return op == CompositeSourceIn || op == CompositeSourceOut || op == CompositeDestinationIn || op == CompositeDestinationAtop; } -static bool parseWinding(const String& windingRuleString, WindRule& windRule) +static WindRule parseWinding(const String& windingRuleString) { if (windingRuleString == "nonzero") - windRule = RULE_NONZERO; - else if (windingRuleString == "evenodd") - windRule = RULE_EVENODD; - else - return false; + return RULE_NONZERO; + if (windingRuleString == "evenodd") + return RULE_EVENODD; - return true; + ASSERT_NOT_REACHED(); + return RULE_EVENODD; } -void CanvasRenderingContext2D::fill(const String& windingRuleString) +void CanvasRenderingContext2D::fillInternal(const Path& path, const String& windingRuleString) { + if (path.isEmpty()) { + return; + } GraphicsContext* c = drawingContext(); - if (!c) + if (!c) { return; - if (!state().m_invertibleCTM) + } + if (!state().m_invertibleCTM) { return; + } FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) + if (!c->getTransformedClipBounds(&clipBounds)) { return; + } // If gradient size is zero, then paint nothing. Gradient* gradient = c->fillGradient(); - if (gradient && gradient->isZeroSize()) + if (gradient && gradient->isZeroSize()) { return; + } - if (!m_path.isEmpty()) { - WindRule windRule = c->fillRule(); - WindRule newWindRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, newWindRule)) - return; - c->setFillRule(newWindRule); + WindRule windRule = c->fillRule(); + c->setFillRule(parseWinding(windingRuleString)); - if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedFill(m_path); - didDraw(clipBounds); - } else if (state().m_globalComposite == CompositeCopy) { - clearCanvas(); - c->fillPath(m_path); - didDraw(clipBounds); - } else { - FloatRect dirtyRect; - if (computeDirtyRect(m_path.boundingRect(), clipBounds, &dirtyRect)) { - c->fillPath(m_path); - didDraw(dirtyRect); - } + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + fullCanvasCompositedFill(path); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->fillPath(path); + didDraw(clipBounds); + } else { + FloatRect dirtyRect; + if (computeDirtyRect(path.boundingRect(), clipBounds, &dirtyRect)) { + c->fillPath(path); + didDraw(dirtyRect); } - - c->setFillRule(windRule); } + + c->setFillRule(windRule); } -void CanvasRenderingContext2D::stroke() +void CanvasRenderingContext2D::fill(const String& windingRuleString) +{ + fillInternal(m_path, windingRuleString); +} + +void CanvasRenderingContext2D::fill(Path2D* domPath, const String& windingRuleString) { + fillInternal(domPath->path(), windingRuleString); +} + +void CanvasRenderingContext2D::strokeInternal(const Path& path) +{ + if (path.isEmpty()) { + return; + } GraphicsContext* c = drawingContext(); - if (!c) + if (!c) { return; - if (!state().m_invertibleCTM) + } + if (!state().m_invertibleCTM) { + return; + } + FloatRect clipBounds; + if (!c->getTransformedClipBounds(&clipBounds)) return; // If gradient size is zero, then paint nothing. Gradient* gradient = c->strokeGradient(); - if (gradient && gradient->isZeroSize()) + if (gradient && gradient->isZeroSize()) { return; + } - if (!m_path.isEmpty()) { - FloatRect bounds = m_path.boundingRect(); + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + fullCanvasCompositedStroke(path); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->strokePath(path); + didDraw(clipBounds); + } else { + FloatRect bounds = path.boundingRect(); inflateStrokeRect(bounds); FloatRect dirtyRect; - if (computeDirtyRect(bounds, &dirtyRect)) { - c->strokePath(m_path); + if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { + c->strokePath(path); didDraw(dirtyRect); } } } -void CanvasRenderingContext2D::clip(const String& windingRuleString) +void CanvasRenderingContext2D::stroke() +{ + strokeInternal(m_path); +} + +void CanvasRenderingContext2D::stroke(Path2D* domPath) +{ + strokeInternal(domPath->path()); +} + +void CanvasRenderingContext2D::clipInternal(const Path& path, const String& windingRuleString) { GraphicsContext* c = drawingContext(); - if (!c) + if (!c) { return; - if (!state().m_invertibleCTM) - return; - - WindRule newWindRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, newWindRule)) + } + if (!state().m_invertibleCTM) { return; + } realizeSaves(); - c->canvasClip(m_path, newWindRule); + c->canvasClip(path, parseWinding(windingRuleString)); +} + +void CanvasRenderingContext2D::clip(const String& windingRuleString) +{ + clipInternal(m_path, windingRuleString); +} + +void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleString) +{ + clipInternal(domPath->path(), windingRuleString); } bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const String& windingRuleString) { + return isPointInPathInternal(m_path, x, y, windingRuleString); +} + +bool CanvasRenderingContext2D::isPointInPath(Path2D* domPath, const float x, const float y, const String& windingRuleString) +{ + return isPointInPathInternal(domPath->path(), x, y, windingRuleString); +} + +bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const float x, const float y, const String& windingRuleString) +{ GraphicsContext* c = drawingContext(); if (!c) return false; @@ -978,15 +1131,20 @@ bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const if (!std::isfinite(transformedPoint.x()) || !std::isfinite(transformedPoint.y())) return false; - WindRule windRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, windRule)) - return false; + return path.contains(transformedPoint, parseWinding(windingRuleString)); +} - return m_path.contains(transformedPoint, windRule); +bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) +{ + return isPointInStrokeInternal(m_path, x, y); } +bool CanvasRenderingContext2D::isPointInStroke(Path2D* domPath, const float x, const float y) +{ + return isPointInStrokeInternal(domPath->path(), x, y); +} -bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) +bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, const float x, const float y) { GraphicsContext* c = drawingContext(); if (!c) @@ -1006,7 +1164,46 @@ bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) strokeData.setLineJoin(getLineJoin()); strokeData.setMiterLimit(miterLimit()); strokeData.setLineDash(getLineDash(), lineDashOffset()); - return m_path.strokeContains(transformedPoint, strokeData); + return path.strokeContains(transformedPoint, strokeData); +} + +void CanvasRenderingContext2D::scrollPathIntoView() +{ + scrollPathIntoViewInternal(m_path); +} + +void CanvasRenderingContext2D::scrollPathIntoView(Path2D* path2d) +{ + scrollPathIntoViewInternal(path2d->path()); +} + +void CanvasRenderingContext2D::scrollPathIntoViewInternal(const Path& path) +{ + if (!state().m_invertibleCTM || path.isEmpty()) + return; + + canvas()->document().updateLayoutIgnorePendingStylesheets(); + + // Apply transformation and get the bounding rect + Path transformedPath = path; + transformedPath.transform(state().m_transform); + FloatRect boundingRect = transformedPath.boundingRect(); + + // Offset by the canvas rect (We should take border and padding into account). + RenderBoxModelObject* rbmo = canvas()->renderBoxModelObject(); + IntRect canvasRect = canvas()->renderer()->absoluteBoundingBoxRect(); + canvasRect.move(rbmo->borderLeft() + rbmo->paddingLeft(), + rbmo->borderTop() + rbmo->paddingTop()); + LayoutRect pathRect = enclosingLayoutRect(boundingRect); + pathRect.moveBy(canvasRect.location()); + + if (canvas()->renderer()) { + canvas()->renderer()->scrollRectToVisible( + pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopAlways); + } + + // TODO: should implement "inform the user" that the caret and/or + // selection the specified rectangle of the canvas. See http://crbug.com/357987 } void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height) @@ -1035,7 +1232,7 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he context->save(); saved = true; } - context->setAlpha(1); + context->setAlphaAsFloat(1); } if (state().m_globalComposite != CompositeSourceOver) { if (!saved) { @@ -1048,6 +1245,7 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he if (saved) context->restore(); + validateStateStack(); didDraw(dirtyRect); } @@ -1062,7 +1260,7 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei if (!state().m_invertibleCTM) return; FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) + if (!c->getTransformedClipBounds(&clipBounds)) return; // from the HTML5 Canvas spec: @@ -1105,6 +1303,9 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h return; if (!state().m_invertibleCTM) return; + FloatRect clipBounds; + if (!c->getTransformedClipBounds(&clipBounds)) + return; // If gradient size is zero, then paint nothing. Gradient* gradient = c->strokeGradient(); @@ -1113,12 +1314,21 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h FloatRect rect(x, y, width, height); - FloatRect boundingRect = rect; - boundingRect.inflate(state().m_lineWidth / 2); - FloatRect dirtyRect; - if (computeDirtyRect(boundingRect, &dirtyRect)) { - c->strokeRect(rect, state().m_lineWidth); - didDraw(dirtyRect); + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + fullCanvasCompositedStroke(rect); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->strokeRect(rect); + didDraw(clipBounds); + } else { + FloatRect boundingRect = rect; + boundingRect.inflate(state().m_lineWidth / 2); + FloatRect dirtyRect; + if (computeDirtyRect(boundingRect, clipBounds, &dirtyRect)) { + c->strokeRect(rect); + didDraw(dirtyRect); + } } } @@ -1190,7 +1400,7 @@ void CanvasRenderingContext2D::applyShadow() if (shouldDrawShadows()) { c->setShadow(state().m_shadowOffset, state().m_shadowBlur, state().m_shadowColor, - DrawLooper::ShadowIgnoresTransforms); + DrawLooperBuilder::ShadowIgnoresTransforms); } else { c->clearShadow(); } @@ -1201,37 +1411,12 @@ bool CanvasRenderingContext2D::shouldDrawShadows() const return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !state().m_shadowOffset.isZero()); } -enum ImageSizeType { - ImageSizeAfterDevicePixelRatio, - ImageSizeBeforeDevicePixelRatio -}; - -static LayoutSize sizeFor(HTMLImageElement* image, ImageSizeType sizeType) -{ - LayoutSize size; - ImageResource* cachedImage = image->cachedImage(); - if (cachedImage) { - size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this. - - if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && image->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image()->hasRelativeWidth()) - size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio()); - } - return size; -} - -static IntSize sizeFor(HTMLVideoElement* video) -{ - if (MediaPlayer* player = video->player()) - return player->naturalSize(); - return IntSize(); -} - static inline FloatRect normalizeRect(const FloatRect& rect) { - return FloatRect(min(rect.x(), rect.maxX()), - min(rect.y(), rect.maxY()), - max(rect.width(), -rect.width()), - max(rect.height(), -rect.height())); + return FloatRect(std::min(rect.x(), rect.maxX()), + std::min(rect.y(), rect.maxY()), + std::max(rect.width(), -rect.width()), + std::max(rect.height(), -rect.height())); } static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* srcRect, FloatRect* dstRect) @@ -1253,363 +1438,110 @@ static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s dstRect->move(offset); } -void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::WebBlendMode& blendMode) -{ - if (!image) - return; - - GraphicsContext* c = drawingContext(); - if (!c) - return; - if (!state().m_invertibleCTM) - return; - FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) - return; - - if (rectContainsTransformedRect(dstRect, clipBounds)) { - c->drawImage(image, dstRect, srcRect, op, blendMode); - didDraw(clipBounds); - } else if (isFullCanvasCompositeMode(op)) { - fullCanvasCompositedDrawImage(image, dstRect, srcRect, op); - didDraw(clipBounds); - } else if (op == CompositeCopy) { - clearCanvas(); - c->drawImage(image, dstRect, srcRect, op, blendMode); - didDraw(clipBounds); - } else { - FloatRect dirtyRect; - if (computeDirtyRect(dstRect, &dirtyRect)) { - c->drawImage(image, dstRect, srcRect, op, blendMode); - didDraw(dirtyRect); - } - } -} - -void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, float x, float y, ExceptionState& exceptionState) +void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x, float y, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - drawImage(bitmap, x, y, bitmap->width(), bitmap->height(), exceptionState); + FloatSize destRectSize = imageSource->defaultDestinationSize(); + drawImage(imageSource, x, y, destRectSize.width(), destRectSize.height(), exceptionState); } -void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, +void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x, float y, float width, float height, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - if (!bitmap->bitmapRect().width() || !bitmap->bitmapRect().height()) - return; - - drawImage(bitmap, 0, 0, bitmap->width(), bitmap->height(), x, y, width, height, exceptionState); + FloatSize sourceRectSize = imageSource->sourceSize(); + drawImage(imageSource, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, width, height, exceptionState); } -void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, +void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - FloatRect srcRect(sx, sy, sw, sh); - FloatRect dstRect(dx, dy, dw, dh); - FloatRect bitmapRect = bitmap->bitmapRect(); - - if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfinite(dstRect.width()) || !std::isfinite(dstRect.height()) - || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::isfinite(srcRect.width()) || !std::isfinite(srcRect.height())) - return; - - if (!dstRect.width() || !dstRect.height()) - return; - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; - } - - ASSERT(bitmap->height() && bitmap->width()); - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - // Clip the rects to where the user thinks that the image is situated. - clipRectsToImageRect(IntRect(IntPoint(), bitmap->size()), &normalizedSrcRect, &normalizedDstRect); - - FloatRect intersectRect = intersection(bitmapRect, normalizedSrcRect); - FloatRect actualSrcRect(intersectRect); - - IntPoint bitmapOffset = bitmap->bitmapOffset(); - actualSrcRect.move(bitmapOffset - bitmapRect.location()); - FloatRect imageRect = FloatRect(bitmapOffset, bitmapRect.size()); - - FloatRect actualDstRect(FloatPoint(intersectRect.location() - normalizedSrcRect.location()), bitmapRect.size()); - actualDstRect.scale(normalizedDstRect.width() / normalizedSrcRect.width() * intersectRect.width() / bitmapRect.width(), - normalizedDstRect.height() / normalizedSrcRect.height() * intersectRect.height() / bitmapRect.height()); - actualDstRect.moveBy(normalizedDstRect.location()); - - if (!imageRect.intersects(actualSrcRect)) - return; - - RefPtr<Image> imageForRendering = bitmap->bitmapImage(); - if (!imageForRendering) - return; - - drawImageInternal(imageForRendering.get(), actualSrcRect, actualDstRect, state().m_globalComposite, state().m_globalBlend); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionState& exceptionState) -{ - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - LayoutSize destRectSize = sizeFor(image, ImageSizeAfterDevicePixelRatio); - drawImage(image, x, y, destRectSize.width(), destRectSize.height(), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, - float x, float y, float width, float height, ExceptionState& exceptionState) -{ - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - LayoutSize sourceRectSize = sizeFor(image, ImageSizeBeforeDevicePixelRatio); - drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.height()), FloatRect(x, y, width, height), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) -{ - drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState) -{ - drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_globalBlend, exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::WebBlendMode& blendMode, ExceptionState& exceptionState) -{ - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfinite(dstRect.width()) || !std::isfinite(dstRect.height()) - || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::isfinite(srcRect.width()) || !std::isfinite(srcRect.height())) - return; - - ImageResource* cachedImage = image->cachedImage(); - if (!cachedImage || !image->complete()) - return; - - LayoutSize size = sizeFor(image, ImageSizeBeforeDevicePixelRatio); - if (!size.width() || !size.height()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - if (!dstRect.width() || !dstRect.height()) - return; - - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - FloatRect imageRect = FloatRect(FloatPoint(), size); - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; - } - if (!imageRect.intersects(normalizedSrcRect)) - return; - - clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect); - - checkOrigin(image); - - Image* imageForRendering = cachedImage->imageForRenderer(image->renderer()); - - // For images that depend on an unavailable container size, we need to fall back to the intrinsic - // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage - // FIXME: Without a specified image size this should resolve against the canvas element's size, see: crbug.com/230163. - if (!image->renderer() && imageForRendering->usesContainerSize()) - imageForRendering->setContainerSize(imageForRendering->size()); - - drawImageInternal(imageForRendering, normalizedSrcRect, normalizedDstRect, op, blendMode); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionState& exceptionState) -{ - drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, - float x, float y, float width, float height, ExceptionState& exceptionState) -{ - drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas->height()), FloatRect(x, y, width, height), exceptionState); + GraphicsContext* c = drawingContext(); // Do not exit yet if !c because we may need to throw exceptions first + CompositeOperator op = c ? c->compositeOperation() : CompositeSourceOver; + blink::WebBlendMode blendMode = c ? c->blendModeOperation() : blink::WebBlendModeNormal; + drawImageInternal(imageSource, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState, op, blendMode); } -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, +void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) -{ - drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect, - const FloatRect& dstRect, ExceptionState& exceptionState) -{ - if (!sourceCanvas) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size()); - - if (!srcCanvasRect.width() || !srcCanvasRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; + float dx, float dy, float dw, float dh, ExceptionState& exceptionState, + CompositeOperator op, blink::WebBlendMode blendMode) +{ + RefPtr<Image> image; + SourceImageStatus sourceImageStatus; + if (!imageSource->isVideoElement()) { + SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolatile : DontCopySourceImage; // Thunking for == + image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); + if (sourceImageStatus == UndecodableSourceImageStatus) + exceptionState.throwDOMException(InvalidStateError, "The HTMLImageElement provided is in the 'broken' state."); + if (!image || !image->width() || !image->height()) + return; } - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height()) - return; - - clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect); - GraphicsContext* c = drawingContext(); if (!c) return; + if (!state().m_invertibleCTM) return; - // FIXME: Do this through platform-independent GraphicsContext API. - ImageBuffer* buffer = sourceCanvas->buffer(); - if (!buffer) + if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dw) || !std::isfinite(dh) + || !std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !std::isfinite(sh) + || !dw || !dh || !sw || !sh) return; FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) + if (!c->getTransformedClipBounds(&clipBounds)) return; - checkOrigin(sourceCanvas); + FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh)); + FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh)); - // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable() - // as that will do a readback to software. - CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext(); - // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible. - if (sourceContext && sourceContext->is3d()) - sourceContext->paintRenderingResultsToCanvas(); + clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->sourceSize()), &srcRect, &dstRect); - if (rectContainsTransformedRect(normalizedDstRect, clipBounds)) { - c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend); - didDraw(clipBounds); - } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite); - didDraw(clipBounds); - } else if (state().m_globalComposite == CompositeCopy) { - clearCanvas(); - c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend); - didDraw(clipBounds); + imageSource->adjustDrawRects(&srcRect, &dstRect); + + if (srcRect.isEmpty()) + return; + + FloatRect dirtyRect = clipBounds; + if (imageSource->isVideoElement()) { + drawVideo(static_cast<HTMLVideoElement*>(imageSource), srcRect, dstRect); + computeDirtyRect(dstRect, clipBounds, &dirtyRect); } else { - FloatRect dirtyRect; - if (computeDirtyRect(normalizedDstRect, clipBounds, &dirtyRect)) { - c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend); - didDraw(dirtyRect); + if (rectContainsTransformedRect(dstRect, clipBounds)) { + c->drawImage(image.get(), dstRect, srcRect, op, blendMode); + } else if (isFullCanvasCompositeMode(op)) { + fullCanvasCompositedDrawImage(image.get(), dstRect, srcRect, op); + } else if (op == CompositeCopy) { + clearCanvas(); + c->drawImage(image.get(), dstRect, srcRect, op, blendMode); + } else { + FloatRect dirtyRect; + computeDirtyRect(dstRect, clipBounds, &dirtyRect); + c->drawImage(image.get(), dstRect, srcRect, op, blendMode); } - } - - // Flush canvas's ImageBuffer when drawImage from WebGL to HW accelerated 2d canvas - if (sourceContext && sourceContext->is3d() && is2d() && isAccelerated() && canvas()->buffer()) - canvas()->buffer()->flush(); -} -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionState& exceptionState) -{ - if (!video) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; + if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && canvas()->buffer()) + canvas()->buffer()->flush(); } - IntSize size = sizeFor(video); - drawImage(video, x, y, size.width(), size.height(), exceptionState); -} -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, - float x, float y, float width, float height, ExceptionState& exceptionState) -{ - if (!video) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - IntSize size = sizeFor(video); - drawImage(video, FloatRect(0, 0, size.width(), size.height()), FloatRect(x, y, width, height), exceptionState); -} + if (canvas()->originClean() && wouldTaintOrigin(imageSource)) + canvas()->setOriginTainted(); -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) -{ - drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState); + didDraw(dirtyRect); } -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState) +void CanvasRenderingContext2D::drawVideo(HTMLVideoElement* video, FloatRect srcRect, FloatRect dstRect) { - if (!video) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readyState() == HTMLMediaElement::HAVE_METADATA) - return; - - FloatRect videoRect = FloatRect(FloatPoint(), sizeFor(video)); - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; - } - - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height()) - return; - - clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect); - GraphicsContext* c = drawingContext(); - if (!c) - return; - if (!state().m_invertibleCTM) - return; - - checkOrigin(video); - - FloatRect dirtyRect; - if (!computeDirtyRect(normalizedDstRect, &dirtyRect)) - return; - GraphicsContextStateSaver stateSaver(*c); - c->clip(normalizedDstRect); - c->translate(normalizedDstRect.x(), normalizedDstRect.y()); - c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), normalizedDstRect.height() / normalizedSrcRect.height())); - c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y()); - video->paintCurrentFrameInContext(c, IntRect(IntPoint(), sizeFor(video))); + c->clip(dstRect); + c->translate(dstRect.x(), dstRect.y()); + c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); + c->translate(-srcRect.x(), -srcRect.y()); + video->paintCurrentFrameInContext(c, IntRect(IntPoint(), IntSize(video->videoWidth(), video->videoHeight()))); stateSaver.restore(); - - didDraw(dirtyRect); + validateStateStack(); } void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, @@ -1617,12 +1549,14 @@ void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, float dx, float dy, float dw, float dh, const String& compositeOperation) { + if (!image) + return; CompositeOperator op; blink::WebBlendMode blendOp = blink::WebBlendModeNormal; if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blendOp != blink::WebBlendModeNormal) op = CompositeSourceOver; - drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, blink::WebBlendModeNormal, IGNORE_EXCEPTION); + drawImageInternal(image, sx, sy, sw, sh, dx, dy, dw, dh, IGNORE_EXCEPTION, op, blendOp); } void CanvasRenderingContext2D::setAlpha(float alpha) @@ -1660,18 +1594,14 @@ static void drawImageToContext(Image* image, GraphicsContext* context, const Flo context->drawImage(image, dest, src, op); } -static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* context, const FloatRect& dest, const FloatRect& src, CompositeOperator op) -{ - context->drawImageBuffer(imageBuffer, dest, src, op); -} - template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage(T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) { ASSERT(isFullCanvasCompositeMode(op)); - drawingContext()->beginLayer(1, op); - drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver); - drawingContext()->endLayer(); + GraphicsContext* c = drawingContext(); + c->beginLayer(1, op); + drawImageToContext(image, c, dest, src, CompositeSourceOver); + c->endLayer(); } static void fillPrimitive(const FloatRect& rect, GraphicsContext* context) @@ -1698,78 +1628,82 @@ template<class T> void CanvasRenderingContext2D::fullCanvasCompositedFill(const c->endLayer(); } -PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1, ExceptionState& exceptionState) +static void strokePrimitive(const FloatRect& rect, GraphicsContext* context) { - if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(x1) || !std::isfinite(y1)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } + context->strokeRect(rect); +} + +static void strokePrimitive(const Path& path, GraphicsContext* context) +{ + context->strokePath(path); +} +template<class T> void CanvasRenderingContext2D::fullCanvasCompositedStroke(const T& area) +{ + ASSERT(isFullCanvasCompositeMode(state().m_globalComposite)); + + GraphicsContext* c = drawingContext(); + ASSERT(c); + c->beginLayer(1, state().m_globalComposite); + CompositeOperator previousOperator = c->compositeOperation(); + c->setCompositeOperation(CompositeSourceOver); + strokePrimitive(area, c); + c->setCompositeOperation(previousOperator); + c->endLayer(); +} + +PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1) +{ RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); return gradient.release(); } PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState& exceptionState) { - if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(r0) || !std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(r1)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } - if (r0 < 0 || r1 < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return 0; + exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); + return nullptr; } RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); return gradient.release(); } -PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image, +PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSource* imageSource, const String& repetitionType, ExceptionState& exceptionState) { - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; - } bool repeatX, repeatY; CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, exceptionState); if (exceptionState.hadException()) - return 0; - - if (!image->complete()) - return 0; - - ImageResource* cachedImage = image->cachedImage(); - Image* imageForRendering = cachedImage ? cachedImage->imageForRenderer(image->renderer()) : 0; - if (!imageForRendering) - return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true); + return nullptr; - // We need to synthesize a container size if a renderer is not available to provide one. - if (!image->renderer() && imageForRendering->usesContainerSize()) - imageForRendering->setContainerSize(imageForRendering->size()); + SourceImageStatus status; + RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(CopySourceImageIfVolatile, &status); - bool originClean = cachedImage->isAccessAllowed(canvas()->securityOrigin()); - return CanvasPattern::create(imageForRendering, repeatX, repeatY, originClean); -} - -PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas, - const String& repetitionType, ExceptionState& exceptionState) -{ - if (!canvas) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; - } - if (!canvas->width() || !canvas->height()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; + switch (status) { + case NormalSourceImageStatus: + break; + case ZeroSizeCanvasSourceImageStatus: + exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSource->sourceSize().width() ? "height" : "width")); + return nullptr; + case UndecodableSourceImageStatus: + exceptionState.throwDOMException(InvalidStateError, "Source image is in the 'broken' state."); + return nullptr; + case InvalidSourceImageStatus: + imageForRendering = Image::nullImage(); + break; + case IncompleteSourceImageStatus: + return nullptr; + default: + case ExternalSourceImageStatus: // should not happen when mode is CopySourceImageIfVolatile + ASSERT_NOT_REACHED(); + return nullptr; } + ASSERT(imageForRendering); - bool repeatX, repeatY; - CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, exceptionState); - if (exceptionState.hadException()) - return 0; - return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas->originClean()); + bool originClean = !wouldTaintOrigin(imageSource); + + return CanvasPattern::create(imageForRendering.release(), repeatX, repeatY, originClean); } bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, FloatRect* dirtyRect) @@ -1822,46 +1756,36 @@ void CanvasRenderingContext2D::didDraw(const FloatRect& dirtyRect) GraphicsContext* CanvasRenderingContext2D::drawingContext() const { + if (isContextLost()) + return 0; return canvas()->drawingContext(); } -static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size) +static PassRefPtrWillBeRawPtr<ImageData> createEmptyImageData(const IntSize& size) { - Checked<int, RecordOverflow> dataSize = 4; - dataSize *= size.width(); - dataSize *= size.height(); - if (dataSize.hasOverflowed()) - return 0; + if (RefPtrWillBeRawPtr<ImageData> data = ImageData::create(size)) { + data->data()->zeroFill(); + return data.release(); + } - RefPtr<ImageData> data = ImageData::create(size); - data->data()->zeroFill(); - return data.release(); + return nullptr; } -PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<ImageData> imageData, ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtrWillBeRawPtr<ImageData> imageData) const { - if (!imageData) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } - return createEmptyImageData(imageData->size()); } -PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const { if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return 0; - } - if (!std::isfinite(sw) || !std::isfinite(sh)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); + return nullptr; } FloatSize logicalSize(fabs(sw), fabs(sh)); if (!logicalSize.isExpressibleAsIntSize()) - return 0; + return nullptr; IntSize size = expandedIntSize(logicalSize); if (size.width() < 1) @@ -1872,26 +1796,15 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float return createEmptyImageData(size); } -PassRefPtr<ImageData> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const { - return getImageData(sx, sy, sw, sh, exceptionState); -} - -PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const -{ - if (!canvas()->originClean()) { + if (!canvas()->originClean()) exceptionState.throwSecurityError("The canvas has been tainted by cross-origin data."); - return 0; - } + else if (!sw || !sh) + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); - if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return 0; - } - if (!std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !std::isfinite(sh)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } + if (exceptionState.hadException()) + return nullptr; if (sw < 0) { sx += sw; @@ -1908,41 +1821,27 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, if (logicalRect.height() < 1) logicalRect.setHeight(1); if (!logicalRect.isExpressibleAsIntRect()) - return 0; + return nullptr; IntRect imageDataRect = enclosingIntRect(logicalRect); ImageBuffer* buffer = canvas()->buffer(); - if (!buffer) + if (!buffer || isContextLost()) return createEmptyImageData(imageDataRect.size()); RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect); if (!byteArray) - return 0; + return nullptr; return ImageData::create(imageDataRect.size(), byteArray.release()); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState) +void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy) { - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - putImageData(data, dx, dy, 0, 0, data->width(), data->height(), exceptionState); + putImageData(data, dx, dy, 0, 0, data->width(), data->height()); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, - float dirtyWidth, float dirtyHeight, ExceptionState& exceptionState) +void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight) { - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dirtyX) || !std::isfinite(dirtyY) || !std::isfinite(dirtyWidth) || !std::isfinite(dirtyHeight)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return; - } - ImageBuffer* buffer = canvas()->buffer(); if (!buffer) return; @@ -1981,11 +1880,11 @@ String CanvasRenderingContext2D::font() const StringBuilder serializedFont; const FontDescription& fontDescription = state().m_font.fontDescription(); - if (fontDescription.italic()) + if (fontDescription.style() == FontStyleItalic) serializedFont.appendLiteral("italic "); if (fontDescription.weight() == FontWeightBold) serializedFont.appendLiteral("bold "); - if (fontDescription.smallCaps() == FontSmallCapsOn) + if (fontDescription.variant() == FontVariantSmallCaps) serializedFont.appendLiteral("small-caps "); serializedFont.appendNumber(fontDescription.computedPixelSize()); @@ -2012,13 +1911,17 @@ String CanvasRenderingContext2D::font() const void CanvasRenderingContext2D::setFont(const String& newFont) { + // The style resolution required for rendering text is not available in frame-less documents. + if (!canvas()->document().frame()) + return; + MutableStylePropertyMap::iterator i = m_fetchedFonts.find(newFont); - RefPtr<MutableStylePropertySet> parsedStyle = i != m_fetchedFonts.end() ? i->value : 0; + RefPtrWillBeRawPtr<MutableStylePropertySet> parsedStyle = i != m_fetchedFonts.end() ? i->value : nullptr; if (!parsedStyle) { parsedStyle = MutableStylePropertySet::create(); CSSParserMode mode = m_usesCSSCompatibilityParseMode ? HTMLQuirksMode : HTMLStandardMode; - CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, newFont, true, mode, 0); + BisonCSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, newFont, true, mode, 0); m_fetchedFonts.add(newFont, parsedStyle); } if (parsedStyle->isEmpty()) @@ -2039,9 +1942,12 @@ void CanvasRenderingContext2D::setFont(const String& newFont) // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work // relative to the canvas. RefPtr<RenderStyle> newStyle = RenderStyle::create(); - if (RenderStyle* computedStyle = canvas()->computedStyle()) - newStyle->setFontDescription(computedStyle->fontDescription()); - else { + if (RenderStyle* computedStyle = canvas()->computedStyle()) { + FontDescription elementFontDescription(computedStyle->fontDescription()); + // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element. + elementFontDescription.setComputedSize(elementFontDescription.specifiedSize()); + newStyle->setFontDescription(elementFontDescription); + } else { FontFamily fontFamily; fontFamily.setFamily(defaultFontFamily); @@ -2068,8 +1974,10 @@ void CanvasRenderingContext2D::setFont(const String& newFont) StyleResolver& styleResolver = canvas()->document().ensureStyleResolver(); styleResolver.applyPropertiesToStyle(properties, WTF_ARRAY_LENGTH(properties), newStyle.get()); +#if !ENABLE(OILPAN) if (state().m_realizedFont) - state().m_font.fontSelector()->unregisterForInvalidationCallbacks(&modifiableState()); + static_cast<CSSFontSelector*>(state().m_font.fontSelector())->unregisterForInvalidationCallbacks(&modifiableState()); +#endif modifiableState().m_font = newStyle->font(); modifiableState().m_font.update(canvas()->document().styleEngine()->fontSelector()); modifiableState().m_realizedFont = true; @@ -2128,31 +2036,84 @@ void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, drawTextInternal(text, x, y, false, maxWidth, true); } -PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) +static inline bool isSpaceCharacter(UChar c) { - FontCachePurgePreventer fontCachePurgePreventer; - RefPtr<TextMetrics> metrics = TextMetrics::create(); - canvas()->document().updateStyleIfNeeded(); - metrics->setWidth(accessFont().width(TextRun(text))); - return metrics.release(); + // According to specification all space characters should be replaced with 0x0020 space character. + // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-preparation-algorithm + // The space characters according to specification are : U+0020, U+0009, U+000A, U+000C, and U+000D. + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#space-character + // This function returns true for 0x000B also, so that this is backward compatible. + // Otherwise, the test LayoutTests/canvas/philip/tests/2d.text.draw.space.collapse.space.html will fail + return c == 0x0009 || c == 0x000A || c == 0x000B || c == 0x000C || c == 0x000D; } -static void replaceCharacterInString(String& text, WTF::CharacterMatchFunctionPtr matchFunction, const String& replacement) +static String normalizeSpaces(const String& text) { - const size_t replacementLength = replacement.length(); - size_t index = 0; - while ((index = text.find(matchFunction, index)) != kNotFound) { - text.replace(index, 1, replacement); - index += replacementLength; + unsigned textLength = text.length(); + Vector<UChar> charVector(textLength); + + for (unsigned i = 0; i < textLength; i++) { + if (isSpaceCharacter(text[i])) + charVector[i] = ' '; + else + charVector[i] = text[i]; } + + return String(charVector); +} + +PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) +{ + RefPtr<TextMetrics> metrics = TextMetrics::create(); + + // The style resolution required for rendering text is not available in frame-less documents. + if (!canvas()->document().frame()) + return metrics.release(); + + FontCachePurgePreventer fontCachePurgePreventer; + canvas()->document().updateRenderTreeIfNeeded(); + const Font& font = accessFont(); + String normalizedText = normalizeSpaces(text); + const TextRun textRun(normalizedText); + FloatRect textBounds = font.selectionRectForText(textRun, FloatPoint(), font.fontDescription().computedSize(), 0, -1, true); + + // x direction + metrics->setWidth(font.width(textRun)); + metrics->setActualBoundingBoxLeft(-textBounds.x()); + metrics->setActualBoundingBoxRight(textBounds.maxX()); + + // y direction + const FontMetrics& fontMetrics = font.fontMetrics(); + const float ascent = fontMetrics.floatAscent(); + const float descent = fontMetrics.floatDescent(); + const float baselineY = getFontBaseline(fontMetrics); + + metrics->setFontBoundingBoxAscent(ascent - baselineY); + metrics->setFontBoundingBoxDescent(descent + baselineY); + metrics->setActualBoundingBoxAscent(-textBounds.y() - baselineY); + metrics->setActualBoundingBoxDescent(textBounds.maxY() + baselineY); + + // Note : top/bottom and ascend/descend are currently the same, so there's no difference + // between the EM box's top and bottom and the font's ascend and descend + metrics->setEmHeightAscent(0); + metrics->setEmHeightDescent(0); + + metrics->setHangingBaseline(-0.8f * ascent + baselineY); + metrics->setAlphabeticBaseline(baselineY); + metrics->setIdeographicBaseline(descent + baselineY); + return metrics.release(); } void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth, bool useMaxWidth) { + // The style resolution required for rendering text is not available in frame-less documents. + if (!canvas()->document().frame()) + return; + // accessFont needs the style to be up to date, but updating style can cause script to run, // (e.g. due to autofocus) which can free the GraphicsContext, so update style before grabbing // the GraphicsContext. - canvas()->document().updateStyleIfNeeded(); + canvas()->document().updateRenderTreeIfNeeded(); GraphicsContext* c = drawingContext(); if (!c) @@ -2177,9 +2138,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo const Font& font = accessFont(); const FontMetrics& fontMetrics = font.fontMetrics(); - // According to spec, all the space characters must be replaced with U+0020 SPACE characters. - String normalizedText = text; - replaceCharacterInString(normalizedText, isSpaceOrNewline, " "); + String normalizedText = normalizeSpaces(text); // FIXME: Need to turn off font smoothing. @@ -2190,24 +2149,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override, true, TextRun::NoRounding); // Draw the item text at the correct point. - FloatPoint location(x, y); - switch (state().m_textBaseline) { - case TopTextBaseline: - case HangingTextBaseline: - location.setY(y + fontMetrics.ascent()); - break; - case BottomTextBaseline: - case IdeographicTextBaseline: - location.setY(y - fontMetrics.descent()); - break; - case MiddleTextBaseline: - location.setY(y - fontMetrics.descent() + fontMetrics.height() / 2); - break; - case AlphabeticTextBaseline: - default: - // Do nothing. - break; - } + FloatPoint location(x, y + getFontBaseline(fontMetrics)); float fontWidth = font.width(TextRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override)); @@ -2240,21 +2182,40 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo if (!fill) inflateStrokeRect(textRunPaintInfo.bounds); - FloatRect dirtyRect; - if (!computeDirtyRect(textRunPaintInfo.bounds, &dirtyRect)) - return; - c->setTextDrawingMode(fill ? TextModeFill : TextModeStroke); + + GraphicsContextStateSaver stateSaver(*c); if (useMaxWidth) { - GraphicsContextStateSaver stateSaver(*c); c->translate(location.x(), location.y()); // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) still work. - c->scale(FloatSize((fontWidth > 0 ? (width / fontWidth) : 0), 1)); - c->drawBidiText(font, textRunPaintInfo, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady); - } else - c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + c->scale((fontWidth > 0 ? (width / fontWidth) : 0), 1); + location = FloatPoint(); + } - didDraw(dirtyRect); + FloatRect clipBounds; + if (!c->getTransformedClipBounds(&clipBounds)) { + return; + } + + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + c->beginLayer(1, state().m_globalComposite); + CompositeOperator previousOperator = c->compositeOperation(); + c->setCompositeOperation(CompositeSourceOver); + c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + c->setCompositeOperation(previousOperator); + c->endLayer(); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + didDraw(clipBounds); + } else { + FloatRect dirtyRect; + if (computeDirtyRect(textRunPaintInfo.bounds, clipBounds, &dirtyRect)) { + c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + didDraw(dirtyRect); + } + } } void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const @@ -2281,6 +2242,28 @@ const Font& CanvasRenderingContext2D::accessFont() return state().m_font; } +int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) const +{ + switch (state().m_textBaseline) { + case TopTextBaseline: + return fontMetrics.ascent(); + case HangingTextBaseline: + // According to http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling + // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of the ascender height" + return (fontMetrics.ascent() * 4) / 5; + case BottomTextBaseline: + case IdeographicTextBaseline: + return -fontMetrics.descent(); + case MiddleTextBaseline: + return -fontMetrics.descent() + fontMetrics.height() / 2; + case AlphabeticTextBaseline: + default: + // Do nothing. + break; + } + return 0; +} + blink::WebLayer* CanvasRenderingContext2D::platformLayer() const { return canvas()->buffer() ? canvas()->buffer()->platformLayer() : 0; @@ -2300,7 +2283,7 @@ void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) modifiableState().m_imageSmoothingEnabled = enabled; GraphicsContext* c = drawingContext(); if (c) - c->setImageInterpolationQuality(enabled ? DefaultInterpolationQuality : InterpolationNone); + c->setImageInterpolationQuality(enabled ? CanvasDefaultInterpolationQuality : InterpolationNone); } PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttributes() const @@ -2310,33 +2293,31 @@ PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttrib return attributes.release(); } -void CanvasRenderingContext2D::drawSystemFocusRing(Element* element) +void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) +{ + drawFocusIfNeededInternal(m_path, element); +} + +void CanvasRenderingContext2D::drawFocusIfNeeded(Path2D* path2d, Element* element) { - if (!focusRingCallIsValid(m_path, element)) + drawFocusIfNeededInternal(path2d->path(), element); +} + +void CanvasRenderingContext2D::drawFocusIfNeededInternal(const Path& path, Element* element) +{ + if (!focusRingCallIsValid(path, element)) return; - updateFocusRingAccessibility(m_path, element); // Note: we need to check document->focusedElement() rather than just calling // element->focused(), because element->focused() isn't updated until after // focus events fire. if (element->document().focusedElement() == element) - drawFocusRing(m_path); -} - -bool CanvasRenderingContext2D::drawCustomFocusRing(Element* element) -{ - if (!focusRingCallIsValid(m_path, element)) - return false; - - updateFocusRingAccessibility(m_path, element); - - // Return true if the application should draw the focus ring. The spec allows us to - // override this for accessibility, but currently Blink doesn't take advantage of this. - return element->focused(); + drawFocusRing(path); } bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* element) { + ASSERT(element); if (!state().m_invertibleCTM) return false; if (path.isEmpty()) @@ -2347,62 +2328,32 @@ bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* e return true; } -void CanvasRenderingContext2D::updateFocusRingAccessibility(const Path& path, Element* element) -{ - if (!canvas()->renderer()) - return; - - // If accessibility is already enabled in this frame, associate this path's - // bounding box with the accessible object. Do this even if the element - // isn't focused because assistive technology might try to explore the object's - // location before it gets focus. - if (AXObjectCache* axObjectCache = element->document().existingAXObjectCache()) { - if (AXObject* obj = axObjectCache->getOrCreate(element)) { - // Get the bounding rect and apply transformations. - FloatRect bounds = m_path.boundingRect(); - AffineTransform ctm = state().m_transform; - FloatRect transformedBounds = ctm.mapRect(bounds); - LayoutRect elementRect = LayoutRect(transformedBounds); - - // Offset by the canvas rect and set the bounds of the accessible element. - IntRect canvasRect = canvas()->renderer()->absoluteBoundingBoxRect(); - elementRect.moveBy(canvasRect.location()); - obj->setElementRect(elementRect); - - // Set the bounds of any ancestor accessible elements, up to the canvas element, - // otherwise this element will appear to not be within its parent element. - obj = obj->parentObject(); - while (obj && obj->node() != canvas()) { - obj->setElementRect(elementRect); - obj = obj->parentObject(); - } - } - } -} - void CanvasRenderingContext2D::drawFocusRing(const Path& path) { GraphicsContext* c = drawingContext(); if (!c) return; + // These should match the style defined in html.css. + Color focusRingColor = RenderTheme::theme().focusRingColor(); + const int focusRingWidth = 5; + const int focusRingOutline = 0; + + // We need to add focusRingWidth to dirtyRect. + StrokeData strokeData; + strokeData.setThickness(focusRingWidth); + FloatRect dirtyRect; - if (!computeDirtyRect(path.boundingRect(), &dirtyRect)) + if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect)) return; c->save(); - c->setAlpha(1.0); + c->setAlphaAsFloat(1.0); c->clearShadow(); c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); - - // These should match the style defined in html.css. - Color focusRingColor = RenderTheme::focusRingColor(); - const int focusRingWidth = 5; - const int focusRingOutline = 0; c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); - c->restore(); - + validateStateStack(); didDraw(dirtyRect); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h index 8493b10b149..65d883d220c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h @@ -26,10 +26,12 @@ #ifndef CanvasRenderingContext2D_h #define CanvasRenderingContext2D_h +#include "bindings/v8/ScriptWrappable.h" +#include "core/css/CSSFontSelectorClient.h" #include "core/html/canvas/Canvas2DContextAttributes.h" #include "core/html/canvas/CanvasPathMethods.h" #include "core/html/canvas/CanvasRenderingContext.h" -#include "core/svg/SVGMatrix.h" +#include "core/svg/SVGMatrixTearOff.h" #include "platform/fonts/Font.h" #include "platform/graphics/Color.h" #include "platform/geometry/FloatSize.h" @@ -45,10 +47,11 @@ namespace blink { class WebLayer; } namespace WebCore { +class CanvasImageSource; class CanvasGradient; class CanvasPattern; class CanvasStyle; -class DOMPath; +class Path2D; class Element; class ExceptionState; class FloatRect; @@ -60,13 +63,13 @@ class ImageBitmap; class ImageData; class TextMetrics; -typedef HashMap<String, RefPtr<MutableStylePropertySet> > MutableStylePropertyMap; +typedef WillBeHeapHashMap<String, RefPtrWillBeMember<MutableStylePropertySet> > MutableStylePropertyMap; -class CanvasRenderingContext2D : public CanvasRenderingContext, public CanvasPathMethods { +class CanvasRenderingContext2D FINAL: public CanvasRenderingContext, public ScriptWrappable, public CanvasPathMethods { public: - static PassOwnPtr<CanvasRenderingContext2D> create(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) + static PassOwnPtrWillBeRawPtr<CanvasRenderingContext2D> create(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) { - return adoptPtr(new CanvasRenderingContext2D(canvas, attrs, usesCSSCompatibilityParseMode)); + return adoptPtrWillBeNoop(new CanvasRenderingContext2D(canvas, attrs, usesCSSCompatibilityParseMode)); } virtual ~CanvasRenderingContext2D(); @@ -90,12 +93,9 @@ public: const Vector<float>& getLineDash() const; void setLineDash(const Vector<float>&); - void setWebkitLineDash(const Vector<float>&); float lineDashOffset() const; void setLineDashOffset(float); - float webkitLineDashOffset() const; - void setWebkitLineDashOffset(float); float shadowOffsetX() const; void setShadowOffsetX(float); @@ -112,17 +112,19 @@ public: float globalAlpha() const; void setGlobalAlpha(float); + bool isContextLost() const; + String globalCompositeOperation() const; void setGlobalCompositeOperation(const String&); - void save() { ++m_unrealizedSaveCount; } + void save() { ++m_stateStack.last()->m_unrealizedSaveCount; } void restore(); - SVGMatrix currentTransform() const + PassRefPtr<SVGMatrixTearOff> currentTransform() const { - return SVGMatrix(state().m_transform); + return SVGMatrixTearOff::create(state().m_transform); } - void setCurrentTransform(const SVGMatrix&); + void setCurrentTransform(PassRefPtr<SVGMatrixTearOff>); void scale(float sx, float sy); void rotate(float angleInRadians); @@ -147,14 +149,20 @@ public: void beginPath(); - PassRefPtr<DOMPath> currentPath(); - void setCurrentPath(DOMPath*); void fill(const String& winding = "nonzero"); + void fill(Path2D*, const String& winding = "nonzero"); void stroke(); + void stroke(Path2D*); void clip(const String& winding = "nonzero"); + void clip(Path2D*, const String& winding = "nonzero"); bool isPointInPath(const float x, const float y, const String& winding = "nonzero"); + bool isPointInPath(Path2D*, const float x, const float y, const String& winding = "nonzero"); bool isPointInStroke(const float x, const float y); + bool isPointInStroke(Path2D*, const float x, const float y); + + void scrollPathIntoView(); + void scrollPathIntoView(Path2D*); void clearRect(float x, float y, float width, float height); void fillRect(float x, float y, float width, float height); @@ -170,22 +178,9 @@ public: void clearShadow(); - void drawImage(ImageBitmap*, float x, float y, ExceptionState&); - void drawImage(ImageBitmap*, float x, float y, float width, float height, ExceptionState&); - void drawImage(ImageBitmap*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLImageElement*, float x, float y, ExceptionState&); - void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionState&); - void drawImage(HTMLImageElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState&); - void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const blink::WebBlendMode&, ExceptionState&); - void drawImage(HTMLCanvasElement*, float x, float y, ExceptionState&); - void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionState&); - void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState&); - void drawImage(HTMLVideoElement*, float x, float y, ExceptionState&); - void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionState&); - void drawImage(HTMLVideoElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLVideoElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState&); + void drawImage(CanvasImageSource*, float x, float y, ExceptionState&); + void drawImage(CanvasImageSource*, float x, float y, float width, float height, ExceptionState&); + void drawImage(CanvasImageSource*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); void drawImageFromRect(HTMLImageElement*, float sx = 0, float sy = 0, float sw = 0, float sh = 0, float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString()); @@ -194,22 +189,15 @@ public: void setCompositeOperation(const String&); - PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1, ExceptionState&); + PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1); PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState&); - PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionState&); - PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionState&); + PassRefPtr<CanvasPattern> createPattern(CanvasImageSource*, const String& repetitionType, ExceptionState&); - PassRefPtr<ImageData> createImageData(PassRefPtr<ImageData>, ExceptionState&) const; - PassRefPtr<ImageData> createImageData(float width, float height, ExceptionState&) const; - PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionState&) const; - void putImageData(ImageData*, float dx, float dy, ExceptionState&); - void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionState&); - - // Slated for deprecation: - void webkitPutImageDataHD(ImageData* image, float dx, float dy, ExceptionState& e) { putImageData(image, dx, dy, e); } - void webkitPutImageDataHD(ImageData* image, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionState& e) { putImageData(image, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight, e); } - PassRefPtr<ImageData> webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionState&) const; - float webkitBackingStorePixelRatio() const { return 1; } + PassRefPtrWillBeRawPtr<ImageData> createImageData(PassRefPtrWillBeRawPtr<ImageData>) const; + PassRefPtrWillBeRawPtr<ImageData> createImageData(float width, float height, ExceptionState&) const; + PassRefPtrWillBeRawPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionState&) const; + void putImageData(ImageData*, float dx, float dy); + void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); void reset(); @@ -236,18 +224,29 @@ public: PassRefPtr<Canvas2DContextAttributes> getContextAttributes() const; - void drawSystemFocusRing(Element*); - bool drawCustomFocusRing(Element*); + void drawFocusIfNeeded(Element*); + void drawFocusIfNeeded(Path2D*, Element*); + + void loseContext(); + void restoreContext(); + + virtual void trace(Visitor*) OVERRIDE; private: - struct State : FontSelectorClient { + class State FINAL : public CSSFontSelectorClient { + public: State(); virtual ~State(); State(const State&); State& operator=(const State&); - virtual void fontsNeedUpdate(FontSelector*) OVERRIDE; + // CSSFontSelectorClient implementation + virtual void fontsNeedUpdate(CSSFontSelector*) OVERRIDE; + + virtual void trace(Visitor* visitor) OVERRIDE { CSSFontSelectorClient::trace(visitor); } + + unsigned m_unrealizedSaveCount; String m_unparsedStrokeColor; String m_unparsedFillColor; @@ -280,15 +279,18 @@ private: CanvasRenderingContext2D(HTMLCanvasElement*, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode); - State& modifiableState() { ASSERT(!m_unrealizedSaveCount); return m_stateStack.last(); } - const State& state() const { return m_stateStack.last(); } + State& modifiableState() { ASSERT(!state().m_unrealizedSaveCount); return *m_stateStack.last(); } + const State& state() const { return *m_stateStack.last(); } void applyLineDash() const; void setShadow(const FloatSize& offset, float blur, RGBA32 color); void applyShadow(); bool shouldDrawShadows() const; - void drawImageInternal(Image*, const FloatRect&, const FloatRect&, const CompositeOperator&, const blink::WebBlendMode&); + void dispatchContextLostEvent(Timer<CanvasRenderingContext2D>*); + void dispatchContextRestoredEvent(Timer<CanvasRenderingContext2D>*); + void tryRestoreContextEvent(Timer<CanvasRenderingContext2D>*); + bool computeDirtyRect(const FloatRect& localBounds, FloatRect*); bool computeDirtyRect(const FloatRect& localBounds, const FloatRect& transformedClipBounds, FloatRect*); void didDraw(const FloatRect&); @@ -296,19 +298,27 @@ private: GraphicsContext* drawingContext() const; void unwindStateStack(); - void realizeSaves() - { - if (m_unrealizedSaveCount) - realizeSavesLoop(); - } - void realizeSavesLoop(); + void realizeSaves(); void applyStrokePattern(); void applyFillPattern(); + void drawImageInternal(CanvasImageSource*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&, CompositeOperator, blink::WebBlendMode); + void drawVideo(HTMLVideoElement*, FloatRect srcRect, FloatRect dstRect); + + void fillInternal(const Path&, const String& windingRuleString); + void strokeInternal(const Path&); + void clipInternal(const Path&, const String& windingRuleString); + + bool isPointInPathInternal(const Path&, const float x, const float y, const String& windingRuleString); + bool isPointInStrokeInternal(const Path&, const float x, const float y); + + void scrollPathIntoViewInternal(const Path&); + void drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth = 0, bool useMaxWidth = false); const Font& accessFont(); + int getFontBaseline(const FontMetrics&) const; void clearCanvas(); bool rectContainsTransformedRect(const FloatRect&, const FloatRect&) const; @@ -316,25 +326,34 @@ private: void inflateStrokeRect(FloatRect&) const; template<class T> void fullCanvasCompositedFill(const T&); + template<class T> void fullCanvasCompositedStroke(const T&); template<class T> void fullCanvasCompositedDrawImage(T*, const FloatRect&, const FloatRect&, CompositeOperator); + void drawFocusIfNeededInternal(const Path&, Element*); bool focusRingCallIsValid(const Path&, Element*); - void updateFocusRingAccessibility(const Path&, Element*); void drawFocusRing(const Path&); + void validateStateStack(); + virtual bool is2d() const OVERRIDE { return true; } virtual bool isAccelerated() const OVERRIDE; virtual bool hasAlpha() const OVERRIDE { return m_hasAlpha; } - virtual bool isTransformInvertible() const { return state().m_invertibleCTM; } + virtual bool isTransformInvertible() const OVERRIDE { return state().m_invertibleCTM; } virtual blink::WebLayer* platformLayer() const OVERRIDE; - Vector<State, 1> m_stateStack; - unsigned m_unrealizedSaveCount; + WillBeHeapVector<OwnPtrWillBeMember<State> > m_stateStack; bool m_usesCSSCompatibilityParseMode; bool m_hasAlpha; + bool m_isContextLost; + bool m_contextRestorable; + Canvas2DContextStorage m_storageMode; MutableStylePropertyMap m_fetchedFonts; + unsigned m_tryRestoreContextAttemptCount; + Timer<CanvasRenderingContext2D> m_dispatchContextLostEventTimer; + Timer<CanvasRenderingContext2D> m_dispatchContextRestoredEventTimer; + Timer<CanvasRenderingContext2D> m_tryRestoreContextEventTimer; }; DEFINE_TYPE_CASTS(CanvasRenderingContext2D, CanvasRenderingContext, context, context->is2d(), context.is2d()); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl index 1c243a6b4a0..1738af041a4 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl @@ -23,154 +23,160 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -enum CanvasWindingRule { "nonzero", "evenodd" }; - -interface CanvasRenderingContext2D : CanvasRenderingContext { - - void save(); - void restore(); - - [RuntimeEnabled=ExperimentalCanvasFeatures, Immutable] attribute SVGMatrix currentTransform; - void scale(float sx, float sy); - void rotate(float angle); - void translate(float tx, float ty); - void transform(float m11, float m12, float m21, float m22, float dx, float dy); - void setTransform(float m11, float m12, float m21, float m22, float dx, float dy); +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasrenderingcontext2d + +// FIXME: float => double throughout +// FIXME: Use union type in drawImage and createPattern once supported: +// http://crbug.com/372891 +typedef (HTMLImageElement or + HTMLVideoElement or + HTMLCanvasElement // or + // CanvasRenderingContext2D or + // ImageBitmap + ) CanvasImageSource; + +enum CanvasFillRule { "nonzero", "evenodd" }; + +[ + TypeChecking=Interface|Nullable|Unrestricted, + WillBeGarbageCollected, +] interface CanvasRenderingContext2D { + // back-reference to the canvas + readonly attribute HTMLCanvasElement canvas; + + // state + void save(); // push state on state stack + void restore(); // pop state stack and restore state + + // transformations (default transform is the identity matrix) + [RuntimeEnabled=ExperimentalCanvasFeatures] attribute SVGMatrix currentTransform; + void scale(unrestricted float x, unrestricted float y); + void rotate(unrestricted float angle); + void translate(unrestricted float x, unrestricted float y); + void transform(unrestricted float a, unrestricted float b, unrestricted float c, unrestricted float d, unrestricted float e, unrestricted float f); + void setTransform(unrestricted float a, unrestricted float b, unrestricted float c, unrestricted float d, unrestricted float e, unrestricted float f); void resetTransform(); - attribute float globalAlpha; - [TreatNullAs=NullString] attribute DOMString globalCompositeOperation; + // compositing + attribute unrestricted float globalAlpha; // (default 1.0) + [TreatNullAs=NullString] attribute DOMString globalCompositeOperation; // (default source-over) - [RaisesException] CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1); - [RaisesException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); - - attribute float lineWidth; - [TreatNullAs=NullString] attribute DOMString lineCap; - [TreatNullAs=NullString] attribute DOMString lineJoin; - attribute float miterLimit; + // image smoothing + [ImplementedAs=imageSmoothingEnabled, MeasureAs=PrefixedImageSmoothingEnabled] attribute boolean webkitImageSmoothingEnabled; + [MeasureAs=UnprefixedImageSmoothingEnabled] attribute boolean imageSmoothingEnabled; - attribute float shadowOffsetX; - attribute float shadowOffsetY; - attribute float shadowBlur; + // colors and styles (see also the CanvasDrawingStyles interface) + // FIXME: Use union types when supported: http://crbug.com/372891 + [Custom] attribute object strokeStyle; // (default black) + [Custom] attribute object fillStyle; // (default black) + CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1); + [RaisesException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); + [RaisesException] CanvasPattern createPattern(HTMLCanvasElement canvas, [TreatNullAs=NullString] DOMString repetitionType); + [RaisesException] CanvasPattern createPattern(HTMLImageElement image, [TreatNullAs=NullString] DOMString repetitionType); + [RaisesException] CanvasPattern createPattern(HTMLVideoElement image, [TreatNullAs=NullString] DOMString repetitionType); + + // shadows + attribute unrestricted float shadowOffsetX; + attribute unrestricted float shadowOffsetY; + attribute unrestricted float shadowBlur; [TreatNullAs=NullString] attribute DOMString shadowColor; - void setLineDash(sequence<float> dash); - sequence<float> getLineDash(); - attribute float lineDashOffset; - - // FIXME: These attributes should be implemented. - // [Custom] attribute Array webkitLineDash; - // attribute float webkitLineDashOffset; - - void clearRect(float x, float y, float width, float height); - void fillRect(float x, float y, float width, float height); + // rects + void clearRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + void fillRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + void strokeRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + // path API (see also CanvasPathMethods) void beginPath(); - - attribute Path currentPath; - - // FIXME: These methods should be shared with CanvasRenderingContext2D in the CanvasPathMethods interface. - void closePath(); - void moveTo(float x, float y); - void lineTo(float x, float y); - void quadraticCurveTo(float cpx, float cpy, float x, float y); - void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y); - [RaisesException] void arcTo(float x1, float y1, float x2, float y2, float radius); - void rect(float x, float y, float width, float height); - [RaisesException] void arc(float x, float y, float radius, float startAngle, float endAngle, [Default=Undefined] optional boolean anticlockwise); - [RaisesException] void ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, boolean anticlockwise); - - void fill(optional CanvasWindingRule winding); + void fill(optional CanvasFillRule winding); + [RuntimeEnabled=Path2D] void fill(Path2D path, optional CanvasFillRule winding); void stroke(); - void clip(optional CanvasWindingRule winding); - boolean isPointInPath(float x, float y, optional CanvasWindingRule winding); - boolean isPointInStroke(float x, float y); - - // text - attribute DOMString font; - attribute DOMString textAlign; - attribute DOMString textBaseline; - + [RuntimeEnabled=Path2D] void stroke(Path2D path); + // Focus rings + void drawFocusIfNeeded(Element element); + [RuntimeEnabled=Path2D] void drawFocusIfNeeded(Path2D path, Element element); + + [RuntimeEnabled=ExperimentalCanvasFeatures] void scrollPathIntoView(optional Path2D path); + void clip(optional CanvasFillRule winding); + [RuntimeEnabled=Path2D] void clip(Path2D path, optional CanvasFillRule winding); + boolean isPointInPath(unrestricted float x, unrestricted float y, optional CanvasFillRule winding); + [RuntimeEnabled=Path2D] boolean isPointInPath(Path2D path, unrestricted float x, unrestricted float y, optional CanvasFillRule winding); + boolean isPointInStroke(unrestricted float x, unrestricted float y); + [RuntimeEnabled=Path2D] boolean isPointInStroke(Path2D path, unrestricted float x, unrestricted float y); + + // text (see also the CanvasDrawingStyles interface) + void fillText(DOMString text, unrestricted float x, unrestricted float y, optional unrestricted float maxWidth); + void strokeText(DOMString text, unrestricted float x, unrestricted float y, optional unrestricted float maxWidth); TextMetrics measureText(DOMString text); - // other - - void setAlpha(float alpha); - void setCompositeOperation(DOMString compositeOperation); - - void setLineWidth(float width); - void setLineCap(DOMString cap); - void setLineJoin(DOMString join); - void setMiterLimit(float limit); - - void clearShadow(); - - void fillText(DOMString text, float x, float y, optional float maxWidth); - void strokeText(DOMString text, float x, float y, optional float maxWidth); - - void setStrokeColor([StrictTypeChecking] DOMString color, optional float alpha); - void setStrokeColor(float grayLevel, optional float alpha); - void setStrokeColor(float r, float g, float b, float a); - void setStrokeColor(float c, float m, float y, float k, float a); - - void setFillColor([StrictTypeChecking] DOMString color, optional float alpha); - void setFillColor(float grayLevel, optional float alpha); - void setFillColor(float r, float g, float b, float a); - void setFillColor(float c, float m, float y, float k, float a); - - void strokeRect(float x, float y, float width, float height); - - [RaisesException] void drawImage(HTMLImageElement? image, float x, float y); - [RaisesException] void drawImage(HTMLImageElement? image, float x, float y, float width, float height); - [RaisesException] void drawImage(HTMLImageElement? image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - [RaisesException] void drawImage(HTMLCanvasElement? canvas, float x, float y); - [RaisesException] void drawImage(HTMLCanvasElement? canvas, float x, float y, float width, float height); - [RaisesException] void drawImage(HTMLCanvasElement? canvas, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - [RaisesException] void drawImage(HTMLVideoElement? video, float x, float y); - [RaisesException] void drawImage(HTMLVideoElement? video, float x, float y, float width, float height); - [RaisesException] void drawImage(HTMLVideoElement? video, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap? imageBitmap, float x, float y); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap? imageBitmap, float x, float y, float width, float height); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap? imageBitmap, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - - void drawImageFromRect(HTMLImageElement image, - optional float sx, optional float sy, optional float sw, optional float sh, - optional float dx, optional float dy, optional float dw, optional float dh, - optional DOMString compositeOperation); - - void setShadow(float width, float height, float blur, [StrictTypeChecking] optional DOMString color, optional float alpha); - void setShadow(float width, float height, float blur, float grayLevel, optional float alpha); - void setShadow(float width, float height, float blur, float r, float g, float b, float a); - void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a); - - [RaisesException] void putImageData(ImageData? imagedata, float dx, float dy); - [RaisesException] void putImageData(ImageData? imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); - - [RaisesException] void webkitPutImageDataHD(ImageData? imagedata, float dx, float dy); - [RaisesException] void webkitPutImageDataHD(ImageData? imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); - - [RaisesException] CanvasPattern createPattern(HTMLCanvasElement? canvas, [TreatNullAs=NullString] DOMString repetitionType); - [RaisesException] CanvasPattern createPattern(HTMLImageElement? image, [TreatNullAs=NullString] DOMString repetitionType); - [RaisesException] ImageData createImageData(ImageData? imagedata); - [RaisesException] ImageData createImageData(float sw, float sh); - - [Custom] attribute object strokeStyle; - [Custom] attribute object fillStyle; + // drawing images + [RaisesException] void drawImage(HTMLImageElement image, unrestricted float x, unrestricted float y); + [RaisesException] void drawImage(HTMLImageElement image, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void drawImage(HTMLImageElement image, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); + [RaisesException] void drawImage(HTMLCanvasElement canvas, unrestricted float x, unrestricted float y); + [RaisesException] void drawImage(HTMLCanvasElement canvas, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void drawImage(HTMLCanvasElement canvas, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); + [RaisesException] void drawImage(HTMLVideoElement video, unrestricted float x, unrestricted float y); + [RaisesException] void drawImage(HTMLVideoElement video, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void drawImage(HTMLVideoElement video, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap imageBitmap, unrestricted float x, unrestricted float y); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap imageBitmap, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap imageBitmap, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); // pixel manipulation + ImageData createImageData(ImageData imagedata); + [RaisesException] ImageData createImageData(float sw, float sh); [RaisesException] ImageData getImageData(float sx, float sy, float sw, float sh); + void putImageData(ImageData imagedata, float dx, float dy); + void putImageData(ImageData imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); - [RaisesException] ImageData webkitGetImageDataHD(float sx, float sy, float sw, float sh); + // Context state + // Should be merged with WebGL counterpart in CanvasRenderingContext, once no-longer experimental + [RuntimeEnabled=ExperimentalCanvasFeatures] boolean isContextLost(); - // Focus rings - [RuntimeEnabled=ExperimentalCanvasFeatures] void drawSystemFocusRing(Element element); - [RuntimeEnabled=ExperimentalCanvasFeatures] boolean drawCustomFocusRing(Element element); + Canvas2DContextAttributes getContextAttributes(); - readonly attribute float webkitBackingStorePixelRatio; + // FIXME: factor out to CanvasDrawingStyles + // line caps/joins + attribute unrestricted float lineWidth; // (default 1) + [TreatNullAs=NullString] attribute DOMString lineCap; // "butt", "round", "square" (default "butt") + [TreatNullAs=NullString] attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter") + attribute unrestricted float miterLimit; // (default 10) - [ImplementedAs=imageSmoothingEnabled] attribute boolean webkitImageSmoothingEnabled; - attribute boolean imageSmoothingEnabled; + // dashed lines + void setLineDash(sequence<unrestricted float> dash); + sequence<unrestricted float> getLineDash(); + attribute unrestricted float lineDashOffset; - Canvas2DContextAttributes getContextAttributes(); + // text + attribute DOMString font; // (default 10px sans-serif) + attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start") + attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic") + + // Non-standard APIs. Candidates for deprecation + // https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D + [MeasureAs=CanvasRenderingContext2DSetAlpha] void setAlpha(unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetCompositeOperation] void setCompositeOperation(DOMString compositeOperation); + [MeasureAs=CanvasRenderingContext2DSetLineWidth] void setLineWidth(unrestricted float width); + [MeasureAs=CanvasRenderingContext2DSetLineCap] void setLineCap(DOMString cap); + [MeasureAs=CanvasRenderingContext2DSetLineJoin] void setLineJoin(DOMString join); + [MeasureAs=CanvasRenderingContext2DSetMiterLimit] void setMiterLimit(unrestricted float limit); + [MeasureAs=CanvasRenderingContext2DClearShadow] void clearShadow(); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(DOMString color, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(unrestricted float grayLevel, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(DOMString color, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(unrestricted float grayLevel, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DDrawImageFromRect] void drawImageFromRect( + HTMLImageElement? image, optional unrestricted float sx, optional unrestricted float sy, optional unrestricted float sw, optional unrestricted float sh, + optional unrestricted float dx, optional unrestricted float dy, optional unrestricted float dw, optional unrestricted float dh, optional DOMString compositeOperation); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, optional DOMString color, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float grayLevel, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); }; +CanvasRenderingContext2D implements CanvasPathMethods; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp index b68421af1f6..ae7e6d41b70 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp @@ -29,8 +29,8 @@ #include "config.h" #include "core/html/canvas/CanvasStyle.h" -#include "CSSPropertyNames.h" -#include "core/css/CSSParser.h" +#include "core/CSSPropertyNames.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/StylePropertySet.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/canvas/CanvasGradient.h" @@ -42,13 +42,14 @@ namespace WebCore { enum ColorParseResult { ParsedRGBA, ParsedCurrentColor, ParsedSystemColor, ParseFailed }; -static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString, Document* document = 0) +static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString) { if (equalIgnoringCase(colorString, "currentcolor")) return ParsedCurrentColor; - if (CSSParser::parseColor(parsedColor, colorString)) + const bool useStrictParsing = true; + if (BisonCSSParser::parseColor(parsedColor, colorString, useStrictParsing)) return ParsedRGBA; - if (CSSParser::parseSystemColor(parsedColor, colorString, document)) + if (BisonCSSParser::parseSystemColor(parsedColor, colorString)) return ParsedSystemColor; return ParseFailed; } @@ -58,13 +59,13 @@ RGBA32 currentColor(HTMLCanvasElement* canvas) if (!canvas || !canvas->inDocument() || !canvas->inlineStyle()) return Color::black; RGBA32 rgba = Color::black; - CSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); + BisonCSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); return rgba; } bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement* canvas) { - ColorParseResult parseResult = parseColor(parsedColor, colorString, canvas ? &canvas->document() : 0); + ColorParseResult parseResult = parseColor(parsedColor, colorString); switch (parseResult) { case ParsedRGBA: case ParsedSystemColor: @@ -123,10 +124,10 @@ CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern) { } -PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color, Document* document) +PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color) { RGBA32 rgba; - ColorParseResult parseResult = parseColor(rgba, color, document); + ColorParseResult parseResult = parseColor(rgba, color); switch (parseResult) { case ParsedRGBA: case ParsedSystemColor: @@ -134,10 +135,10 @@ PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color, Docum case ParsedCurrentColor: return adoptRef(new CanvasStyle(CurrentColor)); case ParseFailed: - return 0; + return nullptr; default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } @@ -151,23 +152,24 @@ PassRefPtr<CanvasStyle> CanvasStyle::createFromStringWithOverrideAlpha(const Str case ParsedCurrentColor: return adoptRef(new CanvasStyle(CurrentColorWithOverrideAlpha, alpha)); case ParseFailed: - return 0; + return nullptr; default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } PassRefPtr<CanvasStyle> CanvasStyle::createFromGradient(PassRefPtr<CanvasGradient> gradient) { if (!gradient) - return 0; + return nullptr; return adoptRef(new CanvasStyle(gradient)); } + PassRefPtr<CanvasStyle> CanvasStyle::createFromPattern(PassRefPtr<CanvasPattern> pattern) { if (!pattern) - return 0; + return nullptr; return adoptRef(new CanvasStyle(pattern)); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h index 526ab716345..f939e3e8214 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h @@ -36,14 +36,13 @@ namespace WebCore { class CanvasGradient; class CanvasPattern; - class Document; class GraphicsContext; class HTMLCanvasElement; class CanvasStyle : public RefCounted<CanvasStyle> { public: static PassRefPtr<CanvasStyle> createFromRGBA(RGBA32 rgba) { return adoptRef(new CanvasStyle(rgba)); } - static PassRefPtr<CanvasStyle> createFromString(const String& color, Document* = 0); + static PassRefPtr<CanvasStyle> createFromString(const String& color); static PassRefPtr<CanvasStyle> createFromStringWithOverrideAlpha(const String& color, float alpha); static PassRefPtr<CanvasStyle> createFromGrayLevelWithAlpha(float grayLevel, float alpha) { return adoptRef(new CanvasStyle(grayLevel, alpha)); } static PassRefPtr<CanvasStyle> createFromRGBAChannels(float r, float g, float b, float a) { return adoptRef(new CanvasStyle(r, g, b, a)); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp index 5a28161937c..41b6cb3332d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp @@ -47,19 +47,19 @@ PassRefPtr<DataView> DataView::create(unsigned length) { RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(length, sizeof(uint8_t)); if (!buffer.get()) - return 0; + return nullptr; return create(buffer, 0, length); } PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { if (byteOffset > buffer->byteLength()) - return 0; + return nullptr; CheckedInt<uint32_t> checkedOffset(byteOffset); CheckedInt<uint32_t> checkedLength(byteLength); CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength; if (!checkedMax.isValid() || checkedMax.value() > buffer->byteLength()) - return 0; + return nullptr; return adoptRef(new DataView(buffer, byteOffset, byteLength)); } @@ -133,7 +133,7 @@ template<typename T> T DataView::getData(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState) const { if (beyondRange<T>(byteOffset)) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided offset (" + String::number(byteOffset) + ") is outside the allowed range."); return 0; } @@ -148,7 +148,7 @@ template<typename T> void DataView::setData(unsigned byteOffset, T value, bool littleEndian, ExceptionState& exceptionState) { if (beyondRange<T>(byteOffset)) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided offset (" + String::number(byteOffset) + ") is outside the allowed range."); return; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h index 4a9728d845e..d497eae2f97 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h @@ -34,14 +34,12 @@ namespace WebCore { class ExceptionState; -class DataView : public ArrayBufferView, public ScriptWrappable { +class DataView FINAL : public ArrayBufferView, public ScriptWrappable { public: static PassRefPtr<DataView> create(unsigned length); static PassRefPtr<DataView> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength); - virtual unsigned length() const { return m_byteLength; } - virtual unsigned byteLength() const { return m_byteLength; } - virtual PassRefPtr<ArrayBufferView> slice(int, int) const { return 0; } + virtual unsigned byteLength() const OVERRIDE { return m_byteLength; } int8_t getInt8(unsigned byteOffset, ExceptionState&); uint8_t getUint8(unsigned byteOffset, ExceptionState&); @@ -73,13 +71,13 @@ public: void setFloat64(unsigned byteOffset, double value, ExceptionState& ec) { setFloat64(byteOffset, value, false, ec); } void setFloat64(unsigned byteOffset, double value, bool littleEndian, ExceptionState&); - virtual ViewType getType() const + virtual ViewType type() const OVERRIDE { return TypeDataView; } protected: - virtual void neuter(); + virtual void neuter() OVERRIDE; private: DataView(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl index a9b9facac3e..4fc89615027 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl @@ -26,30 +26,30 @@ [ Custom=Wrap, CustomConstructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long byteLength), - GlobalContext=Window&WorkerGlobalScope, + Exposed=Window&Worker, + TypeChecking=Interface|Nullable, ] interface DataView : ArrayBufferView { // All these methods raise an exception if they would read or write beyond the end of the view. [RaisesException] byte getInt8(unsigned long byteOffset); [RaisesException] octet getUint8(unsigned long byteOffset); - [StrictTypeChecking, RaisesException] short getInt16(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] unsigned short getUint16(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] long getInt32(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] unsigned long getUint32(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] short getInt16(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] unsigned short getUint16(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] long getInt32(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] unsigned long getUint32(unsigned long byteOffset, optional boolean littleEndian); // Use custom code to handle NaN case for JSC. - [StrictTypeChecking, RaisesException] float getFloat32(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] double getFloat64(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] float getFloat32(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] double getFloat64(unsigned long byteOffset, optional boolean littleEndian); [RaisesException] void setInt8(unsigned long byteOffset, byte value); [RaisesException] void setUint8(unsigned long byteOffset, octet value); - [StrictTypeChecking, RaisesException] void setInt16(unsigned long byteOffset, short value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setUint16(unsigned long byteOffset, unsigned short value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setInt32(unsigned long byteOffset, long value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setUint32(unsigned long byteOffset, unsigned long value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setFloat32(unsigned long byteOffset, float value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setFloat64(unsigned long byteOffset, double value, optional boolean littleEndian); + [RaisesException] void setInt16(unsigned long byteOffset, short value, optional boolean littleEndian); + [RaisesException] void setUint16(unsigned long byteOffset, unsigned short value, optional boolean littleEndian); + [RaisesException] void setInt32(unsigned long byteOffset, long value, optional boolean littleEndian); + [RaisesException] void setUint32(unsigned long byteOffset, unsigned long value, optional boolean littleEndian); + [RaisesException] void setFloat32(unsigned long byteOffset, float value, optional boolean littleEndian); + [RaisesException] void setFloat64(unsigned long byteOffset, double value, optional boolean littleEndian); }; - diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.cpp new file mode 100644 index 00000000000..8ded7388912 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/html/canvas/EXTBlendMinMax.h" + +namespace WebCore { + +EXTBlendMinMax::EXTBlendMinMax(WebGLRenderingContextBase* context) + : WebGLExtension(context) +{ + ScriptWrappable::init(this); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_blend_minmax"); +} + +EXTBlendMinMax::~EXTBlendMinMax() +{ +} + +WebGLExtensionName EXTBlendMinMax::name() const +{ + return EXTBlendMinMaxName; +} + +PassRefPtr<EXTBlendMinMax> EXTBlendMinMax::create(WebGLRenderingContextBase* context) +{ + return adoptRef(new EXTBlendMinMax(context)); +} + +bool EXTBlendMinMax::supported(WebGLRenderingContextBase* context) +{ + return context->extensionsUtil()->supportsExtension("GL_EXT_blend_minmax"); +} + +const char* EXTBlendMinMax::extensionName() +{ + return "EXT_blend_minmax"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.h new file mode 100644 index 00000000000..4c6421760de --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTBlendMinMax_h +#define EXTBlendMinMax_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLExtension.h" +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class EXTBlendMinMax FINAL : public WebGLExtension, public ScriptWrappable { +public: + static PassRefPtr<EXTBlendMinMax> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); + static const char* extensionName(); + + virtual ~EXTBlendMinMax(); + virtual WebGLExtensionName name() const OVERRIDE; + +private: + EXTBlendMinMax(WebGLRenderingContextBase*); +}; + +} // namespace WebCore + +#endif // EXTBlendMinMax_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.idl b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.idl new file mode 100644 index 00000000000..55baea7d615 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.idl @@ -0,0 +1,12 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + DoNotCheckConstants, + NoInterfaceObject, + TypeChecking=Interface|Nullable, +] interface EXTBlendMinMax { + const unsigned long MIN_EXT = 0x8007; + const unsigned long MAX_EXT = 0x8008; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp index a2484d283d3..002deb3df74 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp @@ -27,35 +27,32 @@ #include "core/html/canvas/EXTFragDepth.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -EXTFragDepth::EXTFragDepth(WebGLRenderingContext* context) +EXTFragDepth::EXTFragDepth(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_EXT_frag_depth"); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_frag_depth"); } EXTFragDepth::~EXTFragDepth() { } -WebGLExtension::ExtensionName EXTFragDepth::name() const +WebGLExtensionName EXTFragDepth::name() const { return EXTFragDepthName; } -PassRefPtr<EXTFragDepth> EXTFragDepth::create(WebGLRenderingContext* context) +PassRefPtr<EXTFragDepth> EXTFragDepth::create(WebGLRenderingContextBase* context) { return adoptRef(new EXTFragDepth(context)); } -bool EXTFragDepth::supported(WebGLRenderingContext* context) +bool EXTFragDepth::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_EXT_frag_depth"); + return context->extensionsUtil()->supportsExtension("GL_EXT_frag_depth"); } const char* EXTFragDepth::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h index fc8a9fa6f8e..eee90dcc021 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h @@ -32,17 +32,17 @@ namespace WebCore { -class EXTFragDepth : public WebGLExtension, public ScriptWrappable { +class EXTFragDepth FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<EXTFragDepth> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<EXTFragDepth> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~EXTFragDepth(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - explicit EXTFragDepth(WebGLRenderingContext*); + explicit EXTFragDepth(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.cpp new file mode 100644 index 00000000000..d258bef94cf --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/html/canvas/EXTShaderTextureLOD.h" + +namespace WebCore { + +EXTShaderTextureLOD::EXTShaderTextureLOD(WebGLRenderingContextBase* context) + : WebGLExtension(context) +{ + ScriptWrappable::init(this); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_shader_texture_lod"); +} + +EXTShaderTextureLOD::~EXTShaderTextureLOD() +{ +} + +WebGLExtensionName EXTShaderTextureLOD::name() const +{ + return EXTShaderTextureLODName; +} + +PassRefPtr<EXTShaderTextureLOD> EXTShaderTextureLOD::create(WebGLRenderingContextBase* context) +{ + return adoptRef(new EXTShaderTextureLOD(context)); +} + +bool EXTShaderTextureLOD::supported(WebGLRenderingContextBase* context) +{ + return context->extensionsUtil()->supportsExtension("GL_EXT_shader_texture_lod"); +} + +const char* EXTShaderTextureLOD::extensionName() +{ + return "EXT_shader_texture_lod"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.h new file mode 100644 index 00000000000..342d94d0965 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTShaderTextureLOD_h +#define EXTShaderTextureLOD_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLExtension.h" +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class EXTShaderTextureLOD FINAL : public WebGLExtension, public ScriptWrappable { +public: + static PassRefPtr<EXTShaderTextureLOD> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); + static const char* extensionName(); + + virtual ~EXTShaderTextureLOD(); + virtual WebGLExtensionName name() const OVERRIDE; + +private: + EXTShaderTextureLOD(WebGLRenderingContextBase*); +}; + +} // namespace WebCore + +#endif // EXTShaderTextureLOD_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.idl b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.idl new file mode 100644 index 00000000000..a2e18b616ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.idl @@ -0,0 +1,8 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject +] interface EXTShaderTextureLOD { +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp index 231c3c58662..d98399a4ccc 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/EXTTextureFilterAnisotropic.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContext* context) +EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic"); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_texture_filter_anisotropic"); } EXTTextureFilterAnisotropic::~EXTTextureFilterAnisotropic() { } -WebGLExtension::ExtensionName EXTTextureFilterAnisotropic::name() const +WebGLExtensionName EXTTextureFilterAnisotropic::name() const { return EXTTextureFilterAnisotropicName; } -PassRefPtr<EXTTextureFilterAnisotropic> EXTTextureFilterAnisotropic::create(WebGLRenderingContext* context) +PassRefPtr<EXTTextureFilterAnisotropic> EXTTextureFilterAnisotropic::create(WebGLRenderingContextBase* context) { return adoptRef(new EXTTextureFilterAnisotropic(context)); } -bool EXTTextureFilterAnisotropic::supported(WebGLRenderingContext* context) +bool EXTTextureFilterAnisotropic::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_EXT_texture_filter_anisotropic"); + return context->extensionsUtil()->supportsExtension("GL_EXT_texture_filter_anisotropic"); } const char* EXTTextureFilterAnisotropic::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h index 727f00ee086..a69a9bc3ab2 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h @@ -32,17 +32,17 @@ namespace WebCore { -class EXTTextureFilterAnisotropic : public WebGLExtension, public ScriptWrappable { +class EXTTextureFilterAnisotropic FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<EXTTextureFilterAnisotropic> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<EXTTextureFilterAnisotropic> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~EXTTextureFilterAnisotropic(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - EXTTextureFilterAnisotropic(WebGLRenderingContext*); + EXTTextureFilterAnisotropic(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp index a4b0e29c94d..95fac41b58c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/OESElementIndexUint.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESElementIndexUint::OESElementIndexUint(WebGLRenderingContext* context) +OESElementIndexUint::OESElementIndexUint(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_element_index_uint"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_element_index_uint"); } OESElementIndexUint::~OESElementIndexUint() { } -WebGLExtension::ExtensionName OESElementIndexUint::name() const +WebGLExtensionName OESElementIndexUint::name() const { return OESElementIndexUintName; } -PassRefPtr<OESElementIndexUint> OESElementIndexUint::create(WebGLRenderingContext* context) +PassRefPtr<OESElementIndexUint> OESElementIndexUint::create(WebGLRenderingContextBase* context) { return adoptRef(new OESElementIndexUint(context)); } -bool OESElementIndexUint::supported(WebGLRenderingContext* context) +bool OESElementIndexUint::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_element_index_uint"); + return context->extensionsUtil()->supportsExtension("GL_OES_element_index_uint"); } const char* OESElementIndexUint::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h index 0116c1ddcf1..f11ebd251ee 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESElementIndexUint : public WebGLExtension, public ScriptWrappable { +class OESElementIndexUint FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESElementIndexUint> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESElementIndexUint> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESElementIndexUint(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESElementIndexUint(WebGLRenderingContext*); + OESElementIndexUint(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp index aec473bc686..49b7adff0d8 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/OESStandardDerivatives.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContext* context) +OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_standard_derivatives"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_standard_derivatives"); } OESStandardDerivatives::~OESStandardDerivatives() { } -WebGLExtension::ExtensionName OESStandardDerivatives::name() const +WebGLExtensionName OESStandardDerivatives::name() const { return OESStandardDerivativesName; } -PassRefPtr<OESStandardDerivatives> OESStandardDerivatives::create(WebGLRenderingContext* context) +PassRefPtr<OESStandardDerivatives> OESStandardDerivatives::create(WebGLRenderingContextBase* context) { return adoptRef(new OESStandardDerivatives(context)); } -bool OESStandardDerivatives::supported(WebGLRenderingContext* context) +bool OESStandardDerivatives::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_standard_derivatives"); + return context->extensionsUtil()->supportsExtension("GL_OES_standard_derivatives"); } const char* OESStandardDerivatives::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h index 327a15286d1..8eb7226eb20 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESStandardDerivatives : public WebGLExtension, public ScriptWrappable { +class OESStandardDerivatives FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESStandardDerivatives> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESStandardDerivatives> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESStandardDerivatives(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESStandardDerivatives(WebGLRenderingContext*); + OESStandardDerivatives(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp index 99d1387376c..a949e5c54b0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp @@ -26,35 +26,37 @@ #include "config.h" #include "core/html/canvas/OESTextureFloat.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESTextureFloat::OESTextureFloat(WebGLRenderingContext* context) +OESTextureFloat::OESTextureFloat(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_float"); + if (context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_float")) { + // Implicitly enable rendering to float textures + context->extensionsUtil()->ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"); + context->extensionsUtil()->ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"); + } } OESTextureFloat::~OESTextureFloat() { } -WebGLExtension::ExtensionName OESTextureFloat::name() const +WebGLExtensionName OESTextureFloat::name() const { return OESTextureFloatName; } -PassRefPtr<OESTextureFloat> OESTextureFloat::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureFloat> OESTextureFloat::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureFloat(context)); } -bool OESTextureFloat::supported(WebGLRenderingContext* context) +bool OESTextureFloat::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_float"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_float"); } const char* OESTextureFloat::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h index 255c6741b11..dfc59086c48 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureFloat : public WebGLExtension, public ScriptWrappable { +class OESTextureFloat FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureFloat> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureFloat> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureFloat(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureFloat(WebGLRenderingContext*); + OESTextureFloat(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp index 1e8518d95d6..15a7cd356a4 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp @@ -27,35 +27,32 @@ #include "core/html/canvas/OESTextureFloatLinear.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContext* context) +OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_float_linear"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_float_linear"); } OESTextureFloatLinear::~OESTextureFloatLinear() { } -WebGLExtension::ExtensionName OESTextureFloatLinear::name() const +WebGLExtensionName OESTextureFloatLinear::name() const { return OESTextureFloatLinearName; } -PassRefPtr<OESTextureFloatLinear> OESTextureFloatLinear::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureFloatLinear> OESTextureFloatLinear::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureFloatLinear(context)); } -bool OESTextureFloatLinear::supported(WebGLRenderingContext* context) +bool OESTextureFloatLinear::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_float_linear"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_float_linear"); } const char* OESTextureFloatLinear::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h index 4d7f8d1af53..a0646ccd3a7 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureFloatLinear : public WebGLExtension, public ScriptWrappable { +class OESTextureFloatLinear FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureFloatLinear> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureFloatLinear> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureFloatLinear(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureFloatLinear(WebGLRenderingContext*); + OESTextureFloatLinear(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp index 7253837aa42..dd7f119c947 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/OESTextureHalfFloat.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContext* context) +OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_half_float"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_half_float"); } OESTextureHalfFloat::~OESTextureHalfFloat() { } -WebGLExtension::ExtensionName OESTextureHalfFloat::name() const +WebGLExtensionName OESTextureHalfFloat::name() const { return OESTextureHalfFloatName; } -PassRefPtr<OESTextureHalfFloat> OESTextureHalfFloat::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureHalfFloat> OESTextureHalfFloat::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureHalfFloat(context)); } -bool OESTextureHalfFloat::supported(WebGLRenderingContext* context) +bool OESTextureHalfFloat::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_half_float"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_half_float"); } const char* OESTextureHalfFloat::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h index 953d3110f07..dc5d917a345 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureHalfFloat : public WebGLExtension, public ScriptWrappable { +class OESTextureHalfFloat FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureHalfFloat> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureHalfFloat> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureHalfFloat(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureHalfFloat(WebGLRenderingContext*); + OESTextureHalfFloat(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp index c7da9bd745b..37ceabe5197 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp @@ -27,35 +27,32 @@ #include "core/html/canvas/OESTextureHalfFloatLinear.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContext* context) +OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_half_float_linear"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_half_float_linear"); } OESTextureHalfFloatLinear::~OESTextureHalfFloatLinear() { } -WebGLExtension::ExtensionName OESTextureHalfFloatLinear::name() const +WebGLExtensionName OESTextureHalfFloatLinear::name() const { return OESTextureHalfFloatLinearName; } -PassRefPtr<OESTextureHalfFloatLinear> OESTextureHalfFloatLinear::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureHalfFloatLinear> OESTextureHalfFloatLinear::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureHalfFloatLinear(context)); } -bool OESTextureHalfFloatLinear::supported(WebGLRenderingContext* context) +bool OESTextureHalfFloatLinear::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_half_float_linear"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_half_float_linear"); } const char* OESTextureHalfFloatLinear::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h index 17532033b45..421bbbca4d0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureHalfFloatLinear : public WebGLExtension, public ScriptWrappable { +class OESTextureHalfFloatLinear FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureHalfFloatLinear> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureHalfFloatLinear> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureHalfFloatLinear(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureHalfFloatLinear(WebGLRenderingContext*); + OESTextureHalfFloatLinear(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp index 848c85f5557..932195ed611 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp @@ -28,29 +28,28 @@ #include "core/html/canvas/OESVertexArrayObject.h" #include "bindings/v8/ExceptionState.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "core/html/canvas/WebGLVertexArrayObjectOES.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContext* context) +OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_vertex_array_object"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_vertex_array_object"); } OESVertexArrayObject::~OESVertexArrayObject() { } -WebGLExtension::ExtensionName OESVertexArrayObject::name() const +WebGLExtensionName OESVertexArrayObject::name() const { return OESVertexArrayObjectName; } -PassRefPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingContext* context) +PassRefPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingContextBase* context) { return adoptRef(new OESVertexArrayObject(context)); } @@ -58,7 +57,7 @@ PassRefPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingCont PassRefPtr<WebGLVertexArrayObjectOES> OESVertexArrayObject::createVertexArrayOES() { if (isLost()) - return 0; + return nullptr; RefPtr<WebGLVertexArrayObjectOES> o = WebGLVertexArrayObjectOES::create(m_context, WebGLVertexArrayObjectOES::VaoTypeUser); m_context->addContextObject(o.get()); @@ -71,12 +70,12 @@ void OESVertexArrayObject::deleteVertexArrayOES(WebGLVertexArrayObjectOES* array return; if (!arrayObject->isDefaultObject() && arrayObject == m_context->m_boundVertexArrayObject) - m_context->setBoundVertexArrayObject(0); + m_context->setBoundVertexArrayObject(nullptr); - arrayObject->deleteObject(m_context->graphicsContext3D()); + arrayObject->deleteObject(m_context->webContext()); } -GC3Dboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) +GLboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) { if (!arrayObject || isLost()) return 0; @@ -84,8 +83,7 @@ GC3Dboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* ar if (!arrayObject->hasEverBeenBound()) return 0; - Extensions3D* extensions = m_context->graphicsContext3D()->extensions(); - return extensions->isVertexArrayOES(arrayObject->object()); + return m_context->webContext()->isVertexArrayOES(arrayObject->object()); } void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) @@ -94,26 +92,24 @@ void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayOb return; if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, context()))) { - m_context->graphicsContext3D()->synthesizeGLError(GL_INVALID_OPERATION); + m_context->webContext()->synthesizeGLError(GL_INVALID_OPERATION); return; } - Extensions3D* extensions = m_context->graphicsContext3D()->extensions(); if (arrayObject && !arrayObject->isDefaultObject() && arrayObject->object()) { - extensions->bindVertexArrayOES(arrayObject->object()); + m_context->webContext()->bindVertexArrayOES(arrayObject->object()); arrayObject->setHasEverBeenBound(); m_context->setBoundVertexArrayObject(arrayObject); } else { - extensions->bindVertexArrayOES(0); - m_context->setBoundVertexArrayObject(0); + m_context->webContext()->bindVertexArrayOES(0); + m_context->setBoundVertexArrayObject(nullptr); } } -bool OESVertexArrayObject::supported(WebGLRenderingContext* context) +bool OESVertexArrayObject::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_vertex_array_object"); + return context->extensionsUtil()->supportsExtension("GL_OES_vertex_array_object"); } const char* OESVertexArrayObject::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h index 2fd0735f21a..3f616be0575 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h @@ -28,30 +28,29 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/WebGLExtension.h" -#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; class WebGLVertexArrayObjectOES; -class OESVertexArrayObject : public WebGLExtension, public ScriptWrappable { +class OESVertexArrayObject FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESVertexArrayObject> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESVertexArrayObject> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESVertexArrayObject(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; PassRefPtr<WebGLVertexArrayObjectOES> createVertexArrayOES(); void deleteVertexArrayOES(WebGLVertexArrayObjectOES*); - GC3Dboolean isVertexArrayOES(WebGLVertexArrayObjectOES*); + GLboolean isVertexArrayOES(WebGLVertexArrayObjectOES*); void bindVertexArrayOES(WebGLVertexArrayObjectOES*); private: - OESVertexArrayObject(WebGLRenderingContext*); + OESVertexArrayObject(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl index aa9a16d6377..5a21f238d79 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl @@ -24,13 +24,14 @@ */ [ + DoNotCheckConstants, NoInterfaceObject, - DoNotCheckConstants + TypeChecking=Interface|Nullable, ] interface OESVertexArrayObject { const unsigned long VERTEX_ARRAY_BINDING_OES = 0x85B5; - [StrictTypeChecking] WebGLVertexArrayObjectOES createVertexArrayOES(); - [StrictTypeChecking] void deleteVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); - [StrictTypeChecking] boolean isVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); - [StrictTypeChecking] void bindVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); + WebGLVertexArrayObjectOES createVertexArrayOES(); + void deleteVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES? arrayObject); + boolean isVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES? arrayObject); + void bindVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES? arrayObject); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Path.idl b/chromium/third_party/WebKit/Source/core/html/canvas/Path.idl deleted file mode 100644 index 66435a5da46..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Path.idl +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2012, 2013 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - */ - -[ - RuntimeEnabled=ExperimentalCanvasFeatures, - Constructor, - Constructor(Path path), - Constructor(DOMString text), - ImplementedAs=DOMPath -] interface Path { - - // FIXME: These methods should be shared with CanvasRenderingContext2D in the CanvasPathMethods interface. - void closePath(); - void moveTo([Default=Undefined] optional float x, - [Default=Undefined] optional float y); - void lineTo([Default=Undefined] optional float x, - [Default=Undefined] optional float y); - void quadraticCurveTo([Default=Undefined] optional float cpx, - [Default=Undefined] optional float cpy, - [Default=Undefined] optional float x, - [Default=Undefined] optional float y); - void bezierCurveTo([Default=Undefined] optional float cp1x, - [Default=Undefined] optional float cp1y, - [Default=Undefined] optional float cp2x, - [Default=Undefined] optional float cp2y, - [Default=Undefined] optional float x, - [Default=Undefined] optional float y); - [RaisesException] void arcTo([Default=Undefined] optional float x1, - [Default=Undefined] optional float y1, - [Default=Undefined] optional float x2, - [Default=Undefined] optional float y2, - [Default=Undefined] optional float radius); - void rect([Default=Undefined] optional float x, - [Default=Undefined] optional float y, - [Default=Undefined] optional float width, - [Default=Undefined] optional float height); - [RaisesException] void arc([Default=Undefined] optional float x, - [Default=Undefined] optional float y, - [Default=Undefined] optional float radius, - [Default=Undefined] optional float startAngle, - [Default=Undefined] optional float endAngle, - [Default=Undefined] optional boolean anticlockwise); -}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DOMPath.h b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.h index 9ce2cba9512..f09839bb1e9 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DOMPath.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.h @@ -25,50 +25,60 @@ * SUCH DAMAGE. */ -#ifndef DOMPath_h -#define DOMPath_h +#ifndef Path2D_h +#define Path2D_h #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/CanvasPathMethods.h" +#include "core/svg/SVGMatrixTearOff.h" #include "core/svg/SVGPathUtilities.h" +#include "platform/transforms/AffineTransform.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class DOMPath : public RefCounted<DOMPath>, public CanvasPathMethods, public ScriptWrappable { - WTF_MAKE_NONCOPYABLE(DOMPath); WTF_MAKE_FAST_ALLOCATED; +class Path2D FINAL : public RefCounted<Path2D>, public CanvasPathMethods, public ScriptWrappable { + WTF_MAKE_NONCOPYABLE(Path2D); WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<DOMPath> create() { return adoptRef(new DOMPath); } - static PassRefPtr<DOMPath> create(const String& pathData) { return adoptRef(new DOMPath(pathData)); } - static PassRefPtr<DOMPath> create(DOMPath* path) { return adoptRef(new DOMPath(path)); } + static PassRefPtr<Path2D> create() { return adoptRef(new Path2D); } + static PassRefPtr<Path2D> create(const String& pathData) { return adoptRef(new Path2D(pathData)); } + static PassRefPtr<Path2D> create(Path2D* path) { return adoptRef(new Path2D(path)); } - static PassRefPtr<DOMPath> create(const Path& path) { return adoptRef(new DOMPath(path)); } + static PassRefPtr<Path2D> create(const Path& path) { return adoptRef(new Path2D(path)); } const Path& path() const { return m_path; } - virtual ~DOMPath() { } + void addPath(Path2D* path) + { + addPath(path, 0); + } + + void addPath(Path2D* path, SVGMatrixTearOff* transform) + { + Path src = path->path(); + m_path.addPath(src, transform ? transform->value() : AffineTransform(1, 0, 0, 1, 0, 0)); + } + virtual ~Path2D() { } private: - DOMPath() : CanvasPathMethods() + Path2D() : CanvasPathMethods() { ScriptWrappable::init(this); } - DOMPath(const Path& path) - : CanvasPathMethods() + Path2D(const Path& path) + : CanvasPathMethods(path) { ScriptWrappable::init(this); - m_path = path; } - DOMPath(DOMPath* path) - : CanvasPathMethods() + Path2D(Path2D* path) + : CanvasPathMethods(path->path()) { ScriptWrappable::init(this); - m_path = path->path(); } - DOMPath(const String& pathData) + Path2D(const String& pathData) : CanvasPathMethods() { ScriptWrappable::init(this); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.idl b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.idl new file mode 100644 index 00000000000..262148560a2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.idl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2012, 2013 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + */ + +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#path2d + +[ + Constructor, + Constructor(Path2D path), + Constructor(DOMString text), + RuntimeEnabled=Path2D, +] interface Path2D { + + [RuntimeEnabled=ExperimentalCanvasFeatures, TypeChecking=Interface|Nullable] void addPath(Path2D path, optional SVGMatrix? transform); +}; + +Path2D implements CanvasPathMethods; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h index 7571e3681ec..b1c983484b3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h @@ -27,7 +27,7 @@ #define WebGLActiveInfo_h #include "bindings/v8/ScriptWrappable.h" -#include "platform/graphics/GraphicsContext3D.h" +#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -36,16 +36,16 @@ namespace WebCore { class WebGLActiveInfo : public RefCounted<WebGLActiveInfo>, public ScriptWrappable { public: - static PassRefPtr<WebGLActiveInfo> create(const String& name, GC3Denum type, GC3Dint size) + static PassRefPtr<WebGLActiveInfo> create(const String& name, GLenum type, GLint size) { return adoptRef(new WebGLActiveInfo(name, type, size)); } String name() const { return m_name; } - GC3Denum type() const { return m_type; } - GC3Dint size() const { return m_size; } + GLenum type() const { return m_type; } + GLint size() const { return m_size; } private: - WebGLActiveInfo(const String& name, GC3Denum type, GC3Dint size) + WebGLActiveInfo(const String& name, GLenum type, GLint size) : m_name(name) , m_type(type) , m_size(size) @@ -56,8 +56,8 @@ private: ScriptWrappable::init(this); } String m_name; - GC3Denum m_type; - GC3Dint m_size; + GLenum m_type; + GLint m_size; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp index 48bf88a1ab0..6308eccf192 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp @@ -27,21 +27,21 @@ #include "core/html/canvas/WebGLBuffer.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLBuffer(ctx)); } -WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx) +WebGLBuffer::WebGLBuffer(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_target(0) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createBuffer()); + setObject(ctx->webContext()->createBuffer()); } WebGLBuffer::~WebGLBuffer() @@ -49,12 +49,12 @@ WebGLBuffer::~WebGLBuffer() deleteObject(0); } -void WebGLBuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLBuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteBuffer(object); } -void WebGLBuffer::setTarget(GC3Denum target) +void WebGLBuffer::setTarget(GLenum target) { // In WebGL, a buffer is bound to one target in its lifetime if (m_target) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h index 8483685f58c..9f596be4c8a 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h @@ -33,26 +33,26 @@ namespace WebCore { -class WebGLBuffer : public WebGLSharedObject, public ScriptWrappable { +class WebGLBuffer FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLBuffer(); - static PassRefPtr<WebGLBuffer> create(WebGLRenderingContext*); + static PassRefPtr<WebGLBuffer> create(WebGLRenderingContextBase*); - GC3Denum getTarget() const { return m_target; } - void setTarget(GC3Denum); + GLenum getTarget() const { return m_target; } + void setTarget(GLenum); bool hasEverBeenBound() const { return object() && m_target; } protected: - WebGLBuffer(WebGLRenderingContext*); + WebGLBuffer(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isBuffer() const { return true; } + virtual bool isBuffer() const OVERRIDE { return true; } - GC3Denum m_target; + GLenum m_target; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp index dad7ff49b05..3bfd7d8f0b1 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp @@ -27,37 +27,34 @@ #include "core/html/canvas/WebGLCompressedTextureATC.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContext* context) +WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGB_AMD); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD); + context->addCompressedTextureFormat(GC3D_COMPRESSED_ATC_RGB_AMD); + context->addCompressedTextureFormat(GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD); + context->addCompressedTextureFormat(GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD); } WebGLCompressedTextureATC::~WebGLCompressedTextureATC() { } -WebGLExtension::ExtensionName WebGLCompressedTextureATC::name() const +WebGLExtensionName WebGLCompressedTextureATC::name() const { return WebGLCompressedTextureATCName; } -PassRefPtr<WebGLCompressedTextureATC> WebGLCompressedTextureATC::create(WebGLRenderingContext* context) +PassRefPtr<WebGLCompressedTextureATC> WebGLCompressedTextureATC::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLCompressedTextureATC(context)); } -bool WebGLCompressedTextureATC::supported(WebGLRenderingContext* context) +bool WebGLCompressedTextureATC::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_AMD_compressed_ATC_texture"); + return context->extensionsUtil()->supportsExtension("GL_AMD_compressed_ATC_texture"); } const char* WebGLCompressedTextureATC::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h index eb49bc4bfe8..069fe145bd0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h @@ -34,17 +34,17 @@ namespace WebCore { class WebGLTexture; -class WebGLCompressedTextureATC : public WebGLExtension, public ScriptWrappable { +class WebGLCompressedTextureATC FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLCompressedTextureATC> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLCompressedTextureATC> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLCompressedTextureATC(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLCompressedTextureATC(WebGLRenderingContext*); + WebGLCompressedTextureATC(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.cpp new file mode 100644 index 00000000000..a2abde855a3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.cpp @@ -0,0 +1,45 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/html/canvas/WebGLCompressedTextureETC1.h" + +#include "core/html/canvas/WebGLRenderingContextBase.h" + +namespace WebCore { + +WebGLCompressedTextureETC1::WebGLCompressedTextureETC1(WebGLRenderingContextBase* context) + : WebGLExtension(context) +{ + ScriptWrappable::init(this); + context->addCompressedTextureFormat(GL_ETC1_RGB8_OES); +} + +WebGLCompressedTextureETC1::~WebGLCompressedTextureETC1() +{ +} + +WebGLExtensionName WebGLCompressedTextureETC1::name() const +{ + return WebGLCompressedTextureETC1Name; +} + +PassRefPtr<WebGLCompressedTextureETC1> WebGLCompressedTextureETC1::create(WebGLRenderingContextBase* context) +{ + return adoptRef(new WebGLCompressedTextureETC1(context)); +} + +bool WebGLCompressedTextureETC1::supported(WebGLRenderingContextBase* context) +{ + Extensions3DUtil* extensionsUtil = context->extensionsUtil(); + return extensionsUtil->supportsExtension("GL_OES_compressed_ETC1_RGB8_texture"); +} + +const char* WebGLCompressedTextureETC1::extensionName() +{ + return "WEBGL_compressed_texture_etc1"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.h new file mode 100644 index 00000000000..4cf3a57ed74 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebGLCompressedTextureETC1_h +#define WebGLCompressedTextureETC1_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLExtension.h" +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class WebGLTexture; + +class WebGLCompressedTextureETC1 FINAL : public WebGLExtension, public ScriptWrappable { +public: + static PassRefPtr<WebGLCompressedTextureETC1> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); + static const char* extensionName(); + + virtual ~WebGLCompressedTextureETC1(); + virtual WebGLExtensionName name() const OVERRIDE; + +private: + WebGLCompressedTextureETC1(WebGLRenderingContextBase*); +}; + +} // namespace WebCore + +#endif // WebGLCompressedTextureETC1_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.idl new file mode 100644 index 00000000000..e37d990cb6d --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + DoNotCheckConstants +] interface WebGLCompressedTextureETC1 { + /* Compressed Texture Formats */ + const unsigned long COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp index 8ae4acd2689..d1586ff22d6 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp @@ -27,39 +27,37 @@ #include "core/html/canvas/WebGLCompressedTexturePVRTC.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContext* context) +WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); } WebGLCompressedTexturePVRTC::~WebGLCompressedTexturePVRTC() { } -WebGLExtension::ExtensionName WebGLCompressedTexturePVRTC::name() const +WebGLExtensionName WebGLCompressedTexturePVRTC::name() const { return WebGLCompressedTexturePVRTCName; } -PassRefPtr<WebGLCompressedTexturePVRTC> WebGLCompressedTexturePVRTC::create(WebGLRenderingContext* context) +PassRefPtr<WebGLCompressedTexturePVRTC> WebGLCompressedTexturePVRTC::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLCompressedTexturePVRTC(context)); } -bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContext* context) +bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_IMG_texture_compression_pvrtc"); + return context->extensionsUtil()->supportsExtension("GL_IMG_texture_compression_pvrtc"); } const char* WebGLCompressedTexturePVRTC::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h index dc28e5f9522..27cde75bca7 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h @@ -32,17 +32,17 @@ namespace WebCore { -class WebGLCompressedTexturePVRTC : public WebGLExtension, public ScriptWrappable { +class WebGLCompressedTexturePVRTC FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLCompressedTexturePVRTC> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLCompressedTexturePVRTC> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLCompressedTexturePVRTC(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLCompressedTexturePVRTC(WebGLRenderingContext*); + WebGLCompressedTexturePVRTC(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp index 9d3f2543001..35834cc91ff 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp @@ -27,42 +27,41 @@ #include "core/html/canvas/WebGLCompressedTextureS3TC.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContext* context) +WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); } WebGLCompressedTextureS3TC::~WebGLCompressedTextureS3TC() { } -WebGLExtension::ExtensionName WebGLCompressedTextureS3TC::name() const +WebGLExtensionName WebGLCompressedTextureS3TC::name() const { return WebGLCompressedTextureS3TCName; } -PassRefPtr<WebGLCompressedTextureS3TC> WebGLCompressedTextureS3TC::create(WebGLRenderingContext* context) +PassRefPtr<WebGLCompressedTextureS3TC> WebGLCompressedTextureS3TC::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLCompressedTextureS3TC(context)); } -bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContext* context) +bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_EXT_texture_compression_s3tc") - || (extensions->supports("GL_EXT_texture_compression_dxt1") - && extensions->supports("GL_CHROMIUM_texture_compression_dxt3") - && extensions->supports("GL_CHROMIUM_texture_compression_dxt5")); + Extensions3DUtil* extensionsUtil = context->extensionsUtil(); + return extensionsUtil->supportsExtension("GL_EXT_texture_compression_s3tc") + || (extensionsUtil->supportsExtension("GL_EXT_texture_compression_dxt1") + && extensionsUtil->supportsExtension("GL_CHROMIUM_texture_compression_dxt3") + && extensionsUtil->supportsExtension("GL_CHROMIUM_texture_compression_dxt5")); } const char* WebGLCompressedTextureS3TC::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h index 615f4f587fb..aaed4a7764c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h @@ -34,17 +34,17 @@ namespace WebCore { class WebGLTexture; -class WebGLCompressedTextureS3TC : public WebGLExtension, public ScriptWrappable { +class WebGLCompressedTextureS3TC FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLCompressedTextureS3TC> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLCompressedTextureS3TC> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLCompressedTextureS3TC(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLCompressedTextureS3TC(WebGLRenderingContext*); + WebGLCompressedTextureS3TC(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp index cb26556a731..385720617fd 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp @@ -28,6 +28,8 @@ #include "core/html/canvas/WebGLContextAttributes.h" +#include "core/frame/Settings.h" + namespace WebCore { PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create() @@ -35,20 +37,28 @@ PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create() return adoptRef(new WebGLContextAttributes()); } -PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create(GraphicsContext3D::Attributes attributes) -{ - return adoptRef(new WebGLContextAttributes(attributes)); -} - WebGLContextAttributes::WebGLContextAttributes() : CanvasContextAttributes() + , m_alpha(true) + , m_depth(true) + , m_stencil(false) + , m_antialias(true) + , m_premultipliedAlpha(true) + , m_preserveDrawingBuffer(false) + , m_failIfMajorPerformanceCaveat(false) { ScriptWrappable::init(this); } -WebGLContextAttributes::WebGLContextAttributes(GraphicsContext3D::Attributes attributes) +WebGLContextAttributes::WebGLContextAttributes(const WebGLContextAttributes& attrs) : CanvasContextAttributes() - , m_attrs(attributes) + , m_alpha(attrs.m_alpha) + , m_depth(attrs.m_depth) + , m_stencil(attrs.m_stencil) + , m_antialias(attrs.m_antialias) + , m_premultipliedAlpha(attrs.m_premultipliedAlpha) + , m_preserveDrawingBuffer(attrs.m_preserveDrawingBuffer) + , m_failIfMajorPerformanceCaveat(attrs.m_failIfMajorPerformanceCaveat) { ScriptWrappable::init(this); } @@ -57,79 +67,104 @@ WebGLContextAttributes::~WebGLContextAttributes() { } +PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::clone() const +{ + return adoptRef(new WebGLContextAttributes(*this)); +} + bool WebGLContextAttributes::alpha() const { - return m_attrs.alpha; + return m_alpha; } void WebGLContextAttributes::setAlpha(bool alpha) { - m_attrs.alpha = alpha; + m_alpha = alpha; } bool WebGLContextAttributes::depth() const { - return m_attrs.depth; + return m_depth; } void WebGLContextAttributes::setDepth(bool depth) { - m_attrs.depth = depth; + m_depth = depth; } bool WebGLContextAttributes::stencil() const { - return m_attrs.stencil; + return m_stencil; } void WebGLContextAttributes::setStencil(bool stencil) { - m_attrs.stencil = stencil; + m_stencil = stencil; } bool WebGLContextAttributes::antialias() const { - return m_attrs.antialias; + return m_antialias; } void WebGLContextAttributes::setAntialias(bool antialias) { - m_attrs.antialias = antialias; + m_antialias = antialias; } bool WebGLContextAttributes::premultipliedAlpha() const { - return m_attrs.premultipliedAlpha; + return m_premultipliedAlpha; } void WebGLContextAttributes::setPremultipliedAlpha(bool premultipliedAlpha) { - m_attrs.premultipliedAlpha = premultipliedAlpha; + m_premultipliedAlpha = premultipliedAlpha; } bool WebGLContextAttributes::preserveDrawingBuffer() const { - return m_attrs.preserveDrawingBuffer; + return m_preserveDrawingBuffer; } void WebGLContextAttributes::setPreserveDrawingBuffer(bool preserveDrawingBuffer) { - m_attrs.preserveDrawingBuffer = preserveDrawingBuffer; + m_preserveDrawingBuffer = preserveDrawingBuffer; } bool WebGLContextAttributes::failIfMajorPerformanceCaveat() const { - return m_attrs.failIfMajorPerformanceCaveat; + return m_failIfMajorPerformanceCaveat; } void WebGLContextAttributes::setFailIfMajorPerformanceCaveat(bool failIfMajorPerformanceCaveat) { - m_attrs.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat; + m_failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat; } -GraphicsContext3D::Attributes WebGLContextAttributes::attributes() const +blink::WebGraphicsContext3D::Attributes WebGLContextAttributes::attributes( + const blink::WebString& topDocumentURL, Settings* settings) const { - return m_attrs; + blink::WebGraphicsContext3D::Attributes attrs; + + attrs.alpha = m_alpha; + attrs.depth = m_depth; + attrs.stencil = m_stencil; + attrs.antialias = m_antialias; + if (m_antialias) { + if (settings && !settings->openGLMultisamplingEnabled()) + attrs.antialias = false; + } + attrs.premultipliedAlpha = m_premultipliedAlpha; + attrs.failIfMajorPerformanceCaveat = m_failIfMajorPerformanceCaveat; + + attrs.noExtensions = true; + attrs.shareResources = false; + attrs.preferDiscreteGPU = true; + + attrs.topDocumentURL = topDocumentURL; + + return attrs; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h index 62a576ef736..eeee443e2fa 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h @@ -29,42 +29,44 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/CanvasContextAttributes.h" -#include "platform/graphics/GraphicsContext3D.h" +#include "public/platform/WebGraphicsContext3D.h" #include "wtf/PassRefPtr.h" namespace WebCore { -class WebGLContextAttributes : public CanvasContextAttributes, public ScriptWrappable { +class Settings; + +class WebGLContextAttributes FINAL : public CanvasContextAttributes, public ScriptWrappable { public: virtual ~WebGLContextAttributes(); // Create a new attributes object static PassRefPtr<WebGLContextAttributes> create(); - // Create a new attributes object initialized with preexisting attributes - static PassRefPtr<WebGLContextAttributes> create(GraphicsContext3D::Attributes attributes); + // Create a copy of this object. + PassRefPtr<WebGLContextAttributes> clone() const; // Whether or not the drawing buffer has an alpha channel; default=true bool alpha() const; - void setAlpha(bool alpha); + void setAlpha(bool); // Whether or not the drawing buffer has a depth buffer; default=true bool depth() const; - void setDepth(bool depth); + void setDepth(bool); - // Whether or not the drawing buffer has a stencil buffer; default=true + // Whether or not the drawing buffer has a stencil buffer; default=false bool stencil() const; - void setStencil(bool stencil); + void setStencil(bool); // Whether or not the drawing buffer is antialiased; default=true bool antialias() const; - void setAntialias(bool antialias); + void setAntialias(bool); // Whether or not to treat the values in the drawing buffer as // though their alpha channel has already been multiplied into the // color channels; default=true bool premultipliedAlpha() const; - void setPremultipliedAlpha(bool premultipliedAlpha); + void setPremultipliedAlpha(bool); // Whether or not to preserve the drawing buffer after presentation to the // screen; default=false @@ -76,16 +78,23 @@ public: bool failIfMajorPerformanceCaveat() const; void setFailIfMajorPerformanceCaveat(bool); - // Fetches a copy of the attributes stored in this object in a - // form that can be used to initialize a GraphicsContext3D. - GraphicsContext3D::Attributes attributes() const; + // Set up the attributes that can be used to initialize a WebGraphicsContext3D. + // It's mostly based on WebGLContextAttributes, but would be adjusted based + // on settings. + blink::WebGraphicsContext3D::Attributes attributes(const blink::WebString&, Settings*) const; protected: WebGLContextAttributes(); - WebGLContextAttributes(GraphicsContext3D::Attributes attributes); + WebGLContextAttributes(const WebGLContextAttributes&); private: - GraphicsContext3D::Attributes m_attrs; + bool m_alpha; + bool m_depth; + bool m_stencil; + bool m_antialias; + bool m_premultipliedAlpha; + bool m_preserveDrawingBuffer; + bool m_failIfMajorPerformanceCaveat; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp index 7f4cf7c7576..f26e8441ea3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp @@ -26,8 +26,6 @@ #include "config.h" #include "core/html/canvas/WebGLContextEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { WebGLContextEventInit::WebGLContextEventInit() @@ -62,4 +60,9 @@ const AtomicString& WebGLContextEvent::interfaceName() const return EventNames::WebGLContextEvent; } +void WebGLContextEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h index 18f4a4812f9..0bd83808671 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h @@ -36,25 +36,27 @@ struct WebGLContextEventInit : public EventInit { String statusMessage; }; -class WebGLContextEvent : public Event { +class WebGLContextEvent FINAL : public Event { public: - static PassRefPtr<WebGLContextEvent> create() + static PassRefPtrWillBeRawPtr<WebGLContextEvent> create() { - return adoptRef(new WebGLContextEvent); + return adoptRefWillBeNoop(new WebGLContextEvent); } - static PassRefPtr<WebGLContextEvent> create(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) + static PassRefPtrWillBeRawPtr<WebGLContextEvent> create(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) { - return adoptRef(new WebGLContextEvent(type, canBubble, cancelable, statusMessage)); + return adoptRefWillBeNoop(new WebGLContextEvent(type, canBubble, cancelable, statusMessage)); } - static PassRefPtr<WebGLContextEvent> create(const AtomicString& type, const WebGLContextEventInit& initializer) + static PassRefPtrWillBeRawPtr<WebGLContextEvent> create(const AtomicString& type, const WebGLContextEventInit& initializer) { - return adoptRef(new WebGLContextEvent(type, initializer)); + return adoptRefWillBeNoop(new WebGLContextEvent(type, initializer)); } virtual ~WebGLContextEvent(); const String& statusMessage() const { return m_statusMessage; } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: WebGLContextEvent(); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp index 93ff6f4f4f1..e9e3ebe267e 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp @@ -46,19 +46,19 @@ WebGLContextGroup::~WebGLContextGroup() detachAndRemoveAllObjects(); } -GraphicsContext3D* WebGLContextGroup::getAGraphicsContext3D() +blink::WebGraphicsContext3D* WebGLContextGroup::getAWebGraphicsContext3D() { ASSERT(!m_contexts.isEmpty()); - HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); - return (*it)->graphicsContext3D(); + HashSet<WebGLRenderingContextBase*>::iterator it = m_contexts.begin(); + return (*it)->webContext(); } -void WebGLContextGroup::addContext(WebGLRenderingContext* context) +void WebGLContextGroup::addContext(WebGLRenderingContextBase* context) { m_contexts.add(context); } -void WebGLContextGroup::removeContext(WebGLRenderingContext* context) +void WebGLContextGroup::removeContext(WebGLRenderingContextBase* context) { // We must call detachAndRemoveAllObjects before removing the last context. if (m_contexts.size() == 1 && m_contexts.contains(context)) @@ -85,13 +85,13 @@ void WebGLContextGroup::detachAndRemoveAllObjects() } } -void WebGLContextGroup::loseContextGroup(WebGLRenderingContext::LostContextMode mode) +void WebGLContextGroup::loseContextGroup(WebGLRenderingContextBase::LostContextMode mode) { // Detach must happen before loseContextImpl, which destroys the GraphicsContext3D // and prevents groupObjects from being properly deleted. detachAndRemoveAllObjects(); - for (HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it) + for (HashSet<WebGLRenderingContextBase*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it) (*it)->loseContextImpl(mode); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h index b1fece9111b..6c2f9953540 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h @@ -26,17 +26,20 @@ #ifndef WebGLContextGroup_h #define WebGLContextGroup_h -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "wtf/HashSet.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace WebCore { -class GraphicsContext3D; class WebGLExtension; class WebGLSharedObject; -class WebGLRenderingContext; +class WebGLRenderingContextBase; typedef int ExceptionCode; @@ -45,15 +48,15 @@ public: static PassRefPtr<WebGLContextGroup> create(); ~WebGLContextGroup(); - void addContext(WebGLRenderingContext*); - void removeContext(WebGLRenderingContext*); + void addContext(WebGLRenderingContextBase*); + void removeContext(WebGLRenderingContextBase*); void addObject(WebGLSharedObject*); void removeObject(WebGLSharedObject*); - GraphicsContext3D* getAGraphicsContext3D(); + blink::WebGraphicsContext3D* getAWebGraphicsContext3D(); - void loseContextGroup(WebGLRenderingContext::LostContextMode); + void loseContextGroup(WebGLRenderingContextBase::LostContextMode); private: friend class WebGLObject; @@ -62,7 +65,7 @@ public: void detachAndRemoveAllObjects(); - HashSet<WebGLRenderingContext*> m_contexts; + HashSet<WebGLRenderingContextBase*> m_contexts; HashSet<WebGLSharedObject*> m_groupObjects; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp index ea718c51e7a..83441589def 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp @@ -27,11 +27,11 @@ #include "core/html/canvas/WebGLContextObject.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLContextObject::WebGLContextObject(WebGLRenderingContext* context) +WebGLContextObject::WebGLContextObject(WebGLRenderingContextBase* context) : WebGLObject(context) , m_context(context) { @@ -47,15 +47,15 @@ void WebGLContextObject::detachContext() { detach(); if (m_context) { - deleteObject(m_context->graphicsContext3D()); + deleteObject(m_context->webContext()); m_context->removeContextObject(this); m_context = 0; } } -GraphicsContext3D* WebGLContextObject::getAGraphicsContext3D() const +blink::WebGraphicsContext3D* WebGLContextObject::getAWebGraphicsContext3D() const { - return m_context ? m_context->graphicsContext3D() : 0; + return m_context ? m_context->webContext() : 0; } } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h index 1e4d2965754..21be7a53d8a 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h @@ -28,20 +28,23 @@ #include "core/html/canvas/WebGLObject.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace WebCore { -class GraphicsContext3D; -class WebGLRenderingContext; +class WebGLRenderingContextBase; // WebGLContextObject the base class for objects that are owned by a specific -// WebGLRenderingContext. +// WebGLRenderingContextBase. class WebGLContextObject : public WebGLObject { public: virtual ~WebGLContextObject(); - WebGLRenderingContext* context() const { return m_context; } + WebGLRenderingContextBase* context() const { return m_context; } - virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContext* context) const + virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase* context) const OVERRIDE FINAL { return context == m_context; } @@ -49,17 +52,17 @@ public: void detachContext(); protected: - WebGLContextObject(WebGLRenderingContext*); + WebGLContextObject(WebGLRenderingContextBase*); - virtual bool hasGroupOrContext() const + virtual bool hasGroupOrContext() const OVERRIDE FINAL { return m_context; } - virtual GraphicsContext3D* getAGraphicsContext3D() const; + virtual blink::WebGraphicsContext3D* getAWebGraphicsContext3D() const OVERRIDE FINAL; private: - WebGLRenderingContext* m_context; + WebGLRenderingContextBase* m_context; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp index bca809a7c0e..cc61d268de1 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp @@ -29,7 +29,7 @@ namespace WebCore { -WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContext* context) +WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); @@ -39,17 +39,17 @@ WebGLDebugRendererInfo::~WebGLDebugRendererInfo() { } -WebGLExtension::ExtensionName WebGLDebugRendererInfo::name() const +WebGLExtensionName WebGLDebugRendererInfo::name() const { return WebGLDebugRendererInfoName; } -PassRefPtr<WebGLDebugRendererInfo> WebGLDebugRendererInfo::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDebugRendererInfo> WebGLDebugRendererInfo::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDebugRendererInfo(context)); } -bool WebGLDebugRendererInfo::supported(WebGLRenderingContext*) +bool WebGLDebugRendererInfo::supported(WebGLRenderingContextBase*) { return true; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h index 2baa7abe337..8863aeb30f5 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h @@ -32,22 +32,22 @@ namespace WebCore { -class WebGLDebugRendererInfo : public WebGLExtension, public ScriptWrappable { +class WebGLDebugRendererInfo FINAL : public WebGLExtension, public ScriptWrappable { public: enum EnumType { UNMASKED_VENDOR_WEBGL = 0x9245, UNMASKED_RENDERER_WEBGL = 0x9246 }; - static PassRefPtr<WebGLDebugRendererInfo> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDebugRendererInfo> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDebugRendererInfo(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLDebugRendererInfo(WebGLRenderingContext*); + WebGLDebugRendererInfo(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp index 8ecb09379d2..2b4a0aa5037 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp @@ -27,13 +27,12 @@ #include "core/html/canvas/WebGLDebugShaders.h" #include "bindings/v8/ExceptionState.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "core/html/canvas/WebGLShader.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContext* context) +WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); @@ -43,12 +42,12 @@ WebGLDebugShaders::~WebGLDebugShaders() { } -WebGLExtension::ExtensionName WebGLDebugShaders::name() const +WebGLExtensionName WebGLDebugShaders::name() const { return WebGLDebugShadersName; } -PassRefPtr<WebGLDebugShaders> WebGLDebugShaders::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDebugShaders> WebGLDebugShaders::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDebugShaders(context)); } @@ -59,13 +58,12 @@ String WebGLDebugShaders::getTranslatedShaderSource(WebGLShader* shader) return String(); if (!m_context->validateWebGLObject("getTranslatedShaderSource", shader)) return ""; - return m_context->graphicsContext3D()->extensions()->getTranslatedShaderSourceANGLE(shader->object()); + return m_context->ensureNotNull(m_context->webContext()->getTranslatedShaderSourceANGLE(shader->object())); } -bool WebGLDebugShaders::supported(WebGLRenderingContext* context) +bool WebGLDebugShaders::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_ANGLE_translated_shader_source"); + return context->extensionsUtil()->supportsExtension("GL_ANGLE_translated_shader_source"); } const char* WebGLDebugShaders::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h index 1adbd3074c1..f1ae4f04b00 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h @@ -34,19 +34,19 @@ namespace WebCore { class WebGLShader; -class WebGLDebugShaders : public WebGLExtension, public ScriptWrappable { +class WebGLDebugShaders FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLDebugShaders> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDebugShaders> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDebugShaders(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; String getTranslatedShaderSource(WebGLShader*); private: - WebGLDebugShaders(WebGLRenderingContext*); + WebGLDebugShaders(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl index 55a6f3cb981..74851c7c226 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl @@ -24,7 +24,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + TypeChecking=Interface|Nullable, ] interface WebGLDebugShaders { - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getTranslatedShaderSource(WebGLShader shader); + [TreatReturnedNullStringAs=Null] DOMString getTranslatedShaderSource(WebGLShader? shader); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp index d42019ff82f..eb2e41d905b 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp @@ -27,42 +27,40 @@ #include "core/html/canvas/WebGLDepthTexture.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContext* context) +WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_CHROMIUM_depth_texture"); + context->extensionsUtil()->ensureExtensionEnabled("GL_CHROMIUM_depth_texture"); } WebGLDepthTexture::~WebGLDepthTexture() { } -WebGLExtension::ExtensionName WebGLDepthTexture::name() const +WebGLExtensionName WebGLDepthTexture::name() const { return WebGLDepthTextureName; } -PassRefPtr<WebGLDepthTexture> WebGLDepthTexture::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDepthTexture> WebGLDepthTexture::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDepthTexture(context)); } -bool WebGLDepthTexture::supported(WebGLRenderingContext* context) +bool WebGLDepthTexture::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); + Extensions3DUtil* extensionsUtil = context->extensionsUtil(); // Emulating the UNSIGNED_INT_24_8_WEBGL texture internal format in terms // of two separate texture objects is too difficult, so disable depth // textures unless a packed depth/stencil format is available. - if (!extensions->supports("GL_OES_packed_depth_stencil")) + if (!extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil")) return false; - return extensions->supports("GL_CHROMIUM_depth_texture") - || extensions->supports("GL_OES_depth_texture") - || extensions->supports("GL_ARB_depth_texture"); + return extensionsUtil->supportsExtension("GL_CHROMIUM_depth_texture") + || extensionsUtil->supportsExtension("GL_OES_depth_texture") + || extensionsUtil->supportsExtension("GL_ARB_depth_texture"); } const char* WebGLDepthTexture::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h index 34b052511b0..34017ee1801 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h @@ -32,17 +32,17 @@ namespace WebCore { -class WebGLDepthTexture : public WebGLExtension, public ScriptWrappable { +class WebGLDepthTexture FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLDepthTexture> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDepthTexture> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDepthTexture(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLDepthTexture(WebGLRenderingContext*); + WebGLDepthTexture(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp index 20b21feb5fe..e5b6b48659f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp @@ -27,36 +27,33 @@ #include "core/html/canvas/WebGLDrawBuffers.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContext* context) +WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_EXT_draw_buffers"); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_draw_buffers"); } WebGLDrawBuffers::~WebGLDrawBuffers() { } -WebGLExtension::ExtensionName WebGLDrawBuffers::name() const +WebGLExtensionName WebGLDrawBuffers::name() const { - return WebGLExtension::WebGLDrawBuffersName; + return WebGLDrawBuffersName; } -PassRefPtr<WebGLDrawBuffers> WebGLDrawBuffers::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDrawBuffers> WebGLDrawBuffers::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDrawBuffers(context)); } // static -bool WebGLDrawBuffers::supported(WebGLRenderingContext* context) +bool WebGLDrawBuffers::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return (extensions->supports("GL_EXT_draw_buffers") + return (context->extensionsUtil()->supportsExtension("GL_EXT_draw_buffers") && satisfiesWebGLRequirements(context)); } @@ -65,12 +62,12 @@ const char* WebGLDrawBuffers::extensionName() return "WEBGL_draw_buffers"; } -void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) +void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GLenum>& buffers) { if (isLost()) return; - GC3Dsizei n = buffers.size(); - const GC3Denum* bufs = buffers.data(); + GLsizei n = buffers.size(); + const GLenum* bufs = buffers.data(); if (!m_context->m_framebufferBinding) { if (n != 1) { m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer"); @@ -81,16 +78,16 @@ void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) return; } // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0. - GC3Denum value = (bufs[0] == GL_BACK) ? GL_COLOR_ATTACHMENT0 : GL_NONE; - m_context->graphicsContext3D()->extensions()->drawBuffersEXT(1, &value); + GLenum value = (bufs[0] == GL_BACK) ? GL_COLOR_ATTACHMENT0 : GL_NONE; + m_context->webContext()->drawBuffersEXT(1, &value); m_context->setBackDrawBuffer(bufs[0]); } else { if (n > m_context->maxDrawBuffers()) { m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than max draw buffers"); return; } - for (GC3Dsizei i = 0; i < n; ++i) { - if (bufs[i] != GL_NONE && bufs[i] != static_cast<GC3Denum>(Extensions3D::COLOR_ATTACHMENT0_EXT + i)) { + for (GLsizei i = 0; i < n; ++i) { + if (bufs[i] != GL_NONE && bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i)) { m_context->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "COLOR_ATTACHMENTi_EXT or NONE"); return; } @@ -100,15 +97,16 @@ void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) } // static -bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglContext) +bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase* webglContext) { - GraphicsContext3D* context = webglContext->graphicsContext3D(); + blink::WebGraphicsContext3D* context = webglContext->webContext(); + Extensions3DUtil* extensionsUtil = webglContext->extensionsUtil(); // This is called after we make sure GL_EXT_draw_buffers is supported. - GC3Dint maxDrawBuffers = 0; - GC3Dint maxColorAttachments = 0; - context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); - context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments); + GLint maxDrawBuffers = 0; + GLint maxColorAttachments = 0; + context->getIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); + context->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments); if (maxDrawBuffers < 4 || maxColorAttachments < 4) return false; @@ -116,11 +114,11 @@ bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglCo context->bindFramebuffer(GL_FRAMEBUFFER, fbo); const unsigned char* buffer = 0; // Chromium doesn't allow init data for depth/stencil tetxures. - bool supportsDepth = (context->extensions()->supports("GL_CHROMIUM_depth_texture") - || context->extensions()->supports("GL_OES_depth_texture") - || context->extensions()->supports("GL_ARB_depth_texture")); - bool supportsDepthStencil = (context->extensions()->supports("GL_EXT_packed_depth_stencil") - || context->extensions()->supports("GL_OES_packed_depth_stencil")); + bool supportsDepth = (extensionsUtil->supportsExtension("GL_CHROMIUM_depth_texture") + || extensionsUtil->supportsExtension("GL_OES_depth_texture") + || extensionsUtil->supportsExtension("GL_ARB_depth_texture")); + bool supportsDepthStencil = (extensionsUtil->supportsExtension("GL_EXT_packed_depth_stencil") + || extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil")); Platform3DObject depthStencil = 0; if (supportsDepthStencil) { depthStencil = context->createTexture(); @@ -136,8 +134,8 @@ bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglCo Vector<Platform3DObject> colors; bool ok = true; - GC3Dint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments); - for (GC3Dint i = 0; i < maxAllowedBuffers; ++i) { + GLint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments); + for (GLint i = 0; i < maxAllowedBuffers; ++i) { Platform3DObject color = context->createTexture(); colors.append(color); context->bindTexture(GL_TEXTURE_2D, color); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h index 58e14f12483..be66f91c99d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h @@ -32,21 +32,21 @@ namespace WebCore { -class WebGLDrawBuffers : public WebGLExtension, public ScriptWrappable { +class WebGLDrawBuffers FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLDrawBuffers> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDrawBuffers> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDrawBuffers(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; - void drawBuffersWEBGL(const Vector<GC3Denum>& buffers); + void drawBuffersWEBGL(const Vector<GLenum>& buffers); private: - WebGLDrawBuffers(WebGLRenderingContext*); + WebGLDrawBuffers(WebGLRenderingContextBase*); - static bool satisfiesWebGLRequirements(WebGLRenderingContext*); + static bool satisfiesWebGLRequirements(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp index 9d3c9413c61..73efb94233b 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp @@ -29,7 +29,7 @@ namespace WebCore { -WebGLExtension::WebGLExtension(WebGLRenderingContext* context) +WebGLExtension::WebGLExtension(WebGLRenderingContextBase* context) : m_context(context) { } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h index 1bd4c8bcae9..66e072ed2de 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h @@ -26,7 +26,8 @@ #ifndef WebGLExtension_h #define WebGLExtension_h -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLExtensionName.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "wtf/RefCounted.h" namespace WebCore { @@ -34,36 +35,14 @@ namespace WebCore { class WebGLExtension : public RefCounted<WebGLExtension> { WTF_MAKE_FAST_ALLOCATED; public: - // Extension names are needed to properly wrap instances in JavaScript objects. - enum ExtensionName { - ANGLEInstancedArraysName, - EXTFragDepthName, - EXTTextureFilterAnisotropicName, - OESElementIndexUintName, - OESStandardDerivativesName, - OESTextureFloatLinearName, - OESTextureFloatName, - OESTextureHalfFloatLinearName, - OESTextureHalfFloatName, - OESVertexArrayObjectName, - WebGLCompressedTextureATCName, - WebGLCompressedTexturePVRTCName, - WebGLCompressedTextureS3TCName, - WebGLDebugRendererInfoName, - WebGLDebugShadersName, - WebGLDepthTextureName, - WebGLDrawBuffersName, - WebGLLoseContextName, - }; - - WebGLRenderingContext* context() { return m_context; } + WebGLRenderingContextBase* context() { return m_context; } virtual ~WebGLExtension(); - virtual ExtensionName name() const = 0; + virtual WebGLExtensionName name() const = 0; // Lose this extension. Passing true = force loss. Some extensions // like WEBGL_lose_context are not normally lost when the context - // is lost but must be lost when destroying their WebGLRenderingContext. + // is lost but must be lost when destroying their WebGLRenderingContextBase. virtual void lose(bool) { m_context = 0; @@ -75,9 +54,9 @@ public: } protected: - WebGLExtension(WebGLRenderingContext*); + WebGLExtension(WebGLRenderingContextBase*); - WebGLRenderingContext* m_context; + WebGLRenderingContextBase* m_context; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtensionName.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtensionName.h new file mode 100644 index 00000000000..6946fb1cd96 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtensionName.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebGLExtensionName_h +#define WebGLExtensionName_h + +namespace WebCore { + +// Extension names are needed to properly wrap instances in JavaScript objects. +enum WebGLExtensionName { + ANGLEInstancedArraysName, + EXTBlendMinMaxName, + EXTFragDepthName, + EXTShaderTextureLODName, + EXTTextureFilterAnisotropicName, + OESElementIndexUintName, + OESStandardDerivativesName, + OESTextureFloatLinearName, + OESTextureFloatName, + OESTextureHalfFloatLinearName, + OESTextureHalfFloatName, + OESVertexArrayObjectName, + WebGLCompressedTextureATCName, + WebGLCompressedTextureETC1Name, + WebGLCompressedTexturePVRTCName, + WebGLCompressedTextureS3TCName, + WebGLDebugRendererInfoName, + WebGLDebugShadersName, + WebGLDepthTextureName, + WebGLDrawBuffersName, + WebGLLoseContextName, + WebGLExtensionNameCount, // Must be the last entry +}; + +} + +#endif // WebGLExtensionName_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp index 7ab97df91d1..e968a306e5d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp @@ -27,9 +27,8 @@ #include "core/html/canvas/WebGLFramebuffer.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "platform/NotImplemented.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { @@ -40,24 +39,22 @@ namespace { return object ? object->object() : 0; } - class WebGLRenderbufferAttachment : public WebGLFramebuffer::WebGLAttachment { + class WebGLRenderbufferAttachment FINAL : public WebGLFramebuffer::WebGLAttachment { public: static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLRenderbuffer*); private: WebGLRenderbufferAttachment(WebGLRenderbuffer*); - virtual GC3Dsizei width() const; - virtual GC3Dsizei height() const; - virtual GC3Denum format() const; - virtual GC3Denum type() const; - virtual WebGLSharedObject* object() const; - virtual bool isSharedObject(WebGLSharedObject*) const; - virtual bool valid() const; - virtual bool initialized() const; - virtual void setInitialized(); - virtual void onDetached(GraphicsContext3D*); - virtual void attach(GraphicsContext3D*, GC3Denum attachment); - virtual void unattach(GraphicsContext3D*, GC3Denum attachment); + virtual GLsizei width() const OVERRIDE; + virtual GLsizei height() const OVERRIDE; + virtual GLenum format() const OVERRIDE; + virtual GLenum type() const OVERRIDE; + virtual WebGLSharedObject* object() const OVERRIDE; + virtual bool isSharedObject(WebGLSharedObject*) const OVERRIDE; + virtual bool valid() const OVERRIDE; + virtual void onDetached(blink::WebGraphicsContext3D*) OVERRIDE; + virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; + virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; WebGLRenderbufferAttachment() { }; @@ -74,19 +71,19 @@ namespace { { } - GC3Dsizei WebGLRenderbufferAttachment::width() const + GLsizei WebGLRenderbufferAttachment::width() const { return m_renderbuffer->width(); } - GC3Dsizei WebGLRenderbufferAttachment::height() const + GLsizei WebGLRenderbufferAttachment::height() const { return m_renderbuffer->height(); } - GC3Denum WebGLRenderbufferAttachment::format() const + GLenum WebGLRenderbufferAttachment::format() const { - GC3Denum format = m_renderbuffer->internalFormat(); + GLenum format = m_renderbuffer->internalFormat(); if (format == GL_DEPTH_STENCIL_OES && m_renderbuffer->emulatedStencilBuffer() && m_renderbuffer->emulatedStencilBuffer()->internalFormat() != GL_STENCIL_INDEX8) { @@ -110,23 +107,12 @@ namespace { return m_renderbuffer->object(); } - bool WebGLRenderbufferAttachment::initialized() const - { - return m_renderbuffer->object() && m_renderbuffer->initialized(); - } - - void WebGLRenderbufferAttachment::setInitialized() - { - if (m_renderbuffer->object()) - m_renderbuffer->setInitialized(); - } - - void WebGLRenderbufferAttachment::onDetached(GraphicsContext3D* context) + void WebGLRenderbufferAttachment::onDetached(blink::WebGraphicsContext3D* context) { m_renderbuffer->onDetached(context); } - void WebGLRenderbufferAttachment::attach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLRenderbufferAttachment::attach(blink::WebGraphicsContext3D* context, GLenum attachment) { Platform3DObject object = objectOrZero(m_renderbuffer.get()); if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL && m_renderbuffer->emulatedStencilBuffer()) { @@ -137,7 +123,7 @@ namespace { } } - void WebGLRenderbufferAttachment::unattach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLRenderbufferAttachment::unattach(blink::WebGraphicsContext3D* context, GLenum attachment) { if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); @@ -147,61 +133,59 @@ namespace { } } - GC3Denum WebGLRenderbufferAttachment::type() const + GLenum WebGLRenderbufferAttachment::type() const { notImplemented(); return 0; } - class WebGLTextureAttachment : public WebGLFramebuffer::WebGLAttachment { + class WebGLTextureAttachment FINAL : public WebGLFramebuffer::WebGLAttachment { public: - static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture*, GC3Denum target, GC3Dint level); + static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture*, GLenum target, GLint level); private: - WebGLTextureAttachment(WebGLTexture*, GC3Denum target, GC3Dint level); - virtual GC3Dsizei width() const; - virtual GC3Dsizei height() const; - virtual GC3Denum format() const; - virtual GC3Denum type() const; - virtual WebGLSharedObject* object() const; - virtual bool isSharedObject(WebGLSharedObject*) const; - virtual bool valid() const; - virtual bool initialized() const; - virtual void setInitialized(); - virtual void onDetached(GraphicsContext3D*); - virtual void attach(GraphicsContext3D*, GC3Denum attachment); - virtual void unattach(GraphicsContext3D*, GC3Denum attachment); + WebGLTextureAttachment(WebGLTexture*, GLenum target, GLint level); + virtual GLsizei width() const OVERRIDE; + virtual GLsizei height() const OVERRIDE; + virtual GLenum format() const OVERRIDE; + virtual GLenum type() const OVERRIDE; + virtual WebGLSharedObject* object() const OVERRIDE; + virtual bool isSharedObject(WebGLSharedObject*) const OVERRIDE; + virtual bool valid() const OVERRIDE; + virtual void onDetached(blink::WebGraphicsContext3D*) OVERRIDE; + virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; + virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; WebGLTextureAttachment() { }; RefPtr<WebGLTexture> m_texture; - GC3Denum m_target; - GC3Dint m_level; + GLenum m_target; + GLint m_level; }; - PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create(WebGLTexture* texture, GC3Denum target, GC3Dint level) + PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create(WebGLTexture* texture, GLenum target, GLint level) { return adoptRef(new WebGLTextureAttachment(texture, target, level)); } - WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture, GC3Denum target, GC3Dint level) + WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture, GLenum target, GLint level) : m_texture(texture) , m_target(target) , m_level(level) { } - GC3Dsizei WebGLTextureAttachment::width() const + GLsizei WebGLTextureAttachment::width() const { return m_texture->getWidth(m_target, m_level); } - GC3Dsizei WebGLTextureAttachment::height() const + GLsizei WebGLTextureAttachment::height() const { return m_texture->getHeight(m_target, m_level); } - GC3Denum WebGLTextureAttachment::format() const + GLenum WebGLTextureAttachment::format() const { return m_texture->getInternalFormat(m_target, m_level); } @@ -221,29 +205,18 @@ namespace { return m_texture->object(); } - bool WebGLTextureAttachment::initialized() const - { - // Textures are assumed to be initialized. - return true; - } - - void WebGLTextureAttachment::setInitialized() - { - // Textures are assumed to be initialized. - } - - void WebGLTextureAttachment::onDetached(GraphicsContext3D* context) + void WebGLTextureAttachment::onDetached(blink::WebGraphicsContext3D* context) { m_texture->onDetached(context); } - void WebGLTextureAttachment::attach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLTextureAttachment::attach(blink::WebGraphicsContext3D* context, GLenum attachment) { Platform3DObject object = objectOrZero(m_texture.get()); context->framebufferTexture2D(GL_FRAMEBUFFER, attachment, m_target, object, m_level); } - void WebGLTextureAttachment::unattach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLTextureAttachment::unattach(blink::WebGraphicsContext3D* context, GLenum attachment) { if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_target, 0, m_level); @@ -253,12 +226,12 @@ namespace { } } - GC3Denum WebGLTextureAttachment::type() const + GLenum WebGLTextureAttachment::type() const { return m_texture->getType(m_target, m_level); } - bool isColorRenderable(GC3Denum internalformat) + bool isColorRenderable(GLenum internalformat) { switch (internalformat) { case GL_RGBA4: @@ -280,17 +253,17 @@ WebGLFramebuffer::WebGLAttachment::~WebGLAttachment() { } -PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLFramebuffer(ctx)); } -WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx) +WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx) : WebGLContextObject(ctx) , m_hasEverBeenBound(false) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createFramebuffer()); + setObject(ctx->webContext()->createFramebuffer()); } WebGLFramebuffer::~WebGLFramebuffer() @@ -298,7 +271,7 @@ WebGLFramebuffer::~WebGLFramebuffer() deleteObject(0); } -void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture* texture, GC3Dint level) +void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum attachment, GLenum texTarget, WebGLTexture* texture, GLint level) { ASSERT(isBound()); removeAttachmentFromBoundFramebuffer(attachment); @@ -311,7 +284,7 @@ void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3 } } -void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer* renderbuffer) +void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum attachment, WebGLRenderbuffer* renderbuffer) { ASSERT(isBound()); removeAttachmentFromBoundFramebuffer(attachment); @@ -324,15 +297,15 @@ void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, Web } } -void WebGLFramebuffer::attach(GC3Denum attachment, GC3Denum attachmentPoint) +void WebGLFramebuffer::attach(GLenum attachment, GLenum attachmentPoint) { ASSERT(isBound()); WebGLAttachment* attachmentObject = getAttachment(attachment); if (attachmentObject) - attachmentObject->attach(context()->graphicsContext3D(), attachmentPoint); + attachmentObject->attach(context()->webContext(), attachmentPoint); } -WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GC3Denum attachment) const +WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GLenum attachment) const { if (!object()) return 0; @@ -340,12 +313,12 @@ WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GC3Denum attachment) co return attachmentObject ? attachmentObject->object() : 0; } -bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3Denum attachment, const char** reason) const +bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GLenum attachment, const char** reason) const { ASSERT(attachedObject && attachedObject->valid()); ASSERT(reason); - GC3Denum internalformat = attachedObject->format(); + GLenum internalformat = attachedObject->format(); WebGLSharedObject* object = attachedObject->object(); ASSERT(object && (object->isTexture() || object->isRenderbuffer())); @@ -356,8 +329,8 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 return false; } } else if (object->isTexture()) { - GC3Denum type = attachedObject->type(); - if (!(context()->m_webglDepthTexture && internalformat == GL_DEPTH_COMPONENT + GLenum type = attachedObject->type(); + if (!(context()->extensionEnabled(WebGLDepthTextureName) && internalformat == GL_DEPTH_COMPONENT && (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT))) { *reason = "the attached texture is not a depth texture"; return false; @@ -379,23 +352,23 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 return false; } } else if (object->isTexture()) { - GC3Denum type = attachedObject->type(); - if (!(context()->m_webglDepthTexture && internalformat == GL_DEPTH_STENCIL_OES + GLenum type = attachedObject->type(); + if (!(context()->extensionEnabled(WebGLDepthTextureName) && internalformat == GL_DEPTH_STENCIL_OES && type == GL_UNSIGNED_INT_24_8_OES)) { *reason = "the attached texture is not a DEPTH_STENCIL texture"; return false; } } } else if (attachment == GL_COLOR_ATTACHMENT0 - || (context()->m_webglDrawBuffers && attachment > GL_COLOR_ATTACHMENT0 - && attachment < static_cast<GC3Denum>(GL_COLOR_ATTACHMENT0 + context()->maxColorAttachments()))) { + || (context()->extensionEnabled(WebGLDrawBuffersName) && attachment > GL_COLOR_ATTACHMENT0 + && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + context()->maxColorAttachments()))) { if (object->isRenderbuffer()) { if (!isColorRenderable(internalformat)) { *reason = "the internalformat of the attached renderbuffer is not color-renderable"; return false; } } else if (object->isTexture()) { - GC3Denum type = attachedObject->type(); + GLenum type = attachedObject->type(); if (internalformat != GL_RGBA && internalformat != GL_RGB) { *reason = "the internalformat of the attached texture is not color-renderable"; return false; @@ -408,8 +381,8 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 && type != GL_UNSIGNED_SHORT_5_6_5 && type != GL_UNSIGNED_SHORT_4_4_4_4 && type != GL_UNSIGNED_SHORT_5_5_5_1 - && !(type == GL_FLOAT && context()->m_oesTextureFloat) - && !(type == GL_HALF_FLOAT_OES && context()->m_oesTextureHalfFloat)) { + && !(type == GL_FLOAT && context()->extensionEnabled(OESTextureFloatName)) + && !(type == GL_HALF_FLOAT_OES && context()->extensionEnabled(OESTextureHalfFloatName))) { *reason = "unsupported type: The attached texture is not supported to be rendered to"; return false; } @@ -426,13 +399,13 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 return true; } -WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GC3Denum attachment) const +WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GLenum attachment) const { const AttachmentMap::const_iterator it = m_attachments.find(attachment); return (it != m_attachments.end()) ? it->value.get() : 0; } -void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GC3Denum attachment) +void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum attachment) { ASSERT(isBound()); if (!object()) @@ -440,7 +413,7 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GC3Denum attachment) WebGLAttachment* attachmentObject = getAttachment(attachment); if (attachmentObject) { - attachmentObject->onDetached(context()->graphicsContext3D()); + attachmentObject->onDetached(context()->webContext()); m_attachments.remove(attachment); drawBuffersIfNecessary(false); switch (attachment) { @@ -472,8 +445,8 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLSharedObject* a for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) { WebGLAttachment* attachmentObject = it->value.get(); if (attachmentObject->isSharedObject(attachment)) { - GC3Denum attachmentType = it->key; - attachmentObject->unattach(context()->graphicsContext3D(), attachmentType); + GLenum attachmentType = it->key; + attachmentObject->unattach(context()->webContext(), attachmentType); removeAttachmentFromBoundFramebuffer(attachmentType); checkMore = true; break; @@ -482,29 +455,7 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLSharedObject* a } } -GC3Dsizei WebGLFramebuffer::colorBufferWidth() const -{ - if (!object()) - return 0; - WebGLAttachment* attachment = getAttachment(GL_COLOR_ATTACHMENT0); - if (!attachment) - return 0; - - return attachment->width(); -} - -GC3Dsizei WebGLFramebuffer::colorBufferHeight() const -{ - if (!object()) - return 0; - WebGLAttachment* attachment = getAttachment(GL_COLOR_ATTACHMENT0); - if (!attachment) - return 0; - - return attachment->height(); -} - -GC3Denum WebGLFramebuffer::colorBufferFormat() const +GLenum WebGLFramebuffer::colorBufferFormat() const { if (!object()) return 0; @@ -514,10 +465,10 @@ GC3Denum WebGLFramebuffer::colorBufferFormat() const return attachment->format(); } -GC3Denum WebGLFramebuffer::checkStatus(const char** reason) const +GLenum WebGLFramebuffer::checkStatus(const char** reason) const { - unsigned int count = 0; - GC3Dsizei width = 0, height = 0; + unsigned count = 0; + GLsizei width = 0, height = 0; bool haveDepth = false; bool haveStencil = false; bool haveDepthStencil = false; @@ -571,7 +522,7 @@ GC3Denum WebGLFramebuffer::checkStatus(const char** reason) const return GL_FRAMEBUFFER_COMPLETE; } -bool WebGLFramebuffer::onAccess(GraphicsContext3D* context3d, const char** reason) +bool WebGLFramebuffer::onAccess(blink::WebGraphicsContext3D* context3d, const char** reason) { if (checkStatus(reason) != GL_FRAMEBUFFER_COMPLETE) return false; @@ -586,7 +537,7 @@ bool WebGLFramebuffer::hasStencilBuffer() const return attachment && attachment->valid(); } -void WebGLFramebuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLFramebuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) it->value->onDetached(context3d); @@ -599,7 +550,7 @@ bool WebGLFramebuffer::isBound() const return (context()->m_framebufferBinding.get() == this); } -void WebGLFramebuffer::drawBuffers(const Vector<GC3Denum>& bufs) +void WebGLFramebuffer::drawBuffers(const Vector<GLenum>& bufs) { m_drawBuffers = bufs; m_filteredDrawBuffers.resize(m_drawBuffers.size()); @@ -610,7 +561,7 @@ void WebGLFramebuffer::drawBuffers(const Vector<GC3Denum>& bufs) void WebGLFramebuffer::drawBuffersIfNecessary(bool force) { - if (!context()->m_webglDrawBuffers) + if (!context()->extensionEnabled(WebGLDrawBuffersName)) return; bool reset = force; // This filtering works around graphics driver bugs on Mac OS X. @@ -628,18 +579,18 @@ void WebGLFramebuffer::drawBuffersIfNecessary(bool force) } } if (reset) { - context()->graphicsContext3D()->extensions()->drawBuffersEXT( + context()->webContext()->drawBuffersEXT( m_filteredDrawBuffers.size(), m_filteredDrawBuffers.data()); } } -GC3Denum WebGLFramebuffer::getDrawBuffer(GC3Denum drawBuffer) +GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) { - int index = static_cast<int>(drawBuffer - Extensions3D::DRAW_BUFFER0_EXT); + int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT); ASSERT(index >= 0); if (index < static_cast<int>(m_drawBuffers.size())) return m_drawBuffers[index]; - if (drawBuffer == Extensions3D::DRAW_BUFFER0_EXT) + if (drawBuffer == GL_DRAW_BUFFER0_EXT) return GL_COLOR_ATTACHMENT0; return GL_NONE; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h index 86e2aebf4e8..e8705e61187 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h @@ -37,28 +37,26 @@ namespace WebCore { class WebGLRenderbuffer; class WebGLTexture; -class WebGLFramebuffer : public WebGLContextObject, public ScriptWrappable { +class WebGLFramebuffer FINAL : public WebGLContextObject, public ScriptWrappable { public: class WebGLAttachment : public RefCounted<WebGLAttachment> { public: virtual ~WebGLAttachment(); - virtual GC3Dsizei width() const = 0; - virtual GC3Dsizei height() const = 0; - virtual GC3Denum format() const = 0; + virtual GLsizei width() const = 0; + virtual GLsizei height() const = 0; + virtual GLenum format() const = 0; // For texture attachment, type() returns the type of the attached texture. // For renderbuffer attachment, the type of the renderbuffer may vary with GL implementation. // To avoid confusion, it would be better to not implement type() for renderbuffer attachment and // we should always use the internalformat of the renderbuffer and avoid using type() API. - virtual GC3Denum type() const = 0; + virtual GLenum type() const = 0; virtual WebGLSharedObject* object() const = 0; virtual bool isSharedObject(WebGLSharedObject*) const = 0; virtual bool valid() const = 0; - virtual bool initialized() const = 0; - virtual void setInitialized() = 0; - virtual void onDetached(GraphicsContext3D*) = 0; - virtual void attach(GraphicsContext3D*, GC3Denum attachment) = 0; - virtual void unattach(GraphicsContext3D*, GC3Denum attachment) = 0; + virtual void onDetached(blink::WebGraphicsContext3D*) = 0; + virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) = 0; + virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) = 0; protected: WebGLAttachment(); @@ -66,33 +64,29 @@ public: virtual ~WebGLFramebuffer(); - static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*); + static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContextBase*); - void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level); - void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*); + void setAttachmentForBoundFramebuffer(GLenum attachment, GLenum texTarget, WebGLTexture*, GLint level); + void setAttachmentForBoundFramebuffer(GLenum attachment, WebGLRenderbuffer*); // If an object is attached to the currently bound framebuffer, remove it. void removeAttachmentFromBoundFramebuffer(WebGLSharedObject*); // If a given attachment point for the currently bound framebuffer is not null, remove the attached object. - void removeAttachmentFromBoundFramebuffer(GC3Denum); - WebGLSharedObject* getAttachmentObject(GC3Denum) const; + void removeAttachmentFromBoundFramebuffer(GLenum); + WebGLSharedObject* getAttachmentObject(GLenum) const; - GC3Denum colorBufferFormat() const; - GC3Dsizei colorBufferWidth() const; - GC3Dsizei colorBufferHeight() const; + GLenum colorBufferFormat() const; // This should always be called before drawArray, drawElements, clear, // readPixels, copyTexImage2D, copyTexSubImage2D if this framebuffer is // currently bound. - // Return false if the framebuffer is incomplete; otherwise initialize - // the buffers if they haven't been initialized and - // needToInitializeAttachments is true. - bool onAccess(GraphicsContext3D*, const char** reason); + // Return false if the framebuffer is incomplete. + bool onAccess(blink::WebGraphicsContext3D*, const char** reason); // Software version of glCheckFramebufferStatus(), except that when // FRAMEBUFFER_COMPLETE is returned, it is still possible for // glCheckFramebufferStatus() to return FRAMEBUFFER_UNSUPPORTED, // depending on hardware implementation. - GC3Denum checkStatus(const char** reason) const; + GLenum checkStatus(const char** reason) const; bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; } @@ -101,38 +95,36 @@ public: bool hasStencilBuffer() const; // Wrapper for drawBuffersEXT/drawBuffersARB to work around a driver bug. - void drawBuffers(const Vector<GC3Denum>& bufs); + void drawBuffers(const Vector<GLenum>& bufs); - GC3Denum getDrawBuffer(GC3Denum); + GLenum getDrawBuffer(GLenum); protected: - WebGLFramebuffer(WebGLRenderingContext*); + WebGLFramebuffer(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isFramebuffer() const { return true; } - - WebGLAttachment* getAttachment(GC3Denum) const; - bool isAttachmentComplete(WebGLAttachment* attachedObject, GC3Denum attachment, const char** reason) const; + WebGLAttachment* getAttachment(GLenum) const; + bool isAttachmentComplete(WebGLAttachment* attachedObject, GLenum attachment, const char** reason) const; // Check if the framebuffer is currently bound. bool isBound() const; // attach 'attachment' at 'attachmentPoint'. - void attach(GC3Denum attachment, GC3Denum attachmentPoint); + void attach(GLenum attachment, GLenum attachmentPoint); // Check if a new drawBuffers call should be issued. This is called when we add or remove an attachment. void drawBuffersIfNecessary(bool force); - typedef WTF::HashMap<GC3Denum, RefPtr<WebGLAttachment> > AttachmentMap; + typedef WTF::HashMap<GLenum, RefPtr<WebGLAttachment> > AttachmentMap; AttachmentMap m_attachments; bool m_hasEverBeenBound; - Vector<GC3Denum> m_drawBuffers; - Vector<GC3Denum> m_filteredDrawBuffers; + Vector<GLenum> m_drawBuffers; + Vector<GLenum> m_filteredDrawBuffers; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp index 55cead3c16f..d4f893bc0d2 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp @@ -90,7 +90,7 @@ WebGLGetInfo::WebGLGetInfo(const String& value) { } -WebGLGetInfo::WebGLGetInfo(unsigned int value) +WebGLGetInfo::WebGLGetInfo(unsigned value) : m_type(kTypeUnsignedInt) , m_bool(false) , m_float(0) @@ -234,7 +234,7 @@ const String& WebGLGetInfo::getString() const return m_string; } -unsigned int WebGLGetInfo::getUnsignedInt() const +unsigned WebGLGetInfo::getUnsignedInt() const { ASSERT(getType() == kTypeUnsignedInt); return m_unsignedInt; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h index d72e7f9c65a..4528bb4a2b5 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h @@ -78,7 +78,7 @@ public: // Represents the null value and type. WebGLGetInfo(); explicit WebGLGetInfo(const String& value); - explicit WebGLGetInfo(unsigned int value); + explicit WebGLGetInfo(unsigned value); explicit WebGLGetInfo(PassRefPtr<WebGLBuffer> value); explicit WebGLGetInfo(PassRefPtr<Float32Array> value); explicit WebGLGetInfo(PassRefPtr<WebGLFramebuffer> value); @@ -99,7 +99,7 @@ public: float getFloat() const; int getInt() const; const String& getString() const; - unsigned int getUnsignedInt() const; + unsigned getUnsignedInt() const; PassRefPtr<WebGLBuffer> getWebGLBuffer() const; PassRefPtr<Float32Array> getWebGLFloatArray() const; PassRefPtr<WebGLFramebuffer> getWebGLFramebuffer() const; @@ -120,7 +120,7 @@ private: float m_float; int m_int; String m_string; - unsigned int m_unsignedInt; + unsigned m_unsignedInt; RefPtr<WebGLBuffer> m_webglBuffer; RefPtr<Float32Array> m_webglFloatArray; RefPtr<WebGLFramebuffer> m_webglFramebuffer; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp index ca1226a9ba2..e2fe7bd738d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp @@ -27,11 +27,11 @@ #include "core/html/canvas/WebGLLoseContext.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLLoseContext::WebGLLoseContext(WebGLRenderingContext* context) +WebGLLoseContext::WebGLLoseContext(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); @@ -47,12 +47,12 @@ void WebGLLoseContext::lose(bool force) WebGLExtension::lose(true); } -WebGLExtension::ExtensionName WebGLLoseContext::name() const +WebGLExtensionName WebGLLoseContext::name() const { return WebGLLoseContextName; } -PassRefPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContext* context) +PassRefPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLLoseContext(context)); } @@ -60,7 +60,7 @@ PassRefPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContext* con void WebGLLoseContext::loseContext() { if (!isLost()) - m_context->forceLostContext(WebGLRenderingContext::SyntheticLostContext); + m_context->forceLostContext(WebGLRenderingContextBase::SyntheticLostContext); } void WebGLLoseContext::restoreContext() @@ -69,7 +69,7 @@ void WebGLLoseContext::restoreContext() m_context->forceRestoreContext(); } -bool WebGLLoseContext::supported(WebGLRenderingContext*) +bool WebGLLoseContext::supported(WebGLRenderingContextBase*) { return true; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h index 23140d62632..cab49f34740 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h @@ -32,23 +32,23 @@ namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; -class WebGLLoseContext : public WebGLExtension, public ScriptWrappable { +class WebGLLoseContext FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLLoseContext> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLLoseContext> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLLoseContext(); - virtual ExtensionName name() const; - virtual void lose(bool); + virtual WebGLExtensionName name() const OVERRIDE; + virtual void lose(bool) OVERRIDE; void loseContext(); void restoreContext(); private: - WebGLLoseContext(WebGLRenderingContext*); + WebGLLoseContext(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl index 1ac288f2489..117fcf221ec 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl @@ -24,8 +24,9 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + TypeChecking=Interface|Nullable, ] interface WebGLLoseContext { - [StrictTypeChecking] void loseContext(); - [StrictTypeChecking] void restoreContext(); + void loseContext(); + void restoreContext(); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp index 3ffddaad3fd..14dd8ba5ee8 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp @@ -29,7 +29,7 @@ namespace WebCore { -WebGLObject::WebGLObject(WebGLRenderingContext*) +WebGLObject::WebGLObject(WebGLRenderingContextBase*) : m_object(0) , m_attachmentCount(0) , m_deleted(false) @@ -47,7 +47,7 @@ void WebGLObject::setObject(Platform3DObject object) m_object = object; } -void WebGLObject::deleteObject(GraphicsContext3D* context3d) +void WebGLObject::deleteObject(blink::WebGraphicsContext3D* context3d) { m_deleted = true; if (!m_object) @@ -58,7 +58,7 @@ void WebGLObject::deleteObject(GraphicsContext3D* context3d) if (!m_attachmentCount) { if (!context3d) - context3d = getAGraphicsContext3D(); + context3d = getAWebGraphicsContext3D(); if (context3d) deleteObjectImpl(context3d, m_object); @@ -73,7 +73,7 @@ void WebGLObject::detach() } -void WebGLObject::onDetached(GraphicsContext3D* context3d) +void WebGLObject::onDetached(blink::WebGraphicsContext3D* context3d) { if (m_attachmentCount) --m_attachmentCount; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h index 55a7d51e2da..ae5c439c8a6 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h @@ -26,14 +26,17 @@ #ifndef WebGLObject_h #define WebGLObject_h -#include "platform/graphics/GraphicsContext3D.h" +#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/RefCounted.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace WebCore { -class GraphicsContext3D; class WebGLContextGroup; -class WebGLRenderingContext; +class WebGLRenderingContextBase; class WebGLObject : public RefCounted<WebGLObject> { public: @@ -44,10 +47,10 @@ public: // deleteObject may not always delete the OpenGL resource. For programs and // shaders, deletion is delayed until they are no longer attached. // FIXME: revisit this when resource sharing between contexts are implemented. - void deleteObject(GraphicsContext3D*); + void deleteObject(blink::WebGraphicsContext3D*); void onAttached() { ++m_attachmentCount; } - void onDetached(GraphicsContext3D*); + void onDetached(blink::WebGraphicsContext3D*); // This indicates whether the client side issue a delete call already, not // whether the OpenGL resource is deleted. @@ -55,22 +58,22 @@ public: bool isDeleted() { return m_deleted; } // True if this object belongs to the group or context. - virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContext*) const = 0; + virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase*) const = 0; protected: - WebGLObject(WebGLRenderingContext*); + WebGLObject(WebGLRenderingContextBase*); // setObject should be only called once right after creating a WebGLObject. void setObject(Platform3DObject); // deleteObjectImpl should be only called once to delete the OpenGL resource. - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) = 0; + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) = 0; virtual bool hasGroupOrContext() const = 0; virtual void detach(); - virtual GraphicsContext3D* getAGraphicsContext3D() const = 0; + virtual blink::WebGraphicsContext3D* getAWebGraphicsContext3D() const = 0; private: Platform3DObject m_object; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp index 6a1539331f9..e1e49594139 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp @@ -27,23 +27,23 @@ #include "core/html/canvas/WebGLProgram.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLProgram(ctx)); } -WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx) +WebGLProgram::WebGLProgram(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_linkStatus(false) , m_linkCount(0) , m_infoValid(true) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createProgram()); + setObject(ctx->webContext()->createProgram()); } WebGLProgram::~WebGLProgram() @@ -51,16 +51,16 @@ WebGLProgram::~WebGLProgram() deleteObject(0); } -void WebGLProgram::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject obj) +void WebGLProgram::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject obj) { context3d->deleteProgram(obj); if (m_vertexShader) { m_vertexShader->onDetached(context3d); - m_vertexShader = 0; + m_vertexShader = nullptr; } if (m_fragmentShader) { m_fragmentShader->onDetached(context3d); - m_fragmentShader = 0; + m_fragmentShader = nullptr; } } @@ -70,7 +70,7 @@ unsigned WebGLProgram::numActiveAttribLocations() return m_activeAttribLocations.size(); } -GC3Dint WebGLProgram::getActiveAttribLocation(GC3Duint index) +GLint WebGLProgram::getActiveAttribLocation(GLuint index) { cacheInfoIfNeeded(); if (index >= numActiveAttribLocations()) @@ -94,19 +94,13 @@ bool WebGLProgram::linkStatus() return m_linkStatus; } -void WebGLProgram::setLinkStatus(bool status) -{ - cacheInfoIfNeeded(); - m_linkStatus = status; -} - void WebGLProgram::increaseLinkCount() { ++m_linkCount; m_infoValid = false; } -WebGLShader* WebGLProgram::getAttachedShader(GC3Denum type) +WebGLShader* WebGLProgram::getAttachedShader(GLenum type) { switch (type) { case GL_VERTEX_SHADER: @@ -146,29 +140,29 @@ bool WebGLProgram::detachShader(WebGLShader* shader) case GL_VERTEX_SHADER: if (m_vertexShader != shader) return false; - m_vertexShader = 0; + m_vertexShader = nullptr; return true; case GL_FRAGMENT_SHADER: if (m_fragmentShader != shader) return false; - m_fragmentShader = 0; + m_fragmentShader = nullptr; return true; default: return false; } } -void WebGLProgram::cacheActiveAttribLocations(GraphicsContext3D* context3d) +void WebGLProgram::cacheActiveAttribLocations(blink::WebGraphicsContext3D* context3d) { m_activeAttribLocations.clear(); - GC3Dint numAttribs = 0; + GLint numAttribs = 0; context3d->getProgramiv(object(), GL_ACTIVE_ATTRIBUTES, &numAttribs); m_activeAttribLocations.resize(static_cast<size_t>(numAttribs)); for (int i = 0; i < numAttribs; ++i) { - ActiveInfo info; + blink::WebGraphicsContext3D::ActiveInfo info; context3d->getActiveAttrib(object(), i, info); - m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name); + m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.utf8().data()); } } @@ -180,10 +174,10 @@ void WebGLProgram::cacheInfoIfNeeded() if (!object()) return; - GraphicsContext3D* context = getAGraphicsContext3D(); + blink::WebGraphicsContext3D* context = getAWebGraphicsContext3D(); if (!context) return; - GC3Dint linkStatus = 0; + GLint linkStatus = 0; context->getProgramiv(object(), GL_LINK_STATUS, &linkStatus); m_linkStatus = linkStatus; if (m_linkStatus) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h index 5ba00e7cf70..f68b33048ae 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h @@ -34,19 +34,18 @@ namespace WebCore { -class WebGLProgram : public WebGLSharedObject, public ScriptWrappable { +class WebGLProgram FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLProgram(); - static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*); + static PassRefPtr<WebGLProgram> create(WebGLRenderingContextBase*); unsigned numActiveAttribLocations(); - GC3Dint getActiveAttribLocation(GC3Duint index); + GLint getActiveAttribLocation(GLuint index); bool isUsingVertexAttrib0(); bool linkStatus(); - void setLinkStatus(bool); unsigned linkCount() const { return m_linkCount; } @@ -56,24 +55,24 @@ public: // Also, we invalidate the cached program info. void increaseLinkCount(); - WebGLShader* getAttachedShader(GC3Denum); + WebGLShader* getAttachedShader(GLenum); bool attachShader(WebGLShader*); bool detachShader(WebGLShader*); protected: - WebGLProgram(WebGLRenderingContext*); + WebGLProgram(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isProgram() const { return true; } + virtual bool isProgram() const OVERRIDE { return true; } - void cacheActiveAttribLocations(GraphicsContext3D*); + void cacheActiveAttribLocations(blink::WebGraphicsContext3D*); void cacheInfoIfNeeded(); - Vector<GC3Dint> m_activeAttribLocations; + Vector<GLint> m_activeAttribLocations; - GC3Dint m_linkStatus; + GLint m_linkStatus; // This is used to track whether a WebGLUniformLocation belongs to this // program or not. diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp index da27596f273..76ef482e037 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp @@ -27,11 +27,11 @@ #include "core/html/canvas/WebGLRenderbuffer.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLRenderbuffer(ctx)); } @@ -41,25 +41,24 @@ WebGLRenderbuffer::~WebGLRenderbuffer() deleteObject(0); } -WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) +WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_internalFormat(GL_RGBA4) - , m_initialized(false) , m_width(0) , m_height(0) , m_hasEverBeenBound(false) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createRenderbuffer()); + setObject(ctx->webContext()->createRenderbuffer()); } -void WebGLRenderbuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLRenderbuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteRenderbuffer(object); deleteEmulatedStencilBuffer(context3d); } -void WebGLRenderbuffer::deleteEmulatedStencilBuffer(GraphicsContext3D* context3d) +void WebGLRenderbuffer::deleteEmulatedStencilBuffer(blink::WebGraphicsContext3D* context3d) { if (!m_emulatedStencilBuffer) return; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h index 95688a20d26..4c08712de63 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h @@ -32,29 +32,25 @@ namespace WebCore { -class WebGLRenderbuffer : public WebGLSharedObject, public ScriptWrappable { +class WebGLRenderbuffer FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLRenderbuffer(); - static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*); + static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContextBase*); - void setInternalFormat(GC3Denum internalformat) + void setInternalFormat(GLenum internalformat) { m_internalFormat = internalformat; - m_initialized = false; } - GC3Denum internalFormat() const { return m_internalFormat; } + GLenum internalFormat() const { return m_internalFormat; } - void setSize(GC3Dsizei width, GC3Dsizei height) + void setSize(GLsizei width, GLsizei height) { m_width = width; m_height = height; } - GC3Dsizei width() const { return m_width; } - GC3Dsizei height() const { return m_height; } - - bool initialized() const { return m_initialized; } - void setInitialized() { m_initialized = true; } + GLsizei width() const { return m_width; } + GLsizei height() const { return m_height; } bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; } @@ -62,19 +58,18 @@ public: void setEmulatedStencilBuffer(PassRefPtr<WebGLRenderbuffer> buffer) { m_emulatedStencilBuffer = buffer; } WebGLRenderbuffer* emulatedStencilBuffer() const { return m_emulatedStencilBuffer.get(); } - void deleteEmulatedStencilBuffer(GraphicsContext3D* context3d); + void deleteEmulatedStencilBuffer(blink::WebGraphicsContext3D* context3d); protected: - WebGLRenderbuffer(WebGLRenderingContext*); + WebGLRenderbuffer(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isRenderbuffer() const { return true; } + virtual bool isRenderbuffer() const OVERRIDE { return true; } - GC3Denum m_internalFormat; - bool m_initialized; - GC3Dsizei m_width, m_height; + GLenum m_internalFormat; + GLsizei m_width, m_height; bool m_hasEverBeenBound; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp index ed0d58811ad..e1d1c070724 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp @@ -26,17 +26,11 @@ #include "config.h" #include "core/html/canvas/WebGLRenderingContext.h" -#include "RuntimeEnabledFeatures.h" -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ExceptionState.h" -#include "core/dom/ExceptionCode.h" -#include "core/fetch/ImageResource.h" -#include "core/html/HTMLCanvasElement.h" -#include "core/html/HTMLImageElement.h" -#include "core/html/HTMLVideoElement.h" -#include "core/html/ImageData.h" +#include "core/frame/LocalFrame.h" #include "core/html/canvas/ANGLEInstancedArrays.h" +#include "core/html/canvas/EXTBlendMinMax.h" #include "core/html/canvas/EXTFragDepth.h" +#include "core/html/canvas/EXTShaderTextureLOD.h" #include "core/html/canvas/EXTTextureFilterAnisotropic.h" #include "core/html/canvas/OESElementIndexUint.h" #include "core/html/canvas/OESStandardDerivatives.h" @@ -45,458 +39,36 @@ #include "core/html/canvas/OESTextureHalfFloat.h" #include "core/html/canvas/OESTextureHalfFloatLinear.h" #include "core/html/canvas/OESVertexArrayObject.h" -#include "core/html/canvas/WebGLActiveInfo.h" -#include "core/html/canvas/WebGLBuffer.h" #include "core/html/canvas/WebGLCompressedTextureATC.h" +#include "core/html/canvas/WebGLCompressedTextureETC1.h" #include "core/html/canvas/WebGLCompressedTexturePVRTC.h" #include "core/html/canvas/WebGLCompressedTextureS3TC.h" #include "core/html/canvas/WebGLContextAttributes.h" #include "core/html/canvas/WebGLContextEvent.h" -#include "core/html/canvas/WebGLContextGroup.h" #include "core/html/canvas/WebGLDebugRendererInfo.h" #include "core/html/canvas/WebGLDebugShaders.h" #include "core/html/canvas/WebGLDepthTexture.h" #include "core/html/canvas/WebGLDrawBuffers.h" -#include "core/html/canvas/WebGLFramebuffer.h" #include "core/html/canvas/WebGLLoseContext.h" -#include "core/html/canvas/WebGLProgram.h" -#include "core/html/canvas/WebGLRenderbuffer.h" -#include "core/html/canvas/WebGLShader.h" -#include "core/html/canvas/WebGLShaderPrecisionFormat.h" -#include "core/html/canvas/WebGLTexture.h" -#include "core/html/canvas/WebGLUniformLocation.h" -#include "core/inspector/InspectorInstrumentation.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" #include "core/frame/Settings.h" #include "core/rendering/RenderBox.h" #include "platform/CheckedInt.h" #include "platform/NotImplemented.h" -#include "platform/geometry/IntSize.h" -#include "platform/graphics/Extensions3D.h" -#include "platform/graphics/UnacceleratedImageBufferSurface.h" #include "platform/graphics/gpu/DrawingBuffer.h" - -#include "wtf/PassOwnPtr.h" -#include "wtf/Uint32Array.h" -#include "wtf/text/StringBuilder.h" +#include "public/platform/Platform.h" namespace WebCore { -const double secondsBetweenRestoreAttempts = 1.0; -const int maxGLErrorsAllowedToConsole = 256; -const unsigned maxGLActiveContexts = 16; - -Vector<WebGLRenderingContext*>& WebGLRenderingContext::activeContexts() -{ - DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, activeContexts, ()); - return activeContexts; -} - -Vector<WebGLRenderingContext*>& WebGLRenderingContext::forciblyEvictedContexts() -{ - DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, forciblyEvictedContexts, ()); - return forciblyEvictedContexts; -} - -void WebGLRenderingContext::forciblyLoseOldestContext(const String& reason) -{ - size_t candidateID = oldestContextIndex(); - if (candidateID >= activeContexts().size()) - return; - - WebGLRenderingContext* candidate = activeContexts()[candidateID]; - - activeContexts().remove(candidateID); - - candidate->printWarningToConsole(reason); - InspectorInstrumentation::didFireWebGLWarning(candidate->canvas()); - - // This will call deactivateContext once the context has actually been lost. - candidate->forceLostContext(WebGLRenderingContext::SyntheticLostContext); -} - -size_t WebGLRenderingContext::oldestContextIndex() -{ - if (!activeContexts().size()) - return maxGLActiveContexts; - - WebGLRenderingContext* candidate = activeContexts().first(); - size_t candidateID = 0; - for (size_t ii = 1; ii < activeContexts().size(); ++ii) { - WebGLRenderingContext* context = activeContexts()[ii]; - if (context->graphicsContext3D() && candidate->graphicsContext3D() && context->graphicsContext3D()->lastFlushID() < candidate->graphicsContext3D()->lastFlushID()) { - candidate = context; - candidateID = ii; - } - } - - return candidateID; -} - -IntSize WebGLRenderingContext::oldestContextSize() -{ - IntSize size; - - size_t candidateID = oldestContextIndex(); - if (candidateID < activeContexts().size()) { - WebGLRenderingContext* candidate = activeContexts()[candidateID]; - size.setWidth(candidate->drawingBufferWidth()); - size.setHeight(candidate->drawingBufferHeight()); - } - - return size; -} - -void WebGLRenderingContext::activateContext(WebGLRenderingContext* context) -{ - unsigned removedContexts = 0; - while (activeContexts().size() >= maxGLActiveContexts && removedContexts < maxGLActiveContexts) { - forciblyLoseOldestContext("WARNING: Too many active WebGL contexts. Oldest context will be lost."); - removedContexts++; - } - - if (!activeContexts().contains(context)) - activeContexts().append(context); -} - -void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bool addToEvictedList) -{ - size_t position = activeContexts().find(context); - if (position != WTF::kNotFound) - activeContexts().remove(position); - - if (addToEvictedList && !forciblyEvictedContexts().contains(context)) - forciblyEvictedContexts().append(context); -} - -void WebGLRenderingContext::willDestroyContext(WebGLRenderingContext* context) -{ - size_t position = forciblyEvictedContexts().find(context); - if (position != WTF::kNotFound) - forciblyEvictedContexts().remove(position); - - deactivateContext(context, false); - - // Try to re-enable the oldest inactive contexts. - while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContexts().size()) { - WebGLRenderingContext* evictedContext = forciblyEvictedContexts().first(); - if (!evictedContext->m_restoreAllowed) { - forciblyEvictedContexts().remove(0); - continue; - } - - IntSize desiredSize = evictedContext->m_drawingBuffer->adjustSize(evictedContext->clampedCanvasSize()); - - // If there's room in the pixel budget for this context, restore it. - if (!desiredSize.isEmpty()) { - forciblyEvictedContexts().remove(0); - evictedContext->forceRestoreContext(); - activeContexts().append(evictedContext); - } - break; - } -} - -class WebGLRenderingContextEvictionManager : public ContextEvictionManager { -public: - void forciblyLoseOldestContext(const String& reason) { - WebGLRenderingContext::forciblyLoseOldestContext(reason); - }; - IntSize oldestContextSize() { - return WebGLRenderingContext::oldestContextSize(); - }; -}; - -namespace { - - class ScopedDrawingBufferBinder { - public: - ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding) - : m_drawingBuffer(drawingBuffer) - , m_framebufferBinding(framebufferBinding) - { - // Commit DrawingBuffer if needed (e.g., for multisampling) - if (!m_framebufferBinding && m_drawingBuffer) - m_drawingBuffer->commit(); - } - - ~ScopedDrawingBufferBinder() - { - // Restore DrawingBuffer if needed - if (!m_framebufferBinding && m_drawingBuffer) - m_drawingBuffer->bind(); - } - - private: - DrawingBuffer* m_drawingBuffer; - WebGLFramebuffer* m_framebufferBinding; - }; - - Platform3DObject objectOrZero(WebGLObject* object) - { - return object ? object->object() : 0; - } - - GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max) - { - if (value < min) - value = min; - if (value > max) - value = max; - return value; - } - - // Return true if a character belongs to the ASCII subset as defined in - // GLSL ES 1.0 spec section 3.1. - bool validateCharacter(unsigned char c) - { - // Printing characters are valid except " $ ` @ \ ' DEL. - if (c >= 32 && c <= 126 - && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') - return true; - // Horizontal tab, line feed, vertical tab, form feed, carriage return - // are also valid. - if (c >= 9 && c <= 13) - return true; - return false; - } - - bool isPrefixReserved(const String& name) - { - if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_")) - return true; - return false; - } - - // Strips comments from shader text. This allows non-ASCII characters - // to be used in comments without potentially breaking OpenGL - // implementations not expecting characters outside the GLSL ES set. - class StripComments { - public: - StripComments(const String& str) - : m_parseState(BeginningOfLine) - , m_sourceString(str) - , m_length(str.length()) - , m_position(0) - { - parse(); - } - - String result() - { - return m_builder.toString(); - } - - private: - bool hasMoreCharacters() const - { - return (m_position < m_length); - } - - void parse() - { - while (hasMoreCharacters()) { - process(current()); - // process() might advance the position. - if (hasMoreCharacters()) - advance(); - } - } - - void process(UChar); - - bool peek(UChar& character) const - { - if (m_position + 1 >= m_length) - return false; - character = m_sourceString[m_position + 1]; - return true; - } - - UChar current() - { - ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length); - return m_sourceString[m_position]; - } - - void advance() - { - ++m_position; - } - - static bool isNewline(UChar character) - { - // Don't attempt to canonicalize newline related characters. - return (character == '\n' || character == '\r'); - } - - void emit(UChar character) - { - m_builder.append(character); - } - - enum ParseState { - // Have not seen an ASCII non-whitespace character yet on - // this line. Possible that we might see a preprocessor - // directive. - BeginningOfLine, - - // Have seen at least one ASCII non-whitespace character - // on this line. - MiddleOfLine, - - // Handling a preprocessor directive. Passes through all - // characters up to the end of the line. Disables comment - // processing. - InPreprocessorDirective, - - // Handling a single-line comment. The comment text is - // replaced with a single space. - InSingleLineComment, - - // Handling a multi-line comment. Newlines are passed - // through to preserve line numbers. - InMultiLineComment - }; - - ParseState m_parseState; - String m_sourceString; - unsigned m_length; - unsigned m_position; - StringBuilder m_builder; - }; - - void StripComments::process(UChar c) - { - if (isNewline(c)) { - // No matter what state we are in, pass through newlines - // so we preserve line numbers. - emit(c); - - if (m_parseState != InMultiLineComment) - m_parseState = BeginningOfLine; - - return; - } - - UChar temp = 0; - switch (m_parseState) { - case BeginningOfLine: - if (WTF::isASCIISpace(c)) { - emit(c); - break; - } - - if (c == '#') { - m_parseState = InPreprocessorDirective; - emit(c); - break; - } - - // Transition to normal state and re-handle character. - m_parseState = MiddleOfLine; - process(c); - break; - - case MiddleOfLine: - if (c == '/' && peek(temp)) { - if (temp == '/') { - m_parseState = InSingleLineComment; - emit(' '); - advance(); - break; - } - - if (temp == '*') { - m_parseState = InMultiLineComment; - // Emit the comment start in case the user has - // an unclosed comment and we want to later - // signal an error. - emit('/'); - emit('*'); - advance(); - break; - } - } - - emit(c); - break; - - case InPreprocessorDirective: - // No matter what the character is, just pass it - // through. Do not parse comments in this state. This - // might not be the right thing to do long term, but it - // should handle the #error preprocessor directive. - emit(c); - break; - - case InSingleLineComment: - // The newline code at the top of this function takes care - // of resetting our state when we get out of the - // single-line comment. Swallow all other characters. - break; - - case InMultiLineComment: - if (c == '*' && peek(temp) && temp == '/') { - emit('*'); - emit('/'); - m_parseState = MiddleOfLine; - advance(); - break; - } - - // Swallow all other characters. Unclear whether we may - // want or need to just emit a space per character to try - // to preserve column numbers for debugging purposes. - break; - } - } - - GraphicsContext3D::Attributes adjustAttributes(const GraphicsContext3D::Attributes& attributes, Settings* settings) - { - GraphicsContext3D::Attributes adjustedAttributes = attributes; - if (adjustedAttributes.antialias) { - if (settings && !settings->openGLMultisamplingEnabled()) - adjustedAttributes.antialias = false; - } - - return adjustedAttributes; - } -} // namespace anonymous - -class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback { - WTF_MAKE_FAST_ALLOCATED; -public: - explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { } - virtual void onContextLost() { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); } - virtual ~WebGLRenderingContextLostCallback() {} -private: - WebGLRenderingContext* m_context; -}; - -class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback { - WTF_MAKE_FAST_ALLOCATED; -public: - explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb) : m_context(cb) { } - virtual void onErrorMessage(const String& message, GC3Dint) - { - if (m_context->m_synthesizedErrorsToConsole) - m_context->printGLErrorToConsole(message); - InspectorInstrumentation::didFireWebGLErrorOrWarning(m_context->canvas(), message); - } - virtual ~WebGLRenderingContextErrorMessageCallback() { } -private: - WebGLRenderingContext* m_context; -}; - -PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) +PassOwnPtrWillBeRawPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) { Document& document = canvas->document(); - Frame* frame = document.frame(); - if (!frame) + LocalFrame* frame = document.frame(); + if (!frame) { + canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Web page was not allowed to create a WebGL context.")); return nullptr; + } Settings* settings = frame->settings(); // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in @@ -506,29 +78,30 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen return nullptr; } - GraphicsContext3D::Attributes requestedAttributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes(); - requestedAttributes.noExtensions = true; - requestedAttributes.shareResources = true; - requestedAttributes.preferDiscreteGPU = true; - requestedAttributes.topDocumentURL = document.topDocument()->url(); - - GraphicsContext3D::Attributes attributes = adjustAttributes(requestedAttributes, settings); - - RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes)); - + // The only situation that attrs is null is through Document::getCSSCanvasContext(). + RefPtr<WebGLContextAttributes> defaultAttrs; + if (!attrs) { + defaultAttrs = WebGLContextAttributes::create(); + attrs = defaultAttrs.get(); + } + blink::WebGraphicsContext3D::Attributes attributes = attrs->attributes(document.topDocument().url().string(), settings); + OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(attributes, 0)); if (!context || !context->makeContextCurrent()) { canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context.")); return nullptr; } - Extensions3D* extensions = context->extensions(); - if (extensions->supports("GL_EXT_debug_marker")) - extensions->pushGroupMarkerEXT("WebGLRenderingContext"); + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get()); + if (!extensionsUtil) + return nullptr; + if (extensionsUtil->supportsExtension("GL_EXT_debug_marker")) + context->pushGroupMarkerEXT("WebGLRenderingContext"); - OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context, attributes, requestedAttributes)); + OwnPtrWillBeRawPtr<WebGLRenderingContext> renderingContext = adoptPtrWillBeNoop(new WebGLRenderingContext(canvas, context.release(), attrs)); + renderingContext->registerContextExtensions(); renderingContext->suspendIfNeeded(); - if (renderingContext->m_drawingBuffer->isZeroSized()) { + if (!renderingContext->m_drawingBuffer) { canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context.")); return nullptr; } @@ -536,53 +109,25 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen return renderingContext.release(); } -WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context, GraphicsContext3D::Attributes attributes, GraphicsContext3D::Attributes requestedAttributes) - : CanvasRenderingContext(passedCanvas) - , ActiveDOMObject(&passedCanvas->document()) - , m_context(context) - , m_drawingBuffer(0) - , m_dispatchContextLostEventTimer(this, &WebGLRenderingContext::dispatchContextLostEvent) - , m_restoreAllowed(false) - , m_restoreTimer(this, &WebGLRenderingContext::maybeRestoreContext) - , m_generatedImageCache(4) - , m_contextLost(false) - , m_contextLostMode(SyntheticLostContext) - , m_attributes(attributes) - , m_requestedAttributes(requestedAttributes) - , m_synthesizedErrorsToConsole(true) - , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) - , m_multisamplingAllowed(false) - , m_multisamplingObserverRegistered(false) - , m_onePlusMaxEnabledAttribIndex(0) - , m_onePlusMaxNonDefaultTextureUnit(0) +WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<blink::WebGraphicsContext3D> context, WebGLContextAttributes* requestedAttributes) + : WebGLRenderingContextBase(passedCanvas, context, requestedAttributes) { - ASSERT(m_context); ScriptWrappable::init(this); +} - m_contextGroup = WebGLContextGroup::create(); - m_contextGroup->addContext(this); - - m_maxViewportDims[0] = m_maxViewportDims[1] = 0; - m_context->getIntegerv(GL_MAX_VIEWPORT_DIMS, m_maxViewportDims); - - RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager()); - - // Create the DrawingBuffer and initialize the platform layer. - DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; - m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release()); +WebGLRenderingContext::~WebGLRenderingContext() +{ - if (!m_drawingBuffer->isZeroSized()) { - m_drawingBuffer->bind(); - setupFlags(); - initializeNewContext(); - } +} +void WebGLRenderingContext::registerContextExtensions() +{ // Register extensions. static const char* const webkitPrefix[] = { "WEBKIT_", 0, }; static const char* const bothPrefixes[] = { "", "WEBKIT_", 0, }; registerExtension<ANGLEInstancedArrays>(m_angleInstancedArrays); - registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic, PrefixedExtension, webkitPrefix); + registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic, ApprovedExtension, bothPrefixes); registerExtension<OESElementIndexUint>(m_oesElementIndexUint); registerExtension<OESStandardDerivatives>(m_oesStandardDerivatives); registerExtension<OESTextureFloat>(m_oesTextureFloat); @@ -590,5046 +135,20 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa registerExtension<OESTextureHalfFloat>(m_oesTextureHalfFloat); registerExtension<OESTextureHalfFloatLinear>(m_oesTextureHalfFloatLinear); registerExtension<OESVertexArrayObject>(m_oesVertexArrayObject); - registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, PrefixedExtension, webkitPrefix); - registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC, PrefixedExtension, webkitPrefix); - registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, PrefixedExtension, bothPrefixes); - registerExtension<WebGLDepthTexture>(m_webglDepthTexture, PrefixedExtension, bothPrefixes); + registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, EnabledDraftExtension, webkitPrefix); + registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC, EnabledDraftExtension, webkitPrefix); + registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, ApprovedExtension, bothPrefixes); + registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo); + registerExtension<WebGLDebugShaders>(m_webglDebugShaders); + registerExtension<WebGLDepthTexture>(m_webglDepthTexture, ApprovedExtension, bothPrefixes); registerExtension<WebGLDrawBuffers>(m_webglDrawBuffers); registerExtension<WebGLLoseContext>(m_webglLoseContext, ApprovedExtension, bothPrefixes); // Register draft extensions. + registerExtension<EXTBlendMinMax>(m_extBlendMinMax, DraftExtension); registerExtension<EXTFragDepth>(m_extFragDepth, DraftExtension); - - // Register privileged extensions. - registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo, WebGLDebugRendererInfoExtension); - registerExtension<WebGLDebugShaders>(m_webglDebugShaders, PrivilegedExtension); -} - -void WebGLRenderingContext::initializeNewContext() -{ - ASSERT(!isContextLost()); - m_needsUpdate = true; - m_markedCanvasDirty = false; - m_activeTextureUnit = 0; - m_packAlignment = 4; - m_unpackAlignment = 4; - m_unpackFlipY = false; - m_unpackPremultiplyAlpha = false; - m_unpackColorspaceConversion = GC3D_BROWSER_DEFAULT_WEBGL; - m_boundArrayBuffer = 0; - m_currentProgram = 0; - m_framebufferBinding = 0; - m_renderbufferBinding = 0; - m_depthMask = true; - m_stencilEnabled = false; - m_stencilMask = 0xFFFFFFFF; - m_stencilMaskBack = 0xFFFFFFFF; - m_stencilFuncRef = 0; - m_stencilFuncRefBack = 0; - m_stencilFuncMask = 0xFFFFFFFF; - m_stencilFuncMaskBack = 0xFFFFFFFF; - m_layerCleared = false; - m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole; - - m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0; - m_scissorEnabled = false; - m_clearDepth = 1; - m_clearStencil = 0; - m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true; - - GC3Dint numCombinedTextureImageUnits = 0; - m_context->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); - m_textureUnits.clear(); - m_textureUnits.resize(numCombinedTextureImageUnits); - - GC3Dint numVertexAttribs = 0; - m_context->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs); - m_maxVertexAttribs = numVertexAttribs; - - m_maxTextureSize = 0; - m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); - m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); - m_maxCubeMapTextureSize = 0; - m_context->getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); - m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); - m_maxRenderbufferSize = 0; - m_context->getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize); - - // These two values from EXT_draw_buffers are lazily queried. - m_maxDrawBuffers = 0; - m_maxColorAttachments = 0; - - m_backDrawBuffer = GL_BACK; - - m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault); - addContextObject(m_defaultVertexArrayObject.get()); - m_boundVertexArrayObject = m_defaultVertexArrayObject; - - m_vertexAttribValue.resize(m_maxVertexAttribs); - - createFallbackBlackTextures1x1(); - - IntSize canvasSize = clampedCanvasSize(); - m_drawingBuffer->reset(canvasSize); - - m_context->viewport(0, 0, canvasSize.width(), canvasSize.height()); - m_context->scissor(0, 0, canvasSize.width(), canvasSize.height()); - - m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this))); - m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMessageCallback(this))); - - // This ensures that the context has a valid "lastFlushID" and won't be mistakenly identified as the "least recently used" context. - m_context->flush(); - - activateContext(this); -} - -void WebGLRenderingContext::setupFlags() -{ - ASSERT(m_context); - if (Page* p = canvas()->document().page()) { - m_synthesizedErrorsToConsole = p->settings().webGLErrorsToConsoleEnabled(); - - if (!m_multisamplingObserverRegistered && m_requestedAttributes.antialias) { - m_multisamplingAllowed = m_drawingBuffer->multisample(); - p->addMultisamplingChangedObserver(this); - m_multisamplingObserverRegistered = true; - } - } - - m_isGLES2NPOTStrict = !m_context->extensions()->isEnabled("GL_OES_texture_npot"); - m_isDepthStencilSupported = m_context->extensions()->isEnabled("GL_OES_packed_depth_stencil"); -} - -bool WebGLRenderingContext::allowPrivilegedExtensions() const -{ - if (Page* p = canvas()->document().page()) - return p->settings().privilegedWebGLExtensionsEnabled(); - return false; -} - -bool WebGLRenderingContext::allowWebGLDebugRendererInfo() const -{ - return true; -} - -void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format) -{ - if (!m_compressedTextureFormats.contains(format)) - m_compressedTextureFormats.append(format); -} - -void WebGLRenderingContext::removeAllCompressedTextureFormats() -{ - m_compressedTextureFormats.clear(); -} - -WebGLRenderingContext::~WebGLRenderingContext() -{ - // Remove all references to WebGLObjects so if they are the last reference - // they will be freed before the last context is removed from the context group. - m_boundArrayBuffer = 0; - m_defaultVertexArrayObject = 0; - m_boundVertexArrayObject = 0; - m_vertexAttrib0Buffer = 0; - m_currentProgram = 0; - m_framebufferBinding = 0; - m_renderbufferBinding = 0; - - for (size_t i = 0; i < m_textureUnits.size(); ++i) { - m_textureUnits[i].m_texture2DBinding = 0; - m_textureUnits[i].m_textureCubeMapBinding = 0; - } - - m_blackTexture2D = 0; - m_blackTextureCubeMap = 0; - - detachAndRemoveAllObjects(); - - // release all extensions - for (size_t i = 0; i < m_extensions.size(); ++i) - delete m_extensions[i]; - - // Context must be removed from the group prior to the destruction of the - // GraphicsContext3D, otherwise shared objects may not be properly deleted. - m_contextGroup->removeContext(this); - - destroyGraphicsContext3D(); - - if (m_multisamplingObserverRegistered) { - Page* page = canvas()->document().page(); - if (page) - page->removeMultisamplingChangedObserver(this); - } - - willDestroyContext(this); -} - -void WebGLRenderingContext::destroyGraphicsContext3D() -{ - m_contextLost = true; - - // The drawing buffer holds a context reference. It must also be destroyed - // in order for the context to be released. - m_drawingBuffer->releaseResources(); - - if (m_context) { - m_context->setContextLostCallback(nullptr); - m_context->setErrorMessageCallback(nullptr); - m_context.clear(); - } -} - -void WebGLRenderingContext::markContextChanged() -{ - if (m_framebufferBinding || isContextLost()) - return; - - m_context->markContextChanged(); - m_drawingBuffer->markContentsChanged(); - - m_layerCleared = false; - RenderBox* renderBox = canvas()->renderBox(); - if (renderBox && renderBox->hasAcceleratedCompositing()) { - m_markedCanvasDirty = true; - canvas()->clearCopiedImage(); - renderBox->contentChanged(CanvasChanged); - } else { - if (!m_markedCanvasDirty) { - m_markedCanvasDirty = true; - canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize())); - } - } -} - -bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask) -{ - if (isContextLost()) - return false; - - if (!m_context->layerComposited() || m_layerCleared - || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding)) - return false; - - RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes(); - - // Determine if it's possible to combine the clear the user asked for and this clear. - bool combinedClear = mask && !m_scissorEnabled; - - m_context->disable(GL_SCISSOR_TEST); - if (combinedClear && (mask & GL_COLOR_BUFFER_BIT)) - m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0, - m_colorMask[1] ? m_clearColor[1] : 0, - m_colorMask[2] ? m_clearColor[2] : 0, - m_colorMask[3] ? m_clearColor[3] : 0); - else - m_context->clearColor(0, 0, 0, 0); - m_context->colorMask(true, true, true, true); - GC3Dbitfield clearMask = GL_COLOR_BUFFER_BIT; - if (contextAttributes->depth()) { - if (!combinedClear || !m_depthMask || !(mask & GL_DEPTH_BUFFER_BIT)) - m_context->clearDepth(1.0f); - clearMask |= GL_DEPTH_BUFFER_BIT; - m_context->depthMask(true); - } - if (contextAttributes->stencil()) { - if (combinedClear && (mask & GL_STENCIL_BUFFER_BIT)) - m_context->clearStencil(m_clearStencil & m_stencilMask); - else - m_context->clearStencil(0); - clearMask |= GL_STENCIL_BUFFER_BIT; - m_context->stencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); - } - - m_drawingBuffer->clearFramebuffers(clearMask); - - restoreStateAfterClear(); - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - m_layerCleared = true; - - return combinedClear; -} - -void WebGLRenderingContext::restoreStateAfterClear() -{ - if (isContextLost()) - return; - - // Restore the state that the context set. - if (m_scissorEnabled) - m_context->enable(GL_SCISSOR_TEST); - m_context->clearColor(m_clearColor[0], m_clearColor[1], - m_clearColor[2], m_clearColor[3]); - m_context->colorMask(m_colorMask[0], m_colorMask[1], - m_colorMask[2], m_colorMask[3]); - m_context->clearDepth(m_clearDepth); - m_context->clearStencil(m_clearStencil); - m_context->stencilMaskSeparate(GL_FRONT, m_stencilMask); - m_context->depthMask(m_depthMask); -} - -void WebGLRenderingContext::markLayerComposited() -{ - if (!isContextLost()) - m_context->markLayerComposited(); -} - -void WebGLRenderingContext::paintRenderingResultsToCanvas() -{ - if (isContextLost()) { - canvas()->clearPresentationCopy(); - return; - } - - if (canvas()->document().printing()) - canvas()->clearPresentationCopy(); - - // Until the canvas is written to by the application, the clear that - // happened after it was composited should be ignored by the compositor. - if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) { - m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer()); - - canvas()->makePresentationCopy(); - } else - canvas()->clearPresentationCopy(); - clearIfComposited(); - - if (!m_markedCanvasDirty && !m_layerCleared) - return; - - canvas()->clearCopiedImage(); - m_markedCanvasDirty = false; - - m_drawingBuffer->commit(); - if (!(canvas()->buffer())->copyRenderingResultsFromDrawingBuffer(m_drawingBuffer.get())) { - canvas()->ensureUnacceleratedImageBuffer(); - if (canvas()->hasImageBuffer()) - m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get()); - } - - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - else - m_drawingBuffer->bind(); -} - -PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData() -{ - if (isContextLost()) - return 0; - - clearIfComposited(); - m_drawingBuffer->commit(); - int width, height; - RefPtr<Uint8ClampedArray> imageDataPixels = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get(), width, height); - if (!imageDataPixels) - return 0; - - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - else - m_drawingBuffer->bind(); - - return ImageData::create(IntSize(width, height), imageDataPixels); -} - -void WebGLRenderingContext::reshape(int width, int height) -{ - if (isContextLost()) - return; - - // This is an approximation because at WebGLRenderingContext level we don't - // know if the underlying FBO uses textures or renderbuffers. - GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize); - // Limit drawing buffer size to 4k to avoid memory exhaustion. - const int sizeUpperLimit = 4096; - maxSize = std::min(maxSize, sizeUpperLimit); - GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]); - GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]); - width = clamp(width, 1, maxWidth); - height = clamp(height, 1, maxHeight); - - if (m_needsUpdate) { - RenderBox* renderBox = canvas()->renderBox(); - if (renderBox && renderBox->hasAcceleratedCompositing()) - renderBox->contentChanged(CanvasChanged); - m_needsUpdate = false; - } - - // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off - // clear (and this matches what reshape will do). - m_drawingBuffer->reset(IntSize(width, height)); - restoreStateAfterClear(); - - m_context->bindTexture(GL_TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get())); - m_context->bindRenderbuffer(GL_RENDERBUFFER, objectOrZero(m_renderbufferBinding.get())); - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); -} - -int WebGLRenderingContext::drawingBufferWidth() const -{ - return m_drawingBuffer->size().width(); -} - -int WebGLRenderingContext::drawingBufferHeight() const -{ - return m_drawingBuffer->size().height(); -} - -unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type) -{ - switch (type) { - case GL_BYTE: - return sizeof(GC3Dbyte); - case GL_UNSIGNED_BYTE: - return sizeof(GC3Dubyte); - case GL_SHORT: - return sizeof(GC3Dshort); - case GL_UNSIGNED_SHORT: - return sizeof(GC3Dushort); - case GL_INT: - return sizeof(GC3Dint); - case GL_UNSIGNED_INT: - return sizeof(GC3Duint); - case GL_FLOAT: - return sizeof(GC3Dfloat); - } - ASSERT_NOT_REACHED(); - return 0; -} - -void WebGLRenderingContext::activeTexture(GC3Denum texture) -{ - if (isContextLost()) - return; - if (texture - GL_TEXTURE0 >= m_textureUnits.size()) { - synthesizeGLError(GL_INVALID_ENUM, "activeTexture", "texture unit out of range"); - return; - } - m_activeTextureUnit = texture - GL_TEXTURE0; - m_context->activeTexture(texture); - - m_drawingBuffer->setActiveTextureUnit(texture); - -} - -void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader) -{ - if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) - return; - if (!program->attachShader(shader)) { - synthesizeGLError(GL_INVALID_OPERATION, "attachShader", "shader attachment already has shader"); - return; - } - m_context->attachShader(objectOrZero(program), objectOrZero(shader)); - shader->onAttached(); -} - -void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name) -{ - if (isContextLost() || !validateWebGLObject("bindAttribLocation", program)) - return; - if (!validateLocationLength("bindAttribLocation", name)) - return; - if (!validateString("bindAttribLocation", name)) - return; - if (isPrefixReserved(name)) { - synthesizeGLError(GL_INVALID_OPERATION, "bindAttribLocation", "reserved prefix"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "bindAttribLocation", "index out of range"); - return; - } - m_context->bindAttribLocation(objectOrZero(program), index, name); -} - -bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) -{ - deleted = false; - if (isContextLost()) - return false; - if (object) { - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "object not from this context"); - return false; - } - deleted = !object->object(); - } - return true; -} - -void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer) -{ - bool deleted; - if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) - return; - if (deleted) - buffer = 0; - if (buffer && buffer->getTarget() && buffer->getTarget() != target) { - synthesizeGLError(GL_INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets"); - return; - } - if (target == GL_ARRAY_BUFFER) - m_boundArrayBuffer = buffer; - else if (target == GL_ELEMENT_ARRAY_BUFFER) - m_boundVertexArrayObject->setElementArrayBuffer(buffer); - else { - synthesizeGLError(GL_INVALID_ENUM, "bindBuffer", "invalid target"); - return; - } - - m_context->bindBuffer(target, objectOrZero(buffer)); - if (buffer) - buffer->setTarget(target); -} - -void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer) -{ - bool deleted; - if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) - return; - if (deleted) - buffer = 0; - if (target != GL_FRAMEBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "bindFramebuffer", "invalid target"); - return; - } - m_framebufferBinding = buffer; - m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get())); - if (!m_framebufferBinding) { - // Instead of binding fb 0, bind the drawing buffer. - m_drawingBuffer->bind(); - } else - m_context->bindFramebuffer(target, objectOrZero(buffer)); - if (buffer) - buffer->setHasEverBeenBound(); - applyStencilTest(); -} - -void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer) -{ - bool deleted; - if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) - return; - if (deleted) - renderBuffer = 0; - if (target != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "bindRenderbuffer", "invalid target"); - return; - } - m_renderbufferBinding = renderBuffer; - m_context->bindRenderbuffer(target, objectOrZero(renderBuffer)); - if (renderBuffer) - renderBuffer->setHasEverBeenBound(); -} - -void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture) -{ - bool deleted; - if (!checkObjectToBeBound("bindTexture", texture, deleted)) - return; - if (deleted) - texture = 0; - if (texture && texture->getTarget() && texture->getTarget() != target) { - synthesizeGLError(GL_INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); - return; - } - GC3Dint maxLevel = 0; - if (target == GL_TEXTURE_2D) { - m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture; - maxLevel = m_maxTextureLevel; - - if (!m_activeTextureUnit) - m_drawingBuffer->setTexture2DBinding(objectOrZero(texture)); - - } else if (target == GL_TEXTURE_CUBE_MAP) { - m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture; - maxLevel = m_maxCubeMapTextureLevel; - } else { - synthesizeGLError(GL_INVALID_ENUM, "bindTexture", "invalid target"); - return; - } - - m_context->bindTexture(target, objectOrZero(texture)); - if (texture) { - texture->setTarget(target, maxLevel); - m_onePlusMaxNonDefaultTextureUnit = max(m_activeTextureUnit + 1, m_onePlusMaxNonDefaultTextureUnit); - } else { - // If the disabled index is the current maximum, trace backwards to find the new max enabled texture index - if (m_onePlusMaxNonDefaultTextureUnit == m_activeTextureUnit + 1) { - findNewMaxNonDefaultTextureUnit(); - } - } - - // Note: previously we used to automatically set the TEXTURE_WRAP_R - // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL - // ES 2.0 doesn't expose this flag (a bug in the specification) and - // otherwise the application has no control over the seams in this - // dimension. However, it appears that supporting this properly on all - // platforms is fairly involved (will require a HashMap from texture ID - // in all ports), and we have not had any complaints, so the logic has - // been removed. - -} - -void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha) -{ - if (isContextLost()) - return; - m_context->blendColor(red, green, blue, alpha); -} - -void WebGLRenderingContext::blendEquation(GC3Denum mode) -{ - if (isContextLost() || !validateBlendEquation("blendEquation", mode)) - return; - m_context->blendEquation(mode); -} - -void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - if (isContextLost() || !validateBlendEquation("blendEquationSeparate", modeRGB) || !validateBlendEquation("blendEquationSeparate", modeAlpha)) - return; - m_context->blendEquationSeparate(modeRGB, modeAlpha); -} - - -void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor) -{ - if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor)) - return; - m_context->blendFunc(sfactor, dfactor); -} - -void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - // Note: Alpha does not have the same restrictions as RGB. - if (isContextLost() || !validateBlendFuncFactors("blendFuncSeparate", srcRGB, dstRGB)) - return; - m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (size < 0) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "size < 0"); - return; - } - if (!size) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "size == 0"); - return; - } - - m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (!data) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); - return; - } - m_context->bufferData(target, data->byteLength(), data->data(), usage); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (!data) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); - return; - } - - m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage); -} - -void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GL_STATIC_DRAW); - if (!buffer) - return; - if (offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, "bufferSubData", "offset < 0"); - return; - } - if (!data) - return; - - m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data()); -} - -void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GL_STATIC_DRAW); - if (!buffer) - return; - if (offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, "bufferSubData", "offset < 0"); - return; - } - if (!data) - return; - - m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress()); -} - -GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target) -{ - if (isContextLost()) - return GL_FRAMEBUFFER_UNSUPPORTED; - if (target != GL_FRAMEBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "checkFramebufferStatus", "invalid target"); - return 0; - } - if (!m_framebufferBinding || !m_framebufferBinding->object()) - return GL_FRAMEBUFFER_COMPLETE; - const char* reason = "framebuffer incomplete"; - GC3Denum result = m_framebufferBinding->checkStatus(&reason); - if (result != GL_FRAMEBUFFER_COMPLETE) { - emitGLWarning("checkFramebufferStatus", reason); - return result; - } - result = m_context->checkFramebufferStatus(target); - return result; -} - -void WebGLRenderingContext::clear(GC3Dbitfield mask) -{ - if (isContextLost()) - return; - if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { - synthesizeGLError(GL_INVALID_VALUE, "clear", "invalid mask"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "clear", reason); - return; - } - if (!clearIfComposited(mask)) - m_context->clear(mask); - markContextChanged(); -} - -void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a) -{ - if (isContextLost()) - return; - if (std::isnan(r)) - r = 0; - if (std::isnan(g)) - g = 0; - if (std::isnan(b)) - b = 0; - if (std::isnan(a)) - a = 1; - m_clearColor[0] = r; - m_clearColor[1] = g; - m_clearColor[2] = b; - m_clearColor[3] = a; - m_context->clearColor(r, g, b, a); -} - -void WebGLRenderingContext::clearDepth(GC3Dfloat depth) -{ - if (isContextLost()) - return; - m_clearDepth = depth; - m_context->clearDepth(depth); -} - -void WebGLRenderingContext::clearStencil(GC3Dint s) -{ - if (isContextLost()) - return; - m_clearStencil = s; - m_context->clearStencil(s); -} - -void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - if (isContextLost()) - return; - m_colorMask[0] = red; - m_colorMask[1] = green; - m_colorMask[2] = blue; - m_colorMask[3] = alpha; - m_context->colorMask(red, green, blue, alpha); -} - -void WebGLRenderingContext::compileShader(WebGLShader* shader) -{ - if (isContextLost() || !validateWebGLObject("compileShader", shader)) - return; - m_context->compileShader(objectOrZero(shader)); -} - -void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, - GC3Dsizei height, GC3Dint border, ArrayBufferView* data) -{ - if (isContextLost()) - return; - if (!validateTexFuncLevel("compressedTexImage2D", target, level)) - return; - - if (!validateCompressedTexFormat(internalformat)) { - synthesizeGLError(GL_INVALID_ENUM, "compressedTexImage2D", "invalid internalformat"); - return; - } - if (border) { - synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "border not 0"); - return; - } - if (!validateCompressedTexDimensions("compressedTexImage2D", NotTexSubImage2D, target, level, width, height, internalformat)) - return; - if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data)) - return; - - WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true); - if (!tex) - return; - if (!isGLES2NPOTStrict()) { - if (level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2"); - return; - } - } - graphicsContext3D()->compressedTexImage2D(target, level, internalformat, width, height, - border, data->byteLength(), data->baseAddress()); - tex->setLevelInfo(target, level, internalformat, width, height, GL_UNSIGNED_BYTE); -} - -void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data) -{ - if (isContextLost()) - return; - if (!validateTexFuncLevel("compressedTexSubImage2D", target, level)) - return; - if (!validateCompressedTexFormat(format)) { - synthesizeGLError(GL_INVALID_ENUM, "compressedTexSubImage2D", "invalid format"); - return; - } - if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data)) - return; - - WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true); - if (!tex) - return; - - if (format != tex->getInternalFormat(target, level)) { - synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format"); - return; - } - - if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex)) - return; - - graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset, - width, height, format, data->byteLength(), data->baseAddress()); -} - -bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format) -{ - if (GraphicsContext3D::getClearBitsByFormat(format) & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "format can not be set, only rendered to"); - return false; - } - return true; -} - -void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - if (isContextLost()) - return; - if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GL_UNSIGNED_BYTE)) - return; - if (!validateSettableTexFormat("copyTexImage2D", internalformat)) - return; - WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); - if (!tex) - return; - if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { - synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); - return; - } - if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GL_INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); - return; - } - clearIfComposited(); - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border); - // FIXME: if the framebuffer is not complete, none of the below should be executed. - tex->setLevelInfo(target, level, internalformat, width, height, GL_UNSIGNED_BYTE); -} - -void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (!validateTexFuncLevel("copyTexSubImage2D", target, level)) - return; - WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true); - if (!tex) - return; - if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height)) - return; - // Before checking if it is in the range, check if overflow happens first. - Checked<GC3Dint, RecordOverflow> maxX = xoffset; - maxX += width; - Checked<GC3Dint, RecordOverflow> maxY = yoffset; - maxY += height; - - if (maxX.hasOverflowed() || maxY.hasOverflowed()) { - synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "bad dimensions"); - return; - } - if (maxX.unsafeGet() > tex->getWidth(target, level) || maxY.unsafeGet() > tex->getHeight(target, level)) { - synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range"); - return; - } - GC3Denum internalformat = tex->getInternalFormat(target, level); - if (!validateSettableTexFormat("copyTexSubImage2D", internalformat)) - return; - if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { - synthesizeGLError(GL_INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); - return; - } - clearIfComposited(); - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); -} - -PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLBuffer> o = WebGLBuffer::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this); - addContextObject(o.get()); - return o; -} - -PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLTexture> o = WebGLTexture::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLProgram> o = WebGLProgram::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this); - addSharedObject(o.get()); - return o; -} - -WebGLRenderbuffer* WebGLRenderingContext::ensureEmulatedStencilBuffer(GC3Denum target, WebGLRenderbuffer* renderbuffer) -{ - if (isContextLost()) - return 0; - if (!renderbuffer->emulatedStencilBuffer()) { - renderbuffer->setEmulatedStencilBuffer(createRenderbuffer()); - m_context->bindRenderbuffer(target, objectOrZero(renderbuffer->emulatedStencilBuffer())); - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); - } - return renderbuffer->emulatedStencilBuffer(); -} - -PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type) -{ - if (isContextLost()) - return 0; - if (type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) { - synthesizeGLError(GL_INVALID_ENUM, "createShader", "invalid shader type"); - return 0; - } - - RefPtr<WebGLShader> o = WebGLShader::create(this, type); - addSharedObject(o.get()); - return o; -} - -void WebGLRenderingContext::cullFace(GC3Denum mode) -{ - if (isContextLost()) - return; - switch (mode) { - case GL_FRONT_AND_BACK: - case GL_FRONT: - case GL_BACK: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "cullFace", "invalid mode"); - return; - } - m_context->cullFace(mode); -} - -bool WebGLRenderingContext::deleteObject(WebGLObject* object) -{ - if (isContextLost() || !object) - return false; - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, "delete", "object does not belong to this context"); - return false; - } - if (object->object()) - // We need to pass in context here because we want - // things in this context unbound. - object->deleteObject(graphicsContext3D()); - return true; -} - -void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer) -{ - if (!deleteObject(buffer)) - return; - if (m_boundArrayBuffer == buffer) - m_boundArrayBuffer = 0; - - m_boundVertexArrayObject->unbindBuffer(buffer); -} - -void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer) -{ - if (!deleteObject(framebuffer)) - return; - if (framebuffer == m_framebufferBinding) { - m_framebufferBinding = 0; - m_drawingBuffer->setFramebufferBinding(0); - // Have to call bindFramebuffer here to bind back to internal fbo. - m_drawingBuffer->bind(); - } -} - -void WebGLRenderingContext::deleteProgram(WebGLProgram* program) -{ - deleteObject(program); - // We don't reset m_currentProgram to 0 here because the deletion of the - // current program is delayed. -} - -void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) -{ - if (!deleteObject(renderbuffer)) - return; - if (renderbuffer == m_renderbufferBinding) - m_renderbufferBinding = 0; - if (m_framebufferBinding) - m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer); -} - -void WebGLRenderingContext::deleteShader(WebGLShader* shader) -{ - deleteObject(shader); -} - -void WebGLRenderingContext::deleteTexture(WebGLTexture* texture) -{ - if (!deleteObject(texture)) - return; - - int maxBoundTextureIndex = -1; - for (size_t i = 0; i < m_onePlusMaxNonDefaultTextureUnit; ++i) { - if (texture == m_textureUnits[i].m_texture2DBinding) { - m_textureUnits[i].m_texture2DBinding = 0; - maxBoundTextureIndex = i; - if (!i) - m_drawingBuffer->setTexture2DBinding(0); - } - if (texture == m_textureUnits[i].m_textureCubeMapBinding) { - m_textureUnits[i].m_textureCubeMapBinding = 0; - maxBoundTextureIndex = i; - } - } - if (m_framebufferBinding) - m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture); - - // If the deleted was bound to the the current maximum index, trace backwards to find the new max texture index - if (m_onePlusMaxNonDefaultTextureUnit == static_cast<unsigned long>(maxBoundTextureIndex + 1)) { - findNewMaxNonDefaultTextureUnit(); - } -} - -void WebGLRenderingContext::depthFunc(GC3Denum func) -{ - if (isContextLost()) - return; - if (!validateStencilOrDepthFunc("depthFunc", func)) - return; - m_context->depthFunc(func); -} - -void WebGLRenderingContext::depthMask(GC3Dboolean flag) -{ - if (isContextLost()) - return; - m_depthMask = flag; - m_context->depthMask(flag); -} - -void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar) -{ - if (isContextLost()) - return; - if (zNear > zFar) { - synthesizeGLError(GL_INVALID_OPERATION, "depthRange", "zNear > zFar"); - return; - } - m_context->depthRange(zNear, zFar); -} - -void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader) -{ - if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) - return; - if (!program->detachShader(shader)) { - synthesizeGLError(GL_INVALID_OPERATION, "detachShader", "shader not attached"); - return; - } - m_context->detachShader(objectOrZero(program), objectOrZero(shader)); - shader->onDetached(graphicsContext3D()); -} - -void WebGLRenderingContext::disable(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("disable", cap)) - return; - if (cap == GL_STENCIL_TEST) { - m_stencilEnabled = false; - applyStencilTest(); - return; - } - if (cap == GL_SCISSOR_TEST) { - m_scissorEnabled = false; - m_drawingBuffer->setScissorEnabled(m_scissorEnabled); - } - m_context->disable(cap); -} - -void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index) -{ - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "disableVertexAttribArray", "index out of range"); - return; - } - - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - state.enabled = false; - - // If the disabled index is the current maximum, trace backwards to find the new max enabled attrib index - if (m_onePlusMaxEnabledAttribIndex == index + 1) { - findNewMaxEnabledAttribIndex(); - } - - m_context->disableVertexAttribArray(index); -} - -bool WebGLRenderingContext::validateRenderingState() -{ - if (!m_currentProgram) - return false; - - // Look in each enabled vertex attrib and check if they've been bound to a buffer. - for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); - if (state.enabled - && (!state.bufferBinding || !state.bufferBinding->object())) - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object) -{ - if (!object || !object->object()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no object or object deleted"); - return false; - } - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "object does not belong to this context"); - return false; - } - return true; -} - -void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - if (!validateDrawArrays("drawArrays", mode, first, count)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawArrays", true); - m_context->drawArrays(mode, first, count); - handleTextureCompleteness("drawArrays", false); - markContextChanged(); -} - -void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset) -{ - if (!validateDrawElements("drawElements", mode, count, type, offset)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawElements", true); - m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset)); - handleTextureCompleteness("drawElements", false); - markContextChanged(); -} - -void WebGLRenderingContext::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) -{ - if (!validateDrawArrays("drawArraysInstancedANGLE", mode, first, count)) - return; - - if (!validateDrawInstanced("drawArraysInstancedANGLE", primcount)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawArraysInstancedANGLE", true); - m_context->extensions()->drawArraysInstancedANGLE(mode, first, count, primcount); - handleTextureCompleteness("drawArraysInstancedANGLE", false); - markContextChanged(); -} - -void WebGLRenderingContext::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) -{ - if (!validateDrawElements("drawElementsInstancedANGLE", mode, count, type, offset)) - return; - - if (!validateDrawInstanced("drawElementsInstancedANGLE", primcount)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawElementsInstancedANGLE", true); - m_context->extensions()->drawElementsInstancedANGLE(mode, count, type, static_cast<GC3Dintptr>(offset), primcount); - handleTextureCompleteness("drawElementsInstancedANGLE", false); - markContextChanged(); -} - -void WebGLRenderingContext::enable(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("enable", cap)) - return; - if (cap == GL_STENCIL_TEST) { - m_stencilEnabled = true; - applyStencilTest(); - return; - } - if (cap == GL_SCISSOR_TEST) { - m_scissorEnabled = true; - m_drawingBuffer->setScissorEnabled(m_scissorEnabled); - } - m_context->enable(cap); -} - -void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index) -{ - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "enableVertexAttribArray", "index out of range"); - return; - } - - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - state.enabled = true; - - m_onePlusMaxEnabledAttribIndex = max(index + 1, m_onePlusMaxEnabledAttribIndex); - - m_context->enableVertexAttribArray(index); -} - -void WebGLRenderingContext::finish() -{ - if (isContextLost()) - return; - m_context->flush(); // Intentionally a flush, not a finish. -} - -void WebGLRenderingContext::flush() -{ - if (isContextLost()) - return; - m_context->flush(); -} - -void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer) -{ - if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) - return; - if (renderbuffertarget != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); - return; - } - if (buffer && !buffer->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context"); - return; - } - // Don't allow the default framebuffer to be mutated; all current - // implementations use an FBO internally in place of the default - // FBO. - if (!m_framebufferBinding || !m_framebufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound"); - return; - } - Platform3DObject bufferObject = objectOrZero(buffer); - switch (attachment) { - case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: - if (isDepthStencilSupported() || !buffer) { - m_context->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); - m_context->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); - } else { - WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(renderbuffertarget, buffer); - if (!emulatedStencilBuffer) { - synthesizeGLError(GL_OUT_OF_MEMORY, "framebufferRenderbuffer", "out of memory"); - return; - } - m_context->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); - m_context->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, objectOrZero(emulatedStencilBuffer)); - } - break; - default: - m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject); - } - m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer); - applyStencilTest(); -} - -void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level) -{ - if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) - return; - if (level) { - synthesizeGLError(GL_INVALID_VALUE, "framebufferTexture2D", "level not 0"); - return; - } - if (texture && !texture->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context"); - return; - } - // Don't allow the default framebuffer to be mutated; all current - // implementations use an FBO internally in place of the default - // FBO. - if (!m_framebufferBinding || !m_framebufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound"); - return; - } - Platform3DObject textureObject = objectOrZero(texture); - switch (attachment) { - case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: - m_context->framebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, textureObject, level); - m_context->framebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, textureObject, level); - break; - case GL_DEPTH_ATTACHMENT: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - break; - case GL_STENCIL_ATTACHMENT: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - break; - default: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - } - m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level); - applyStencilTest(); -} - -void WebGLRenderingContext::frontFace(GC3Denum mode) -{ - if (isContextLost()) - return; - switch (mode) { - case GL_CW: - case GL_CCW: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "frontFace", "invalid mode"); - return; - } - m_context->frontFace(mode); -} - -void WebGLRenderingContext::generateMipmap(GC3Denum target) -{ - if (isContextLost()) - return; - WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); - if (!tex) - return; - if (!tex->canGenerateMipmaps()) { - synthesizeGLError(GL_INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size"); - return; - } - if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0))) - return; - - // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR - // on Mac. Remove the hack once this driver bug is fixed. -#if OS(MACOSX) - bool needToResetMinFilter = false; - if (tex->getMinFilter() != GL_NEAREST_MIPMAP_LINEAR) { - m_context->texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - needToResetMinFilter = true; - } -#endif - m_context->generateMipmap(target); -#if OS(MACOSX) - if (needToResetMinFilter) - m_context->texParameteri(target, GL_TEXTURE_MIN_FILTER, tex->getMinFilter()); -#endif - tex->generateMipmapLevelInfo(); -} - -PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index) -{ - if (isContextLost() || !validateWebGLObject("getActiveAttrib", program)) - return 0; - ActiveInfo info; - if (!m_context->getActiveAttrib(objectOrZero(program), index, info)) - return 0; - return WebGLActiveInfo::create(info.name, info.type, info.size); -} - -PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index) -{ - if (isContextLost() || !validateWebGLObject("getActiveUniform", program)) - return 0; - ActiveInfo info; - if (!m_context->getActiveUniform(objectOrZero(program), index, info)) - return 0; - return WebGLActiveInfo::create(info.name, info.type, info.size); -} - -bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader> >& shaderObjects) -{ - shaderObjects.clear(); - if (isContextLost() || !validateWebGLObject("getAttachedShaders", program)) - return false; - - const GC3Denum shaderType[] = { - GL_VERTEX_SHADER, - GL_FRAGMENT_SHADER - }; - for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) { - WebGLShader* shader = program->getAttachedShader(shaderType[i]); - if (shader) - shaderObjects.append(shader); - } - return true; -} - -GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name) -{ - if (isContextLost() || !validateWebGLObject("getAttribLocation", program)) - return -1; - if (!validateLocationLength("getAttribLocation", name)) - return -1; - if (!validateString("getAttribLocation", name)) - return -1; - if (isPrefixReserved(name)) - return -1; - if (!program->linkStatus()) { - synthesizeGLError(GL_INVALID_OPERATION, "getAttribLocation", "program not linked"); - return 0; - } - return m_context->getAttribLocation(objectOrZero(program), name); -} - -WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - if (target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid target"); - return WebGLGetInfo(); - } - - if (pname != GL_BUFFER_SIZE && pname != GL_BUFFER_USAGE) { - synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid parameter name"); - return WebGLGetInfo(); - } - - GC3Dint value = 0; - m_context->getBufferParameteriv(target, pname, &value); - if (pname == GL_BUFFER_SIZE) - return WebGLGetInfo(value); - return WebGLGetInfo(static_cast<unsigned int>(value)); -} - -PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes() -{ - if (isContextLost()) - return 0; - // We always need to return a new WebGLContextAttributes object to - // prevent the user from mutating any cached version. - - // Also, we need to enforce requested values of "false" for depth - // and stencil, regardless of the properties of the underlying - // GraphicsContext3D or DrawingBuffer. - RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes()); - if (!m_attributes.depth) - attributes->setDepth(false); - if (!m_attributes.stencil) - attributes->setStencil(false); - // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(), - // but it makes its own determination of whether multisampling is supported. - attributes->setAntialias(m_drawingBuffer->multisample()); - return attributes.release(); -} - -GC3Denum WebGLRenderingContext::getError() -{ - if (lost_context_errors_.size()) { - GC3Denum err = lost_context_errors_.first(); - lost_context_errors_.remove(0); - return err; - } - - if (isContextLost()) - return GL_NO_ERROR; - - return m_context->getError(); -} - -bool WebGLRenderingContext::ExtensionTracker::matchesNameWithPrefixes(const String& name) const -{ - static const char* const unprefixed[] = { "", 0, }; - - const char* const* prefixes = m_prefixes ? m_prefixes : unprefixed; - for (; *prefixes; ++prefixes) { - String prefixedName = String(*prefixes) + extensionName(); - if (equalIgnoringCase(prefixedName, name)) { - return true; - } - } - return false; -} - -PassRefPtr<WebGLExtension> WebGLRenderingContext::getExtension(const String& name) -{ - if (isContextLost()) - return 0; - - for (size_t i = 0; i < m_extensions.size(); ++i) { - ExtensionTracker* tracker = m_extensions[i]; - if (tracker->matchesNameWithPrefixes(name)) { - if (tracker->webglDebugRendererInfo() && !allowWebGLDebugRendererInfo()) - return 0; - if (tracker->privileged() && !allowPrivilegedExtensions()) - return 0; - if (tracker->draft() && !RuntimeEnabledFeatures::webGLDraftExtensionsEnabled()) - return 0; - if (!tracker->supported(this)) - return 0; - return tracker->getExtension(this); - } - } - - return 0; -} - -WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) -{ - if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) - return WebGLGetInfo(); - - if (!m_framebufferBinding || !m_framebufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound"); - return WebGLGetInfo(); - } - - WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment); - if (!object) { - if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) - return WebGLGetInfo(GL_NONE); - // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL - // specifies INVALID_OPERATION. - synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name"); - return WebGLGetInfo(); - } - - ASSERT(object->isTexture() || object->isRenderbuffer()); - if (object->isTexture()) { - switch (pname) { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - return WebGLGetInfo(GL_TEXTURE); - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(static_cast<WebGLTexture*>(object))); - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - { - GC3Dint value = 0; - m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); - return WebGLGetInfo(value); - } - default: - synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment"); - return WebGLGetInfo(); - } - } else { - switch (pname) { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - return WebGLGetInfo(GL_RENDERBUFFER); - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(static_cast<WebGLRenderbuffer*>(object))); - default: - synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); - return WebGLGetInfo(); - } - } -} - -WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - const int intZero = 0; - switch (pname) { - case GL_ACTIVE_TEXTURE: - return getUnsignedIntParameter(pname); - case GL_ALIASED_LINE_WIDTH_RANGE: - return getWebGLFloatArrayParameter(pname); - case GL_ALIASED_POINT_SIZE_RANGE: - return getWebGLFloatArrayParameter(pname); - case GL_ALPHA_BITS: - return getIntParameter(pname); - case GL_ARRAY_BUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer)); - case GL_BLEND: - return getBooleanParameter(pname); - case GL_BLEND_COLOR: - return getWebGLFloatArrayParameter(pname); - case GL_BLEND_DST_ALPHA: - return getUnsignedIntParameter(pname); - case GL_BLEND_DST_RGB: - return getUnsignedIntParameter(pname); - case GL_BLEND_EQUATION_ALPHA: - return getUnsignedIntParameter(pname); - case GL_BLEND_EQUATION_RGB: - return getUnsignedIntParameter(pname); - case GL_BLEND_SRC_ALPHA: - return getUnsignedIntParameter(pname); - case GL_BLEND_SRC_RGB: - return getUnsignedIntParameter(pname); - case GL_BLUE_BITS: - return getIntParameter(pname); - case GL_COLOR_CLEAR_VALUE: - return getWebGLFloatArrayParameter(pname); - case GL_COLOR_WRITEMASK: - return getBooleanArrayParameter(pname); - case GL_COMPRESSED_TEXTURE_FORMATS: - return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())); - case GL_CULL_FACE: - return getBooleanParameter(pname); - case GL_CULL_FACE_MODE: - return getUnsignedIntParameter(pname); - case GL_CURRENT_PROGRAM: - return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram)); - case GL_DEPTH_BITS: - if (!m_framebufferBinding && !m_attributes.depth) - return WebGLGetInfo(intZero); - return getIntParameter(pname); - case GL_DEPTH_CLEAR_VALUE: - return getFloatParameter(pname); - case GL_DEPTH_FUNC: - return getUnsignedIntParameter(pname); - case GL_DEPTH_RANGE: - return getWebGLFloatArrayParameter(pname); - case GL_DEPTH_TEST: - return getBooleanParameter(pname); - case GL_DEPTH_WRITEMASK: - return getBooleanParameter(pname); - case GL_DITHER: - return getBooleanParameter(pname); - case GL_ELEMENT_ARRAY_BUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->boundElementArrayBuffer())); - case GL_FRAMEBUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding)); - case GL_FRONT_FACE: - return getUnsignedIntParameter(pname); - case GL_GENERATE_MIPMAP_HINT: - return getUnsignedIntParameter(pname); - case GL_GREEN_BITS: - return getIntParameter(pname); - case GL_LINE_WIDTH: - return getFloatParameter(pname); - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: - return getIntParameter(pname); - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: - return getIntParameter(pname); - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: - return getIntParameter(pname); - case GL_MAX_RENDERBUFFER_SIZE: - return getIntParameter(pname); - case GL_MAX_TEXTURE_IMAGE_UNITS: - return getIntParameter(pname); - case GL_MAX_TEXTURE_SIZE: - return getIntParameter(pname); - case GL_MAX_VARYING_VECTORS: - return getIntParameter(pname); - case GL_MAX_VERTEX_ATTRIBS: - return getIntParameter(pname); - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: - return getIntParameter(pname); - case GL_MAX_VERTEX_UNIFORM_VECTORS: - return getIntParameter(pname); - case GL_MAX_VIEWPORT_DIMS: - return getWebGLIntArrayParameter(pname); - case GL_NUM_SHADER_BINARY_FORMATS: - // FIXME: should we always return 0 for this? - return getIntParameter(pname); - case GL_PACK_ALIGNMENT: - return getIntParameter(pname); - case GL_POLYGON_OFFSET_FACTOR: - return getFloatParameter(pname); - case GL_POLYGON_OFFSET_FILL: - return getBooleanParameter(pname); - case GL_POLYGON_OFFSET_UNITS: - return getFloatParameter(pname); - case GL_RED_BITS: - return getIntParameter(pname); - case GL_RENDERBUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding)); - case GL_RENDERER: - return WebGLGetInfo(String("WebKit WebGL")); - case GL_SAMPLE_BUFFERS: - return getIntParameter(pname); - case GL_SAMPLE_COVERAGE_INVERT: - return getBooleanParameter(pname); - case GL_SAMPLE_COVERAGE_VALUE: - return getFloatParameter(pname); - case GL_SAMPLES: - return getIntParameter(pname); - case GL_SCISSOR_BOX: - return getWebGLIntArrayParameter(pname); - case GL_SCISSOR_TEST: - return getBooleanParameter(pname); - case GL_SHADING_LANGUAGE_VERSION: - return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GL_SHADING_LANGUAGE_VERSION) + ")"); - case GL_STENCIL_BACK_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_FUNC: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_PASS_DEPTH_PASS: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_REF: - return getIntParameter(pname); - case GL_STENCIL_BACK_VALUE_MASK: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_WRITEMASK: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BITS: - if (!m_framebufferBinding && !m_attributes.stencil) - return WebGLGetInfo(intZero); - return getIntParameter(pname); - case GL_STENCIL_CLEAR_VALUE: - return getIntParameter(pname); - case GL_STENCIL_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_FUNC: - return getUnsignedIntParameter(pname); - case GL_STENCIL_PASS_DEPTH_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_PASS_DEPTH_PASS: - return getUnsignedIntParameter(pname); - case GL_STENCIL_REF: - return getIntParameter(pname); - case GL_STENCIL_TEST: - return getBooleanParameter(pname); - case GL_STENCIL_VALUE_MASK: - return getUnsignedIntParameter(pname); - case GL_STENCIL_WRITEMASK: - return getUnsignedIntParameter(pname); - case GL_SUBPIXEL_BITS: - return getIntParameter(pname); - case GL_TEXTURE_BINDING_2D: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding)); - case GL_TEXTURE_BINDING_CUBE_MAP: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding)); - case GL_UNPACK_ALIGNMENT: - return getIntParameter(pname); - case GC3D_UNPACK_FLIP_Y_WEBGL: - return WebGLGetInfo(m_unpackFlipY); - case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: - return WebGLGetInfo(m_unpackPremultiplyAlpha); - case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: - return WebGLGetInfo(m_unpackColorspaceConversion); - case GL_VENDOR: - return WebGLGetInfo(String("WebKit")); - case GL_VERSION: - return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GL_VERSION) + ")"); - case GL_VIEWPORT: - return getWebGLIntArrayParameter(pname); - case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives - if (m_oesStandardDerivatives) - return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled"); - return WebGLGetInfo(); - case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL: - if (m_webglDebugRendererInfo) - return WebGLGetInfo(m_context->getString(GL_RENDERER)); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); - return WebGLGetInfo(); - case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL: - if (m_webglDebugRendererInfo) - return WebGLGetInfo(m_context->getString(GL_VENDOR)); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); - return WebGLGetInfo(); - case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object - if (m_oesVertexArrayObject) { - if (!m_boundVertexArrayObject->isDefaultObject()) - return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject)); - return WebGLGetInfo(); - } - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled"); - return WebGLGetInfo(); - case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (m_extTextureFilterAnisotropic) - return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); - return WebGLGetInfo(); - case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN - if (m_webglDrawBuffers) - return WebGLGetInfo(maxColorAttachments()); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); - return WebGLGetInfo(); - case Extensions3D::MAX_DRAW_BUFFERS_EXT: - if (m_webglDrawBuffers) - return WebGLGetInfo(maxDrawBuffers()); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); - return WebGLGetInfo(); - default: - if (m_webglDrawBuffers - && pname >= Extensions3D::DRAW_BUFFER0_EXT - && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + maxDrawBuffers())) { - GC3Dint value = GL_NONE; - if (m_framebufferBinding) - value = m_framebufferBinding->getDrawBuffer(pname); - else // emulated backbuffer - value = m_backDrawBuffer; - return WebGLGetInfo(value); - } - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname) -{ - if (isContextLost() || !validateWebGLObject("getProgramParameter", program)) - return WebGLGetInfo(); - - GC3Dint value = 0; - switch (pname) { - case GL_DELETE_STATUS: - return WebGLGetInfo(program->isDeleted()); - case GL_VALIDATE_STATUS: - m_context->getProgramiv(objectOrZero(program), pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); - case GL_LINK_STATUS: - return WebGLGetInfo(program->linkStatus()); - case GL_ATTACHED_SHADERS: - case GL_ACTIVE_ATTRIBUTES: - case GL_ACTIVE_UNIFORMS: - m_context->getProgramiv(objectOrZero(program), pname, &value); - return WebGLGetInfo(value); - default: - synthesizeGLError(GL_INVALID_ENUM, "getProgramParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program) -{ - if (isContextLost()) - return String(); - if (!validateWebGLObject("getProgramInfoLog", program)) - return ""; - return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program))); -} - -WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - if (target != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid target"); - return WebGLGetInfo(); - } - if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound"); - return WebGLGetInfo(); - } - - GC3Dint value = 0; - switch (pname) { - case GL_RENDERBUFFER_WIDTH: - case GL_RENDERBUFFER_HEIGHT: - case GL_RENDERBUFFER_RED_SIZE: - case GL_RENDERBUFFER_GREEN_SIZE: - case GL_RENDERBUFFER_BLUE_SIZE: - case GL_RENDERBUFFER_ALPHA_SIZE: - case GL_RENDERBUFFER_DEPTH_SIZE: - m_context->getRenderbufferParameteriv(target, pname, &value); - return WebGLGetInfo(value); - case GL_RENDERBUFFER_STENCIL_SIZE: - if (m_renderbufferBinding->emulatedStencilBuffer()) { - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding->emulatedStencilBuffer())); - m_context->getRenderbufferParameteriv(target, pname, &value); - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); - } else { - m_context->getRenderbufferParameteriv(target, pname, &value); - } - return WebGLGetInfo(value); - case GL_RENDERBUFFER_INTERNAL_FORMAT: - return WebGLGetInfo(m_renderbufferBinding->internalFormat()); - default: - synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname) -{ - if (isContextLost() || !validateWebGLObject("getShaderParameter", shader)) - return WebGLGetInfo(); - GC3Dint value = 0; - switch (pname) { - case GL_DELETE_STATUS: - return WebGLGetInfo(shader->isDeleted()); - case GL_COMPILE_STATUS: - m_context->getShaderiv(objectOrZero(shader), pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); - case GL_SHADER_TYPE: - m_context->getShaderiv(objectOrZero(shader), pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - default: - synthesizeGLError(GL_INVALID_ENUM, "getShaderParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader) -{ - if (isContextLost()) - return String(); - if (!validateWebGLObject("getShaderInfoLog", shader)) - return ""; - return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader))); -} - -PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType) -{ - if (isContextLost()) - return 0; - switch (shaderType) { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type"); - return 0; - } - switch (precisionType) { - case GL_LOW_FLOAT: - case GL_MEDIUM_FLOAT: - case GL_HIGH_FLOAT: - case GL_LOW_INT: - case GL_MEDIUM_INT: - case GL_HIGH_INT: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type"); - return 0; - } - - GC3Dint range[2] = {0, 0}; - GC3Dint precision = 0; - m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision); - return WebGLShaderPrecisionFormat::create(range[0], range[1], precision); -} - -String WebGLRenderingContext::getShaderSource(WebGLShader* shader) -{ - if (isContextLost()) - return String(); - if (!validateWebGLObject("getShaderSource", shader)) - return ""; - return ensureNotNull(shader->source()); -} - -Vector<String> WebGLRenderingContext::getSupportedExtensions() -{ - Vector<String> result; - if (isContextLost()) - return result; - - for (size_t i = 0; i < m_extensions.size(); ++i) { - ExtensionTracker* tracker = m_extensions[i]; - if (tracker->webglDebugRendererInfo() && !allowWebGLDebugRendererInfo()) - continue; - if (tracker->privileged() && !allowPrivilegedExtensions()) - continue; - if (tracker->draft() && !RuntimeEnabledFeatures::webGLDraftExtensionsEnabled()) - continue; - if (tracker->supported(this)) - result.append(String(tracker->prefixed() ? "WEBKIT_" : "") + tracker->extensionName()); - } - - return result; -} - -WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); - if (!tex) - return WebGLGetInfo(); - GC3Dint value = 0; - switch (pname) { - case GL_TEXTURE_MAG_FILTER: - case GL_TEXTURE_MIN_FILTER: - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - m_context->getTexParameteriv(target, pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (m_extTextureFilterAnisotropic) { - m_context->getTexParameteriv(target, pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - } - synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); - return WebGLGetInfo(); - default: - synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation) -{ - if (isContextLost() || !validateWebGLObject("getUniform", program)) - return WebGLGetInfo(); - if (!uniformLocation || uniformLocation->program() != program) { - synthesizeGLError(GL_INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); - return WebGLGetInfo(); - } - GC3Dint location = uniformLocation->location(); - - // FIXME: make this more efficient using WebGLUniformLocation and caching types in it - GC3Dint activeUniforms = 0; - m_context->getProgramiv(objectOrZero(program), GL_ACTIVE_UNIFORMS, &activeUniforms); - for (GC3Dint i = 0; i < activeUniforms; i++) { - ActiveInfo info; - if (!m_context->getActiveUniform(objectOrZero(program), i, info)) - return WebGLGetInfo(); - // Strip "[0]" from the name if it's an array. - if (info.size > 1 && info.name.endsWith("[0]")) - info.name = info.name.left(info.name.length() - 3); - // If it's an array, we need to iterate through each element, appending "[index]" to the name. - for (GC3Dint index = 0; index < info.size; ++index) { - String name = info.name; - if (info.size > 1 && index >= 1) { - name.append('['); - name.append(String::number(index)); - name.append(']'); - } - // Now need to look this up by name again to find its location - GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name); - if (loc == location) { - // Found it. Use the type in the ActiveInfo to determine the return type. - GC3Denum baseType; - unsigned int length; - switch (info.type) { - case GL_BOOL: - baseType = GL_BOOL; - length = 1; - break; - case GL_BOOL_VEC2: - baseType = GL_BOOL; - length = 2; - break; - case GL_BOOL_VEC3: - baseType = GL_BOOL; - length = 3; - break; - case GL_BOOL_VEC4: - baseType = GL_BOOL; - length = 4; - break; - case GL_INT: - baseType = GL_INT; - length = 1; - break; - case GL_INT_VEC2: - baseType = GL_INT; - length = 2; - break; - case GL_INT_VEC3: - baseType = GL_INT; - length = 3; - break; - case GL_INT_VEC4: - baseType = GL_INT; - length = 4; - break; - case GL_FLOAT: - baseType = GL_FLOAT; - length = 1; - break; - case GL_FLOAT_VEC2: - baseType = GL_FLOAT; - length = 2; - break; - case GL_FLOAT_VEC3: - baseType = GL_FLOAT; - length = 3; - break; - case GL_FLOAT_VEC4: - baseType = GL_FLOAT; - length = 4; - break; - case GL_FLOAT_MAT2: - baseType = GL_FLOAT; - length = 4; - break; - case GL_FLOAT_MAT3: - baseType = GL_FLOAT; - length = 9; - break; - case GL_FLOAT_MAT4: - baseType = GL_FLOAT; - length = 16; - break; - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - baseType = GL_INT; - length = 1; - break; - default: - // Can't handle this type - synthesizeGLError(GL_INVALID_VALUE, "getUniform", "unhandled type"); - return WebGLGetInfo(); - } - switch (baseType) { - case GL_FLOAT: { - GC3Dfloat value[16] = {0}; - m_context->getUniformfv(objectOrZero(program), location, value); - if (length == 1) - return WebGLGetInfo(value[0]); - return WebGLGetInfo(Float32Array::create(value, length)); - } - case GL_INT: { - GC3Dint value[4] = {0}; - m_context->getUniformiv(objectOrZero(program), location, value); - if (length == 1) - return WebGLGetInfo(value[0]); - return WebGLGetInfo(Int32Array::create(value, length)); - } - case GL_BOOL: { - GC3Dint value[4] = {0}; - m_context->getUniformiv(objectOrZero(program), location, value); - if (length > 1) { - bool boolValue[16] = {0}; - for (unsigned j = 0; j < length; j++) - boolValue[j] = static_cast<bool>(value[j]); - return WebGLGetInfo(boolValue, length); - } - return WebGLGetInfo(static_cast<bool>(value[0])); - } - default: - notImplemented(); - } - } - } - } - // If we get here, something went wrong in our unfortunately complex logic above - synthesizeGLError(GL_INVALID_VALUE, "getUniform", "unknown error"); - return WebGLGetInfo(); -} - -PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name) -{ - if (isContextLost() || !validateWebGLObject("getUniformLocation", program)) - return 0; - if (!validateLocationLength("getUniformLocation", name)) - return 0; - if (!validateString("getUniformLocation", name)) - return 0; - if (isPrefixReserved(name)) - return 0; - if (!program->linkStatus()) { - synthesizeGLError(GL_INVALID_OPERATION, "getUniformLocation", "program not linked"); - return 0; - } - GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name); - if (uniformLocation == -1) - return 0; - return WebGLUniformLocation::create(program, uniformLocation); -} - -WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "getVertexAttrib", "index out of range"); - return WebGLGetInfo(); - } - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - - if (m_angleInstancedArrays && pname == Extensions3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) - return WebGLGetInfo(state.divisor); - - switch (pname) { - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - if (!state.bufferBinding || !state.bufferBinding->object()) - return WebGLGetInfo(); - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding)); - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - return WebGLGetInfo(state.enabled); - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - return WebGLGetInfo(state.normalized); - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - return WebGLGetInfo(state.size); - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - return WebGLGetInfo(state.originalStride); - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - return WebGLGetInfo(state.type); - case GL_CURRENT_VERTEX_ATTRIB: - return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4)); - default: - synthesizeGLError(GL_INVALID_ENUM, "getVertexAttrib", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname) -{ - if (isContextLost()) - return 0; - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { - synthesizeGLError(GL_INVALID_ENUM, "getVertexAttribOffset", "invalid parameter name"); - return 0; - } - GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname); - return static_cast<long long>(result); -} - -void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode) -{ - if (isContextLost()) - return; - bool isValid = false; - switch (target) { - case GL_GENERATE_MIPMAP_HINT: - isValid = true; - break; - case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives - if (m_oesStandardDerivatives) - isValid = true; - break; - } - if (!isValid) { - synthesizeGLError(GL_INVALID_ENUM, "hint", "invalid target"); - return; - } - m_context->hint(target, mode); -} - -GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer) -{ - if (!buffer || isContextLost()) - return 0; - - if (!buffer->hasEverBeenBound()) - return 0; - - return m_context->isBuffer(buffer->object()); -} - -bool WebGLRenderingContext::isContextLost() -{ - return m_contextLost; -} - -GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("isEnabled", cap)) - return 0; - if (cap == GL_STENCIL_TEST) - return m_stencilEnabled; - return m_context->isEnabled(cap); -} - -GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer) -{ - if (!framebuffer || isContextLost()) - return 0; - - if (!framebuffer->hasEverBeenBound()) - return 0; - - return m_context->isFramebuffer(framebuffer->object()); -} - -GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program) -{ - if (!program || isContextLost()) - return 0; - - return m_context->isProgram(program->object()); -} - -GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer) -{ - if (!renderbuffer || isContextLost()) - return 0; - - if (!renderbuffer->hasEverBeenBound()) - return 0; - - return m_context->isRenderbuffer(renderbuffer->object()); -} - -GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader) -{ - if (!shader || isContextLost()) - return 0; - - return m_context->isShader(shader->object()); -} - -GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture) -{ - if (!texture || isContextLost()) - return 0; - - if (!texture->hasEverBeenBound()) - return 0; - - return m_context->isTexture(texture->object()); -} - -void WebGLRenderingContext::lineWidth(GC3Dfloat width) -{ - if (isContextLost()) - return; - m_context->lineWidth(width); -} - -void WebGLRenderingContext::linkProgram(WebGLProgram* program) -{ - if (isContextLost() || !validateWebGLObject("linkProgram", program)) - return; - - m_context->linkProgram(objectOrZero(program)); - program->increaseLinkCount(); -} - -void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param) -{ - if (isContextLost()) - return; - switch (pname) { - case GC3D_UNPACK_FLIP_Y_WEBGL: - m_unpackFlipY = param; - break; - case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: - m_unpackPremultiplyAlpha = param; - break; - case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: - if (static_cast<GC3Denum>(param) == GC3D_BROWSER_DEFAULT_WEBGL || param == GL_NONE) - m_unpackColorspaceConversion = static_cast<GC3Denum>(param); - else { - synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL"); - return; - } - break; - case GL_PACK_ALIGNMENT: - case GL_UNPACK_ALIGNMENT: - if (param == 1 || param == 2 || param == 4 || param == 8) { - if (pname == GL_PACK_ALIGNMENT) - m_packAlignment = param; - else // GL_UNPACK_ALIGNMENT: - m_unpackAlignment = param; - m_context->pixelStorei(pname, param); - } else { - synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for alignment"); - return; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "pixelStorei", "invalid parameter name"); - return; - } -} - -void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - if (isContextLost()) - return; - m_context->polygonOffset(factor, units); -} - -void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels) -{ - if (isContextLost()) - return; - // Due to WebGL's same-origin restrictions, it is not possible to - // taint the origin using the WebGL API. - ASSERT(canvas()->originClean()); - // Validate input parameters. - if (!pixels) { - synthesizeGLError(GL_INVALID_VALUE, "readPixels", "no destination ArrayBufferView"); - return; - } - switch (format) { - case GL_ALPHA: - case GL_RGB: - case GL_RGBA: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid format"); - return; - } - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid type"); - return; - } - if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) { - synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE"); - return; - } - // Validate array type against pixel type. - if (pixels->getType() != ArrayBufferView::TypeUint8) { - synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); - return; - } - // Calculate array size, taking into consideration of PACK_ALIGNMENT. - unsigned int totalBytesRequired = 0; - unsigned int padding = 0; - GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); - if (error != GL_NO_ERROR) { - synthesizeGLError(error, "readPixels", "invalid dimensions"); - return; - } - if (pixels->byteLength() < totalBytesRequired) { - synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); - return; - } - - clearIfComposited(); - void* data = pixels->baseAddress(); - - { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->readPixels(x, y, width, height, format, type, data); - } - -#if OS(MACOSX) - // FIXME: remove this section when GL driver bug on Mac is fixed, i.e., - // when alpha is off, readPixels should set alpha to 255 instead of 0. - if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) { - unsigned char* pixels = reinterpret_cast<unsigned char*>(data); - for (GC3Dsizei iy = 0; iy < height; ++iy) { - for (GC3Dsizei ix = 0; ix < width; ++ix) { - pixels[3] = 255; - pixels += 4; - } - pixels += padding; - } - } -#endif -} - -void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (target != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid target"); - return; - } - if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); - return; - } - if (!validateSize("renderbufferStorage", width, height)) - return; - switch (internalformat) { - case GL_DEPTH_COMPONENT16: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_STENCIL_INDEX8: - m_context->renderbufferStorage(target, internalformat, width, height); - m_renderbufferBinding->setInternalFormat(internalformat); - m_renderbufferBinding->setSize(width, height); - m_renderbufferBinding->deleteEmulatedStencilBuffer(m_context.get()); - break; - case GL_DEPTH_STENCIL_OES: - if (isDepthStencilSupported()) { - m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height); - } else { - WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(target, m_renderbufferBinding.get()); - if (!emulatedStencilBuffer) { - synthesizeGLError(GL_OUT_OF_MEMORY, "renderbufferStorage", "out of memory"); - return; - } - m_context->renderbufferStorage(target, GL_DEPTH_COMPONENT16, width, height); - m_context->bindRenderbuffer(target, objectOrZero(emulatedStencilBuffer)); - m_context->renderbufferStorage(target, GL_STENCIL_INDEX8, width, height); - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); - emulatedStencilBuffer->setSize(width, height); - emulatedStencilBuffer->setInternalFormat(GL_STENCIL_INDEX8); - } - m_renderbufferBinding->setSize(width, height); - m_renderbufferBinding->setInternalFormat(internalformat); - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); - return; - } - applyStencilTest(); -} - -void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert) -{ - if (isContextLost()) - return; - m_context->sampleCoverage(value, invert); -} - -void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (!validateSize("scissor", width, height)) - return; - m_context->scissor(x, y, width, height); -} - -void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string) -{ - if (isContextLost() || !validateWebGLObject("shaderSource", shader)) - return; - String stringWithoutComments = StripComments(string).result(); - if (!validateString("shaderSource", stringWithoutComments)) - return; - shader->setSource(string); - m_context->shaderSource(objectOrZero(shader), stringWithoutComments); -} - -void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - if (isContextLost()) - return; - if (!validateStencilOrDepthFunc("stencilFunc", func)) - return; - m_stencilFuncRef = ref; - m_stencilFuncRefBack = ref; - m_stencilFuncMask = mask; - m_stencilFuncMaskBack = mask; - m_context->stencilFunc(func, ref, mask); -} - -void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - if (isContextLost()) - return; - if (!validateStencilOrDepthFunc("stencilFuncSeparate", func)) - return; - switch (face) { - case GL_FRONT_AND_BACK: - m_stencilFuncRef = ref; - m_stencilFuncRefBack = ref; - m_stencilFuncMask = mask; - m_stencilFuncMaskBack = mask; - break; - case GL_FRONT: - m_stencilFuncRef = ref; - m_stencilFuncMask = mask; - break; - case GL_BACK: - m_stencilFuncRefBack = ref; - m_stencilFuncMaskBack = mask; - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "stencilFuncSeparate", "invalid face"); - return; - } - m_context->stencilFuncSeparate(face, func, ref, mask); -} - -void WebGLRenderingContext::stencilMask(GC3Duint mask) -{ - if (isContextLost()) - return; - m_stencilMask = mask; - m_stencilMaskBack = mask; - m_context->stencilMask(mask); -} - -void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - if (isContextLost()) - return; - switch (face) { - case GL_FRONT_AND_BACK: - m_stencilMask = mask; - m_stencilMaskBack = mask; - break; - case GL_FRONT: - m_stencilMask = mask; - break; - case GL_BACK: - m_stencilMaskBack = mask; - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "stencilMaskSeparate", "invalid face"); - return; - } - m_context->stencilMaskSeparate(face, mask); -} - -void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - if (isContextLost()) - return; - m_context->stencilOp(fail, zfail, zpass); -} - -void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - if (isContextLost()) - return; - m_context->stencilOpSeparate(face, fail, zfail, zpass); -} - -void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState& exceptionState) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - // FIXME: Handle errors. - WebGLTexture* tex = validateTextureBinding("texImage2D", target, true); - ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type)); - ASSERT(tex); - ASSERT(!level || !WebGLTexture::isNPOT(width, height)); - ASSERT(!pixels || validateSettableTexFormat("texImage2D", internalformat)); - m_context->texImage2D(target, level, internalformat, width, height, - border, format, type, pixels); - tex->setLevelInfo(target, level, internalformat, width, height, type); -} - -void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - Vector<uint8_t> data; - GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); - if (!imageExtractor.extractSucceeded()) { - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); - GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); - const void* imagePixelData = imageExtractor.imagePixelData(); - - bool needConversion = true; - if (type == GL_UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GL_RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY) - needConversion = false; - else { - if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "packImage error"); - return; - } - } - - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset) -{ - if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type)) - return false; - - WebGLTexture* texture = validateTextureBinding(functionName, target, true); - if (!texture) - return false; - - if (functionType == NotTexSubImage2D) { - if (level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "level > 0 not power of 2"); - return false; - } - // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat - // by checking if the ArrayBufferView is null or not. - if (sourceType != SourceArrayBufferView) { - if (!validateSettableTexFormat(functionName, format)) - return false; - } - } else { - if (!validateSettableTexFormat(functionName, format)) - return false; - if (!validateSize(functionName, xoffset, yoffset)) - return false; - // Before checking if it is in the range, check if overflow happens first. - if (xoffset + width < 0 || yoffset + height < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "bad dimensions"); - return false; - } - if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "dimensions out of range"); - return false; - } - if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type and format do not match texture"); - return false; - } - } - - return true; -} - -PassRefPtr<Image> WebGLRenderingContext::drawImageIntoBuffer(Image* image, int width, int height) -{ - IntSize size(width, height); - ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); - if (!buf) { - synthesizeGLError(GL_OUT_OF_MEMORY, "texImage2D", "out of memory"); - return 0; - } - - IntRect srcRect(IntPoint(), image->size()); - IntRect destRect(0, 0, size.width(), size.height()); - buf->context()->drawImage(image, destRect, srcRect); - return buf->copyImage(ImageBuffer::fastCopyImageMode()); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed) - || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0)) - return; - void* data = pixels ? pixels->baseAddress() : 0; - Vector<uint8_t> tempData; - bool changeUnpackAlignment = false; - if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { - if (!m_context->extractTextureData(width, height, format, type, - m_unpackAlignment, - m_unpackFlipY, m_unpackPremultiplyAlpha, - data, - tempData)) - return; - data = tempData.data(); - changeUnpackAlignment = true; - } - if (changeUnpackAlignment) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, width, height, border, format, type, data, exceptionState); - if (changeUnpackAlignment) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionState& exceptionState) -{ - if (isContextLost() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0)) - return; - Vector<uint8_t> data; - bool needConversion = true; - // The data from ImageData is always of format RGBA8. - // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. - if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GL_RGBA && type == GL_UNSIGNED_BYTE) - needConversion = false; - else { - if (!m_context->extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - } - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLImageElement("texImage2D", image, exceptionState)) - return; - - RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); - if (imageForRender->isSVGImage()) - imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height()); - - if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0)) - return; - - texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, exceptionState) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0)) - return; - - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); - // If possible, copy from the canvas element directly to the texture - // via the GPU, without a read-back to system memory. - if (GL_TEXTURE_2D == target && texture) { - if (!canvas->is3D()) { - ImageBuffer* buffer = canvas->buffer(); - if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, type, - level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { - texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); - return; - } - } else { - WebGLRenderingContext* gl = toWebGLRenderingContext(canvas->renderingContext()); - if (gl && gl->m_drawingBuffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, type, - level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { - texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); - return; - } - } - } - - RefPtr<ImageData> imageData = canvas->getImageData(); - if (imageData) - texImage2D(target, level, internalformat, format, type, imageData.get(), exceptionState); - else - texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy) -{ - IntSize size(video->videoWidth(), video->videoHeight()); - ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); - if (!buf) { - synthesizeGLError(GL_OUT_OF_MEMORY, "texImage2D", "out of memory"); - return 0; - } - IntRect destRect(0, 0, size.width(), size.height()); - // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback. - video->paintCurrentFrameInContext(buf->context(), destRect); - return buf->copyImage(backingStoreCopy); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLVideoElement("texImage2D", video, exceptionState) - || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0)) - return; - - // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible. - // Otherwise, it will fall back to the normal SW path. - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); - if (GL_TEXTURE_2D == target && texture) { - if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { - texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type); - return; - } - } - - // Normal pure SW path. - RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); - if (!image) - return; - texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat) -{ - if (isContextLost()) - return; - WebGLTexture* tex = validateTextureBinding("texParameter", target, false); - if (!tex) - return; - switch (pname) { - case GL_TEXTURE_MIN_FILTER: - case GL_TEXTURE_MAG_FILTER: - break; - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - if ((isFloat && paramf != GL_CLAMP_TO_EDGE && paramf != GL_MIRRORED_REPEAT && paramf != GL_REPEAT) - || (!isFloat && parami != GL_CLAMP_TO_EDGE && parami != GL_MIRRORED_REPEAT && parami != GL_REPEAT)) { - synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter"); - return; - } - break; - case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (!m_extTextureFilterAnisotropic) { - synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled"); - return; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter name"); - return; - } - if (isFloat) { - tex->setParameterf(pname, paramf); - m_context->texParameterf(target, pname, paramf); - } else { - tex->setParameteri(pname, parami); - m_context->texParameteri(target, pname, parami); - } -} - -void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param) -{ - texParameter(target, pname, param, 0, true); -} - -void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param) -{ - texParameter(target, pname, 0, param, false); -} - -void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState& exceptionState) -{ - // FIXME: Handle errors. - ASSERT(!isContextLost()); - ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type)); - ASSERT(validateSize("texSubImage2D", xoffset, yoffset)); - ASSERT(validateSettableTexFormat("texSubImage2D", format)); - WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true); - if (!tex) { - ASSERT_NOT_REACHED(); - return; - } - ASSERT((xoffset + width) >= 0); - ASSERT((yoffset + height) >= 0); - ASSERT(tex->getWidth(target, level) >= (xoffset + width)); - ASSERT(tex->getHeight(target, level) >= (yoffset + height)); - ASSERT(tex->getInternalFormat(target, level) == format); - ASSERT(tex->getType(target, level) == type); - m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); -} - -void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - Vector<uint8_t> data; - GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); - if (!imageExtractor.extractSucceeded()) { - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image"); - return; - } - GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); - GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); - const void* imagePixelData = imageExtractor.imagePixelData(); - - bool needConversion = true; - if (type == GL_UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GL_RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY) - needConversion = false; - else { - if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - } - - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset)) - return; - void* data = pixels->baseAddress(); - Vector<uint8_t> tempData; - bool changeUnpackAlignment = false; - if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { - if (!m_context->extractTextureData(width, height, format, type, - m_unpackAlignment, - m_unpackFlipY, m_unpackPremultiplyAlpha, - data, - tempData)) - return; - data = tempData.data(); - changeUnpackAlignment = true; - } - if (changeUnpackAlignment) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, exceptionState); - if (changeUnpackAlignment) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionState& exceptionState) -{ - if (isContextLost() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset)) - return; - - Vector<uint8_t> data; - bool needConversion = true; - // The data from ImageData is always of format RGBA8. - // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. - if (format == GL_RGBA && type == GL_UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) - needConversion = false; - else { - if (!m_context->extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data"); - return; - } - } - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLImageElement("texSubImage2D", image, exceptionState)) - return; - - RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); - if (imageForRender->isSVGImage()) - imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height()); - - if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset)) - return; - - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLCanvasElement("texSubImage2D", canvas, exceptionState) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset)) - return; - - RefPtr<ImageData> imageData = canvas->getImageData(); - if (imageData) - texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), exceptionState); - else - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLVideoElement("texSubImage2D", video, exceptionState) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset)) - return; - - RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); - if (!image) - return; - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform1f", "location not for current program"); - return; - } - - m_context->uniform1f(location->location(), x); -} - -void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1)) - return; - - m_context->uniform1fv(location->location(), v->length(), v->data()); -} - -void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1)) - return; - - m_context->uniform1fv(location->location(), size, v); -} - -void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform1i", "location not for current program"); - return; - } - - m_context->uniform1i(location->location(), x); -} - -void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1)) - return; - - m_context->uniform1iv(location->location(), v->length(), v->data()); -} - -void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1)) - return; - - m_context->uniform1iv(location->location(), size, v); -} - -void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform2f", "location not for current program"); - return; - } - - m_context->uniform2f(location->location(), x, y); -} - -void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2)) - return; - - m_context->uniform2fv(location->location(), v->length() / 2, v->data()); -} - -void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2)) - return; - - m_context->uniform2fv(location->location(), size / 2, v); -} - -void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform2i", "location not for current program"); - return; - } - - m_context->uniform2i(location->location(), x, y); -} - -void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2)) - return; - - m_context->uniform2iv(location->location(), v->length() / 2, v->data()); -} - -void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2)) - return; - - m_context->uniform2iv(location->location(), size / 2, v); -} - -void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform3f", "location not for current program"); - return; - } - - m_context->uniform3f(location->location(), x, y, z); -} - -void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3)) - return; - - m_context->uniform3fv(location->location(), v->length() / 3, v->data()); -} - -void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3)) - return; - - m_context->uniform3fv(location->location(), size / 3, v); -} - -void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform3i", "location not for current program"); - return; - } - - m_context->uniform3i(location->location(), x, y, z); -} - -void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3)) - return; - - m_context->uniform3iv(location->location(), v->length() / 3, v->data()); -} - -void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3)) - return; - - m_context->uniform3iv(location->location(), size / 3, v); -} - -void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform4f", "location not for current program"); - return; - } - - m_context->uniform4f(location->location(), x, y, z, w); -} - -void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4)) - return; - - m_context->uniform4fv(location->location(), v->length() / 4, v->data()); -} - -void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4)) - return; - - m_context->uniform4fv(location->location(), size / 4, v); -} - -void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform4i", "location not for current program"); - return; - } - - m_context->uniform4i(location->location(), x, y, z, w); -} - -void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4)) - return; - - m_context->uniform4iv(location->location(), v->length() / 4, v->data()); -} - -void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4)) - return; - - m_context->uniform4iv(location->location(), size / 4, v); -} - -void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) - return; - m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data()); -} - -void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) - return; - m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v); -} - -void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) - return; - m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data()); -} - -void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) - return; - m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v); -} - -void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) - return; - m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data()); -} - -void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) - return; - m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v); -} - -void WebGLRenderingContext::useProgram(WebGLProgram* program) -{ - bool deleted; - if (!checkObjectToBeBound("useProgram", program, deleted)) - return; - if (deleted) - program = 0; - if (program && !program->linkStatus()) { - synthesizeGLError(GL_INVALID_OPERATION, "useProgram", "program not valid"); - return; - } - if (m_currentProgram != program) { - if (m_currentProgram) - m_currentProgram->onDetached(graphicsContext3D()); - m_currentProgram = program; - m_context->useProgram(objectOrZero(program)); - if (program) - program->onAttached(); - } -} - -void WebGLRenderingContext::validateProgram(WebGLProgram* program) -{ - if (isContextLost() || !validateWebGLObject("validateProgram", program)) - return; - m_context->validateProgram(objectOrZero(program)); -} - -void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0) -{ - vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f); -} - -void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib1fv", index, v, 1); -} - -void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1); -} - -void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1) -{ - vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f); -} - -void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib2fv", index, v, 2); -} - -void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2); -} - -void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) -{ - vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f); -} - -void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib3fv", index, v, 3); -} - -void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3); -} - -void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) -{ - vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3); -} - -void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib4fv", index, v, 4); -} - -void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4); -} - -void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset) -{ - if (isContextLost()) - return; - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FLOAT: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "index out of range"); - return; - } - if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset"); - return; - } - if (!m_boundArrayBuffer) { - synthesizeGLError(GL_INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER"); - return; - } - // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride - unsigned int typeSize = sizeInBytes(type); - if (!typeSize) { - synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); - return; - } - if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) { - synthesizeGLError(GL_INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type"); - return; - } - GC3Dsizei bytesPerElement = size * typeSize; - - m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer); - m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset)); -} - -void WebGLRenderingContext::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor) -{ - if (isContextLost()) - return; - - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "vertexAttribDivisorANGLE", "index out of range"); - return; - } - - m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor); - m_context->extensions()->vertexAttribDivisorANGLE(index, divisor); -} - -void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (!validateSize("viewport", width, height)) - return; - m_context->viewport(x, y, width, height); -} - -void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode) -{ - if (isContextLost()) { - synthesizeGLError(GL_INVALID_OPERATION, "loseContext", "context already lost"); - return; - } - - m_contextGroup->loseContextGroup(mode); -} - -void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode) -{ - if (isContextLost()) - return; - - m_contextLost = true; - m_contextLostMode = mode; - - if (mode == RealLostContext) { - // Inform the embedder that a lost context was received. In response, the embedder might - // decide to take action such as asking the user for permission to use WebGL again. - if (Frame* frame = canvas()->document().frame()) - frame->loader().client()->didLoseWebGLContext(m_context->extensions()->getGraphicsResetStatusARB()); - } - - // Make absolutely sure we do not refer to an already-deleted texture or framebuffer. - m_drawingBuffer->setTexture2DBinding(0); - m_drawingBuffer->setFramebufferBinding(0); - - detachAndRemoveAllObjects(); - - // Lose all the extensions. - for (size_t i = 0; i < m_extensions.size(); ++i) { - ExtensionTracker* tracker = m_extensions[i]; - tracker->loseExtension(); - } - - removeAllCompressedTextureFormats(); - - if (mode != RealLostContext) - destroyGraphicsContext3D(); - - ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole; - synthesizeGLError(GC3D_CONTEXT_LOST_WEBGL, "loseContext", "context lost", display); - - // Don't allow restoration unless the context lost event has both been - // dispatched and its default behavior prevented. - m_restoreAllowed = false; - - // Always defer the dispatch of the context lost event, to implement - // the spec behavior of queueing a task. - m_dispatchContextLostEventTimer.startOneShot(0); -} - -void WebGLRenderingContext::forceRestoreContext() -{ - if (!isContextLost()) { - synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context not lost"); - return; - } - - if (!m_restoreAllowed) { - if (m_contextLostMode == SyntheticLostContext) - synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context restoration not allowed"); - return; - } - - if (!m_restoreTimer.isActive()) - m_restoreTimer.startOneShot(0); -} - -blink::WebLayer* WebGLRenderingContext::platformLayer() const -{ - return m_drawingBuffer->platformLayer(); -} - -void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object) -{ - m_contextGroup->removeObject(object); -} - -void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object) -{ - ASSERT(!isContextLost()); - m_contextGroup->addObject(object); -} - -void WebGLRenderingContext::removeContextObject(WebGLContextObject* object) -{ - m_contextObjects.remove(object); -} - -void WebGLRenderingContext::addContextObject(WebGLContextObject* object) -{ - ASSERT(!isContextLost()); - m_contextObjects.add(object); -} - -void WebGLRenderingContext::detachAndRemoveAllObjects() -{ - while (m_contextObjects.size() > 0) { - HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin(); - (*it)->detachContext(); - } -} - -bool WebGLRenderingContext::hasPendingActivity() const -{ - return false; -} - -void WebGLRenderingContext::stop() -{ - if (!isContextLost()) { - forceLostContext(SyntheticLostContext); - destroyGraphicsContext3D(); - } -} - -WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname) -{ - GC3Dboolean value = 0; - if (!isContextLost()) - m_context->getBooleanv(pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); -} - -WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname) -{ - if (pname != GL_COLOR_WRITEMASK) { - notImplemented(); - return WebGLGetInfo(0, 0); - } - GC3Dboolean value[4] = {0}; - if (!isContextLost()) - m_context->getBooleanv(pname, value); - bool boolValue[4]; - for (int ii = 0; ii < 4; ++ii) - boolValue[ii] = static_cast<bool>(value[ii]); - return WebGLGetInfo(boolValue, 4); -} - -WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname) -{ - GC3Dfloat value = 0; - if (!isContextLost()) - m_context->getFloatv(pname, &value); - return WebGLGetInfo(value); -} - -WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname) -{ - GC3Dint value = 0; - if (!isContextLost()) - m_context->getIntegerv(pname, &value); - return WebGLGetInfo(value); -} - -WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname) -{ - GC3Dint value = 0; - if (!isContextLost()) - m_context->getIntegerv(pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); -} - -WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname) -{ - GC3Dfloat value[4] = {0}; - if (!isContextLost()) - m_context->getFloatv(pname, value); - unsigned length = 0; - switch (pname) { - case GL_ALIASED_POINT_SIZE_RANGE: - case GL_ALIASED_LINE_WIDTH_RANGE: - case GL_DEPTH_RANGE: - length = 2; - break; - case GL_BLEND_COLOR: - case GL_COLOR_CLEAR_VALUE: - length = 4; - break; - default: - notImplemented(); - } - return WebGLGetInfo(Float32Array::create(value, length)); -} - -WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname) -{ - GC3Dint value[4] = {0}; - if (!isContextLost()) - m_context->getIntegerv(pname, value); - unsigned length = 0; - switch (pname) { - case GL_MAX_VIEWPORT_DIMS: - length = 2; - break; - case GL_SCISSOR_BOX: - case GL_VIEWPORT: - length = 4; - break; - default: - notImplemented(); - } - return WebGLGetInfo(Int32Array::create(value, length)); -} - -void WebGLRenderingContext::handleTextureCompleteness(const char* functionName, bool prepareToDraw) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - bool resetActiveUnit = false; - WebGLTexture::TextureExtensionFlag flag = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureFloatLinearExtensionEnabled : 0) - | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureHalfFloatLinearExtensionEnabled : 0)); - for (unsigned ii = 0; ii < m_onePlusMaxNonDefaultTextureUnit; ++ii) { - if ((m_textureUnits[ii].m_texture2DBinding.get() && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) - || (m_textureUnits[ii].m_textureCubeMapBinding.get() && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag))) { - if (ii != m_activeTextureUnit) { - m_context->activeTexture(ii); - resetActiveUnit = true; - } else if (resetActiveUnit) { - m_context->activeTexture(ii); - resetActiveUnit = false; - } - WebGLTexture* tex2D; - WebGLTexture* texCubeMap; - if (prepareToDraw) { - String msg(String("texture bound to texture unit ") + String::number(ii) - + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'." - + " Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled."); - emitGLWarning(functionName, msg.utf8().data()); - tex2D = m_blackTexture2D.get(); - texCubeMap = m_blackTextureCubeMap.get(); - } else { - tex2D = m_textureUnits[ii].m_texture2DBinding.get(); - texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get(); - } - if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) - m_context->bindTexture(GL_TEXTURE_2D, objectOrZero(tex2D)); - if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag)) - m_context->bindTexture(GL_TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); - } - } - if (resetActiveUnit) - m_context->activeTexture(m_activeTextureUnit); -} - -void WebGLRenderingContext::createFallbackBlackTextures1x1() -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - unsigned char black[] = {0, 0, 0, 255}; - m_blackTexture2D = createTexture(); - m_context->bindTexture(GL_TEXTURE_2D, m_blackTexture2D->object()); - m_context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->bindTexture(GL_TEXTURE_2D, 0); - m_blackTextureCubeMap = createTexture(); - m_context->bindTexture(GL_TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->bindTexture(GL_TEXTURE_CUBE_MAP, 0); -} - -bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, - GC3Denum colorBufferFormat) -{ - unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat); - unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat); - return (need & have) == need; -} - -GC3Denum WebGLRenderingContext::boundFramebufferColorFormat() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->colorBufferFormat(); - if (m_attributes.alpha) - return GL_RGBA; - return GL_RGB; -} - -int WebGLRenderingContext::boundFramebufferWidth() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->colorBufferWidth(); - return m_drawingBuffer->size().width(); -} - -int WebGLRenderingContext::boundFramebufferHeight() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->colorBufferHeight(); - return m_drawingBuffer->size().height(); -} - -WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap) -{ - WebGLTexture* tex = 0; - switch (target) { - case GL_TEXTURE_2D: - tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get(); - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (!useSixEnumsForCubeMap) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); - return 0; - } - tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); - break; - case GL_TEXTURE_CUBE_MAP: - if (useSixEnumsForCubeMap) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); - return 0; - } - tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); - return 0; - } - if (!tex) - synthesizeGLError(GL_INVALID_OPERATION, functionName, "no texture"); - return tex; -} - -bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string) -{ - const unsigned maxWebGLLocationLength = 256; - if (string.length() > maxWebGLLocationLength) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "location length > 256"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y) -{ - if (x < 0 || y < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "size < 0"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateString(const char* functionName, const String& string) -{ - for (size_t i = 0; i < string.length(); ++i) { - if (!validateCharacter(string[i])) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "string not ASCII"); - return false; - } - } - return true; -} - -bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level) -{ - switch (format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_RGB: - case GL_RGBA: - break; - case GL_DEPTH_STENCIL_OES: - case GL_DEPTH_COMPONENT: - if (m_webglDepthTexture) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "depth texture formats not enabled"); - return false; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture format"); - return false; - } - - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - break; - case GL_FLOAT: - if (m_oesTextureFloat) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - case GL_HALF_FLOAT_OES: - if (m_oesTextureHalfFloat) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_24_8_OES: - case GL_UNSIGNED_SHORT: - if (m_webglDepthTexture) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - } - - // Verify that the combination of format and type is supported. - switch (format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - if (type != GL_UNSIGNED_BYTE - && type != GL_FLOAT - && type != GL_HALF_FLOAT_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for format"); - return false; - } - break; - case GL_RGB: - if (type != GL_UNSIGNED_BYTE - && type != GL_UNSIGNED_SHORT_5_6_5 - && type != GL_FLOAT - && type != GL_HALF_FLOAT_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGB format"); - return false; - } - break; - case GL_RGBA: - if (type != GL_UNSIGNED_BYTE - && type != GL_UNSIGNED_SHORT_4_4_4_4 - && type != GL_UNSIGNED_SHORT_5_5_5_1 - && type != GL_FLOAT - && type != GL_HALF_FLOAT_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGBA format"); - return false; - } - break; - case GL_DEPTH_COMPONENT: - if (!m_webglDepthTexture) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled"); - return false; - } - if (type != GL_UNSIGNED_SHORT - && type != GL_UNSIGNED_INT) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format"); - return false; - } - if (level > 0) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format"); - return false; - } - break; - case GL_DEPTH_STENCIL_OES: - if (!m_webglDepthTexture) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled"); - return false; - } - if (type != GL_UNSIGNED_INT_24_8_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format"); - return false; - } - if (level > 0) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format"); - return false; - } - break; - default: - ASSERT_NOT_REACHED(); - } - - return true; -} - -bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level) -{ - if (level < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "level < 0"); - return false; - } - switch (target) { - case GL_TEXTURE_2D: - if (level >= m_maxTextureLevel) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "level out of range"); - return false; - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (level >= m_maxCubeMapTextureLevel) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "level out of range"); - return false; - } - break; - } - // This function only checks if level is legal, so we return true and don't - // generate INVALID_ENUM if target is illegal. - return true; -} - -bool WebGLRenderingContext::validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType functionType, - GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height) -{ - if (width < 0 || height < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); - return false; - } - - switch (target) { - case GL_TEXTURE_2D: - if (width > (m_maxTextureSize >> level) || height > (m_maxTextureSize >> level)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range"); - return false; - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (functionType != TexSubImage2D && width != height) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width != height for cube map"); - return false; - } - // No need to check height here. For texImage width == height. - // For texSubImage that will be checked when checking yoffset + height is in range. - if (width > (m_maxCubeMapTextureSize >> level)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range for cube map"); - return false; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType functionType, GC3Denum target, - GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type) -{ - // We absolutely have to validate the format and type combination. - // The texImage2D entry points taking HTMLImage, etc. will produce - // temporary data based on this combination, so it must be legal. - if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level)) - return false; - - if (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) - return false; - - if (format != internalformat) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "format != internalformat"); - return false; - } - - if (border) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "border != 0"); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, - ArrayBufferView* pixels, - NullDisposition disposition) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - if (!pixels) { - if (disposition == NullAllowed) - return true; - synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); - return false; - } - - if (!validateTexFuncFormatAndType(functionName, format, type, level)) - return false; - if (!validateSettableTexFormat(functionName, format)) - return false; - - switch (type) { - case GL_UNSIGNED_BYTE: - if (pixels->getType() != ArrayBufferView::TypeUint8) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array"); - return false; - } - break; - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - if (pixels->getType() != ArrayBufferView::TypeUint16) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array"); - return false; - } - break; - case GL_FLOAT: // OES_texture_float - if (pixels->getType() != ArrayBufferView::TypeFloat32) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array"); - return false; - } - break; - case GL_HALF_FLOAT_OES: // OES_texture_half_float - // As per the specification, ArrayBufferView should be null when - // OES_texture_half_float is enabled. - if (pixels) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL"); - return false; - } - break; - default: - ASSERT_NOT_REACHED(); - } - - unsigned int totalBytesRequired; - GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0); - if (error != GL_NO_ERROR) { - synthesizeGLError(error, functionName, "invalid texture dimensions"); - return false; - } - if (pixels->byteLength() < totalBytesRequired) { - if (m_unpackAlignment != 1) { - error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0); - if (pixels->byteLength() == totalBytesRequired) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1"); - return false; - } - } - synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format) -{ - return m_compressedTextureFormats.contains(format); -} - -bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, ArrayBufferView* pixels) -{ - if (!pixels) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); - return false; - } - if (width < 0 || height < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); - return false; - } - - unsigned int bytesRequired = 0; - - switch (format) { - case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: - { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - const int kBlockSize = 8; - int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; - int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; - int numBlocks = numBlocksAcross * numBlocksDown; - bytesRequired = numBlocks * kBlockSize; - } - break; - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: - { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - const int kBlockSize = 16; - int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; - int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; - int numBlocks = numBlocksAcross * numBlocksDown; - bytesRequired = numBlocks * kBlockSize; - } - break; - case Extensions3D::COMPRESSED_ATC_RGB_AMD: - { - bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 8; - } - break; - case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: - case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: - { - bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 16; - } - case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG: - case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: - { - bytesRequired = max(width, 8) * max(height, 8) / 2; - } - break; - case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG: - case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: - { - bytesRequired = max(width, 8) * max(height, 8) / 4; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format"); - return false; - } - - if (pixels->byteLength() != bytesRequired) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions"); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType functionType, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format) -{ - if (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) - return false; - - switch (format) { - case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - bool widthValid = (level && width == 1) || (level && width == 2) || !(width % kBlockWidth); - bool heightValid = (level && height == 1) || (level && height == 2) || !(height % kBlockHeight); - if (!widthValid || !heightValid) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "width or height invalid for level"); - return false; - } - return true; - } - default: - return false; - } -} - -bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex) -{ - if (xoffset < 0 || yoffset < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "xoffset or yoffset < 0"); - return false; - } - - switch (format) { - case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4"); - return false; - } - if (width - xoffset > tex->getWidth(target, level) - || height - yoffset > tex->getHeight(target, level)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "dimensions out of range"); - return false; - } - return validateCompressedTexDimensions(functionName, TexSubImage2D, target, level, width, height, format); - } - default: - return false; - } -} - -bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode) -{ - switch (mode) { - case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_LINES: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - case GL_TRIANGLES: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid draw mode"); - return false; - } -} - -bool WebGLRenderingContext::validateStencilSettings(const char* functionName) -{ - if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "front and back stencils settings do not match"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateStencilOrDepthFunc(const char* functionName, GC3Denum func) -{ - switch (func) { - case GL_NEVER: - case GL_LESS: - case GL_LEQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_EQUAL: - case GL_NOTEQUAL: - case GL_ALWAYS: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid function"); - return false; - } -} - -void WebGLRenderingContext::printGLErrorToConsole(const String& message) -{ - if (!m_numGLErrorsToConsoleAllowed) - return; - - --m_numGLErrorsToConsoleAllowed; - printWarningToConsole(message); - - if (!m_numGLErrorsToConsoleAllowed) - printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context."); - - return; -} - -void WebGLRenderingContext::printWarningToConsole(const String& message) -{ - if (!canvas()) - return; - canvas()->document().addConsoleMessage(RenderingMessageSource, WarningMessageLevel, message); -} - -bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) -{ - if (target != GL_FRAMEBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); - return false; - } - switch (attachment) { - case GL_COLOR_ATTACHMENT0: - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: - break; - default: - if (m_webglDrawBuffers - && attachment > GL_COLOR_ATTACHMENT0 - && attachment < static_cast<GC3Denum>(GL_COLOR_ATTACHMENT0 + maxColorAttachments())) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid attachment"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode) -{ - switch (mode) { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid mode"); - return false; - } -} - -bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst) -{ - if (((src == GL_CONSTANT_COLOR || src == GL_ONE_MINUS_CONSTANT_COLOR) - && (dst == GL_CONSTANT_ALPHA || dst == GL_ONE_MINUS_CONSTANT_ALPHA)) - || ((dst == GL_CONSTANT_COLOR || dst == GL_ONE_MINUS_CONSTANT_COLOR) - && (src == GL_CONSTANT_ALPHA || src == GL_ONE_MINUS_CONSTANT_ALPHA))) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "incompatible src and dst"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap) -{ - switch (cap) { - case GL_BLEND: - case GL_CULL_FACE: - case GL_DEPTH_TEST: - case GL_DITHER: - case GL_POLYGON_OFFSET_FILL: - case GL_SAMPLE_ALPHA_TO_COVERAGE: - case GL_SAMPLE_COVERAGE: - case GL_SCISSOR_TEST: - case GL_STENCIL_TEST: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid capability"); - return false; - } -} - -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return false; - } - return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return false; - } - return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) -{ - return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return false; - } - return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) -{ - if (!location) - return false; - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "location is not from current program"); - return false; - } - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return false; - } - if (transpose) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "transpose not FALSE"); - return false; - } - if (size < requiredMinSize || (size % requiredMinSize)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); - return false; - } - return true; -} - -WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage) -{ - WebGLBuffer* buffer = 0; - switch (target) { - case GL_ELEMENT_ARRAY_BUFFER: - buffer = m_boundVertexArrayObject->boundElementArrayBuffer().get(); - break; - case GL_ARRAY_BUFFER: - buffer = m_boundArrayBuffer.get(); - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); - return 0; - } - if (!buffer) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "no buffer"); - return 0; - } - switch (usage) { - case GL_STREAM_DRAW: - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - return buffer; - } - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid usage"); - return 0; -} - -bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionState& exceptionState) -{ - if (!image || !image->cachedImage()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no image"); - return false; - } - const KURL& url = image->cachedImage()->response().url(); - if (url.isNull() || url.isEmpty() || !url.isValid()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid image"); - return false; - } - if (wouldTaintOrigin(image)) { - exceptionState.throwSecurityError("The cross-origin image at " + url.elidedString() + " may not be loaded."); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionState& exceptionState) -{ - if (!canvas || !canvas->buffer()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no canvas"); - return false; - } - if (wouldTaintOrigin(canvas)) { - exceptionState.throwSecurityError("Tainted canvases may not be loaded."); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionState& exceptionState) -{ - if (!video || !video->videoWidth() || !video->videoHeight()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no video"); - return false; - } - if (wouldTaintOrigin(video)) { - exceptionState.throwSecurityError("The video element contains cross-origin data, and may not be loaded."); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - if (isContextLost() || !validateDrawMode(functionName, mode)) - return false; - - if (!validateStencilSettings(functionName)) - return false; - - if (first < 0 || count < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "first or count < 0"); - return false; - } - - if (!count) { - markContextChanged(); - return false; - } - - if (!validateRenderingState()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "attribs not setup correctly"); - return false; - } - - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset) -{ - if (isContextLost() || !validateDrawMode(functionName, mode)) - return false; - - if (!validateStencilSettings(functionName)) - return false; - - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (m_oesElementIndexUint) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); - return false; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); - return false; - } - - if (count < 0 || offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "count or offset < 0"); - return false; - } - - if (!count) { - markContextChanged(); - return false; - } - - if (!m_boundVertexArrayObject->boundElementArrayBuffer()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound"); - return false; - } - - if (!validateRenderingState()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "attribs not setup correctly"); - return false; - } - - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); - return false; - } - - return true; -} - -// Helper function to validate draw*Instanced calls -bool WebGLRenderingContext::validateDrawInstanced(const char* functionName, GC3Dsizei primcount) -{ - if (primcount < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "primcount < 0"); - return false; - } - - // Ensure at least one enabled vertex attrib has a divisor of 0. - for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); - if (state.enabled && !state.divisor) - return true; - } - - synthesizeGLError(GL_INVALID_OPERATION, functionName, "at least one enabled attribute must have a divisor of 0"); - return false; -} - -void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) -{ - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); - return; - } - // In GL, we skip setting vertexAttrib0 values. - switch (expectedSize) { - case 1: - m_context->vertexAttrib1f(index, v0); - break; - case 2: - m_context->vertexAttrib2f(index, v0, v1); - break; - case 3: - m_context->vertexAttrib3f(index, v0, v1, v2); - break; - case 4: - m_context->vertexAttrib4f(index, v0, v1, v2, v3); - break; - } - VertexAttribValue& attribValue = m_vertexAttribValue[index]; - attribValue.value[0] = v0; - attribValue.value[1] = v1; - attribValue.value[2] = v2; - attribValue.value[3] = v3; -} - -void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize) -{ - if (isContextLost()) - return; - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return; - } - vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize); -} - -void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize) -{ - if (isContextLost()) - return; - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return; - } - if (size < expectedSize) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); - return; - } - // In GL, we skip setting vertexAttrib0 values. - switch (expectedSize) { - case 1: - m_context->vertexAttrib1fv(index, v); - break; - case 2: - m_context->vertexAttrib2fv(index, v); - break; - case 3: - m_context->vertexAttrib3fv(index, v); - break; - case 4: - m_context->vertexAttrib4fv(index, v); - break; - } - VertexAttribValue& attribValue = m_vertexAttribValue[index]; - attribValue.initValue(); - for (int ii = 0; ii < expectedSize; ++ii) - attribValue.value[ii] = v[ii]; -} - -void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext>*) -{ - RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(EventTypeNames::webglcontextlost, false, true, ""); - canvas()->dispatchEvent(event); - m_restoreAllowed = event->defaultPrevented(); - deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAllowed); - if ((m_contextLostMode == RealLostContext || m_contextLostMode == AutoRecoverSyntheticLostContext) && m_restoreAllowed) - m_restoreTimer.startOneShot(0); -} - -void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*) -{ - ASSERT(isContextLost()); - - // The rendering context is not restored unless the default behavior of the - // webglcontextlost event was prevented earlier. - // - // Because of the way m_restoreTimer is set up for real vs. synthetic lost - // context events, we don't have to worry about this test short-circuiting - // the retry loop for real context lost events. - if (!m_restoreAllowed) - return; - - Frame* frame = canvas()->document().frame(); - if (!frame) - return; - - Settings* settings = frame->settings(); - - if (!frame->loader().client()->allowWebGL(settings && settings->webGLEnabled())) - return; - - // Reset the context attributes back to the requested attributes and re-apply restrictions - m_attributes = adjustAttributes(m_requestedAttributes, settings); - - RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes)); - - if (!context) { - if (m_contextLostMode == RealLostContext) { - m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); - } else { - // This likely shouldn't happen but is the best way to report it to the WebGL app. - synthesizeGLError(GL_INVALID_OPERATION, "", "error restoring context"); - } - return; - } - - RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager()); - - // Construct a new drawing buffer with the new GraphicsContext3D. - m_drawingBuffer->releaseResources(); - DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; - m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release()); - - if (m_drawingBuffer->isZeroSized()) - return; - - m_drawingBuffer->bind(); - - lost_context_errors_.clear(); - - m_context = context; - m_contextLost = false; - - setupFlags(); - initializeNewContext(); - canvas()->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextrestored, false, true, "")); -} - -String WebGLRenderingContext::ensureNotNull(const String& text) const -{ - if (text.isNull()) - return WTF::emptyString(); - return text; -} - -WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity) - : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity])) - , m_capacity(capacity) -{ -} - -ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size) -{ - int i; - for (i = 0; i < m_capacity; ++i) { - ImageBuffer* buf = m_buffers[i].get(); - if (!buf) - break; - if (buf->size() != size) - continue; - bubbleToFront(i); - return buf; - } - - OwnPtr<ImageBuffer> temp(ImageBuffer::create(size)); - if (!temp) - return 0; - i = std::min(m_capacity - 1, i); - m_buffers[i] = temp.release(); - - ImageBuffer* buf = m_buffers[i].get(); - bubbleToFront(i); - return buf; -} - -void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx) -{ - for (int i = idx; i > 0; --i) - m_buffers[i].swap(m_buffers[i-1]); -} - -namespace { - - String GetErrorString(GC3Denum error) - { - switch (error) { - case GL_INVALID_ENUM: - return "INVALID_ENUM"; - case GL_INVALID_VALUE: - return "INVALID_VALUE"; - case GL_INVALID_OPERATION: - return "INVALID_OPERATION"; - case GL_OUT_OF_MEMORY: - return "OUT_OF_MEMORY"; - case GL_INVALID_FRAMEBUFFER_OPERATION: - return "INVALID_FRAMEBUFFER_OPERATION"; - case GC3D_CONTEXT_LOST_WEBGL: - return "CONTEXT_LOST_WEBGL"; - default: - return String::format("WebGL ERROR(0x%04X)", error); - } - } - -} // namespace anonymous - -void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display) -{ - String errorType = GetErrorString(error); - if (m_synthesizedErrorsToConsole && display == DisplayInConsole) { - String message = String("WebGL: ") + errorType + ": " + String(functionName) + ": " + String(description); - printGLErrorToConsole(message); - } - if (!isContextLost()) - m_context->synthesizeGLError(error); - else { - if (lost_context_errors_.find(error) == WTF::kNotFound) - lost_context_errors_.append(error); - } - InspectorInstrumentation::didFireWebGLError(canvas(), errorType); -} - -void WebGLRenderingContext::emitGLWarning(const char* functionName, const char* description) -{ - if (m_synthesizedErrorsToConsole) { - String message = String("WebGL: ") + String(functionName) + ": " + String(description); - printGLErrorToConsole(message); - } - InspectorInstrumentation::didFireWebGLWarning(canvas()); -} - -void WebGLRenderingContext::applyStencilTest() -{ - bool haveStencilBuffer = false; - - if (m_framebufferBinding) - haveStencilBuffer = m_framebufferBinding->hasStencilBuffer(); - else { - RefPtr<WebGLContextAttributes> attributes = getContextAttributes(); - haveStencilBuffer = attributes->stencil(); - } - enableOrDisable(GL_STENCIL_TEST, - m_stencilEnabled && haveStencilBuffer); -} - -void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable) -{ - if (isContextLost()) - return; - if (enable) - m_context->enable(capability); - else - m_context->disable(capability); -} - -IntSize WebGLRenderingContext::clampedCanvasSize() -{ - return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]), - clamp(canvas()->height(), 1, m_maxViewportDims[1])); -} - -GC3Dint WebGLRenderingContext::maxDrawBuffers() -{ - if (isContextLost() || !m_webglDrawBuffers) - return 0; - if (!m_maxDrawBuffers) - m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers); - if (!m_maxColorAttachments) - m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); - // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS. - return std::min(m_maxDrawBuffers, m_maxColorAttachments); -} - -GC3Dint WebGLRenderingContext::maxColorAttachments() -{ - if (isContextLost() || !m_webglDrawBuffers) - return 0; - if (!m_maxColorAttachments) - m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); - return m_maxColorAttachments; -} - -void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf) -{ - m_backDrawBuffer = buf; -} - -void WebGLRenderingContext::restoreCurrentFramebuffer() -{ - bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding.get()); -} - -void WebGLRenderingContext::restoreCurrentTexture2D() -{ - bindTexture(GL_TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()); -} - -void WebGLRenderingContext::multisamplingChanged(bool enabled) -{ - if (m_multisamplingAllowed != enabled) { - m_multisamplingAllowed = enabled; - forceLostContext(WebGLRenderingContext::AutoRecoverSyntheticLostContext); - } -} - -void WebGLRenderingContext::findNewMaxEnabledAttribIndex() -{ - // Trace backwards from the current max to find the new max enabled attrib index - int startIndex = m_onePlusMaxEnabledAttribIndex - 1; - for (int i = startIndex; i >= 0; --i) { - if (m_boundVertexArrayObject->getVertexAttribState(i).enabled) { - m_onePlusMaxEnabledAttribIndex = i + 1; - return; - } - } - m_onePlusMaxEnabledAttribIndex = 0; -} - -void WebGLRenderingContext::findNewMaxNonDefaultTextureUnit() -{ - // Trace backwards from the current max to find the new max non-default texture unit - int startIndex = m_onePlusMaxNonDefaultTextureUnit - 1; - for (int i = startIndex; i >= 0; --i) { - if (m_textureUnits[i].m_texture2DBinding - || m_textureUnits[i].m_textureCubeMapBinding) { - m_onePlusMaxNonDefaultTextureUnit = i + 1; - return; - } - } - m_onePlusMaxNonDefaultTextureUnit = 0; + registerExtension<EXTShaderTextureLOD>(m_extShaderTextureLOD, DraftExtension); + registerExtension<WebGLCompressedTextureETC1>(m_webglCompressedTextureETC1, DraftExtension); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h index e1e3911e9f1..db0e651b39c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h @@ -26,497 +26,28 @@ #ifndef WebGLRenderingContext_h #define WebGLRenderingContext_h -#include "core/dom/ActiveDOMObject.h" -#include "core/html/canvas/CanvasRenderingContext.h" -#include "core/html/canvas/WebGLGetInfo.h" -#include "core/page/Page.h" -#include "platform/Timer.h" -#include "platform/graphics/GraphicsContext3D.h" -#include "platform/graphics/ImageBuffer.h" - -#include "wtf/Float32Array.h" -#include "wtf/Int32Array.h" -#include "wtf/OwnPtr.h" -#include "wtf/text/WTFString.h" - -namespace blink { class WebLayer; } +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -class ANGLEInstancedArrays; -class DrawingBuffer; -class EXTFragDepth; -class EXTTextureFilterAnisotropic; -class ExceptionState; -class HTMLImageElement; -class HTMLVideoElement; -class ImageBuffer; -class ImageData; -class IntSize; -class OESElementIndexUint; -class OESStandardDerivatives; -class OESTextureFloat; -class OESTextureFloatLinear; -class OESTextureHalfFloat; -class OESTextureHalfFloatLinear; -class OESVertexArrayObject; -class WebGLActiveInfo; -class WebGLBuffer; -class WebGLCompressedTextureATC; -class WebGLCompressedTexturePVRTC; -class WebGLCompressedTextureS3TC; -class WebGLContextAttributes; -class WebGLContextGroup; -class WebGLContextObject; -class WebGLDebugRendererInfo; -class WebGLDebugShaders; -class WebGLDepthTexture; -class WebGLDrawBuffers; -class WebGLExtension; -class WebGLFramebuffer; -class WebGLLoseContext; -class WebGLObject; -class WebGLProgram; -class WebGLRenderbuffer; -class WebGLShader; -class WebGLShaderPrecisionFormat; -class WebGLSharedObject; -class WebGLTexture; -class WebGLUniformLocation; -class WebGLVertexArrayObjectOES; - -class WebGLRenderingContext : public CanvasRenderingContext, public ActiveDOMObject, private Page::MultisamplingChangedObserver { +class WebGLRenderingContext FINAL : public WebGLRenderingContextBase, public ScriptWrappable { public: - static PassOwnPtr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*); + static PassOwnPtrWillBeRawPtr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*); virtual ~WebGLRenderingContext(); - virtual bool is3d() const { return true; } - virtual bool isAccelerated() const { return true; } - - int drawingBufferWidth() const; - int drawingBufferHeight() const; - - void activeTexture(GC3Denum texture); - void attachShader(WebGLProgram*, WebGLShader*); - void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name); - void bindBuffer(GC3Denum target, WebGLBuffer*); - void bindFramebuffer(GC3Denum target, WebGLFramebuffer*); - void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*); - void bindTexture(GC3Denum target, WebGLTexture*); - void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); - void blendEquation(GC3Denum mode); - void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha); - void blendFunc(GC3Denum sfactor, GC3Denum dfactor); - void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha); - - void bufferData(GC3Denum target, long long size, GC3Denum usage); - void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage); - void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage); - void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data); - void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data); - - GC3Denum checkFramebufferStatus(GC3Denum target); - void clear(GC3Dbitfield mask); - void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); - void clearDepth(GC3Dfloat); - void clearStencil(GC3Dint); - void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha); - void compileShader(WebGLShader*); - - void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, - GC3Dsizei height, GC3Dint border, ArrayBufferView* data); - void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data); - - void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border); - void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - - PassRefPtr<WebGLBuffer> createBuffer(); - PassRefPtr<WebGLFramebuffer> createFramebuffer(); - PassRefPtr<WebGLProgram> createProgram(); - PassRefPtr<WebGLRenderbuffer> createRenderbuffer(); - PassRefPtr<WebGLShader> createShader(GC3Denum type); - PassRefPtr<WebGLTexture> createTexture(); - - void cullFace(GC3Denum mode); - - void deleteBuffer(WebGLBuffer*); - void deleteFramebuffer(WebGLFramebuffer*); - void deleteProgram(WebGLProgram*); - void deleteRenderbuffer(WebGLRenderbuffer*); - void deleteShader(WebGLShader*); - void deleteTexture(WebGLTexture*); - - void depthFunc(GC3Denum); - void depthMask(GC3Dboolean); - void depthRange(GC3Dfloat zNear, GC3Dfloat zFar); - void detachShader(WebGLProgram*, WebGLShader*); - void disable(GC3Denum cap); - void disableVertexAttribArray(GC3Duint index); - void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count); - void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset); - - void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); - void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount); - - void enable(GC3Denum cap); - void enableVertexAttribArray(GC3Duint index); - void finish(); - void flush(); - void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*); - void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level); - void frontFace(GC3Denum mode); - void generateMipmap(GC3Denum target); - - PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index); - PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index); - bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader> >&); - GC3Dint getAttribLocation(WebGLProgram*, const String& name); - WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname); - PassRefPtr<WebGLContextAttributes> getContextAttributes(); - GC3Denum getError(); - PassRefPtr<WebGLExtension> getExtension(const String& name); - WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname); - WebGLGetInfo getParameter(GC3Denum pname); - WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname); - String getProgramInfoLog(WebGLProgram*); - WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname); - WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname); - String getShaderInfoLog(WebGLShader*); - PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType); - String getShaderSource(WebGLShader*); - Vector<String> getSupportedExtensions(); - WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname); - WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*); - PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&); - WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname); - long long getVertexAttribOffset(GC3Duint index, GC3Denum pname); - - void hint(GC3Denum target, GC3Denum mode); - GC3Dboolean isBuffer(WebGLBuffer*); - bool isContextLost(); - GC3Dboolean isEnabled(GC3Denum cap); - GC3Dboolean isFramebuffer(WebGLFramebuffer*); - GC3Dboolean isProgram(WebGLProgram*); - GC3Dboolean isRenderbuffer(WebGLRenderbuffer*); - GC3Dboolean isShader(WebGLShader*); - GC3Dboolean isTexture(WebGLTexture*); - - void lineWidth(GC3Dfloat); - void linkProgram(WebGLProgram*); - void pixelStorei(GC3Denum pname, GC3Dint param); - void polygonOffset(GC3Dfloat factor, GC3Dfloat units); - void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels); - void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height); - void sampleCoverage(GC3Dfloat value, GC3Dboolean invert); - void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - void shaderSource(WebGLShader*, const String&); - void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilMask(GC3Duint); - void stencilMaskSeparate(GC3Denum face, GC3Duint mask); - void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass); - void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass); - - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, ImageData*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionState&); - - void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param); - void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param); - - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, ImageData*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionState&); - - void uniform1f(const WebGLUniformLocation*, GC3Dfloat x); - void uniform1fv(const WebGLUniformLocation*, Float32Array* v); - void uniform1fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform1i(const WebGLUniformLocation*, GC3Dint x); - void uniform1iv(const WebGLUniformLocation*, Int32Array* v); - void uniform1iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniform2f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y); - void uniform2fv(const WebGLUniformLocation*, Float32Array* v); - void uniform2fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform2i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y); - void uniform2iv(const WebGLUniformLocation*, Int32Array* v); - void uniform2iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniform3f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void uniform3fv(const WebGLUniformLocation*, Float32Array* v); - void uniform3fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform3i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z); - void uniform3iv(const WebGLUniformLocation*, Int32Array* v); - void uniform3iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniform4f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void uniform4fv(const WebGLUniformLocation*, Float32Array* v); - void uniform4fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform4i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); - void uniform4iv(const WebGLUniformLocation*, Int32Array* v); - void uniform4iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value); - void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei); - void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value); - void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei); - void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value); - void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei); - - void useProgram(WebGLProgram*); - void validateProgram(WebGLProgram*); - - void vertexAttrib1f(GC3Duint index, GC3Dfloat x); - void vertexAttrib1fv(GC3Duint index, Float32Array* values); - void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); - void vertexAttrib2fv(GC3Duint index, Float32Array* values); - void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void vertexAttrib3fv(GC3Duint index, Float32Array* values); - void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void vertexAttrib4fv(GC3Duint index, Float32Array* values); - void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, - GC3Dsizei stride, long long offset); - - void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor); - - void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - - // WEBKIT_lose_context support - enum LostContextMode { - // Lost context occurred at the graphics system level. - RealLostContext, - - // Lost context provoked by WEBKIT_lose_context. - SyntheticLostContext, - - // A synthetic lost context that should attempt to recover automatically - AutoRecoverSyntheticLostContext - }; - void forceLostContext(LostContextMode); - void forceRestoreContext(); - void loseContextImpl(LostContextMode); - - GraphicsContext3D* graphicsContext3D() const { return m_context.get(); } - WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } - virtual blink::WebLayer* platformLayer() const; - - void reshape(int width, int height); - - void markLayerComposited(); - virtual void paintRenderingResultsToCanvas(); - virtual PassRefPtr<ImageData> paintRenderingResultsToImageData(); - - void removeSharedObject(WebGLSharedObject*); - void removeContextObject(WebGLContextObject*); - - unsigned maxVertexAttribs() const { return m_maxVertexAttribs; } - - // ActiveDOMObject notifications - virtual bool hasPendingActivity() const; - virtual void stop(); - - private: - friend class WebGLDrawBuffers; - friend class WebGLFramebuffer; - friend class WebGLObject; - friend class OESVertexArrayObject; - friend class WebGLDebugShaders; - friend class WebGLCompressedTextureATC; - friend class WebGLCompressedTexturePVRTC; - friend class WebGLCompressedTextureS3TC; - friend class WebGLRenderingContextErrorMessageCallback; - friend class WebGLVertexArrayObjectOES; - - WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes, GraphicsContext3D::Attributes); - void initializeNewContext(); - void setupFlags(); - - void addSharedObject(WebGLSharedObject*); - void addContextObject(WebGLContextObject*); - void detachAndRemoveAllObjects(); - - void destroyGraphicsContext3D(); - void markContextChanged(); + virtual unsigned version() const OVERRIDE { return 1; } + virtual String contextName() const OVERRIDE { return "WebGLRenderingContext"; } + virtual void registerContextExtensions() OVERRIDE; - // Query if the GL implementation is NPOT strict. - bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; } - // Query if depth_stencil buffer is supported. - bool isDepthStencilSupported() { return m_isDepthStencilSupported; } - - // Helper to return the size in bytes of OpenGL data types - // like GL_FLOAT, GL_INT, etc. - unsigned int sizeInBytes(GC3Denum type); - - // Check if each enabled vertex attribute is bound to a buffer. - bool validateRenderingState(); - - bool validateWebGLObject(const char*, WebGLObject*); - - // Adds a compressed texture format. - void addCompressedTextureFormat(GC3Denum); - void removeAllCompressedTextureFormats(); - - PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height); - - PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy); - - WebGLRenderbuffer* ensureEmulatedStencilBuffer(GC3Denum target, WebGLRenderbuffer*); - - RefPtr<GraphicsContext3D> m_context; - RefPtr<WebGLContextGroup> m_contextGroup; - - // Structure for rendering to a DrawingBuffer, instead of directly - // to the back-buffer of m_context. - RefPtr<DrawingBuffer> m_drawingBuffer; - - // Dispatches a context lost event once it is determined that one is needed. - // This is used both for synthetic and real context losses. For real ones, it's - // likely that there's no JavaScript on the stack, but that might be dependent - // on how exactly the platform discovers that the context was lost. For better - // portability we always defer the dispatch of the event. - Timer<WebGLRenderingContext> m_dispatchContextLostEventTimer; - bool m_restoreAllowed; - Timer<WebGLRenderingContext> m_restoreTimer; - - bool m_needsUpdate; - bool m_markedCanvasDirty; - HashSet<WebGLContextObject*> m_contextObjects; - - // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER - RefPtr<WebGLBuffer> m_boundArrayBuffer; - - RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject; - RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject; - void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject) - { - if (arrayObject) - m_boundVertexArrayObject = arrayObject; - else - m_boundVertexArrayObject = m_defaultVertexArrayObject; - } - - class VertexAttribValue { - public: - VertexAttribValue() - { - initValue(); - } - - void initValue() - { - value[0] = 0.0f; - value[1] = 0.0f; - value[2] = 0.0f; - value[3] = 1.0f; - } - - GC3Dfloat value[4]; - }; - Vector<VertexAttribValue> m_vertexAttribValue; - unsigned m_maxVertexAttribs; - RefPtr<WebGLBuffer> m_vertexAttrib0Buffer; - long m_vertexAttrib0BufferSize; - GC3Dfloat m_vertexAttrib0BufferValue[4]; - bool m_forceAttrib0BufferRefill; - bool m_vertexAttrib0UsedBefore; - - RefPtr<WebGLProgram> m_currentProgram; - RefPtr<WebGLFramebuffer> m_framebufferBinding; - RefPtr<WebGLRenderbuffer> m_renderbufferBinding; - class TextureUnitState { - public: - RefPtr<WebGLTexture> m_texture2DBinding; - RefPtr<WebGLTexture> m_textureCubeMapBinding; - }; - Vector<TextureUnitState> m_textureUnits; - unsigned long m_activeTextureUnit; - - RefPtr<WebGLTexture> m_blackTexture2D; - RefPtr<WebGLTexture> m_blackTextureCubeMap; - - Vector<GC3Denum> m_compressedTextureFormats; - - // Fixed-size cache of reusable image buffers for video texImage2D calls. - class LRUImageBufferCache { - public: - LRUImageBufferCache(int capacity); - // The pointer returned is owned by the image buffer map. - ImageBuffer* imageBuffer(const IntSize& size); - private: - void bubbleToFront(int idx); - OwnPtr<OwnPtr<ImageBuffer>[]> m_buffers; - int m_capacity; - }; - LRUImageBufferCache m_generatedImageCache; - - GC3Dint m_maxTextureSize; - GC3Dint m_maxCubeMapTextureSize; - GC3Dint m_maxRenderbufferSize; - GC3Dint m_maxViewportDims[2]; - GC3Dint m_maxTextureLevel; - GC3Dint m_maxCubeMapTextureLevel; - - GC3Dint m_maxDrawBuffers; - GC3Dint m_maxColorAttachments; - GC3Denum m_backDrawBuffer; - bool m_drawBuffersWebGLRequirementsChecked; - bool m_drawBuffersSupported; - - GC3Dint m_packAlignment; - GC3Dint m_unpackAlignment; - bool m_unpackFlipY; - bool m_unpackPremultiplyAlpha; - GC3Denum m_unpackColorspaceConversion; - bool m_contextLost; - LostContextMode m_contextLostMode; - GraphicsContext3D::Attributes m_attributes; - GraphicsContext3D::Attributes m_requestedAttributes; - - bool m_layerCleared; - GC3Dfloat m_clearColor[4]; - bool m_scissorEnabled; - GC3Dfloat m_clearDepth; - GC3Dint m_clearStencil; - GC3Dboolean m_colorMask[4]; - GC3Dboolean m_depthMask; - - bool m_stencilEnabled; - GC3Duint m_stencilMask, m_stencilMaskBack; - GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value. - GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack; - - bool m_isGLES2NPOTStrict; - bool m_isDepthStencilSupported; - - bool m_synthesizedErrorsToConsole; - int m_numGLErrorsToConsoleAllowed; - - bool m_multisamplingAllowed; - bool m_multisamplingObserverRegistered; - - GC3Duint m_onePlusMaxEnabledAttribIndex; - unsigned long m_onePlusMaxNonDefaultTextureUnit; +private: + WebGLRenderingContext(HTMLCanvasElement*, PassOwnPtr<blink::WebGraphicsContext3D>, WebGLContextAttributes*); // Enabled extension objects. RefPtr<ANGLEInstancedArrays> m_angleInstancedArrays; + RefPtr<EXTBlendMinMax> m_extBlendMinMax; RefPtr<EXTFragDepth> m_extFragDepth; + RefPtr<EXTShaderTextureLOD> m_extShaderTextureLOD; RefPtr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic; RefPtr<OESTextureFloat> m_oesTextureFloat; RefPtr<OESTextureFloatLinear> m_oesTextureFloatLinear; @@ -530,403 +61,15 @@ public: RefPtr<WebGLDebugShaders> m_webglDebugShaders; RefPtr<WebGLDrawBuffers> m_webglDrawBuffers; RefPtr<WebGLCompressedTextureATC> m_webglCompressedTextureATC; + RefPtr<WebGLCompressedTextureETC1> m_webglCompressedTextureETC1; RefPtr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC; RefPtr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC; RefPtr<WebGLDepthTexture> m_webglDepthTexture; - - enum ExtensionFlags { - ApprovedExtension = 0x00, - DraftExtension = 0x01, - PrivilegedExtension = 0x02, - PrefixedExtension = 0x04, - WebGLDebugRendererInfoExtension = 0x08, - }; - - class ExtensionTracker { - public: - ExtensionTracker(ExtensionFlags flags, const char* const* prefixes) - : m_privileged(flags & PrivilegedExtension) - , m_draft(flags & DraftExtension) - , m_prefixed(flags & PrefixedExtension) - , m_webglDebugRendererInfo(flags & WebGLDebugRendererInfoExtension) - , m_prefixes(prefixes) - { - } - - virtual ~ExtensionTracker() - { - } - - bool prefixed() const - { - return m_prefixed; - } - - bool privileged() const - { - return m_privileged; - } - - bool draft() const - { - return m_draft; - } - - bool webglDebugRendererInfo() const - { - return m_webglDebugRendererInfo; - } - - bool matchesNameWithPrefixes(const String&) const; - - virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContext*) const = 0; - virtual bool supported(WebGLRenderingContext*) const = 0; - virtual const char* extensionName() const = 0; - virtual void loseExtension() = 0; - - private: - bool m_privileged; - bool m_draft; - bool m_prefixed; - bool m_webglDebugRendererInfo; - const char* const* m_prefixes; - }; - - template <typename T> - class TypedExtensionTracker : public ExtensionTracker { - public: - TypedExtensionTracker(RefPtr<T>& extensionField, ExtensionFlags flags, const char* const* prefixes) - : ExtensionTracker(flags, prefixes) - , m_extensionField(extensionField) - { - } - - ~TypedExtensionTracker() - { - if (m_extensionField) { - m_extensionField->lose(true); - m_extensionField = 0; - } - } - - virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContext* context) const - { - if (!m_extensionField) - m_extensionField = T::create(context); - - return m_extensionField; - } - - virtual bool supported(WebGLRenderingContext* context) const - { - return T::supported(context); - } - - virtual const char* extensionName() const - { - return T::extensionName(); - } - - virtual void loseExtension() - { - if (m_extensionField) { - m_extensionField->lose(false); - if (m_extensionField->isLost()) - m_extensionField = 0; - } - } - - private: - RefPtr<T>& m_extensionField; - }; - - Vector<ExtensionTracker*> m_extensions; - - template <typename T> - void registerExtension(RefPtr<T>& extensionPtr, ExtensionFlags flags = ApprovedExtension, const char* const* prefixes = 0) - { - m_extensions.append(new TypedExtensionTracker<T>(extensionPtr, flags, prefixes)); - } - - // Errors raised by synthesizeGLError() while the context is lost. - Vector<GC3Denum> lost_context_errors_; - - // Helpers for getParameter and others - WebGLGetInfo getBooleanParameter(GC3Denum); - WebGLGetInfo getBooleanArrayParameter(GC3Denum); - WebGLGetInfo getFloatParameter(GC3Denum); - WebGLGetInfo getIntParameter(GC3Denum); - WebGLGetInfo getUnsignedIntParameter(GC3Denum); - WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum); - WebGLGetInfo getWebGLIntArrayParameter(GC3Denum); - - // Clear the backbuffer if it was composited since the last operation. - // clearMask is set to the bitfield of any clear that would happen anyway at this time - // and the function returns true if that clear is now unnecessary. - bool clearIfComposited(GC3Dbitfield clearMask = 0); - - // Helper to restore state that clearing the framebuffer may destroy. - void restoreStateAfterClear(); - - void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState&); - void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); - void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState&); - void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); - - void handleTextureCompleteness(const char*, bool); - void createFallbackBlackTextures1x1(); - - // Helper function for copyTex{Sub}Image, check whether the internalformat - // and the color buffer format of the current bound framebuffer combination - // is valid. - bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, - GC3Denum colorBufferFormat); - - // Helper function to get the bound framebuffer's color buffer format. - GC3Denum boundFramebufferColorFormat(); - - // Helper function to get the bound framebuffer's width. - int boundFramebufferWidth(); - - // Helper function to get the bound framebuffer's height. - int boundFramebufferHeight(); - - // Helper function to verify limits on the length of uniform and attribute locations. - bool validateLocationLength(const char* functionName, const String&); - - // Helper function to check if size is non-negative. - // Generate GL error and return false for negative inputs; otherwise, return true. - bool validateSize(const char* functionName, GC3Dint x, GC3Dint y); - - // Helper function to check if all characters in the string belong to the - // ASCII subset as defined in GLSL ES 1.0 spec section 3.1. - bool validateString(const char* functionName, const String&); - - // Helper function to check target and texture bound to the target. - // Generate GL errors and return 0 if target is invalid or texture bound is - // null. Otherwise, return the texture bound to the target. - WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap); - - // Helper function to check input format/type for functions {copy}Tex{Sub}Image. - // Generates GL error and returns false if parameters are invalid. - bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level); - - // Helper function to check input level for functions {copy}Tex{Sub}Image. - // Generates GL error and returns false if level is invalid. - bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level); - - enum TexFuncValidationFunctionType { - NotTexSubImage2D, - TexSubImage2D, - }; - - enum TexFuncValidationSourceType { - SourceArrayBufferView, - SourceImageData, - SourceHTMLImageElement, - SourceHTMLCanvasElement, - SourceHTMLVideoElement, - }; - - // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid. - // Otherwise, it would return quickly without doing other work. - bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, - GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset); - - // Helper function to check input width and height for functions {copy, compressed}Tex{Sub}Image. - // Generates GL error and returns false if width or height is invalid. - bool validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType, - GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height); - - // Helper function to check input parameters for functions {copy}Tex{Sub}Image. - // Generates GL error and returns false if parameters are invalid. - bool validateTexFuncParameters(const char* functionName, - TexFuncValidationFunctionType, - GC3Denum target, GC3Dint level, - GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type); - - enum NullDisposition { - NullAllowed, - NullNotAllowed - }; - - // Helper function to validate that the given ArrayBufferView - // is of the correct type and contains enough data for the texImage call. - // Generates GL error and returns false if parameters are invalid. - bool validateTexFuncData(const char* functionName, GC3Dint level, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, - ArrayBufferView* pixels, - NullDisposition); - - // Helper function to validate a given texture format is settable as in - // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and - // copyTexSubImage2D. - // Generates GL error and returns false if the format is not settable. - bool validateSettableTexFormat(const char* functionName, GC3Denum format); - - // Helper function to validate compressed texture data is correct size - // for the given format and dimensions. - bool validateCompressedTexFuncData(const char* functionName, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, ArrayBufferView* pixels); - - // Helper function for validating compressed texture formats. - bool validateCompressedTexFormat(GC3Denum format); - - // Helper function to validate compressed texture dimensions are valid for - // the given format. - bool validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format); - - // Helper function to validate compressed texture dimensions are valid for - // the given format. - bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*); - - // Helper function to validate mode for draw{Arrays/Elements}. - bool validateDrawMode(const char* functionName, GC3Denum); - - // Helper function to validate if front/back stencilMask and stencilFunc settings are the same. - bool validateStencilSettings(const char* functionName); - - // Helper function to validate stencil or depth func. - bool validateStencilOrDepthFunc(const char* functionName, GC3Denum); - - // Helper function for texParameterf and texParameteri. - void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat); - - // Helper function to print GL errors to console. - void printGLErrorToConsole(const String&); - - // Helper function to print warnings to console. Currently - // used only to warn about use of obsolete functions. - void printWarningToConsole(const String&); - - // Helper function to validate input parameters for framebuffer functions. - // Generate GL error if parameters are illegal. - bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment); - - // Helper function to validate blend equation mode. - bool validateBlendEquation(const char* functionName, GC3Denum); - - // Helper function to validate blend func factors. - bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst); - - // Helper function to validate a GL capability. - bool validateCapability(const char* functionName, GC3Denum); - - // Helper function to validate input parameters for uniform functions. - bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod); - bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod); - bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod); - bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod); - bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod); - - // Helper function to validate parameters for bufferData. - // Return the current bound buffer to target, or 0 if parameters are invalid. - WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage); - - // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin. - bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionState&); - - // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin. - bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionState&); - - // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin. - bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionState&); - - // Helper function to validate drawArrays(Instanced) calls - bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count); - - // Helper function to validate drawElements(Instanced) calls - bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset); - - // Helper function to validate draw*Instanced calls - bool validateDrawInstanced(const char* functionName, GC3Dsizei primcount); - - // Helper functions for vertexAttribNf{v}. - void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat); - void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize); - void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize); - - // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions. - // Return false if caller should return without further processing. - bool deleteObject(WebGLObject*); - - // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram. - // If the object has already been deleted, set deleted to true upon return. - // Return false if caller should return without further processing. - bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted); - - void dispatchContextLostEvent(Timer<WebGLRenderingContext>*); - // Helper for restoration after context lost. - void maybeRestoreContext(Timer<WebGLRenderingContext>*); - - // Determine if we are running privileged code in the browser, for example, - // a Safari or Chrome extension. - bool allowPrivilegedExtensions() const; - - // Determine if WEBGL_debug_renderer_info extension is enabled. For the - // moment it can be enabled either through a chromium finch experiment - // or for privileged code in the browser. - bool allowWebGLDebugRendererInfo() const; - - enum ConsoleDisplayPreference { - DisplayInConsole, - DontDisplayInConsole - }; - - // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message - // to the JavaScript console. - void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole); - void emitGLWarning(const char* function, const char* reason); - - String ensureNotNull(const String&) const; - - // Enable or disable stencil test based on user setting and - // whether the current FBO has a stencil buffer. - void applyStencilTest(); - - // Helper for enabling or disabling a capability. - void enableOrDisable(GC3Denum capability, bool enable); - - // Clamp the width and height to GL_MAX_VIEWPORT_DIMS. - IntSize clampedCanvasSize(); - - // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0. - // Later, return the cached value. - GC3Dint maxDrawBuffers(); - GC3Dint maxColorAttachments(); - - void setBackDrawBuffer(GC3Denum); - - void restoreCurrentFramebuffer(); - void restoreCurrentTexture2D(); - - virtual void multisamplingChanged(bool); - - void findNewMaxEnabledAttribIndex(); - void findNewMaxNonDefaultTextureUnit(); - - friend class WebGLStateRestorer; - friend class WebGLRenderingContextEvictionManager; - - static Vector<WebGLRenderingContext*>& activeContexts(); - static Vector<WebGLRenderingContext*>& forciblyEvictedContexts(); - - static void activateContext(WebGLRenderingContext*); - static void deactivateContext(WebGLRenderingContext*, bool addToInactiveList); - static void willDestroyContext(WebGLRenderingContext*); - static void forciblyLoseOldestContext(const String& reason); - // Return the least recently used context's position in the active context vector. - // If the vector is empty, return the maximum allowed active context number. - static size_t oldestContextIndex(); - static IntSize oldestContextSize(); }; -DEFINE_TYPE_CASTS(WebGLRenderingContext, CanvasRenderingContext, context, context->is3d(), context.is3d()); +DEFINE_TYPE_CASTS(WebGLRenderingContext, CanvasRenderingContext, context, + context->is3d() && WebGLRenderingContextBase::getWebGLVersion(context) == 1, + context.is3d() && WebGLRenderingContextBase::getWebGLVersion(&context) == 1); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl index a006bae1c53..ce2d4837ff3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl @@ -23,640 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -typedef unsigned long GLenum; -typedef boolean GLboolean; -typedef unsigned long GLbitfield; -typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */ -typedef short GLshort; -typedef long GLint; -typedef long GLsizei; -typedef long long GLintptr; -typedef long long GLsizeiptr; -typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */ -typedef unsigned short GLushort; -typedef unsigned long GLuint; -typedef /*unrestricted*/ float GLfloat; -typedef /*unrestricted*/ float GLclampf; +// http://www.khronos.org/registry/webgl/specs/latest/1.0/#WebGLRenderingContext [ - DoNotCheckConstants -] interface WebGLRenderingContext : CanvasRenderingContext { - - /* ClearBufferMask */ - const GLenum DEPTH_BUFFER_BIT = 0x00000100; - const GLenum STENCIL_BUFFER_BIT = 0x00000400; - const GLenum COLOR_BUFFER_BIT = 0x00004000; - - /* BeginMode */ - const GLenum POINTS = 0x0000; - const GLenum LINES = 0x0001; - const GLenum LINE_LOOP = 0x0002; - const GLenum LINE_STRIP = 0x0003; - const GLenum TRIANGLES = 0x0004; - const GLenum TRIANGLE_STRIP = 0x0005; - const GLenum TRIANGLE_FAN = 0x0006; - - /* AlphaFunction (not supported in ES20) */ - /* NEVER */ - /* LESS */ - /* EQUAL */ - /* LEQUAL */ - /* GREATER */ - /* NOTEQUAL */ - /* GEQUAL */ - /* ALWAYS */ - - /* BlendingFactorDest */ - const GLenum ZERO = 0; - const GLenum ONE = 1; - const GLenum SRC_COLOR = 0x0300; - const GLenum ONE_MINUS_SRC_COLOR = 0x0301; - const GLenum SRC_ALPHA = 0x0302; - const GLenum ONE_MINUS_SRC_ALPHA = 0x0303; - const GLenum DST_ALPHA = 0x0304; - const GLenum ONE_MINUS_DST_ALPHA = 0x0305; - - /* BlendingFactorSrc */ - /* ZERO */ - /* ONE */ - const GLenum DST_COLOR = 0x0306; - const GLenum ONE_MINUS_DST_COLOR = 0x0307; - const GLenum SRC_ALPHA_SATURATE = 0x0308; - /* SRC_ALPHA */ - /* ONE_MINUS_SRC_ALPHA */ - /* DST_ALPHA */ - /* ONE_MINUS_DST_ALPHA */ - - /* BlendEquationSeparate */ - const GLenum FUNC_ADD = 0x8006; - const GLenum BLEND_EQUATION = 0x8009; - const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */ - const GLenum BLEND_EQUATION_ALPHA = 0x883D; - - /* BlendSubtract */ - const GLenum FUNC_SUBTRACT = 0x800A; - const GLenum FUNC_REVERSE_SUBTRACT = 0x800B; - - /* Separate Blend Functions */ - const GLenum BLEND_DST_RGB = 0x80C8; - const GLenum BLEND_SRC_RGB = 0x80C9; - const GLenum BLEND_DST_ALPHA = 0x80CA; - const GLenum BLEND_SRC_ALPHA = 0x80CB; - const GLenum CONSTANT_COLOR = 0x8001; - const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002; - const GLenum CONSTANT_ALPHA = 0x8003; - const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004; - const GLenum BLEND_COLOR = 0x8005; - - /* Buffer Objects */ - const GLenum ARRAY_BUFFER = 0x8892; - const GLenum ELEMENT_ARRAY_BUFFER = 0x8893; - const GLenum ARRAY_BUFFER_BINDING = 0x8894; - const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895; - - const GLenum STREAM_DRAW = 0x88E0; - const GLenum STATIC_DRAW = 0x88E4; - const GLenum DYNAMIC_DRAW = 0x88E8; - - const GLenum BUFFER_SIZE = 0x8764; - const GLenum BUFFER_USAGE = 0x8765; - - const GLenum CURRENT_VERTEX_ATTRIB = 0x8626; - - /* CullFaceMode */ - const GLenum FRONT = 0x0404; - const GLenum BACK = 0x0405; - const GLenum FRONT_AND_BACK = 0x0408; - - /* DepthFunction */ - /* NEVER */ - /* LESS */ - /* EQUAL */ - /* LEQUAL */ - /* GREATER */ - /* NOTEQUAL */ - /* GEQUAL */ - /* ALWAYS */ - - /* EnableCap */ - const GLenum TEXTURE_2D = 0x0DE1; - const GLenum CULL_FACE = 0x0B44; - const GLenum BLEND = 0x0BE2; - const GLenum DITHER = 0x0BD0; - const GLenum STENCIL_TEST = 0x0B90; - const GLenum DEPTH_TEST = 0x0B71; - const GLenum SCISSOR_TEST = 0x0C11; - const GLenum POLYGON_OFFSET_FILL = 0x8037; - const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E; - const GLenum SAMPLE_COVERAGE = 0x80A0; - - /* ErrorCode */ - const GLenum NO_ERROR = 0; - const GLenum INVALID_ENUM = 0x0500; - const GLenum INVALID_VALUE = 0x0501; - const GLenum INVALID_OPERATION = 0x0502; - const GLenum OUT_OF_MEMORY = 0x0505; - - /* FrontFaceDirection */ - const GLenum CW = 0x0900; - const GLenum CCW = 0x0901; - - /* GetPName */ - const GLenum LINE_WIDTH = 0x0B21; - const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D; - const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E; - const GLenum CULL_FACE_MODE = 0x0B45; - const GLenum FRONT_FACE = 0x0B46; - const GLenum DEPTH_RANGE = 0x0B70; - const GLenum DEPTH_WRITEMASK = 0x0B72; - const GLenum DEPTH_CLEAR_VALUE = 0x0B73; - const GLenum DEPTH_FUNC = 0x0B74; - const GLenum STENCIL_CLEAR_VALUE = 0x0B91; - const GLenum STENCIL_FUNC = 0x0B92; - const GLenum STENCIL_FAIL = 0x0B94; - const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95; - const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96; - const GLenum STENCIL_REF = 0x0B97; - const GLenum STENCIL_VALUE_MASK = 0x0B93; - const GLenum STENCIL_WRITEMASK = 0x0B98; - const GLenum STENCIL_BACK_FUNC = 0x8800; - const GLenum STENCIL_BACK_FAIL = 0x8801; - const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802; - const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803; - const GLenum STENCIL_BACK_REF = 0x8CA3; - const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4; - const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5; - const GLenum VIEWPORT = 0x0BA2; - const GLenum SCISSOR_BOX = 0x0C10; - /* SCISSOR_TEST */ - const GLenum COLOR_CLEAR_VALUE = 0x0C22; - const GLenum COLOR_WRITEMASK = 0x0C23; - const GLenum UNPACK_ALIGNMENT = 0x0CF5; - const GLenum PACK_ALIGNMENT = 0x0D05; - const GLenum MAX_TEXTURE_SIZE = 0x0D33; - const GLenum MAX_VIEWPORT_DIMS = 0x0D3A; - const GLenum SUBPIXEL_BITS = 0x0D50; - const GLenum RED_BITS = 0x0D52; - const GLenum GREEN_BITS = 0x0D53; - const GLenum BLUE_BITS = 0x0D54; - const GLenum ALPHA_BITS = 0x0D55; - const GLenum DEPTH_BITS = 0x0D56; - const GLenum STENCIL_BITS = 0x0D57; - const GLenum POLYGON_OFFSET_UNITS = 0x2A00; - /* POLYGON_OFFSET_FILL */ - const GLenum POLYGON_OFFSET_FACTOR = 0x8038; - const GLenum TEXTURE_BINDING_2D = 0x8069; - const GLenum SAMPLE_BUFFERS = 0x80A8; - const GLenum SAMPLES = 0x80A9; - const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA; - const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB; - - /* GetTextureParameter */ - /* TEXTURE_MAG_FILTER */ - /* TEXTURE_MIN_FILTER */ - /* TEXTURE_WRAP_S */ - /* TEXTURE_WRAP_T */ - - const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3; - - /* HintMode */ - const GLenum DONT_CARE = 0x1100; - const GLenum FASTEST = 0x1101; - const GLenum NICEST = 0x1102; - - /* HintTarget */ - const GLenum GENERATE_MIPMAP_HINT = 0x8192; - - /* DataType */ - const GLenum BYTE = 0x1400; - const GLenum UNSIGNED_BYTE = 0x1401; - const GLenum SHORT = 0x1402; - const GLenum UNSIGNED_SHORT = 0x1403; - const GLenum INT = 0x1404; - const GLenum UNSIGNED_INT = 0x1405; - const GLenum FLOAT = 0x1406; - - /* PixelFormat */ - const GLenum DEPTH_COMPONENT = 0x1902; - const GLenum ALPHA = 0x1906; - const GLenum RGB = 0x1907; - const GLenum RGBA = 0x1908; - const GLenum LUMINANCE = 0x1909; - const GLenum LUMINANCE_ALPHA = 0x190A; - - /* PixelType */ - /* UNSIGNED_BYTE */ - const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033; - const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034; - const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363; - - /* Shaders */ - const GLenum FRAGMENT_SHADER = 0x8B30; - const GLenum VERTEX_SHADER = 0x8B31; - const GLenum MAX_VERTEX_ATTRIBS = 0x8869; - const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; - const GLenum MAX_VARYING_VECTORS = 0x8DFC; - const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D; - const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; - const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872; - const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD; - const GLenum SHADER_TYPE = 0x8B4F; - const GLenum DELETE_STATUS = 0x8B80; - const GLenum LINK_STATUS = 0x8B82; - const GLenum VALIDATE_STATUS = 0x8B83; - const GLenum ATTACHED_SHADERS = 0x8B85; - const GLenum ACTIVE_UNIFORMS = 0x8B86; - const GLenum ACTIVE_ATTRIBUTES = 0x8B89; - const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C; - const GLenum CURRENT_PROGRAM = 0x8B8D; - - /* StencilFunction */ - const GLenum NEVER = 0x0200; - const GLenum LESS = 0x0201; - const GLenum EQUAL = 0x0202; - const GLenum LEQUAL = 0x0203; - const GLenum GREATER = 0x0204; - const GLenum NOTEQUAL = 0x0205; - const GLenum GEQUAL = 0x0206; - const GLenum ALWAYS = 0x0207; - - /* StencilOp */ - /* ZERO */ - const GLenum KEEP = 0x1E00; - const GLenum REPLACE = 0x1E01; - const GLenum INCR = 0x1E02; - const GLenum DECR = 0x1E03; - const GLenum INVERT = 0x150A; - const GLenum INCR_WRAP = 0x8507; - const GLenum DECR_WRAP = 0x8508; - - /* StringName */ - const GLenum VENDOR = 0x1F00; - const GLenum RENDERER = 0x1F01; - const GLenum VERSION = 0x1F02; - - /* TextureMagFilter */ - const GLenum NEAREST = 0x2600; - const GLenum LINEAR = 0x2601; - - /* TextureMinFilter */ - /* NEAREST */ - /* LINEAR */ - const GLenum NEAREST_MIPMAP_NEAREST = 0x2700; - const GLenum LINEAR_MIPMAP_NEAREST = 0x2701; - const GLenum NEAREST_MIPMAP_LINEAR = 0x2702; - const GLenum LINEAR_MIPMAP_LINEAR = 0x2703; - - /* TextureParameterName */ - const GLenum TEXTURE_MAG_FILTER = 0x2800; - const GLenum TEXTURE_MIN_FILTER = 0x2801; - const GLenum TEXTURE_WRAP_S = 0x2802; - const GLenum TEXTURE_WRAP_T = 0x2803; - - /* TextureTarget */ - /* TEXTURE_2D */ - const GLenum TEXTURE = 0x1702; - - const GLenum TEXTURE_CUBE_MAP = 0x8513; - const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514; - const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; - const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; - const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; - const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; - const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; - const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; - const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; - - /* TextureUnit */ - const GLenum TEXTURE0 = 0x84C0; - const GLenum TEXTURE1 = 0x84C1; - const GLenum TEXTURE2 = 0x84C2; - const GLenum TEXTURE3 = 0x84C3; - const GLenum TEXTURE4 = 0x84C4; - const GLenum TEXTURE5 = 0x84C5; - const GLenum TEXTURE6 = 0x84C6; - const GLenum TEXTURE7 = 0x84C7; - const GLenum TEXTURE8 = 0x84C8; - const GLenum TEXTURE9 = 0x84C9; - const GLenum TEXTURE10 = 0x84CA; - const GLenum TEXTURE11 = 0x84CB; - const GLenum TEXTURE12 = 0x84CC; - const GLenum TEXTURE13 = 0x84CD; - const GLenum TEXTURE14 = 0x84CE; - const GLenum TEXTURE15 = 0x84CF; - const GLenum TEXTURE16 = 0x84D0; - const GLenum TEXTURE17 = 0x84D1; - const GLenum TEXTURE18 = 0x84D2; - const GLenum TEXTURE19 = 0x84D3; - const GLenum TEXTURE20 = 0x84D4; - const GLenum TEXTURE21 = 0x84D5; - const GLenum TEXTURE22 = 0x84D6; - const GLenum TEXTURE23 = 0x84D7; - const GLenum TEXTURE24 = 0x84D8; - const GLenum TEXTURE25 = 0x84D9; - const GLenum TEXTURE26 = 0x84DA; - const GLenum TEXTURE27 = 0x84DB; - const GLenum TEXTURE28 = 0x84DC; - const GLenum TEXTURE29 = 0x84DD; - const GLenum TEXTURE30 = 0x84DE; - const GLenum TEXTURE31 = 0x84DF; - const GLenum ACTIVE_TEXTURE = 0x84E0; - - /* TextureWrapMode */ - const GLenum REPEAT = 0x2901; - const GLenum CLAMP_TO_EDGE = 0x812F; - const GLenum MIRRORED_REPEAT = 0x8370; - - /* Uniform Types */ - const GLenum FLOAT_VEC2 = 0x8B50; - const GLenum FLOAT_VEC3 = 0x8B51; - const GLenum FLOAT_VEC4 = 0x8B52; - const GLenum INT_VEC2 = 0x8B53; - const GLenum INT_VEC3 = 0x8B54; - const GLenum INT_VEC4 = 0x8B55; - const GLenum BOOL = 0x8B56; - const GLenum BOOL_VEC2 = 0x8B57; - const GLenum BOOL_VEC3 = 0x8B58; - const GLenum BOOL_VEC4 = 0x8B59; - const GLenum FLOAT_MAT2 = 0x8B5A; - const GLenum FLOAT_MAT3 = 0x8B5B; - const GLenum FLOAT_MAT4 = 0x8B5C; - const GLenum SAMPLER_2D = 0x8B5E; - const GLenum SAMPLER_CUBE = 0x8B60; - - /* Vertex Arrays */ - const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622; - const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623; - const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624; - const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625; - const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A; - const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645; - const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F; - - /* Shader Source */ - const GLenum COMPILE_STATUS = 0x8B81; - - /* Shader Precision-Specified Types */ - const GLenum LOW_FLOAT = 0x8DF0; - const GLenum MEDIUM_FLOAT = 0x8DF1; - const GLenum HIGH_FLOAT = 0x8DF2; - const GLenum LOW_INT = 0x8DF3; - const GLenum MEDIUM_INT = 0x8DF4; - const GLenum HIGH_INT = 0x8DF5; - - /* Framebuffer Object. */ - const GLenum FRAMEBUFFER = 0x8D40; - const GLenum RENDERBUFFER = 0x8D41; - - const GLenum RGBA4 = 0x8056; - const GLenum RGB5_A1 = 0x8057; - const GLenum RGB565 = 0x8D62; - const GLenum DEPTH_COMPONENT16 = 0x81A5; - const GLenum STENCIL_INDEX = 0x1901; - const GLenum STENCIL_INDEX8 = 0x8D48; - const GLenum DEPTH_STENCIL = 0x84F9; - - const GLenum RENDERBUFFER_WIDTH = 0x8D42; - const GLenum RENDERBUFFER_HEIGHT = 0x8D43; - const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44; - const GLenum RENDERBUFFER_RED_SIZE = 0x8D50; - const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51; - const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52; - const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53; - const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54; - const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55; - - const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0; - const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1; - const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2; - const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3; - - const GLenum COLOR_ATTACHMENT0 = 0x8CE0; - const GLenum DEPTH_ATTACHMENT = 0x8D00; - const GLenum STENCIL_ATTACHMENT = 0x8D20; - const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; - - const GLenum NONE = 0; - - const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5; - const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6; - const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7; - const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9; - const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD; - - const GLenum FRAMEBUFFER_BINDING = 0x8CA6; - const GLenum RENDERBUFFER_BINDING = 0x8CA7; - const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8; - - const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506; - - /* WebGL-specific enums */ - const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240; - const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; - const GLenum CONTEXT_LOST_WEBGL = 0x9242; - const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; - const GLenum BROWSER_DEFAULT_WEBGL = 0x9244; - - readonly attribute GLsizei drawingBufferWidth; - readonly attribute GLsizei drawingBufferHeight; - - [StrictTypeChecking] void activeTexture(GLenum texture); - [StrictTypeChecking] void attachShader(WebGLProgram program, WebGLShader shader); - [StrictTypeChecking] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name); - [StrictTypeChecking] void bindBuffer(GLenum target, WebGLBuffer buffer); - [StrictTypeChecking] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer); - [StrictTypeChecking] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] void bindTexture(GLenum target, WebGLTexture texture); - [StrictTypeChecking] void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - [StrictTypeChecking] void blendEquation(GLenum mode); - [StrictTypeChecking] void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); - [StrictTypeChecking] void blendFunc(GLenum sfactor, GLenum dfactor); - [StrictTypeChecking] void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); - [StrictTypeChecking] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage); - [StrictTypeChecking] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage); - [StrictTypeChecking] void bufferData(GLenum target, GLsizeiptr size, GLenum usage); - [StrictTypeChecking] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data); - [StrictTypeChecking] void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView? data); - - [StrictTypeChecking] GLenum checkFramebufferStatus(GLenum target); - [StrictTypeChecking] void clear(GLbitfield mask); - [StrictTypeChecking] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - [StrictTypeChecking] void clearDepth(GLclampf depth); - [StrictTypeChecking] void clearStencil(GLint s); - [StrictTypeChecking] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); - [StrictTypeChecking] void compileShader(WebGLShader shader); - - [StrictTypeChecking] void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, ArrayBufferView data); - [StrictTypeChecking] void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, GLenum format, ArrayBufferView data); - - [StrictTypeChecking] void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); - [StrictTypeChecking] void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); - - [StrictTypeChecking] WebGLBuffer createBuffer(); - [StrictTypeChecking] WebGLFramebuffer createFramebuffer(); - [StrictTypeChecking] WebGLProgram createProgram(); - [StrictTypeChecking] WebGLRenderbuffer createRenderbuffer(); - [StrictTypeChecking] WebGLShader createShader(GLenum type); - [StrictTypeChecking] WebGLTexture createTexture(); - - [StrictTypeChecking] void cullFace(GLenum mode); - - [StrictTypeChecking] void deleteBuffer(WebGLBuffer buffer); - [StrictTypeChecking] void deleteFramebuffer(WebGLFramebuffer framebuffer); - [StrictTypeChecking] void deleteProgram(WebGLProgram program); - [StrictTypeChecking] void deleteRenderbuffer(WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] void deleteShader(WebGLShader shader); - [StrictTypeChecking] void deleteTexture(WebGLTexture texture); - - [StrictTypeChecking] void depthFunc(GLenum func); - [StrictTypeChecking] void depthMask(GLboolean flag); - [StrictTypeChecking] void depthRange(GLclampf zNear, GLclampf zFar); - [StrictTypeChecking] void detachShader(WebGLProgram program, WebGLShader shader); - [StrictTypeChecking] void disable(GLenum cap); - [StrictTypeChecking] void disableVertexAttribArray(GLuint index); - [StrictTypeChecking] void drawArrays(GLenum mode, GLint first, GLsizei count); - [StrictTypeChecking] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset); - - [StrictTypeChecking] void enable(GLenum cap); - [StrictTypeChecking] void enableVertexAttribArray(GLuint index); - [StrictTypeChecking] void finish(); - [StrictTypeChecking] void flush(); - [StrictTypeChecking] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level); - [StrictTypeChecking] void frontFace(GLenum mode); - [StrictTypeChecking] void generateMipmap(GLenum target); - - [StrictTypeChecking] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index); - [StrictTypeChecking] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index); - - [StrictTypeChecking, Custom] void getAttachedShaders(WebGLProgram program); - - [StrictTypeChecking] GLint getAttribLocation(WebGLProgram program, DOMString name); - - [StrictTypeChecking, Custom] any getBufferParameter(GLenum target, GLenum pname); - - [StrictTypeChecking] WebGLContextAttributes getContextAttributes(); - - [StrictTypeChecking] GLenum getError(); - - // object getExtension(DOMString name); - [StrictTypeChecking, Custom] any getExtension(DOMString name); - - [StrictTypeChecking, Custom] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); - [StrictTypeChecking, Custom] any getParameter(GLenum pname); - [StrictTypeChecking, Custom] any getProgramParameter(WebGLProgram program, GLenum pname); - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getProgramInfoLog(WebGLProgram program); - [StrictTypeChecking, Custom] any getRenderbufferParameter(GLenum target, GLenum pname); - [StrictTypeChecking, Custom] any getShaderParameter(WebGLShader shader, GLenum pname); - - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getShaderInfoLog(WebGLShader shader); - - [StrictTypeChecking] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); - - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getShaderSource(WebGLShader shader); - - [StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions(); - - [StrictTypeChecking, Custom] any getTexParameter(GLenum target, GLenum pname); - - [StrictTypeChecking, Custom] any getUniform(WebGLProgram program, WebGLUniformLocation location); - - [StrictTypeChecking] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name); - - [StrictTypeChecking, Custom] any getVertexAttrib(GLuint index, GLenum pname); - - [StrictTypeChecking] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); - - [StrictTypeChecking] void hint(GLenum target, GLenum mode); - [StrictTypeChecking] GLboolean isBuffer(WebGLBuffer buffer); - [StrictTypeChecking] GLboolean isContextLost(); - [StrictTypeChecking] GLboolean isEnabled(GLenum cap); - [StrictTypeChecking] GLboolean isFramebuffer(WebGLFramebuffer framebuffer); - [StrictTypeChecking] GLboolean isProgram(WebGLProgram program); - [StrictTypeChecking] GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] GLboolean isShader(WebGLShader shader); - [StrictTypeChecking] GLboolean isTexture(WebGLTexture texture); - [StrictTypeChecking] void lineWidth(GLfloat width); - [StrictTypeChecking] void linkProgram(WebGLProgram program); - [StrictTypeChecking] void pixelStorei(GLenum pname, GLint param); - [StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units); - - [StrictTypeChecking] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels); - - [StrictTypeChecking] void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); - [StrictTypeChecking] void sampleCoverage(GLclampf value, GLboolean invert); - [StrictTypeChecking] void scissor(GLint x, GLint y, GLsizei width, GLsizei height); - [StrictTypeChecking] void shaderSource(WebGLShader shader, DOMString string); - [StrictTypeChecking] void stencilFunc(GLenum func, GLint ref, GLuint mask); - [StrictTypeChecking] void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); - [StrictTypeChecking] void stencilMask(GLuint mask); - [StrictTypeChecking] void stencilMaskSeparate(GLenum face, GLuint mask); - [StrictTypeChecking] void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); - [StrictTypeChecking] void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); - - [StrictTypeChecking] void texParameterf(GLenum target, GLenum pname, GLfloat param); - [StrictTypeChecking] void texParameteri(GLenum target, GLenum pname, GLint param); - - // Supported forms: - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, ImageData? pixels); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLImageElement? image); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLCanvasElement? canvas); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLVideoElement? video); - - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, ArrayBufferView? pixels); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, ImageData? pixels); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLImageElement? image); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLCanvasElement? canvas); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLVideoElement? video); - - [StrictTypeChecking] void uniform1f(WebGLUniformLocation location, GLfloat x); - [StrictTypeChecking, Custom] void uniform1fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform1i(WebGLUniformLocation location, GLint x); - [StrictTypeChecking, Custom] void uniform1iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y); - [StrictTypeChecking, Custom] void uniform2fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform2i(WebGLUniformLocation location, GLint x, GLint y); - [StrictTypeChecking, Custom] void uniform2iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z); - [StrictTypeChecking, Custom] void uniform3fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z); - [StrictTypeChecking, Custom] void uniform3iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - [StrictTypeChecking, Custom] void uniform4fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w); - [StrictTypeChecking, Custom] void uniform4iv(WebGLUniformLocation location, Int32Array v); - - [StrictTypeChecking, Custom] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - [StrictTypeChecking, Custom] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - [StrictTypeChecking, Custom] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - - [StrictTypeChecking] void useProgram(WebGLProgram program); - [StrictTypeChecking] void validateProgram(WebGLProgram program); - - [StrictTypeChecking] void vertexAttrib1f(GLuint indx, GLfloat x); - [StrictTypeChecking, Custom] void vertexAttrib1fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); - [StrictTypeChecking, Custom] void vertexAttrib2fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); - [StrictTypeChecking, Custom] void vertexAttrib3fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - [StrictTypeChecking, Custom] void vertexAttrib4fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, - GLsizei stride, GLintptr offset); - - [StrictTypeChecking] void viewport(GLint x, GLint y, GLsizei width, GLsizei height); -}; + DoNotCheckConstants, + TypeChecking=Interface|Nullable, + WillBeGarbageCollected, +] interface WebGLRenderingContext { }; +WebGLRenderingContext implements WebGLRenderingContextBase; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.cpp new file mode 100644 index 00000000000..b587a6899c1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.cpp @@ -0,0 +1,5728 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" + +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" +#include "core/fetch/ImageResource.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLCanvasElement.h" +#include "core/html/HTMLImageElement.h" +#include "core/html/HTMLVideoElement.h" +#include "core/html/ImageData.h" +#include "core/html/canvas/ANGLEInstancedArrays.h" +#include "core/html/canvas/EXTBlendMinMax.h" +#include "core/html/canvas/EXTFragDepth.h" +#include "core/html/canvas/EXTShaderTextureLOD.h" +#include "core/html/canvas/EXTTextureFilterAnisotropic.h" +#include "core/html/canvas/OESElementIndexUint.h" +#include "core/html/canvas/OESStandardDerivatives.h" +#include "core/html/canvas/OESTextureFloat.h" +#include "core/html/canvas/OESTextureFloatLinear.h" +#include "core/html/canvas/OESTextureHalfFloat.h" +#include "core/html/canvas/OESTextureHalfFloatLinear.h" +#include "core/html/canvas/OESVertexArrayObject.h" +#include "core/html/canvas/WebGLActiveInfo.h" +#include "core/html/canvas/WebGLBuffer.h" +#include "core/html/canvas/WebGLCompressedTextureATC.h" +#include "core/html/canvas/WebGLCompressedTextureETC1.h" +#include "core/html/canvas/WebGLCompressedTexturePVRTC.h" +#include "core/html/canvas/WebGLCompressedTextureS3TC.h" +#include "core/html/canvas/WebGLContextAttributes.h" +#include "core/html/canvas/WebGLContextEvent.h" +#include "core/html/canvas/WebGLContextGroup.h" +#include "core/html/canvas/WebGLDebugRendererInfo.h" +#include "core/html/canvas/WebGLDebugShaders.h" +#include "core/html/canvas/WebGLDepthTexture.h" +#include "core/html/canvas/WebGLDrawBuffers.h" +#include "core/html/canvas/WebGLFramebuffer.h" +#include "core/html/canvas/WebGLLoseContext.h" +#include "core/html/canvas/WebGLProgram.h" +#include "core/html/canvas/WebGLRenderbuffer.h" +#include "core/html/canvas/WebGLShader.h" +#include "core/html/canvas/WebGLShaderPrecisionFormat.h" +#include "core/html/canvas/WebGLTexture.h" +#include "core/html/canvas/WebGLUniformLocation.h" +#include "core/inspector/InspectorInstrumentation.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/rendering/RenderBox.h" +#include "platform/CheckedInt.h" +#include "platform/NotImplemented.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/geometry/IntSize.h" +#include "platform/graphics/GraphicsContext.h" +#include "platform/graphics/UnacceleratedImageBufferSurface.h" +#include "platform/graphics/gpu/DrawingBuffer.h" +#include "public/platform/Platform.h" + +#include "wtf/PassOwnPtr.h" +#include "wtf/Uint32Array.h" +#include "wtf/text/StringBuilder.h" + +namespace WebCore { + +const double secondsBetweenRestoreAttempts = 1.0; +const int maxGLErrorsAllowedToConsole = 256; +const unsigned maxGLActiveContexts = 16; + +Vector<WebGLRenderingContextBase*>& WebGLRenderingContextBase::activeContexts() +{ + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContextBase*>, activeContexts, ()); + return activeContexts; +} + +Vector<WebGLRenderingContextBase*>& WebGLRenderingContextBase::forciblyEvictedContexts() +{ + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContextBase*>, forciblyEvictedContexts, ()); + return forciblyEvictedContexts; +} + +void WebGLRenderingContextBase::forciblyLoseOldestContext(const String& reason) +{ + size_t candidateID = oldestContextIndex(); + if (candidateID >= activeContexts().size()) + return; + + WebGLRenderingContextBase* candidate = activeContexts()[candidateID]; + + activeContexts().remove(candidateID); + + candidate->printWarningToConsole(reason); + InspectorInstrumentation::didFireWebGLWarning(candidate->canvas()); + + // This will call deactivateContext once the context has actually been lost. + candidate->forceLostContext(WebGLRenderingContextBase::SyntheticLostContext); +} + +size_t WebGLRenderingContextBase::oldestContextIndex() +{ + if (!activeContexts().size()) + return maxGLActiveContexts; + + WebGLRenderingContextBase* candidate = activeContexts().first(); + blink::WebGraphicsContext3D* candidateWGC3D = candidate->isContextLost() ? 0 : candidate->webContext(); + size_t candidateID = 0; + for (size_t ii = 1; ii < activeContexts().size(); ++ii) { + WebGLRenderingContextBase* context = activeContexts()[ii]; + blink::WebGraphicsContext3D* contextWGC3D = context->isContextLost() ? 0 : context->webContext(); + if (contextWGC3D && candidateWGC3D && contextWGC3D->lastFlushID() < candidateWGC3D->lastFlushID()) { + candidate = context; + candidateID = ii; + } + } + + return candidateID; +} + +IntSize WebGLRenderingContextBase::oldestContextSize() +{ + IntSize size; + + size_t candidateID = oldestContextIndex(); + if (candidateID < activeContexts().size()) { + WebGLRenderingContextBase* candidate = activeContexts()[candidateID]; + size.setWidth(candidate->drawingBufferWidth()); + size.setHeight(candidate->drawingBufferHeight()); + } + + return size; +} + +void WebGLRenderingContextBase::activateContext(WebGLRenderingContextBase* context) +{ + unsigned removedContexts = 0; + while (activeContexts().size() >= maxGLActiveContexts && removedContexts < maxGLActiveContexts) { + forciblyLoseOldestContext("WARNING: Too many active WebGL contexts. Oldest context will be lost."); + removedContexts++; + } + + if (!activeContexts().contains(context)) + activeContexts().append(context); +} + +void WebGLRenderingContextBase::deactivateContext(WebGLRenderingContextBase* context, bool addToEvictedList) +{ + size_t position = activeContexts().find(context); + if (position != WTF::kNotFound) + activeContexts().remove(position); + + if (addToEvictedList && !forciblyEvictedContexts().contains(context)) + forciblyEvictedContexts().append(context); +} + +void WebGLRenderingContextBase::willDestroyContext(WebGLRenderingContextBase* context) +{ + size_t position = forciblyEvictedContexts().find(context); + if (position != WTF::kNotFound) + forciblyEvictedContexts().remove(position); + + deactivateContext(context, false); + + // Try to re-enable the oldest inactive contexts. + while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContexts().size()) { + WebGLRenderingContextBase* evictedContext = forciblyEvictedContexts().first(); + if (!evictedContext->m_restoreAllowed) { + forciblyEvictedContexts().remove(0); + continue; + } + + IntSize desiredSize = DrawingBuffer::adjustSize(evictedContext->clampedCanvasSize(), IntSize(), evictedContext->m_maxTextureSize); + + // If there's room in the pixel budget for this context, restore it. + if (!desiredSize.isEmpty()) { + forciblyEvictedContexts().remove(0); + evictedContext->forceRestoreContext(); + activeContexts().append(evictedContext); + } + break; + } +} + +class WebGLRenderingContextEvictionManager : public ContextEvictionManager { +public: + void forciblyLoseOldestContext(const String& reason) { + WebGLRenderingContextBase::forciblyLoseOldestContext(reason); + }; + IntSize oldestContextSize() { + return WebGLRenderingContextBase::oldestContextSize(); + }; +}; + +namespace { + + class ScopedDrawingBufferBinder { + public: + ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding) + : m_drawingBuffer(drawingBuffer) + , m_framebufferBinding(framebufferBinding) + { + // Commit DrawingBuffer if needed (e.g., for multisampling) + if (!m_framebufferBinding && m_drawingBuffer) + m_drawingBuffer->commit(); + } + + ~ScopedDrawingBufferBinder() + { + // Restore DrawingBuffer if needed + if (!m_framebufferBinding && m_drawingBuffer) + m_drawingBuffer->bind(); + } + + private: + DrawingBuffer* m_drawingBuffer; + WebGLFramebuffer* m_framebufferBinding; + }; + + Platform3DObject objectOrZero(WebGLObject* object) + { + return object ? object->object() : 0; + } + + GLint clamp(GLint value, GLint min, GLint max) + { + if (value < min) + value = min; + if (value > max) + value = max; + return value; + } + + // Return true if a character belongs to the ASCII subset as defined in + // GLSL ES 1.0 spec section 3.1. + bool validateCharacter(unsigned char c) + { + // Printing characters are valid except " $ ` @ \ ' DEL. + if (c >= 32 && c <= 126 + && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') + return true; + // Horizontal tab, line feed, vertical tab, form feed, carriage return + // are also valid. + if (c >= 9 && c <= 13) + return true; + return false; + } + + bool isPrefixReserved(const String& name) + { + if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_")) + return true; + return false; + } + + // Strips comments from shader text. This allows non-ASCII characters + // to be used in comments without potentially breaking OpenGL + // implementations not expecting characters outside the GLSL ES set. + class StripComments { + public: + StripComments(const String& str) + : m_parseState(BeginningOfLine) + , m_sourceString(str) + , m_length(str.length()) + , m_position(0) + { + parse(); + } + + String result() + { + return m_builder.toString(); + } + + private: + bool hasMoreCharacters() const + { + return (m_position < m_length); + } + + void parse() + { + while (hasMoreCharacters()) { + process(current()); + // process() might advance the position. + if (hasMoreCharacters()) + advance(); + } + } + + void process(UChar); + + bool peek(UChar& character) const + { + if (m_position + 1 >= m_length) + return false; + character = m_sourceString[m_position + 1]; + return true; + } + + UChar current() + { + ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length); + return m_sourceString[m_position]; + } + + void advance() + { + ++m_position; + } + + static bool isNewline(UChar character) + { + // Don't attempt to canonicalize newline related characters. + return (character == '\n' || character == '\r'); + } + + void emit(UChar character) + { + m_builder.append(character); + } + + enum ParseState { + // Have not seen an ASCII non-whitespace character yet on + // this line. Possible that we might see a preprocessor + // directive. + BeginningOfLine, + + // Have seen at least one ASCII non-whitespace character + // on this line. + MiddleOfLine, + + // Handling a preprocessor directive. Passes through all + // characters up to the end of the line. Disables comment + // processing. + InPreprocessorDirective, + + // Handling a single-line comment. The comment text is + // replaced with a single space. + InSingleLineComment, + + // Handling a multi-line comment. Newlines are passed + // through to preserve line numbers. + InMultiLineComment + }; + + ParseState m_parseState; + String m_sourceString; + unsigned m_length; + unsigned m_position; + StringBuilder m_builder; + }; + + void StripComments::process(UChar c) + { + if (isNewline(c)) { + // No matter what state we are in, pass through newlines + // so we preserve line numbers. + emit(c); + + if (m_parseState != InMultiLineComment) + m_parseState = BeginningOfLine; + + return; + } + + UChar temp = 0; + switch (m_parseState) { + case BeginningOfLine: + if (WTF::isASCIISpace(c)) { + emit(c); + break; + } + + if (c == '#') { + m_parseState = InPreprocessorDirective; + emit(c); + break; + } + + // Transition to normal state and re-handle character. + m_parseState = MiddleOfLine; + process(c); + break; + + case MiddleOfLine: + if (c == '/' && peek(temp)) { + if (temp == '/') { + m_parseState = InSingleLineComment; + emit(' '); + advance(); + break; + } + + if (temp == '*') { + m_parseState = InMultiLineComment; + // Emit the comment start in case the user has + // an unclosed comment and we want to later + // signal an error. + emit('/'); + emit('*'); + advance(); + break; + } + } + + emit(c); + break; + + case InPreprocessorDirective: + // No matter what the character is, just pass it + // through. Do not parse comments in this state. This + // might not be the right thing to do long term, but it + // should handle the #error preprocessor directive. + emit(c); + break; + + case InSingleLineComment: + // The newline code at the top of this function takes care + // of resetting our state when we get out of the + // single-line comment. Swallow all other characters. + break; + + case InMultiLineComment: + if (c == '*' && peek(temp) && temp == '/') { + emit('*'); + emit('/'); + m_parseState = MiddleOfLine; + advance(); + break; + } + + // Swallow all other characters. Unclear whether we may + // want or need to just emit a space per character to try + // to preserve column numbers for debugging purposes. + break; + } + } +} // namespace anonymous + +class ScopedTexture2DRestorer { +public: + ScopedTexture2DRestorer(WebGLRenderingContextBase* context) + : m_context(context) + { + } + + ~ScopedTexture2DRestorer() + { + m_context->restoreCurrentTexture2D(); + } + +private: + WebGLRenderingContextBase* m_context; +}; + +class WebGLRenderingContextLostCallback : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WebGLRenderingContextLostCallback(WebGLRenderingContextBase* cb) : m_context(cb) { } + virtual void onContextLost() { m_context->forceLostContext(WebGLRenderingContextBase::RealLostContext); } + virtual ~WebGLRenderingContextLostCallback() {} +private: + WebGLRenderingContextBase* m_context; +}; + +class WebGLRenderingContextErrorMessageCallback : public blink::WebGraphicsContext3D::WebGraphicsErrorMessageCallback { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContextBase* cb) : m_context(cb) { } + virtual void onErrorMessage(const blink::WebString& message, blink::WGC3Dint) + { + if (m_context->m_synthesizedErrorsToConsole) + m_context->printGLErrorToConsole(message); + InspectorInstrumentation::didFireWebGLErrorOrWarning(m_context->canvas(), message); + } + virtual ~WebGLRenderingContextErrorMessageCallback() { } +private: + WebGLRenderingContextBase* m_context; +}; + +WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, PassOwnPtr<blink::WebGraphicsContext3D> context, WebGLContextAttributes* requestedAttributes) + : CanvasRenderingContext(passedCanvas) + , ActiveDOMObject(&passedCanvas->document()) + , m_drawingBuffer(nullptr) + , m_dispatchContextLostEventTimer(this, &WebGLRenderingContextBase::dispatchContextLostEvent) + , m_restoreAllowed(false) + , m_restoreTimer(this, &WebGLRenderingContextBase::maybeRestoreContext) + , m_generatedImageCache(4) + , m_contextLost(false) + , m_contextLostMode(SyntheticLostContext) + , m_requestedAttributes(requestedAttributes->clone()) + , m_synthesizedErrorsToConsole(true) + , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) + , m_multisamplingAllowed(false) + , m_multisamplingObserverRegistered(false) + , m_onePlusMaxEnabledAttribIndex(0) + , m_onePlusMaxNonDefaultTextureUnit(0) + , m_savingImage(false) +{ + ASSERT(context); + + m_contextGroup = WebGLContextGroup::create(); + m_contextGroup->addContext(this); + + m_maxViewportDims[0] = m_maxViewportDims[1] = 0; + context->getIntegerv(GL_MAX_VIEWPORT_DIMS, m_maxViewportDims); + + m_drawingBuffer = createDrawingBuffer(context); + if (!m_drawingBuffer) + return; + + m_drawingBuffer->bind(); + setupFlags(); + initializeNewContext(); +} + +PassRefPtr<DrawingBuffer> WebGLRenderingContextBase::createDrawingBuffer(PassOwnPtr<blink::WebGraphicsContext3D> context) +{ + RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager()); + + blink::WebGraphicsContext3D::Attributes attrs; + attrs.alpha = m_requestedAttributes->alpha(); + attrs.depth = m_requestedAttributes->depth(); + attrs.stencil = m_requestedAttributes->stencil(); + attrs.antialias = m_requestedAttributes->antialias(); + attrs.premultipliedAlpha = m_requestedAttributes->premultipliedAlpha(); + DrawingBuffer::PreserveDrawingBuffer preserve = m_requestedAttributes->preserveDrawingBuffer() ? DrawingBuffer::Preserve : DrawingBuffer::Discard; + return DrawingBuffer::create(context, clampedCanvasSize(), preserve, attrs, contextEvictionManager.release()); +} + +void WebGLRenderingContextBase::initializeNewContext() +{ + ASSERT(!isContextLost()); + m_needsUpdate = true; + m_markedCanvasDirty = false; + m_activeTextureUnit = 0; + m_packAlignment = 4; + m_unpackAlignment = 4; + m_unpackFlipY = false; + m_unpackPremultiplyAlpha = false; + m_unpackColorspaceConversion = GC3D_BROWSER_DEFAULT_WEBGL; + m_boundArrayBuffer = nullptr; + m_currentProgram = nullptr; + m_framebufferBinding = nullptr; + m_renderbufferBinding = nullptr; + m_depthMask = true; + m_stencilEnabled = false; + m_stencilMask = 0xFFFFFFFF; + m_stencilMaskBack = 0xFFFFFFFF; + m_stencilFuncRef = 0; + m_stencilFuncRefBack = 0; + m_stencilFuncMask = 0xFFFFFFFF; + m_stencilFuncMaskBack = 0xFFFFFFFF; + m_layerCleared = false; + m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole; + + m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0; + m_scissorEnabled = false; + m_clearDepth = 1; + m_clearStencil = 0; + m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true; + + GLint numCombinedTextureImageUnits = 0; + webContext()->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); + m_textureUnits.clear(); + m_textureUnits.resize(numCombinedTextureImageUnits); + + GLint numVertexAttribs = 0; + webContext()->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs); + m_maxVertexAttribs = numVertexAttribs; + + m_maxTextureSize = 0; + webContext()->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); + m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); + m_maxCubeMapTextureSize = 0; + webContext()->getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); + m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); + m_maxRenderbufferSize = 0; + webContext()->getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize); + + // These two values from EXT_draw_buffers are lazily queried. + m_maxDrawBuffers = 0; + m_maxColorAttachments = 0; + + m_backDrawBuffer = GL_BACK; + + m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault); + addContextObject(m_defaultVertexArrayObject.get()); + m_boundVertexArrayObject = m_defaultVertexArrayObject; + + m_vertexAttribValue.resize(m_maxVertexAttribs); + + createFallbackBlackTextures1x1(); + + webContext()->viewport(0, 0, drawingBufferWidth(), drawingBufferHeight()); + webContext()->scissor(0, 0, drawingBufferWidth(), drawingBufferHeight()); + + m_contextLostCallbackAdapter = adoptPtr(new WebGLRenderingContextLostCallback(this)); + m_errorMessageCallbackAdapter = adoptPtr(new WebGLRenderingContextErrorMessageCallback(this)); + + webContext()->setContextLostCallback(m_contextLostCallbackAdapter.get()); + webContext()->setErrorMessageCallback(m_errorMessageCallbackAdapter.get()); + + // This ensures that the context has a valid "lastFlushID" and won't be mistakenly identified as the "least recently used" context. + webContext()->flush(); + + for (int i = 0; i < WebGLExtensionNameCount; ++i) + m_extensionEnabled[i] = false; + + activateContext(this); +} + +void WebGLRenderingContextBase::setupFlags() +{ + ASSERT(m_drawingBuffer); + if (Page* p = canvas()->document().page()) { + m_synthesizedErrorsToConsole = p->settings().webGLErrorsToConsoleEnabled(); + + if (!m_multisamplingObserverRegistered && m_requestedAttributes->antialias()) { + m_multisamplingAllowed = m_drawingBuffer->multisample(); + p->addMultisamplingChangedObserver(this); + m_multisamplingObserverRegistered = true; + } + } + + m_isGLES2NPOTStrict = !extensionsUtil()->isExtensionEnabled("GL_OES_texture_npot"); + m_isDepthStencilSupported = extensionsUtil()->isExtensionEnabled("GL_OES_packed_depth_stencil"); +} + +void WebGLRenderingContextBase::addCompressedTextureFormat(GLenum format) +{ + if (!m_compressedTextureFormats.contains(format)) + m_compressedTextureFormats.append(format); +} + +void WebGLRenderingContextBase::removeAllCompressedTextureFormats() +{ + m_compressedTextureFormats.clear(); +} + +// Helper function for V8 bindings to identify what version of WebGL a CanvasRenderingContext supports. +unsigned WebGLRenderingContextBase::getWebGLVersion(const CanvasRenderingContext* context) +{ + if (!context->is3d()) + return 0; + return static_cast<const WebGLRenderingContextBase*>(context)->version(); +} + +WebGLRenderingContextBase::~WebGLRenderingContextBase() +{ + // Remove all references to WebGLObjects so if they are the last reference + // they will be freed before the last context is removed from the context group. + m_boundArrayBuffer = nullptr; + m_defaultVertexArrayObject = nullptr; + m_boundVertexArrayObject = nullptr; + m_vertexAttrib0Buffer = nullptr; + m_currentProgram = nullptr; + m_framebufferBinding = nullptr; + m_renderbufferBinding = nullptr; + + for (size_t i = 0; i < m_textureUnits.size(); ++i) { + m_textureUnits[i].m_texture2DBinding = nullptr; + m_textureUnits[i].m_textureCubeMapBinding = nullptr; + } + + m_blackTexture2D = nullptr; + m_blackTextureCubeMap = nullptr; + + detachAndRemoveAllObjects(); + + // release all extensions + for (size_t i = 0; i < m_extensions.size(); ++i) + delete m_extensions[i]; + + // Context must be removed from the group prior to the destruction of the + // WebGraphicsContext3D, otherwise shared objects may not be properly deleted. + m_contextGroup->removeContext(this); + + destroyContext(); + +#if !ENABLE(OILPAN) + if (m_multisamplingObserverRegistered) { + Page* page = canvas()->document().page(); + if (page) + page->removeMultisamplingChangedObserver(this); + } +#endif + + willDestroyContext(this); +} + +void WebGLRenderingContextBase::destroyContext() +{ + m_contextLost = true; + + if (!m_drawingBuffer) + return; + + m_extensionsUtil.clear(); + + webContext()->setContextLostCallback(0); + webContext()->setErrorMessageCallback(0); + + ASSERT(m_drawingBuffer); + m_drawingBuffer->beginDestruction(); + m_drawingBuffer.clear(); +} + +void WebGLRenderingContextBase::markContextChanged(ContentChangeType changeType) +{ + if (m_framebufferBinding || isContextLost()) + return; + + m_drawingBuffer->markContentsChanged(); + + m_layerCleared = false; + RenderBox* renderBox = canvas()->renderBox(); + if (renderBox && renderBox->hasAcceleratedCompositing()) { + m_markedCanvasDirty = true; + canvas()->clearCopiedImage(); + renderBox->contentChanged(changeType); + } else { + if (!m_markedCanvasDirty) { + m_markedCanvasDirty = true; + canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize())); + } + } +} + +bool WebGLRenderingContextBase::clearIfComposited(GLbitfield mask) +{ + if (isContextLost()) + return false; + + if (!m_drawingBuffer->layerComposited() || m_layerCleared + || m_requestedAttributes->preserveDrawingBuffer() || (mask && m_framebufferBinding)) + return false; + + RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes(); + + // Determine if it's possible to combine the clear the user asked for and this clear. + bool combinedClear = mask && !m_scissorEnabled; + + webContext()->disable(GL_SCISSOR_TEST); + if (combinedClear && (mask & GL_COLOR_BUFFER_BIT)) { + webContext()->clearColor(m_colorMask[0] ? m_clearColor[0] : 0, + m_colorMask[1] ? m_clearColor[1] : 0, + m_colorMask[2] ? m_clearColor[2] : 0, + m_colorMask[3] ? m_clearColor[3] : 0); + } else { + webContext()->clearColor(0, 0, 0, 0); + } + webContext()->colorMask(true, true, true, true); + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; + if (contextAttributes->depth()) { + if (!combinedClear || !m_depthMask || !(mask & GL_DEPTH_BUFFER_BIT)) + webContext()->clearDepth(1.0f); + clearMask |= GL_DEPTH_BUFFER_BIT; + webContext()->depthMask(true); + } + if (contextAttributes->stencil()) { + if (combinedClear && (mask & GL_STENCIL_BUFFER_BIT)) + webContext()->clearStencil(m_clearStencil & m_stencilMask); + else + webContext()->clearStencil(0); + clearMask |= GL_STENCIL_BUFFER_BIT; + webContext()->stencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); + } + + m_drawingBuffer->clearFramebuffers(clearMask); + + restoreStateAfterClear(); + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + m_layerCleared = true; + + return combinedClear; +} + +void WebGLRenderingContextBase::restoreStateAfterClear() +{ + if (isContextLost()) + return; + + // Restore the state that the context set. + if (m_scissorEnabled) + webContext()->enable(GL_SCISSOR_TEST); + webContext()->clearColor(m_clearColor[0], m_clearColor[1], + m_clearColor[2], m_clearColor[3]); + webContext()->colorMask(m_colorMask[0], m_colorMask[1], + m_colorMask[2], m_colorMask[3]); + webContext()->clearDepth(m_clearDepth); + webContext()->clearStencil(m_clearStencil); + webContext()->stencilMaskSeparate(GL_FRONT, m_stencilMask); + webContext()->depthMask(m_depthMask); +} + +void WebGLRenderingContextBase::markLayerComposited() +{ + if (!isContextLost()) + m_drawingBuffer->markLayerComposited(); +} + +void WebGLRenderingContextBase::paintRenderingResultsToCanvas() +{ + if (isContextLost()) { + canvas()->clearPresentationCopy(); + return; + } + + if (canvas()->document().printing()) + canvas()->clearPresentationCopy(); + + // Until the canvas is written to by the application, the clear that + // happened after it was composited should be ignored by the compositor. + if (m_drawingBuffer->layerComposited() && !m_requestedAttributes->preserveDrawingBuffer()) { + m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer()); + + canvas()->makePresentationCopy(); + } else + canvas()->clearPresentationCopy(); + + clearIfComposited(); + + if (!m_markedCanvasDirty && !m_layerCleared) + return; + + canvas()->clearCopiedImage(); + m_markedCanvasDirty = false; + + ScopedTexture2DRestorer restorer(this); + + m_drawingBuffer->commit(); + if (!(canvas()->buffer())->copyRenderingResultsFromDrawingBuffer(m_drawingBuffer.get(), m_savingImage)) { + canvas()->ensureUnacceleratedImageBuffer(); + if (canvas()->hasImageBuffer()) + m_drawingBuffer->paintRenderingResultsToCanvas(canvas()->buffer()); + } + + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + else + m_drawingBuffer->bind(); +} + +PassRefPtrWillBeRawPtr<ImageData> WebGLRenderingContextBase::paintRenderingResultsToImageData() +{ + if (isContextLost()) + return nullptr; + + clearIfComposited(); + m_drawingBuffer->commit(); + int width, height; + RefPtr<Uint8ClampedArray> imageDataPixels = m_drawingBuffer->paintRenderingResultsToImageData(width, height); + if (!imageDataPixels) + return nullptr; + + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + else + m_drawingBuffer->bind(); + + return ImageData::create(IntSize(width, height), imageDataPixels); +} + +void WebGLRenderingContextBase::reshape(int width, int height) +{ + if (isContextLost()) + return; + + // This is an approximation because at WebGLRenderingContextBase level we don't + // know if the underlying FBO uses textures or renderbuffers. + GLint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize); + // Limit drawing buffer size to 4k to avoid memory exhaustion. + const int sizeUpperLimit = 4096; + maxSize = std::min(maxSize, sizeUpperLimit); + GLint maxWidth = std::min(maxSize, m_maxViewportDims[0]); + GLint maxHeight = std::min(maxSize, m_maxViewportDims[1]); + width = clamp(width, 1, maxWidth); + height = clamp(height, 1, maxHeight); + + if (m_needsUpdate) { + RenderBox* renderBox = canvas()->renderBox(); + if (renderBox && renderBox->hasAcceleratedCompositing()) + renderBox->contentChanged(CanvasChanged); + m_needsUpdate = false; + } + + // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off + // clear (and this matches what reshape will do). + m_drawingBuffer->reset(IntSize(width, height)); + restoreStateAfterClear(); + + webContext()->bindTexture(GL_TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get())); + webContext()->bindRenderbuffer(GL_RENDERBUFFER, objectOrZero(m_renderbufferBinding.get())); + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); +} + +int WebGLRenderingContextBase::drawingBufferWidth() const +{ + return isContextLost() ? 0 : m_drawingBuffer->size().width(); +} + +int WebGLRenderingContextBase::drawingBufferHeight() const +{ + return isContextLost() ? 0 : m_drawingBuffer->size().height(); +} + +unsigned WebGLRenderingContextBase::sizeInBytes(GLenum type) +{ + switch (type) { + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_FLOAT: + return sizeof(GLfloat); + } + ASSERT_NOT_REACHED(); + return 0; +} + +void WebGLRenderingContextBase::activeTexture(GLenum texture) +{ + if (isContextLost()) + return; + if (texture - GL_TEXTURE0 >= m_textureUnits.size()) { + synthesizeGLError(GL_INVALID_ENUM, "activeTexture", "texture unit out of range"); + return; + } + m_activeTextureUnit = texture - GL_TEXTURE0; + webContext()->activeTexture(texture); + + m_drawingBuffer->setActiveTextureUnit(texture); + +} + +void WebGLRenderingContextBase::attachShader(WebGLProgram* program, WebGLShader* shader) +{ + if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) + return; + if (!program->attachShader(shader)) { + synthesizeGLError(GL_INVALID_OPERATION, "attachShader", "shader attachment already has shader"); + return; + } + webContext()->attachShader(objectOrZero(program), objectOrZero(shader)); + shader->onAttached(); +} + +void WebGLRenderingContextBase::bindAttribLocation(WebGLProgram* program, GLuint index, const String& name) +{ + if (isContextLost() || !validateWebGLObject("bindAttribLocation", program)) + return; + if (!validateLocationLength("bindAttribLocation", name)) + return; + if (!validateString("bindAttribLocation", name)) + return; + if (isPrefixReserved(name)) { + synthesizeGLError(GL_INVALID_OPERATION, "bindAttribLocation", "reserved prefix"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "bindAttribLocation", "index out of range"); + return; + } + webContext()->bindAttribLocation(objectOrZero(program), index, name.utf8().data()); +} + +bool WebGLRenderingContextBase::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) +{ + deleted = false; + if (isContextLost()) + return false; + if (object) { + if (!object->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "object not from this context"); + return false; + } + deleted = !object->object(); + } + return true; +} + +void WebGLRenderingContextBase::bindBuffer(GLenum target, WebGLBuffer* buffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) + return; + if (deleted) + buffer = 0; + if (buffer && buffer->getTarget() && buffer->getTarget() != target) { + synthesizeGLError(GL_INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets"); + return; + } + if (target == GL_ARRAY_BUFFER) + m_boundArrayBuffer = buffer; + else if (target == GL_ELEMENT_ARRAY_BUFFER) + m_boundVertexArrayObject->setElementArrayBuffer(buffer); + else { + synthesizeGLError(GL_INVALID_ENUM, "bindBuffer", "invalid target"); + return; + } + + webContext()->bindBuffer(target, objectOrZero(buffer)); + if (buffer) + buffer->setTarget(target); +} + +void WebGLRenderingContextBase::bindFramebuffer(GLenum target, WebGLFramebuffer* buffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) + return; + if (deleted) + buffer = 0; + if (target != GL_FRAMEBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "bindFramebuffer", "invalid target"); + return; + } + m_framebufferBinding = buffer; + m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get())); + if (!m_framebufferBinding) { + // Instead of binding fb 0, bind the drawing buffer. + m_drawingBuffer->bind(); + } else { + webContext()->bindFramebuffer(target, objectOrZero(buffer)); + } + if (buffer) + buffer->setHasEverBeenBound(); + applyStencilTest(); +} + +void WebGLRenderingContextBase::bindRenderbuffer(GLenum target, WebGLRenderbuffer* renderBuffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) + return; + if (deleted) + renderBuffer = 0; + if (target != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "bindRenderbuffer", "invalid target"); + return; + } + m_renderbufferBinding = renderBuffer; + webContext()->bindRenderbuffer(target, objectOrZero(renderBuffer)); + if (renderBuffer) + renderBuffer->setHasEverBeenBound(); +} + +void WebGLRenderingContextBase::bindTexture(GLenum target, WebGLTexture* texture) +{ + bool deleted; + if (!checkObjectToBeBound("bindTexture", texture, deleted)) + return; + if (deleted) + texture = 0; + if (texture && texture->getTarget() && texture->getTarget() != target) { + synthesizeGLError(GL_INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); + return; + } + GLint maxLevel = 0; + if (target == GL_TEXTURE_2D) { + m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture; + maxLevel = m_maxTextureLevel; + + if (!m_activeTextureUnit) + m_drawingBuffer->setTexture2DBinding(objectOrZero(texture)); + + } else if (target == GL_TEXTURE_CUBE_MAP) { + m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture; + maxLevel = m_maxCubeMapTextureLevel; + } else { + synthesizeGLError(GL_INVALID_ENUM, "bindTexture", "invalid target"); + return; + } + + webContext()->bindTexture(target, objectOrZero(texture)); + if (texture) { + texture->setTarget(target, maxLevel); + m_onePlusMaxNonDefaultTextureUnit = max(m_activeTextureUnit + 1, m_onePlusMaxNonDefaultTextureUnit); + } else { + // If the disabled index is the current maximum, trace backwards to find the new max enabled texture index + if (m_onePlusMaxNonDefaultTextureUnit == m_activeTextureUnit + 1) { + findNewMaxNonDefaultTextureUnit(); + } + } + + // Note: previously we used to automatically set the TEXTURE_WRAP_R + // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL + // ES 2.0 doesn't expose this flag (a bug in the specification) and + // otherwise the application has no control over the seams in this + // dimension. However, it appears that supporting this properly on all + // platforms is fairly involved (will require a HashMap from texture ID + // in all ports), and we have not had any complaints, so the logic has + // been removed. + +} + +void WebGLRenderingContextBase::blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + if (isContextLost()) + return; + webContext()->blendColor(red, green, blue, alpha); +} + +void WebGLRenderingContextBase::blendEquation(GLenum mode) +{ + if (isContextLost() || !validateBlendEquation("blendEquation", mode)) + return; + webContext()->blendEquation(mode); +} + +void WebGLRenderingContextBase::blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + if (isContextLost() || !validateBlendEquation("blendEquationSeparate", modeRGB) || !validateBlendEquation("blendEquationSeparate", modeAlpha)) + return; + webContext()->blendEquationSeparate(modeRGB, modeAlpha); +} + + +void WebGLRenderingContextBase::blendFunc(GLenum sfactor, GLenum dfactor) +{ + if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor)) + return; + webContext()->blendFunc(sfactor, dfactor); +} + +void WebGLRenderingContextBase::blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + // Note: Alpha does not have the same restrictions as RGB. + if (isContextLost() || !validateBlendFuncFactors("blendFuncSeparate", srcRGB, dstRGB)) + return; + webContext()->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +void WebGLRenderingContextBase::bufferDataImpl(GLenum target, long long size, const void* data, GLenum usage) +{ + WebGLBuffer* buffer = validateBufferDataTarget("bufferData", target); + if (!buffer) + return; + + switch (usage) { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "bufferData", "invalid usage"); + return; + } + + if (!validateValueFitNonNegInt32("bufferData", "size", size)) + return; + + webContext()->bufferData(target, static_cast<GLsizeiptr>(size), data, usage); +} + +void WebGLRenderingContextBase::bufferData(GLenum target, long long size, GLenum usage) +{ + if (isContextLost()) + return; + if (!size) { + synthesizeGLError(GL_INVALID_VALUE, "bufferData", "size == 0"); + return; + } + bufferDataImpl(target, size, 0, usage); +} + +void WebGLRenderingContextBase::bufferData(GLenum target, ArrayBuffer* data, GLenum usage) +{ + if (isContextLost()) + return; + if (!data) { + synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); + return; + } + bufferDataImpl(target, data->byteLength(), data->data(), usage); +} + +void WebGLRenderingContextBase::bufferData(GLenum target, ArrayBufferView* data, GLenum usage) +{ + if (isContextLost()) + return; + if (!data) { + synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); + return; + } + bufferDataImpl(target, data->byteLength(), data->baseAddress(), usage); +} + +void WebGLRenderingContextBase::bufferSubDataImpl(GLenum target, long long offset, GLsizeiptr size, const void* data) +{ + WebGLBuffer* buffer = validateBufferDataTarget("bufferSubData", target); + if (!buffer) + return; + if (!validateValueFitNonNegInt32("bufferSubData", "offset", offset)) + return; + if (!data) + return; + + webContext()->bufferSubData(target, static_cast<GLintptr>(offset), size, data); +} + +void WebGLRenderingContextBase::bufferSubData(GLenum target, long long offset, ArrayBuffer* data) +{ + if (isContextLost()) + return; + if (!data) + return; + bufferSubDataImpl(target, offset, data->byteLength(), data->data()); +} + +void WebGLRenderingContextBase::bufferSubData(GLenum target, long long offset, ArrayBufferView* data) +{ + if (isContextLost()) + return; + if (!data) + return; + bufferSubDataImpl(target, offset, data->byteLength(), data->baseAddress()); +} + +GLenum WebGLRenderingContextBase::checkFramebufferStatus(GLenum target) +{ + if (isContextLost()) + return GL_FRAMEBUFFER_UNSUPPORTED; + if (target != GL_FRAMEBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "checkFramebufferStatus", "invalid target"); + return 0; + } + if (!m_framebufferBinding || !m_framebufferBinding->object()) + return GL_FRAMEBUFFER_COMPLETE; + const char* reason = "framebuffer incomplete"; + GLenum result = m_framebufferBinding->checkStatus(&reason); + if (result != GL_FRAMEBUFFER_COMPLETE) { + emitGLWarning("checkFramebufferStatus", reason); + return result; + } + result = webContext()->checkFramebufferStatus(target); + return result; +} + +void WebGLRenderingContextBase::clear(GLbitfield mask) +{ + if (isContextLost()) + return; + if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { + synthesizeGLError(GL_INVALID_VALUE, "clear", "invalid mask"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "clear", reason); + return; + } + if (!clearIfComposited(mask)) + webContext()->clear(mask); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::clearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) +{ + if (isContextLost()) + return; + if (std::isnan(r)) + r = 0; + if (std::isnan(g)) + g = 0; + if (std::isnan(b)) + b = 0; + if (std::isnan(a)) + a = 1; + m_clearColor[0] = r; + m_clearColor[1] = g; + m_clearColor[2] = b; + m_clearColor[3] = a; + webContext()->clearColor(r, g, b, a); +} + +void WebGLRenderingContextBase::clearDepth(GLfloat depth) +{ + if (isContextLost()) + return; + m_clearDepth = depth; + webContext()->clearDepth(depth); +} + +void WebGLRenderingContextBase::clearStencil(GLint s) +{ + if (isContextLost()) + return; + m_clearStencil = s; + webContext()->clearStencil(s); +} + +void WebGLRenderingContextBase::colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + if (isContextLost()) + return; + m_colorMask[0] = red; + m_colorMask[1] = green; + m_colorMask[2] = blue; + m_colorMask[3] = alpha; + webContext()->colorMask(red, green, blue, alpha); +} + +void WebGLRenderingContextBase::compileShader(WebGLShader* shader) +{ + if (isContextLost() || !validateWebGLObject("compileShader", shader)) + return; + webContext()->compileShader(objectOrZero(shader)); +} + +void WebGLRenderingContextBase::compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, ArrayBufferView* data) +{ + if (isContextLost()) + return; + if (!validateTexFuncLevel("compressedTexImage2D", target, level)) + return; + + if (!validateCompressedTexFormat(internalformat)) { + synthesizeGLError(GL_INVALID_ENUM, "compressedTexImage2D", "invalid internalformat"); + return; + } + if (border) { + synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "border not 0"); + return; + } + if (!validateCompressedTexDimensions("compressedTexImage2D", NotTexSubImage2D, target, level, width, height, internalformat)) + return; + if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data)) + return; + + WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true); + if (!tex) + return; + if (!isGLES2NPOTStrict()) { + if (level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2"); + return; + } + } + webContext()->compressedTexImage2D(target, level, internalformat, width, height, + border, data->byteLength(), data->baseAddress()); + tex->setLevelInfo(target, level, internalformat, width, height, GL_UNSIGNED_BYTE); +} + +void WebGLRenderingContextBase::compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* data) +{ + if (isContextLost()) + return; + if (!validateTexFuncLevel("compressedTexSubImage2D", target, level)) + return; + if (!validateCompressedTexFormat(format)) { + synthesizeGLError(GL_INVALID_ENUM, "compressedTexSubImage2D", "invalid format"); + return; + } + if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data)) + return; + + WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true); + if (!tex) + return; + + if (format != tex->getInternalFormat(target, level)) { + synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format"); + return; + } + + if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex)) + return; + + webContext()->compressedTexSubImage2D(target, level, xoffset, yoffset, + width, height, format, data->byteLength(), data->baseAddress()); +} + +bool WebGLRenderingContextBase::validateSettableTexFormat(const char* functionName, GLenum format) +{ + if (WebGLImageConversion::getClearBitsByFormat(format) & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "format can not be set, only rendered to"); + return false; + } + return true; +} + +void WebGLRenderingContextBase::copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + if (isContextLost()) + return; + if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GL_UNSIGNED_BYTE)) + return; + if (!validateSettableTexFormat("copyTexImage2D", internalformat)) + return; + WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); + if (!tex) + return; + if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { + synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); + return; + } + if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GL_INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); + return; + } + clearIfComposited(); + ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); + webContext()->copyTexImage2D(target, level, internalformat, x, y, width, height, border); + // FIXME: if the framebuffer is not complete, none of the below should be executed. + tex->setLevelInfo(target, level, internalformat, width, height, GL_UNSIGNED_BYTE); +} + +void WebGLRenderingContextBase::copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (!validateTexFuncLevel("copyTexSubImage2D", target, level)) + return; + WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true); + if (!tex) + return; + if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height)) + return; + // Before checking if it is in the range, check if overflow happens first. + Checked<GLint, RecordOverflow> maxX = xoffset; + maxX += width; + Checked<GLint, RecordOverflow> maxY = yoffset; + maxY += height; + if (maxX.hasOverflowed() || maxY.hasOverflowed()) { + synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "bad dimensions"); + return; + } + if (maxX.unsafeGet() > tex->getWidth(target, level) || maxY.unsafeGet() > tex->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range"); + return; + } + GLenum internalformat = tex->getInternalFormat(target, level); + if (!validateSettableTexFormat("copyTexSubImage2D", internalformat)) + return; + if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { + synthesizeGLError(GL_INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); + return; + } + clearIfComposited(); + ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); + webContext()->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +PassRefPtr<WebGLBuffer> WebGLRenderingContextBase::createBuffer() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLBuffer> o = WebGLBuffer::create(this); + addSharedObject(o.get()); + return o; +} + +PassRefPtr<WebGLFramebuffer> WebGLRenderingContextBase::createFramebuffer() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this); + addContextObject(o.get()); + return o; +} + +PassRefPtr<WebGLTexture> WebGLRenderingContextBase::createTexture() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLTexture> o = WebGLTexture::create(this); + addSharedObject(o.get()); + return o; +} + +PassRefPtr<WebGLProgram> WebGLRenderingContextBase::createProgram() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLProgram> o = WebGLProgram::create(this); + addSharedObject(o.get()); + return o; +} + +PassRefPtr<WebGLRenderbuffer> WebGLRenderingContextBase::createRenderbuffer() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this); + addSharedObject(o.get()); + return o; +} + +WebGLRenderbuffer* WebGLRenderingContextBase::ensureEmulatedStencilBuffer(GLenum target, WebGLRenderbuffer* renderbuffer) +{ + if (isContextLost()) + return 0; + if (!renderbuffer->emulatedStencilBuffer()) { + renderbuffer->setEmulatedStencilBuffer(createRenderbuffer()); + webContext()->bindRenderbuffer(target, objectOrZero(renderbuffer->emulatedStencilBuffer())); + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); + } + return renderbuffer->emulatedStencilBuffer(); +} + +PassRefPtr<WebGLShader> WebGLRenderingContextBase::createShader(GLenum type) +{ + if (isContextLost()) + return nullptr; + if (type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) { + synthesizeGLError(GL_INVALID_ENUM, "createShader", "invalid shader type"); + return nullptr; + } + + RefPtr<WebGLShader> o = WebGLShader::create(this, type); + addSharedObject(o.get()); + return o; +} + +void WebGLRenderingContextBase::cullFace(GLenum mode) +{ + if (isContextLost()) + return; + switch (mode) { + case GL_FRONT_AND_BACK: + case GL_FRONT: + case GL_BACK: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "cullFace", "invalid mode"); + return; + } + webContext()->cullFace(mode); +} + +bool WebGLRenderingContextBase::deleteObject(WebGLObject* object) +{ + if (isContextLost() || !object) + return false; + if (!object->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, "delete", "object does not belong to this context"); + return false; + } + if (object->object()) { + // We need to pass in context here because we want + // things in this context unbound. + object->deleteObject(webContext()); + } + return true; +} + +void WebGLRenderingContextBase::deleteBuffer(WebGLBuffer* buffer) +{ + if (!deleteObject(buffer)) + return; + if (m_boundArrayBuffer == buffer) + m_boundArrayBuffer = nullptr; + + m_boundVertexArrayObject->unbindBuffer(buffer); +} + +void WebGLRenderingContextBase::deleteFramebuffer(WebGLFramebuffer* framebuffer) +{ + if (!deleteObject(framebuffer)) + return; + if (framebuffer == m_framebufferBinding) { + m_framebufferBinding = nullptr; + m_drawingBuffer->setFramebufferBinding(0); + // Have to call bindFramebuffer here to bind back to internal fbo. + m_drawingBuffer->bind(); + } +} + +void WebGLRenderingContextBase::deleteProgram(WebGLProgram* program) +{ + deleteObject(program); + // We don't reset m_currentProgram to 0 here because the deletion of the + // current program is delayed. +} + +void WebGLRenderingContextBase::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) +{ + if (!deleteObject(renderbuffer)) + return; + if (renderbuffer == m_renderbufferBinding) + m_renderbufferBinding = nullptr; + if (m_framebufferBinding) + m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer); +} + +void WebGLRenderingContextBase::deleteShader(WebGLShader* shader) +{ + deleteObject(shader); +} + +void WebGLRenderingContextBase::deleteTexture(WebGLTexture* texture) +{ + if (!deleteObject(texture)) + return; + + int maxBoundTextureIndex = -1; + for (size_t i = 0; i < m_onePlusMaxNonDefaultTextureUnit; ++i) { + if (texture == m_textureUnits[i].m_texture2DBinding) { + m_textureUnits[i].m_texture2DBinding = nullptr; + maxBoundTextureIndex = i; + if (!i) + m_drawingBuffer->setTexture2DBinding(0); + } + if (texture == m_textureUnits[i].m_textureCubeMapBinding) { + m_textureUnits[i].m_textureCubeMapBinding = nullptr; + maxBoundTextureIndex = i; + } + } + if (m_framebufferBinding) + m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture); + + // If the deleted was bound to the the current maximum index, trace backwards to find the new max texture index + if (m_onePlusMaxNonDefaultTextureUnit == static_cast<unsigned long>(maxBoundTextureIndex + 1)) { + findNewMaxNonDefaultTextureUnit(); + } +} + +void WebGLRenderingContextBase::depthFunc(GLenum func) +{ + if (isContextLost()) + return; + if (!validateStencilOrDepthFunc("depthFunc", func)) + return; + webContext()->depthFunc(func); +} + +void WebGLRenderingContextBase::depthMask(GLboolean flag) +{ + if (isContextLost()) + return; + m_depthMask = flag; + webContext()->depthMask(flag); +} + +void WebGLRenderingContextBase::depthRange(GLfloat zNear, GLfloat zFar) +{ + if (isContextLost()) + return; + if (zNear > zFar) { + synthesizeGLError(GL_INVALID_OPERATION, "depthRange", "zNear > zFar"); + return; + } + webContext()->depthRange(zNear, zFar); +} + +void WebGLRenderingContextBase::detachShader(WebGLProgram* program, WebGLShader* shader) +{ + if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) + return; + if (!program->detachShader(shader)) { + synthesizeGLError(GL_INVALID_OPERATION, "detachShader", "shader not attached"); + return; + } + webContext()->detachShader(objectOrZero(program), objectOrZero(shader)); + shader->onDetached(webContext()); +} + +void WebGLRenderingContextBase::disable(GLenum cap) +{ + if (isContextLost() || !validateCapability("disable", cap)) + return; + if (cap == GL_STENCIL_TEST) { + m_stencilEnabled = false; + applyStencilTest(); + return; + } + if (cap == GL_SCISSOR_TEST) { + m_scissorEnabled = false; + m_drawingBuffer->setScissorEnabled(m_scissorEnabled); + } + webContext()->disable(cap); +} + +void WebGLRenderingContextBase::disableVertexAttribArray(GLuint index) +{ + if (isContextLost()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "disableVertexAttribArray", "index out of range"); + return; + } + + WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + state.enabled = false; + + // If the disabled index is the current maximum, trace backwards to find the new max enabled attrib index + if (m_onePlusMaxEnabledAttribIndex == index + 1) { + findNewMaxEnabledAttribIndex(); + } + + webContext()->disableVertexAttribArray(index); +} + +bool WebGLRenderingContextBase::validateRenderingState(const char* functionName) +{ + if (!m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no valid shader program in use"); + return false; + } + + // Look in each enabled vertex attrib and check if they've been bound to a buffer. + for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { + const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); + if (state.enabled + && (!state.bufferBinding || !state.bufferBinding->object())) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, String::format("attribute %d is enabled but has no buffer bound", i).utf8().data()); + return false; + } + } + + return true; +} + +bool WebGLRenderingContextBase::validateWebGLObject(const char* functionName, WebGLObject* object) +{ + if (!object || !object->object()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no object or object deleted"); + return false; + } + if (!object->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "object does not belong to this context"); + return false; + } + return true; +} + +void WebGLRenderingContextBase::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + if (!validateDrawArrays("drawArrays", mode, first, count)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawArrays", true); + webContext()->drawArrays(mode, first, count); + handleTextureCompleteness("drawArrays", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::drawElements(GLenum mode, GLsizei count, GLenum type, long long offset) +{ + if (!validateDrawElements("drawElements", mode, count, type, offset)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawElements", true); + webContext()->drawElements(mode, count, type, static_cast<GLintptr>(offset)); + handleTextureCompleteness("drawElements", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (!validateDrawArrays("drawArraysInstancedANGLE", mode, first, count)) + return; + + if (!validateDrawInstanced("drawArraysInstancedANGLE", primcount)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawArraysInstancedANGLE", true); + webContext()->drawArraysInstancedANGLE(mode, first, count, primcount); + handleTextureCompleteness("drawArraysInstancedANGLE", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount) +{ + if (!validateDrawElements("drawElementsInstancedANGLE", mode, count, type, offset)) + return; + + if (!validateDrawInstanced("drawElementsInstancedANGLE", primcount)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawElementsInstancedANGLE", true); + webContext()->drawElementsInstancedANGLE(mode, count, type, static_cast<GLintptr>(offset), primcount); + handleTextureCompleteness("drawElementsInstancedANGLE", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::enable(GLenum cap) +{ + if (isContextLost() || !validateCapability("enable", cap)) + return; + if (cap == GL_STENCIL_TEST) { + m_stencilEnabled = true; + applyStencilTest(); + return; + } + if (cap == GL_SCISSOR_TEST) { + m_scissorEnabled = true; + m_drawingBuffer->setScissorEnabled(m_scissorEnabled); + } + webContext()->enable(cap); +} + +void WebGLRenderingContextBase::enableVertexAttribArray(GLuint index) +{ + if (isContextLost()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "enableVertexAttribArray", "index out of range"); + return; + } + + WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + state.enabled = true; + + m_onePlusMaxEnabledAttribIndex = max(index + 1, m_onePlusMaxEnabledAttribIndex); + + webContext()->enableVertexAttribArray(index); +} + +void WebGLRenderingContextBase::finish() +{ + if (isContextLost()) + return; + webContext()->flush(); // Intentionally a flush, not a finish. +} + +void WebGLRenderingContextBase::flush() +{ + if (isContextLost()) + return; + webContext()->flush(); +} + +void WebGLRenderingContextBase::framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer* buffer) +{ + if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) + return; + if (renderbuffertarget != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); + return; + } + if (buffer && !buffer->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context"); + return; + } + // Don't allow the default framebuffer to be mutated; all current + // implementations use an FBO internally in place of the default + // FBO. + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound"); + return; + } + Platform3DObject bufferObject = objectOrZero(buffer); + switch (attachment) { + case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: + if (isDepthStencilSupported() || !buffer) { + webContext()->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); + webContext()->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); + } else { + WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(renderbuffertarget, buffer); + if (!emulatedStencilBuffer) { + synthesizeGLError(GL_OUT_OF_MEMORY, "framebufferRenderbuffer", "out of memory"); + return; + } + webContext()->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); + webContext()->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, objectOrZero(emulatedStencilBuffer)); + } + break; + default: + webContext()->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject); + } + m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer); + applyStencilTest(); +} + +void WebGLRenderingContextBase::framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture* texture, GLint level) +{ + if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) + return; + if (level) { + synthesizeGLError(GL_INVALID_VALUE, "framebufferTexture2D", "level not 0"); + return; + } + if (texture && !texture->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context"); + return; + } + // Don't allow the default framebuffer to be mutated; all current + // implementations use an FBO internally in place of the default + // FBO. + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound"); + return; + } + Platform3DObject textureObject = objectOrZero(texture); + switch (attachment) { + case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: + webContext()->framebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, textureObject, level); + webContext()->framebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, textureObject, level); + break; + case GL_DEPTH_ATTACHMENT: + webContext()->framebufferTexture2D(target, attachment, textarget, textureObject, level); + break; + case GL_STENCIL_ATTACHMENT: + webContext()->framebufferTexture2D(target, attachment, textarget, textureObject, level); + break; + default: + webContext()->framebufferTexture2D(target, attachment, textarget, textureObject, level); + } + m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level); + applyStencilTest(); +} + +void WebGLRenderingContextBase::frontFace(GLenum mode) +{ + if (isContextLost()) + return; + switch (mode) { + case GL_CW: + case GL_CCW: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "frontFace", "invalid mode"); + return; + } + webContext()->frontFace(mode); +} + +void WebGLRenderingContextBase::generateMipmap(GLenum target) +{ + if (isContextLost()) + return; + WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); + if (!tex) + return; + if (!tex->canGenerateMipmaps()) { + synthesizeGLError(GL_INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size"); + return; + } + if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0))) + return; + + // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR + // on Mac. Remove the hack once this driver bug is fixed. +#if OS(MACOSX) + bool needToResetMinFilter = false; + if (tex->getMinFilter() != GL_NEAREST_MIPMAP_LINEAR) { + webContext()->texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + needToResetMinFilter = true; + } +#endif + webContext()->generateMipmap(target); +#if OS(MACOSX) + if (needToResetMinFilter) + webContext()->texParameteri(target, GL_TEXTURE_MIN_FILTER, tex->getMinFilter()); +#endif + tex->generateMipmapLevelInfo(); +} + +PassRefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveAttrib(WebGLProgram* program, GLuint index) +{ + if (isContextLost() || !validateWebGLObject("getActiveAttrib", program)) + return nullptr; + blink::WebGraphicsContext3D::ActiveInfo info; + if (!webContext()->getActiveAttrib(objectOrZero(program), index, info)) + return nullptr; + return WebGLActiveInfo::create(info.name, info.type, info.size); +} + +PassRefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveUniform(WebGLProgram* program, GLuint index) +{ + if (isContextLost() || !validateWebGLObject("getActiveUniform", program)) + return nullptr; + blink::WebGraphicsContext3D::ActiveInfo info; + if (!webContext()->getActiveUniform(objectOrZero(program), index, info)) + return nullptr; + return WebGLActiveInfo::create(info.name, info.type, info.size); +} + +bool WebGLRenderingContextBase::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader> >& shaderObjects) +{ + shaderObjects.clear(); + if (isContextLost() || !validateWebGLObject("getAttachedShaders", program)) + return false; + + const GLenum shaderType[] = { + GL_VERTEX_SHADER, + GL_FRAGMENT_SHADER + }; + for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GLenum); ++i) { + WebGLShader* shader = program->getAttachedShader(shaderType[i]); + if (shader) + shaderObjects.append(shader); + } + return true; +} + +GLint WebGLRenderingContextBase::getAttribLocation(WebGLProgram* program, const String& name) +{ + if (isContextLost() || !validateWebGLObject("getAttribLocation", program)) + return -1; + if (!validateLocationLength("getAttribLocation", name)) + return -1; + if (!validateString("getAttribLocation", name)) + return -1; + if (isPrefixReserved(name)) + return -1; + if (!program->linkStatus()) { + synthesizeGLError(GL_INVALID_OPERATION, "getAttribLocation", "program not linked"); + return 0; + } + return webContext()->getAttribLocation(objectOrZero(program), name.utf8().data()); +} + +WebGLGetInfo WebGLRenderingContextBase::getBufferParameter(GLenum target, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + if (target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid target"); + return WebGLGetInfo(); + } + + if (pname != GL_BUFFER_SIZE && pname != GL_BUFFER_USAGE) { + synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid parameter name"); + return WebGLGetInfo(); + } + + GLint value = 0; + webContext()->getBufferParameteriv(target, pname, &value); + if (pname == GL_BUFFER_SIZE) + return WebGLGetInfo(value); + return WebGLGetInfo(static_cast<unsigned>(value)); +} + +PassRefPtr<WebGLContextAttributes> WebGLRenderingContextBase::getContextAttributes() +{ + if (isContextLost()) + return nullptr; + // We always need to return a new WebGLContextAttributes object to + // prevent the user from mutating any cached version. + blink::WebGraphicsContext3D::Attributes attrs = m_drawingBuffer->getActualAttributes(); + RefPtr<WebGLContextAttributes> attributes = m_requestedAttributes->clone(); + // Some requested attributes may not be honored, so we need to query the underlying + // context/drawing buffer and adjust accordingly. + if (m_requestedAttributes->depth() && !attrs.depth) + attributes->setDepth(false); + if (m_requestedAttributes->stencil() && !attrs.stencil) + attributes->setStencil(false); + attributes->setAntialias(m_drawingBuffer->multisample()); + return attributes.release(); +} + +GLenum WebGLRenderingContextBase::getError() +{ + if (m_lostContextErrors.size()) { + GLenum err = m_lostContextErrors.first(); + m_lostContextErrors.remove(0); + return err; + } + + if (isContextLost()) + return GL_NO_ERROR; + + return webContext()->getError(); +} + +const char* const* WebGLRenderingContextBase::ExtensionTracker::prefixes() const +{ + static const char* const unprefixed[] = { "", 0, }; + return m_prefixes ? m_prefixes : unprefixed; +} + +bool WebGLRenderingContextBase::ExtensionTracker::matchesNameWithPrefixes(const String& name) const +{ + const char* const* prefixSet = prefixes(); + for (; *prefixSet; ++prefixSet) { + String prefixedName = String(*prefixSet) + extensionName(); + if (equalIgnoringCase(prefixedName, name)) { + return true; + } + } + return false; +} + +bool WebGLRenderingContextBase::extensionSupportedAndAllowed(const ExtensionTracker* tracker) +{ + if (tracker->draft() && !RuntimeEnabledFeatures::webGLDraftExtensionsEnabled()) + return false; + if (!tracker->supported(this)) + return false; + return true; +} + + +PassRefPtr<WebGLExtension> WebGLRenderingContextBase::getExtension(const String& name) +{ + if (isContextLost()) + return nullptr; + + for (size_t i = 0; i < m_extensions.size(); ++i) { + ExtensionTracker* tracker = m_extensions[i]; + if (tracker->matchesNameWithPrefixes(name)) { + if (!extensionSupportedAndAllowed(tracker)) + return nullptr; + + RefPtr<WebGLExtension> extension = tracker->getExtension(this); + if (extension) + m_extensionEnabled[extension->name()] = true; + return extension.release(); + } + } + + return nullptr; +} + +WebGLGetInfo WebGLRenderingContextBase::getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname) +{ + if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) + return WebGLGetInfo(); + + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound"); + return WebGLGetInfo(); + } + + WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment); + if (!object) { + if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) + return WebGLGetInfo(GL_NONE); + // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL + // specifies INVALID_OPERATION. + synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name"); + return WebGLGetInfo(); + } + + ASSERT(object->isTexture() || object->isRenderbuffer()); + if (object->isTexture()) { + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return WebGLGetInfo(GL_TEXTURE); + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return WebGLGetInfo(PassRefPtr<WebGLTexture>(static_cast<WebGLTexture*>(object))); + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + { + GLint value = 0; + webContext()->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); + return WebGLGetInfo(value); + } + default: + synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment"); + return WebGLGetInfo(); + } + } else { + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return WebGLGetInfo(GL_RENDERBUFFER); + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(static_cast<WebGLRenderbuffer*>(object))); + default: + synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); + return WebGLGetInfo(); + } + } +} + +WebGLGetInfo WebGLRenderingContextBase::getParameter(GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + const int intZero = 0; + switch (pname) { + case GL_ACTIVE_TEXTURE: + return getUnsignedIntParameter(pname); + case GL_ALIASED_LINE_WIDTH_RANGE: + return getWebGLFloatArrayParameter(pname); + case GL_ALIASED_POINT_SIZE_RANGE: + return getWebGLFloatArrayParameter(pname); + case GL_ALPHA_BITS: + return getIntParameter(pname); + case GL_ARRAY_BUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer)); + case GL_BLEND: + return getBooleanParameter(pname); + case GL_BLEND_COLOR: + return getWebGLFloatArrayParameter(pname); + case GL_BLEND_DST_ALPHA: + return getUnsignedIntParameter(pname); + case GL_BLEND_DST_RGB: + return getUnsignedIntParameter(pname); + case GL_BLEND_EQUATION_ALPHA: + return getUnsignedIntParameter(pname); + case GL_BLEND_EQUATION_RGB: + return getUnsignedIntParameter(pname); + case GL_BLEND_SRC_ALPHA: + return getUnsignedIntParameter(pname); + case GL_BLEND_SRC_RGB: + return getUnsignedIntParameter(pname); + case GL_BLUE_BITS: + return getIntParameter(pname); + case GL_COLOR_CLEAR_VALUE: + return getWebGLFloatArrayParameter(pname); + case GL_COLOR_WRITEMASK: + return getBooleanArrayParameter(pname); + case GL_COMPRESSED_TEXTURE_FORMATS: + return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())); + case GL_CULL_FACE: + return getBooleanParameter(pname); + case GL_CULL_FACE_MODE: + return getUnsignedIntParameter(pname); + case GL_CURRENT_PROGRAM: + return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram)); + case GL_DEPTH_BITS: + if (!m_framebufferBinding && !m_requestedAttributes->depth()) + return WebGLGetInfo(intZero); + return getIntParameter(pname); + case GL_DEPTH_CLEAR_VALUE: + return getFloatParameter(pname); + case GL_DEPTH_FUNC: + return getUnsignedIntParameter(pname); + case GL_DEPTH_RANGE: + return getWebGLFloatArrayParameter(pname); + case GL_DEPTH_TEST: + return getBooleanParameter(pname); + case GL_DEPTH_WRITEMASK: + return getBooleanParameter(pname); + case GL_DITHER: + return getBooleanParameter(pname); + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->boundElementArrayBuffer())); + case GL_FRAMEBUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding)); + case GL_FRONT_FACE: + return getUnsignedIntParameter(pname); + case GL_GENERATE_MIPMAP_HINT: + return getUnsignedIntParameter(pname); + case GL_GREEN_BITS: + return getIntParameter(pname); + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + return getIntParameter(pname); + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + return getIntParameter(pname); + case GL_LINE_WIDTH: + return getFloatParameter(pname); + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: + return getIntParameter(pname); + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: + return getIntParameter(pname); + case GL_MAX_RENDERBUFFER_SIZE: + return getIntParameter(pname); + case GL_MAX_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GL_MAX_TEXTURE_SIZE: + return getIntParameter(pname); + case GL_MAX_VARYING_VECTORS: + return getIntParameter(pname); + case GL_MAX_VERTEX_ATTRIBS: + return getIntParameter(pname); + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GL_MAX_VERTEX_UNIFORM_VECTORS: + return getIntParameter(pname); + case GL_MAX_VIEWPORT_DIMS: + return getWebGLIntArrayParameter(pname); + case GL_NUM_SHADER_BINARY_FORMATS: + // FIXME: should we always return 0 for this? + return getIntParameter(pname); + case GL_PACK_ALIGNMENT: + return getIntParameter(pname); + case GL_POLYGON_OFFSET_FACTOR: + return getFloatParameter(pname); + case GL_POLYGON_OFFSET_FILL: + return getBooleanParameter(pname); + case GL_POLYGON_OFFSET_UNITS: + return getFloatParameter(pname); + case GL_RED_BITS: + return getIntParameter(pname); + case GL_RENDERBUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding)); + case GL_RENDERER: + return WebGLGetInfo(String("WebKit WebGL")); + case GL_SAMPLE_BUFFERS: + return getIntParameter(pname); + case GL_SAMPLE_COVERAGE_INVERT: + return getBooleanParameter(pname); + case GL_SAMPLE_COVERAGE_VALUE: + return getFloatParameter(pname); + case GL_SAMPLES: + return getIntParameter(pname); + case GL_SCISSOR_BOX: + return getWebGLIntArrayParameter(pname); + case GL_SCISSOR_TEST: + return getBooleanParameter(pname); + case GL_SHADING_LANGUAGE_VERSION: + return WebGLGetInfo("WebGL GLSL ES 1.0 (" + String(webContext()->getString(GL_SHADING_LANGUAGE_VERSION)) + ")"); + case GL_STENCIL_BACK_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_FUNC: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_REF: + return getIntParameter(pname); + case GL_STENCIL_BACK_VALUE_MASK: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_WRITEMASK: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BITS: + if (!m_framebufferBinding && !m_requestedAttributes->stencil()) + return WebGLGetInfo(intZero); + return getIntParameter(pname); + case GL_STENCIL_CLEAR_VALUE: + return getIntParameter(pname); + case GL_STENCIL_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_FUNC: + return getUnsignedIntParameter(pname); + case GL_STENCIL_PASS_DEPTH_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_PASS_DEPTH_PASS: + return getUnsignedIntParameter(pname); + case GL_STENCIL_REF: + return getIntParameter(pname); + case GL_STENCIL_TEST: + return getBooleanParameter(pname); + case GL_STENCIL_VALUE_MASK: + return getUnsignedIntParameter(pname); + case GL_STENCIL_WRITEMASK: + return getUnsignedIntParameter(pname); + case GL_SUBPIXEL_BITS: + return getIntParameter(pname); + case GL_TEXTURE_BINDING_2D: + return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding)); + case GL_TEXTURE_BINDING_CUBE_MAP: + return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding)); + case GL_UNPACK_ALIGNMENT: + return getIntParameter(pname); + case GC3D_UNPACK_FLIP_Y_WEBGL: + return WebGLGetInfo(m_unpackFlipY); + case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: + return WebGLGetInfo(m_unpackPremultiplyAlpha); + case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: + return WebGLGetInfo(m_unpackColorspaceConversion); + case GL_VENDOR: + return WebGLGetInfo(String("WebKit")); + case GL_VERSION: + return WebGLGetInfo("WebGL 1.0 (" + String(webContext()->getString(GL_VERSION)) + ")"); + case GL_VIEWPORT: + return getWebGLIntArrayParameter(pname); + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives + if (extensionEnabled(OESStandardDerivativesName)) + return getUnsignedIntParameter(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled"); + return WebGLGetInfo(); + case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL: + if (extensionEnabled(WebGLDebugRendererInfoName)) + return WebGLGetInfo(webContext()->getString(GL_RENDERER)); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); + return WebGLGetInfo(); + case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL: + if (extensionEnabled(WebGLDebugRendererInfoName)) + return WebGLGetInfo(webContext()->getString(GL_VENDOR)); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); + return WebGLGetInfo(); + case GL_VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object + if (extensionEnabled(OESVertexArrayObjectName)) { + if (!m_boundVertexArrayObject->isDefaultObject()) + return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject)); + return WebGLGetInfo(); + } + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled"); + return WebGLGetInfo(); + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (extensionEnabled(EXTTextureFilterAnisotropicName)) + return getUnsignedIntParameter(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); + return WebGLGetInfo(); + case GL_MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN + if (extensionEnabled(WebGLDrawBuffersName)) + return WebGLGetInfo(maxColorAttachments()); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); + return WebGLGetInfo(); + case GL_MAX_DRAW_BUFFERS_EXT: + if (extensionEnabled(WebGLDrawBuffersName)) + return WebGLGetInfo(maxDrawBuffers()); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); + return WebGLGetInfo(); + default: + if (extensionEnabled(WebGLDrawBuffersName) + && pname >= GL_DRAW_BUFFER0_EXT + && pname < static_cast<GLenum>(GL_DRAW_BUFFER0_EXT + maxDrawBuffers())) { + GLint value = GL_NONE; + if (m_framebufferBinding) + value = m_framebufferBinding->getDrawBuffer(pname); + else // emulated backbuffer + value = m_backDrawBuffer; + return WebGLGetInfo(value); + } + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getProgramParameter(WebGLProgram* program, GLenum pname) +{ + if (isContextLost() || !validateWebGLObject("getProgramParameter", program)) + return WebGLGetInfo(); + + GLint value = 0; + switch (pname) { + case GL_DELETE_STATUS: + return WebGLGetInfo(program->isDeleted()); + case GL_VALIDATE_STATUS: + webContext()->getProgramiv(objectOrZero(program), pname, &value); + return WebGLGetInfo(static_cast<bool>(value)); + case GL_LINK_STATUS: + return WebGLGetInfo(program->linkStatus()); + case GL_ATTACHED_SHADERS: + case GL_ACTIVE_ATTRIBUTES: + case GL_ACTIVE_UNIFORMS: + webContext()->getProgramiv(objectOrZero(program), pname, &value); + return WebGLGetInfo(value); + default: + synthesizeGLError(GL_INVALID_ENUM, "getProgramParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +String WebGLRenderingContextBase::getProgramInfoLog(WebGLProgram* program) +{ + if (isContextLost()) + return String(); + if (!validateWebGLObject("getProgramInfoLog", program)) + return ""; + return ensureNotNull(webContext()->getProgramInfoLog(objectOrZero(program))); +} + +WebGLGetInfo WebGLRenderingContextBase::getRenderbufferParameter(GLenum target, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + if (target != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid target"); + return WebGLGetInfo(); + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound"); + return WebGLGetInfo(); + } + + GLint value = 0; + switch (pname) { + case GL_RENDERBUFFER_WIDTH: + case GL_RENDERBUFFER_HEIGHT: + case GL_RENDERBUFFER_RED_SIZE: + case GL_RENDERBUFFER_GREEN_SIZE: + case GL_RENDERBUFFER_BLUE_SIZE: + case GL_RENDERBUFFER_ALPHA_SIZE: + case GL_RENDERBUFFER_DEPTH_SIZE: + webContext()->getRenderbufferParameteriv(target, pname, &value); + return WebGLGetInfo(value); + case GL_RENDERBUFFER_STENCIL_SIZE: + if (m_renderbufferBinding->emulatedStencilBuffer()) { + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding->emulatedStencilBuffer())); + webContext()->getRenderbufferParameteriv(target, pname, &value); + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); + } else { + webContext()->getRenderbufferParameteriv(target, pname, &value); + } + return WebGLGetInfo(value); + case GL_RENDERBUFFER_INTERNAL_FORMAT: + return WebGLGetInfo(m_renderbufferBinding->internalFormat()); + default: + synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getShaderParameter(WebGLShader* shader, GLenum pname) +{ + if (isContextLost() || !validateWebGLObject("getShaderParameter", shader)) + return WebGLGetInfo(); + GLint value = 0; + switch (pname) { + case GL_DELETE_STATUS: + return WebGLGetInfo(shader->isDeleted()); + case GL_COMPILE_STATUS: + webContext()->getShaderiv(objectOrZero(shader), pname, &value); + return WebGLGetInfo(static_cast<bool>(value)); + case GL_SHADER_TYPE: + webContext()->getShaderiv(objectOrZero(shader), pname, &value); + return WebGLGetInfo(static_cast<unsigned>(value)); + default: + synthesizeGLError(GL_INVALID_ENUM, "getShaderParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +String WebGLRenderingContextBase::getShaderInfoLog(WebGLShader* shader) +{ + if (isContextLost()) + return String(); + if (!validateWebGLObject("getShaderInfoLog", shader)) + return ""; + return ensureNotNull(webContext()->getShaderInfoLog(objectOrZero(shader))); +} + +PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContextBase::getShaderPrecisionFormat(GLenum shaderType, GLenum precisionType) +{ + if (isContextLost()) + return nullptr; + switch (shaderType) { + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type"); + return nullptr; + } + switch (precisionType) { + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type"); + return nullptr; + } + + GLint range[2] = {0, 0}; + GLint precision = 0; + webContext()->getShaderPrecisionFormat(shaderType, precisionType, range, &precision); + return WebGLShaderPrecisionFormat::create(range[0], range[1], precision); +} + +String WebGLRenderingContextBase::getShaderSource(WebGLShader* shader) +{ + if (isContextLost()) + return String(); + if (!validateWebGLObject("getShaderSource", shader)) + return ""; + return ensureNotNull(shader->source()); +} + +Vector<String> WebGLRenderingContextBase::getSupportedExtensions() +{ + Vector<String> result; + if (isContextLost()) + return result; + + for (size_t i = 0; i < m_extensions.size(); ++i) { + ExtensionTracker* tracker = m_extensions[i]; + if (extensionSupportedAndAllowed(tracker)) { + const char* const* prefixes = tracker->prefixes(); + for (; *prefixes; ++prefixes) { + String prefixedName = String(*prefixes) + tracker->extensionName(); + result.append(prefixedName); + } + } + } + + return result; +} + +WebGLGetInfo WebGLRenderingContextBase::getTexParameter(GLenum target, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); + if (!tex) + return WebGLGetInfo(); + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + { + GLint value = 0; + webContext()->getTexParameteriv(target, pname, &value); + return WebGLGetInfo(static_cast<unsigned>(value)); + } + case GL_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (extensionEnabled(EXTTextureFilterAnisotropicName)) { + GLfloat value = 0.f; + webContext()->getTexParameterfv(target, pname, &value); + return WebGLGetInfo(value); + } + synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); + return WebGLGetInfo(); + default: + synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation) +{ + if (isContextLost() || !validateWebGLObject("getUniform", program)) + return WebGLGetInfo(); + if (!uniformLocation || uniformLocation->program() != program) { + synthesizeGLError(GL_INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); + return WebGLGetInfo(); + } + GLint location = uniformLocation->location(); + + // FIXME: make this more efficient using WebGLUniformLocation and caching types in it + GLint activeUniforms = 0; + webContext()->getProgramiv(objectOrZero(program), GL_ACTIVE_UNIFORMS, &activeUniforms); + for (GLint i = 0; i < activeUniforms; i++) { + blink::WebGraphicsContext3D::ActiveInfo info; + if (!webContext()->getActiveUniform(objectOrZero(program), i, info)) + return WebGLGetInfo(); + String name = info.name; + StringBuilder nameBuilder; + // Strip "[0]" from the name if it's an array. + if (info.size > 1 && name.endsWith("[0]")) + info.name = name.left(name.length() - 3); + // If it's an array, we need to iterate through each element, appending "[index]" to the name. + for (GLint index = 0; index < info.size; ++index) { + nameBuilder.clear(); + nameBuilder.append(info.name); + if (info.size > 1 && index >= 1) { + nameBuilder.append('['); + nameBuilder.append(String::number(index)); + nameBuilder.append(']'); + } + // Now need to look this up by name again to find its location + GLint loc = webContext()->getUniformLocation(objectOrZero(program), nameBuilder.toString().utf8().data()); + if (loc == location) { + // Found it. Use the type in the ActiveInfo to determine the return type. + GLenum baseType; + unsigned length; + switch (info.type) { + case GL_BOOL: + baseType = GL_BOOL; + length = 1; + break; + case GL_BOOL_VEC2: + baseType = GL_BOOL; + length = 2; + break; + case GL_BOOL_VEC3: + baseType = GL_BOOL; + length = 3; + break; + case GL_BOOL_VEC4: + baseType = GL_BOOL; + length = 4; + break; + case GL_INT: + baseType = GL_INT; + length = 1; + break; + case GL_INT_VEC2: + baseType = GL_INT; + length = 2; + break; + case GL_INT_VEC3: + baseType = GL_INT; + length = 3; + break; + case GL_INT_VEC4: + baseType = GL_INT; + length = 4; + break; + case GL_FLOAT: + baseType = GL_FLOAT; + length = 1; + break; + case GL_FLOAT_VEC2: + baseType = GL_FLOAT; + length = 2; + break; + case GL_FLOAT_VEC3: + baseType = GL_FLOAT; + length = 3; + break; + case GL_FLOAT_VEC4: + baseType = GL_FLOAT; + length = 4; + break; + case GL_FLOAT_MAT2: + baseType = GL_FLOAT; + length = 4; + break; + case GL_FLOAT_MAT3: + baseType = GL_FLOAT; + length = 9; + break; + case GL_FLOAT_MAT4: + baseType = GL_FLOAT; + length = 16; + break; + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + baseType = GL_INT; + length = 1; + break; + default: + // Can't handle this type + synthesizeGLError(GL_INVALID_VALUE, "getUniform", "unhandled type"); + return WebGLGetInfo(); + } + switch (baseType) { + case GL_FLOAT: { + GLfloat value[16] = {0}; + webContext()->getUniformfv(objectOrZero(program), location, value); + if (length == 1) + return WebGLGetInfo(value[0]); + return WebGLGetInfo(Float32Array::create(value, length)); + } + case GL_INT: { + GLint value[4] = {0}; + webContext()->getUniformiv(objectOrZero(program), location, value); + if (length == 1) + return WebGLGetInfo(value[0]); + return WebGLGetInfo(Int32Array::create(value, length)); + } + case GL_BOOL: { + GLint value[4] = {0}; + webContext()->getUniformiv(objectOrZero(program), location, value); + if (length > 1) { + bool boolValue[16] = {0}; + for (unsigned j = 0; j < length; j++) + boolValue[j] = static_cast<bool>(value[j]); + return WebGLGetInfo(boolValue, length); + } + return WebGLGetInfo(static_cast<bool>(value[0])); + } + default: + notImplemented(); + } + } + } + } + // If we get here, something went wrong in our unfortunately complex logic above + synthesizeGLError(GL_INVALID_VALUE, "getUniform", "unknown error"); + return WebGLGetInfo(); +} + +PassRefPtr<WebGLUniformLocation> WebGLRenderingContextBase::getUniformLocation(WebGLProgram* program, const String& name) +{ + if (isContextLost() || !validateWebGLObject("getUniformLocation", program)) + return nullptr; + if (!validateLocationLength("getUniformLocation", name)) + return nullptr; + if (!validateString("getUniformLocation", name)) + return nullptr; + if (isPrefixReserved(name)) + return nullptr; + if (!program->linkStatus()) { + synthesizeGLError(GL_INVALID_OPERATION, "getUniformLocation", "program not linked"); + return nullptr; + } + GLint uniformLocation = webContext()->getUniformLocation(objectOrZero(program), name.utf8().data()); + if (uniformLocation == -1) + return nullptr; + return WebGLUniformLocation::create(program, uniformLocation); +} + +WebGLGetInfo WebGLRenderingContextBase::getVertexAttrib(GLuint index, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "getVertexAttrib", "index out of range"); + return WebGLGetInfo(); + } + const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + + if (extensionEnabled(ANGLEInstancedArraysName) && pname == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) + return WebGLGetInfo(state.divisor); + + switch (pname) { + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + if (!state.bufferBinding || !state.bufferBinding->object()) + return WebGLGetInfo(); + return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding)); + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + return WebGLGetInfo(state.enabled); + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + return WebGLGetInfo(state.normalized); + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + return WebGLGetInfo(state.size); + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + return WebGLGetInfo(state.originalStride); + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + return WebGLGetInfo(state.type); + case GL_CURRENT_VERTEX_ATTRIB: + return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4)); + default: + synthesizeGLError(GL_INVALID_ENUM, "getVertexAttrib", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +long long WebGLRenderingContextBase::getVertexAttribOffset(GLuint index, GLenum pname) +{ + if (isContextLost()) + return 0; + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { + synthesizeGLError(GL_INVALID_ENUM, "getVertexAttribOffset", "invalid parameter name"); + return 0; + } + GLsizeiptr result = webContext()->getVertexAttribOffset(index, pname); + return static_cast<long long>(result); +} + +void WebGLRenderingContextBase::hint(GLenum target, GLenum mode) +{ + if (isContextLost()) + return; + bool isValid = false; + switch (target) { + case GL_GENERATE_MIPMAP_HINT: + isValid = true; + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives + if (extensionEnabled(OESStandardDerivativesName)) + isValid = true; + break; + } + if (!isValid) { + synthesizeGLError(GL_INVALID_ENUM, "hint", "invalid target"); + return; + } + webContext()->hint(target, mode); +} + +GLboolean WebGLRenderingContextBase::isBuffer(WebGLBuffer* buffer) +{ + if (!buffer || isContextLost()) + return 0; + + if (!buffer->hasEverBeenBound()) + return 0; + + return webContext()->isBuffer(buffer->object()); +} + +bool WebGLRenderingContextBase::isContextLost() const +{ + return m_contextLost; +} + +GLboolean WebGLRenderingContextBase::isEnabled(GLenum cap) +{ + if (isContextLost() || !validateCapability("isEnabled", cap)) + return 0; + if (cap == GL_STENCIL_TEST) + return m_stencilEnabled; + return webContext()->isEnabled(cap); +} + +GLboolean WebGLRenderingContextBase::isFramebuffer(WebGLFramebuffer* framebuffer) +{ + if (!framebuffer || isContextLost()) + return 0; + + if (!framebuffer->hasEverBeenBound()) + return 0; + + return webContext()->isFramebuffer(framebuffer->object()); +} + +GLboolean WebGLRenderingContextBase::isProgram(WebGLProgram* program) +{ + if (!program || isContextLost()) + return 0; + + return webContext()->isProgram(program->object()); +} + +GLboolean WebGLRenderingContextBase::isRenderbuffer(WebGLRenderbuffer* renderbuffer) +{ + if (!renderbuffer || isContextLost()) + return 0; + + if (!renderbuffer->hasEverBeenBound()) + return 0; + + return webContext()->isRenderbuffer(renderbuffer->object()); +} + +GLboolean WebGLRenderingContextBase::isShader(WebGLShader* shader) +{ + if (!shader || isContextLost()) + return 0; + + return webContext()->isShader(shader->object()); +} + +GLboolean WebGLRenderingContextBase::isTexture(WebGLTexture* texture) +{ + if (!texture || isContextLost()) + return 0; + + if (!texture->hasEverBeenBound()) + return 0; + + return webContext()->isTexture(texture->object()); +} + +void WebGLRenderingContextBase::lineWidth(GLfloat width) +{ + if (isContextLost()) + return; + webContext()->lineWidth(width); +} + +void WebGLRenderingContextBase::linkProgram(WebGLProgram* program) +{ + if (isContextLost() || !validateWebGLObject("linkProgram", program)) + return; + + webContext()->linkProgram(objectOrZero(program)); + program->increaseLinkCount(); +} + +void WebGLRenderingContextBase::pixelStorei(GLenum pname, GLint param) +{ + if (isContextLost()) + return; + switch (pname) { + case GC3D_UNPACK_FLIP_Y_WEBGL: + m_unpackFlipY = param; + break; + case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: + m_unpackPremultiplyAlpha = param; + break; + case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: + if (static_cast<GLenum>(param) == GC3D_BROWSER_DEFAULT_WEBGL || param == GL_NONE) { + m_unpackColorspaceConversion = static_cast<GLenum>(param); + } else { + synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL"); + return; + } + break; + case GL_PACK_ALIGNMENT: + case GL_UNPACK_ALIGNMENT: + if (param == 1 || param == 2 || param == 4 || param == 8) { + if (pname == GL_PACK_ALIGNMENT) { + m_packAlignment = param; + m_drawingBuffer->setPackAlignment(param); + } else { // GL_UNPACK_ALIGNMENT: + m_unpackAlignment = param; + } + webContext()->pixelStorei(pname, param); + } else { + synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for alignment"); + return; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "pixelStorei", "invalid parameter name"); + return; + } +} + +void WebGLRenderingContextBase::polygonOffset(GLfloat factor, GLfloat units) +{ + if (isContextLost()) + return; + webContext()->polygonOffset(factor, units); +} + +void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView* pixels) +{ + if (isContextLost()) + return; + // Due to WebGL's same-origin restrictions, it is not possible to + // taint the origin using the WebGL API. + ASSERT(canvas()->originClean()); + // Validate input parameters. + if (!pixels) { + synthesizeGLError(GL_INVALID_VALUE, "readPixels", "no destination ArrayBufferView"); + return; + } + switch (format) { + case GL_ALPHA: + case GL_RGB: + case GL_RGBA: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid format"); + return; + } + + ArrayBufferView::ViewType expectedViewType; + + switch (type) { + case GL_UNSIGNED_BYTE: + expectedViewType = ArrayBufferView::TypeUint8; + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + expectedViewType = ArrayBufferView::TypeUint16; + break; + case GL_FLOAT: + expectedViewType = ArrayBufferView::TypeFloat32; + break; + case GL_HALF_FLOAT_OES: + expectedViewType = ArrayBufferView::TypeUint16; + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid type"); + return; + } + if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) { + // Check against the implementation color read format and type. + blink::WGC3Dint implFormat = 0, implType = 0; + webContext()->getIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &implFormat); + webContext()->getIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &implType); + if (!implFormat || !implType || format != static_cast<GLenum>(implFormat) || type != static_cast<GLenum>(implType)) { + synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "format/type not RGBA/UNSIGNED_BYTE or implementation-defined values"); + return; + } + } + // Validate array type against pixel type. + if (pixels->type() != expectedViewType) { + synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView was the wrong type for the pixel format"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); + return; + } + // Calculate array size, taking into consideration of PACK_ALIGNMENT. + unsigned totalBytesRequired = 0; + unsigned padding = 0; + GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); + if (error != GL_NO_ERROR) { + synthesizeGLError(error, "readPixels", "invalid dimensions"); + return; + } + if (pixels->byteLength() < totalBytesRequired) { + synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); + return; + } + + clearIfComposited(); + void* data = pixels->baseAddress(); + + { + ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); + webContext()->readPixels(x, y, width, height, format, type, data); + } + +#if OS(MACOSX) + // FIXME: remove this section when GL driver bug on Mac is fixed, i.e., + // when alpha is off, readPixels should set alpha to 255 instead of 0. + if (!m_framebufferBinding && !m_drawingBuffer->getActualAttributes().alpha) { + unsigned char* pixels = reinterpret_cast<unsigned char*>(data); + for (GLsizei iy = 0; iy < height; ++iy) { + for (GLsizei ix = 0; ix < width; ++ix) { + pixels[3] = 255; + pixels += 4; + } + pixels += padding; + } + } +#endif +} + +void WebGLRenderingContextBase::renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (target != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid target"); + return; + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); + return; + } + if (!validateSize("renderbufferStorage", width, height)) + return; + switch (internalformat) { + case GL_DEPTH_COMPONENT16: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_STENCIL_INDEX8: + webContext()->renderbufferStorage(target, internalformat, width, height); + m_renderbufferBinding->setInternalFormat(internalformat); + m_renderbufferBinding->setSize(width, height); + m_renderbufferBinding->deleteEmulatedStencilBuffer(webContext()); + break; + case GL_DEPTH_STENCIL_OES: + if (isDepthStencilSupported()) { + webContext()->renderbufferStorage(target, GL_DEPTH24_STENCIL8_OES, width, height); + } else { + WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(target, m_renderbufferBinding.get()); + if (!emulatedStencilBuffer) { + synthesizeGLError(GL_OUT_OF_MEMORY, "renderbufferStorage", "out of memory"); + return; + } + webContext()->renderbufferStorage(target, GL_DEPTH_COMPONENT16, width, height); + webContext()->bindRenderbuffer(target, objectOrZero(emulatedStencilBuffer)); + webContext()->renderbufferStorage(target, GL_STENCIL_INDEX8, width, height); + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); + emulatedStencilBuffer->setSize(width, height); + emulatedStencilBuffer->setInternalFormat(GL_STENCIL_INDEX8); + } + m_renderbufferBinding->setSize(width, height); + m_renderbufferBinding->setInternalFormat(internalformat); + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); + return; + } + applyStencilTest(); +} + +void WebGLRenderingContextBase::sampleCoverage(GLfloat value, GLboolean invert) +{ + if (isContextLost()) + return; + webContext()->sampleCoverage(value, invert); +} + +void WebGLRenderingContextBase::scissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (!validateSize("scissor", width, height)) + return; + webContext()->scissor(x, y, width, height); +} + +void WebGLRenderingContextBase::shaderSource(WebGLShader* shader, const String& string) +{ + if (isContextLost() || !validateWebGLObject("shaderSource", shader)) + return; + String stringWithoutComments = StripComments(string).result(); + if (!validateString("shaderSource", stringWithoutComments)) + return; + shader->setSource(string); + webContext()->shaderSource(objectOrZero(shader), stringWithoutComments.utf8().data()); +} + +void WebGLRenderingContextBase::stencilFunc(GLenum func, GLint ref, GLuint mask) +{ + if (isContextLost()) + return; + if (!validateStencilOrDepthFunc("stencilFunc", func)) + return; + m_stencilFuncRef = ref; + m_stencilFuncRefBack = ref; + m_stencilFuncMask = mask; + m_stencilFuncMaskBack = mask; + webContext()->stencilFunc(func, ref, mask); +} + +void WebGLRenderingContextBase::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + if (isContextLost()) + return; + if (!validateStencilOrDepthFunc("stencilFuncSeparate", func)) + return; + switch (face) { + case GL_FRONT_AND_BACK: + m_stencilFuncRef = ref; + m_stencilFuncRefBack = ref; + m_stencilFuncMask = mask; + m_stencilFuncMaskBack = mask; + break; + case GL_FRONT: + m_stencilFuncRef = ref; + m_stencilFuncMask = mask; + break; + case GL_BACK: + m_stencilFuncRefBack = ref; + m_stencilFuncMaskBack = mask; + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "stencilFuncSeparate", "invalid face"); + return; + } + webContext()->stencilFuncSeparate(face, func, ref, mask); +} + +void WebGLRenderingContextBase::stencilMask(GLuint mask) +{ + if (isContextLost()) + return; + m_stencilMask = mask; + m_stencilMaskBack = mask; + webContext()->stencilMask(mask); +} + +void WebGLRenderingContextBase::stencilMaskSeparate(GLenum face, GLuint mask) +{ + if (isContextLost()) + return; + switch (face) { + case GL_FRONT_AND_BACK: + m_stencilMask = mask; + m_stencilMaskBack = mask; + break; + case GL_FRONT: + m_stencilMask = mask; + break; + case GL_BACK: + m_stencilMaskBack = mask; + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "stencilMaskSeparate", "invalid face"); + return; + } + webContext()->stencilMaskSeparate(face, mask); +} + +void WebGLRenderingContextBase::stencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + if (isContextLost()) + return; + webContext()->stencilOp(fail, zfail, zpass); +} + +void WebGLRenderingContextBase::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + if (isContextLost()) + return; + webContext()->stencilOpSeparate(face, fail, zfail, zpass); +} + +GLenum WebGLRenderingContextBase::convertTexInternalFormat(GLenum internalformat, GLenum type) +{ + // Convert to sized internal formats that are renderable with GL_CHROMIUM_color_buffer_float_rgb(a). + if (type == GL_FLOAT && internalformat == GL_RGBA + && extensionsUtil()->isExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")) + return GL_RGBA32F_EXT; + if (type == GL_FLOAT && internalformat == GL_RGB + && extensionsUtil()->isExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb")) + return GL_RGB32F_EXT; + return internalformat; +} + +void WebGLRenderingContextBase::texImage2DBase(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels, ExceptionState& exceptionState) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + // FIXME: Handle errors. + WebGLTexture* tex = validateTextureBinding("texImage2D", target, true); + ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type)); + ASSERT(tex); + ASSERT(!level || !WebGLTexture::isNPOT(width, height)); + ASSERT(!pixels || validateSettableTexFormat("texImage2D", internalformat)); + webContext()->texImage2D(target, level, convertTexInternalFormat(internalformat, type), width, height, border, format, type, pixels); + tex->setLevelInfo(target, level, internalformat, width, height, type); +} + +void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + Vector<uint8_t> data; + WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); + if (!imageExtractor.extractSucceeded()) { + synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); + return; + } + WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + + bool needConversion = true; + if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY) + needConversion = false; + else { + if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { + synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "packImage error"); + return; + } + } + + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 0, format, type, needConversion ? data.data() : imagePixelData, exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint xoffset, GLint yoffset) +{ + if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type)) + return false; + + WebGLTexture* texture = validateTextureBinding(functionName, target, true); + if (!texture) + return false; + + if (functionType == NotTexSubImage2D) { + if (level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "level > 0 not power of 2"); + return false; + } + // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat + // by checking if the ArrayBufferView is null or not. + if (sourceType != SourceArrayBufferView) { + if (!validateSettableTexFormat(functionName, format)) + return false; + } + } else { + if (!validateSettableTexFormat(functionName, format)) + return false; + if (!validateSize(functionName, xoffset, yoffset)) + return false; + // Before checking if it is in the range, check if overflow happens first. + if (xoffset + width < 0 || yoffset + height < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "bad dimensions"); + return false; + } + if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "dimensions out of range"); + return false; + } + if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type and format do not match texture"); + return false; + } + } + + return true; +} + +bool WebGLRenderingContextBase::validateValueFitNonNegInt32(const char* functionName, const char* paramName, long long value) +{ + if (value < 0) { + String errorMsg = String(paramName) + " < 0"; + synthesizeGLError(GL_INVALID_VALUE, functionName, errorMsg.ascii().data()); + return false; + } + if (value > static_cast<long long>(std::numeric_limits<int>::max())) { + String errorMsg = String(paramName) + " more than 32-bit"; + synthesizeGLError(GL_INVALID_OPERATION, functionName, errorMsg.ascii().data()); + return false; + } + return true; +} + +PassRefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(Image* image, int width, int height, const char* functionName) +{ + IntSize size(width, height); + ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); + if (!buf) { + synthesizeGLError(GL_OUT_OF_MEMORY, functionName, "out of memory"); + return nullptr; + } + + IntRect srcRect(IntPoint(), image->size()); + IntRect destRect(0, 0, size.width(), size.height()); + buf->context()->drawImage(image, destRect, srcRect); + return buf->copyImage(ImageBuffer::fastCopyImageMode()); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, ArrayBufferView* pixels, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed) + || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0)) + return; + void* data = pixels ? pixels->baseAddress() : 0; + Vector<uint8_t> tempData; + bool changeUnpackAlignment = false; + if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { + if (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData)) + return; + data = tempData.data(); + changeUnpackAlignment = true; + } + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, width, height, border, format, type, data, exceptionState); + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, ImageData* pixels, ExceptionState& exceptionState) +{ + if (isContextLost() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0)) + return; + Vector<uint8_t> data; + bool needConversion = true; + // The data from ImageData is always of format RGBA8. + // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. + if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GL_RGBA && type == GL_UNSIGNED_BYTE) + needConversion = false; + else { + if (!WebGLImageConversion::extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { + synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); + return; + } + } + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLImageElement("texImage2D", image, exceptionState)) + return; + + RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); + if (imageForRender->isSVGImage()) + imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), "texImage2D"); + + if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0)) + return; + + texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, exceptionState) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0)) + return; + + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); + + // If possible, copy from the canvas element directly to the texture + // via the GPU, without a read-back to system memory. + if (GL_TEXTURE_2D == target && texture) { + ScopedTexture2DRestorer restorer(this); + + if (!canvas->is3D()) { + ImageBuffer* buffer = canvas->buffer(); + if (buffer && buffer->copyToPlatformTexture(webContext(), texture->object(), internalformat, type, + level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); + return; + } + } else { + WebGLRenderingContextBase* gl = toWebGLRenderingContextBase(canvas->renderingContext()); + ScopedTexture2DRestorer restorer(gl); + if (gl && gl->m_drawingBuffer->copyToPlatformTexture(webContext(), texture->object(), internalformat, type, + level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); + return; + } + } + } + + RefPtrWillBeRawPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texImage2D(target, level, internalformat, format, type, imageData.get(), exceptionState); + else + texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy) +{ + IntSize size(video->videoWidth(), video->videoHeight()); + ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); + if (!buf) { + synthesizeGLError(GL_OUT_OF_MEMORY, "texImage2D", "out of memory"); + return nullptr; + } + IntRect destRect(0, 0, size.width(), size.height()); + // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback. + video->paintCurrentFrameInContext(buf->context(), destRect); + return buf->copyImage(backingStoreCopy); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLVideoElement("texImage2D", video, exceptionState) + || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0)) + return; + + // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible. + // Otherwise, it will fall back to the normal SW path. + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); + if (GL_TEXTURE_2D == target && texture) { + if (video->copyVideoTextureToPlatformTexture(webContext(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type); + return; + } + } + + // Normal pure SW path. + RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); + if (!image) + return; + texImage2DImpl(target, level, internalformat, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texParameter(GLenum target, GLenum pname, GLfloat paramf, GLint parami, bool isFloat) +{ + if (isContextLost()) + return; + WebGLTexture* tex = validateTextureBinding("texParameter", target, false); + if (!tex) + return; + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + break; + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + if ((isFloat && paramf != GL_CLAMP_TO_EDGE && paramf != GL_MIRRORED_REPEAT && paramf != GL_REPEAT) + || (!isFloat && parami != GL_CLAMP_TO_EDGE && parami != GL_MIRRORED_REPEAT && parami != GL_REPEAT)) { + synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter"); + return; + } + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (!extensionEnabled(EXTTextureFilterAnisotropicName)) { + synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled"); + return; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter name"); + return; + } + if (isFloat) { + tex->setParameterf(pname, paramf); + webContext()->texParameterf(target, pname, paramf); + } else { + tex->setParameteri(pname, parami); + webContext()->texParameteri(target, pname, parami); + } +} + +void WebGLRenderingContextBase::texParameterf(GLenum target, GLenum pname, GLfloat param) +{ + texParameter(target, pname, param, 0, true); +} + +void WebGLRenderingContextBase::texParameteri(GLenum target, GLenum pname, GLint param) +{ + texParameter(target, pname, 0, param, false); +} + +void WebGLRenderingContextBase::texSubImage2DBase(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels, ExceptionState& exceptionState) +{ + // FIXME: Handle errors. + ASSERT(!isContextLost()); + ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type)); + ASSERT(validateSize("texSubImage2D", xoffset, yoffset)); + ASSERT(validateSettableTexFormat("texSubImage2D", format)); + WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true); + if (!tex) { + ASSERT_NOT_REACHED(); + return; + } + ASSERT((xoffset + width) >= 0); + ASSERT((yoffset + height) >= 0); + ASSERT(tex->getWidth(target, level) >= (xoffset + width)); + ASSERT(tex->getHeight(target, level) >= (yoffset + height)); + ASSERT(tex->getInternalFormat(target, level) == format); + ASSERT(tex->getType(target, level) == type); + webContext()->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +void WebGLRenderingContextBase::texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + Vector<uint8_t> data; + WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); + if (!imageExtractor.extractSucceeded()) { + synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image"); + return; + } + WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + + bool needConversion = true; + if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY) + needConversion = false; + else { + if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { + synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data"); + return; + } + } + + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texSubImage2DBase(target, level, xoffset, yoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), format, type, needConversion ? data.data() : imagePixelData, exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, ArrayBufferView* pixels, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed) + || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset)) + return; + void* data = pixels->baseAddress(); + Vector<uint8_t> tempData; + bool changeUnpackAlignment = false; + if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { + if (!WebGLImageConversion::extractTextureData(width, height, format, type, + m_unpackAlignment, + m_unpackFlipY, m_unpackPremultiplyAlpha, + data, + tempData)) + return; + data = tempData.data(); + changeUnpackAlignment = true; + } + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, exceptionState); + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, ImageData* pixels, ExceptionState& exceptionState) +{ + if (isContextLost() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset)) + return; + + Vector<uint8_t> data; + bool needConversion = true; + // The data from ImageData is always of format RGBA8. + // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. + if (format == GL_RGBA && type == GL_UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) + needConversion = false; + else { + if (!WebGLImageConversion::extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { + synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data"); + return; + } + } + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLImageElement("texSubImage2D", image, exceptionState)) + return; + + RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); + if (imageForRender->isSVGImage()) + imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), "texSubImage2D"); + + if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset)) + return; + + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLCanvasElement("texSubImage2D", canvas, exceptionState) + || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset)) + return; + + RefPtrWillBeRawPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), exceptionState); + else + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLVideoElement("texSubImage2D", video, exceptionState) + || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset)) + return; + + RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); + if (!image) + return; + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GLfloat x) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform1f", "location not for current program"); + return; + } + + webContext()->uniform1f(location->location(), x); +} + +void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1)) + return; + + webContext()->uniform1fv(location->location(), v->length(), v->data()); +} + +void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1)) + return; + + webContext()->uniform1fv(location->location(), size, v); +} + +void WebGLRenderingContextBase::uniform1i(const WebGLUniformLocation* location, GLint x) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform1i", "location not for current program"); + return; + } + + webContext()->uniform1i(location->location(), x); +} + +void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1)) + return; + + webContext()->uniform1iv(location->location(), v->length(), v->data()); +} + +void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1)) + return; + + webContext()->uniform1iv(location->location(), size, v); +} + +void WebGLRenderingContextBase::uniform2f(const WebGLUniformLocation* location, GLfloat x, GLfloat y) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform2f", "location not for current program"); + return; + } + + webContext()->uniform2f(location->location(), x, y); +} + +void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2)) + return; + + webContext()->uniform2fv(location->location(), v->length() / 2, v->data()); +} + +void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2)) + return; + + webContext()->uniform2fv(location->location(), size / 2, v); +} + +void WebGLRenderingContextBase::uniform2i(const WebGLUniformLocation* location, GLint x, GLint y) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform2i", "location not for current program"); + return; + } + + webContext()->uniform2i(location->location(), x, y); +} + +void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2)) + return; + + webContext()->uniform2iv(location->location(), v->length() / 2, v->data()); +} + +void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2)) + return; + + webContext()->uniform2iv(location->location(), size / 2, v); +} + +void WebGLRenderingContextBase::uniform3f(const WebGLUniformLocation* location, GLfloat x, GLfloat y, GLfloat z) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform3f", "location not for current program"); + return; + } + + webContext()->uniform3f(location->location(), x, y, z); +} + +void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3)) + return; + + webContext()->uniform3fv(location->location(), v->length() / 3, v->data()); +} + +void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3)) + return; + + webContext()->uniform3fv(location->location(), size / 3, v); +} + +void WebGLRenderingContextBase::uniform3i(const WebGLUniformLocation* location, GLint x, GLint y, GLint z) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform3i", "location not for current program"); + return; + } + + webContext()->uniform3i(location->location(), x, y, z); +} + +void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3)) + return; + + webContext()->uniform3iv(location->location(), v->length() / 3, v->data()); +} + +void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3)) + return; + + webContext()->uniform3iv(location->location(), size / 3, v); +} + +void WebGLRenderingContextBase::uniform4f(const WebGLUniformLocation* location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform4f", "location not for current program"); + return; + } + + webContext()->uniform4f(location->location(), x, y, z, w); +} + +void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4)) + return; + + webContext()->uniform4fv(location->location(), v->length() / 4, v->data()); +} + +void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4)) + return; + + webContext()->uniform4fv(location->location(), size / 4, v); +} + +void WebGLRenderingContextBase::uniform4i(const WebGLUniformLocation* location, GLint x, GLint y, GLint z, GLint w) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform4i", "location not for current program"); + return; + } + + webContext()->uniform4i(location->location(), x, y, z, w); +} + +void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4)) + return; + + webContext()->uniform4iv(location->location(), v->length() / 4, v->data()); +} + +void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4)) + return; + + webContext()->uniform4iv(location->location(), size / 4, v); +} + +void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) + return; + webContext()->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data()); +} + +void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GLboolean transpose, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) + return; + webContext()->uniformMatrix2fv(location->location(), size / 4, transpose, v); +} + +void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) + return; + webContext()->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data()); +} + +void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GLboolean transpose, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) + return; + webContext()->uniformMatrix3fv(location->location(), size / 9, transpose, v); +} + +void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) + return; + webContext()->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data()); +} + +void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GLboolean transpose, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) + return; + webContext()->uniformMatrix4fv(location->location(), size / 16, transpose, v); +} + +void WebGLRenderingContextBase::useProgram(WebGLProgram* program) +{ + bool deleted; + if (!checkObjectToBeBound("useProgram", program, deleted)) + return; + if (deleted) + program = 0; + if (program && !program->linkStatus()) { + synthesizeGLError(GL_INVALID_OPERATION, "useProgram", "program not valid"); + return; + } + if (m_currentProgram != program) { + if (m_currentProgram) + m_currentProgram->onDetached(webContext()); + m_currentProgram = program; + webContext()->useProgram(objectOrZero(program)); + if (program) + program->onAttached(); + } +} + +void WebGLRenderingContextBase::validateProgram(WebGLProgram* program) +{ + if (isContextLost() || !validateWebGLObject("validateProgram", program)) + return; + webContext()->validateProgram(objectOrZero(program)); +} + +void WebGLRenderingContextBase::vertexAttrib1f(GLuint index, GLfloat v0) +{ + vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib1fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib1fv", index, v, 1); +} + +void WebGLRenderingContextBase::vertexAttrib1fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1); +} + +void WebGLRenderingContextBase::vertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) +{ + vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib2fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib2fv", index, v, 2); +} + +void WebGLRenderingContextBase::vertexAttrib2fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2); +} + +void WebGLRenderingContextBase::vertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) +{ + vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib3fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib3fv", index, v, 3); +} + +void WebGLRenderingContextBase::vertexAttrib3fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3); +} + +void WebGLRenderingContextBase::vertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3); +} + +void WebGLRenderingContextBase::vertexAttrib4fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib4fv", index, v, 4); +} + +void WebGLRenderingContextBase::vertexAttrib4fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4); +} + +void WebGLRenderingContextBase::vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, long long offset) +{ + if (isContextLost()) + return; + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FLOAT: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "index out of range"); + return; + } + if (size < 1 || size > 4 || stride < 0 || stride > 255) { + synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad size or stride"); + return; + } + if (!validateValueFitNonNegInt32("vertexAttribPointer", "offset", offset)) + return; + if (!m_boundArrayBuffer) { + synthesizeGLError(GL_INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER"); + return; + } + // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride + unsigned typeSize = sizeInBytes(type); + if (!typeSize) { + synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); + return; + } + if ((stride % typeSize) || (static_cast<GLintptr>(offset) % typeSize)) { + synthesizeGLError(GL_INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type"); + return; + } + GLsizei bytesPerElement = size * typeSize; + + m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GLintptr>(offset), m_boundArrayBuffer); + webContext()->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GLintptr>(offset)); +} + +void WebGLRenderingContextBase::vertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + if (isContextLost()) + return; + + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "vertexAttribDivisorANGLE", "index out of range"); + return; + } + + m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor); + webContext()->vertexAttribDivisorANGLE(index, divisor); +} + +void WebGLRenderingContextBase::viewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (!validateSize("viewport", width, height)) + return; + webContext()->viewport(x, y, width, height); +} + +void WebGLRenderingContextBase::forceLostContext(WebGLRenderingContextBase::LostContextMode mode) +{ + if (isContextLost()) { + synthesizeGLError(GL_INVALID_OPERATION, "loseContext", "context already lost"); + return; + } + + m_contextGroup->loseContextGroup(mode); +} + +void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode) +{ +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): begin"); +#endif + + if (isContextLost()) + return; + + m_contextLost = true; + m_contextLostMode = mode; + + if (mode == RealLostContext) { + // Inform the embedder that a lost context was received. In response, the embedder might + // decide to take action such as asking the user for permission to use WebGL again. + if (LocalFrame* frame = canvas()->document().frame()) + frame->loader().client()->didLoseWebGLContext(webContext()->getGraphicsResetStatusARB()); + } + + // Make absolutely sure we do not refer to an already-deleted texture or framebuffer. + m_drawingBuffer->setTexture2DBinding(0); + m_drawingBuffer->setFramebufferBinding(0); + + detachAndRemoveAllObjects(); + +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): after detachAndRemoveAllObjects()"); +#endif + + // Lose all the extensions. + for (size_t i = 0; i < m_extensions.size(); ++i) { + ExtensionTracker* tracker = m_extensions[i]; + tracker->loseExtension(); + } + + for (size_t i = 0; i < WebGLExtensionNameCount; ++i) + m_extensionEnabled[i] = false; + + removeAllCompressedTextureFormats(); + + if (mode != RealLostContext) + destroyContext(); + +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): after destroyContext()"); +#endif + + ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole; + synthesizeGLError(GC3D_CONTEXT_LOST_WEBGL, "loseContext", "context lost", display); + + // Don't allow restoration unless the context lost event has both been + // dispatched and its default behavior prevented. + m_restoreAllowed = false; + + // Always defer the dispatch of the context lost event, to implement + // the spec behavior of queueing a task. + m_dispatchContextLostEventTimer.startOneShot(0, FROM_HERE); + +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): end"); +#endif +} + +void WebGLRenderingContextBase::forceRestoreContext() +{ + if (!isContextLost()) { + synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context not lost"); + return; + } + + if (!m_restoreAllowed) { + if (m_contextLostMode == SyntheticLostContext) + synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context restoration not allowed"); + return; + } + + if (!m_restoreTimer.isActive()) + m_restoreTimer.startOneShot(0, FROM_HERE); +} + +blink::WebLayer* WebGLRenderingContextBase::platformLayer() const +{ + return isContextLost() ? 0 : m_drawingBuffer->platformLayer(); +} + +Extensions3DUtil* WebGLRenderingContextBase::extensionsUtil() +{ + ASSERT(!isContextLost()); + if (!m_extensionsUtil) + m_extensionsUtil = Extensions3DUtil::create(webContext()); + return m_extensionsUtil.get(); +} + +void WebGLRenderingContextBase::removeSharedObject(WebGLSharedObject* object) +{ + m_contextGroup->removeObject(object); +} + +void WebGLRenderingContextBase::addSharedObject(WebGLSharedObject* object) +{ + ASSERT(!isContextLost()); + m_contextGroup->addObject(object); +} + +void WebGLRenderingContextBase::removeContextObject(WebGLContextObject* object) +{ + m_contextObjects.remove(object); +} + +void WebGLRenderingContextBase::addContextObject(WebGLContextObject* object) +{ + ASSERT(!isContextLost()); + m_contextObjects.add(object); +} + +void WebGLRenderingContextBase::detachAndRemoveAllObjects() +{ + while (m_contextObjects.size() > 0) { + HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin(); + (*it)->detachContext(); + } +} + +bool WebGLRenderingContextBase::hasPendingActivity() const +{ + return false; +} + +void WebGLRenderingContextBase::stop() +{ + if (!isContextLost()) { + forceLostContext(SyntheticLostContext); + destroyContext(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getBooleanParameter(GLenum pname) +{ + GLboolean value = 0; + if (!isContextLost()) + webContext()->getBooleanv(pname, &value); + return WebGLGetInfo(static_cast<bool>(value)); +} + +WebGLGetInfo WebGLRenderingContextBase::getBooleanArrayParameter(GLenum pname) +{ + if (pname != GL_COLOR_WRITEMASK) { + notImplemented(); + return WebGLGetInfo(0, 0); + } + GLboolean value[4] = {0}; + if (!isContextLost()) + webContext()->getBooleanv(pname, value); + bool boolValue[4]; + for (int ii = 0; ii < 4; ++ii) + boolValue[ii] = static_cast<bool>(value[ii]); + return WebGLGetInfo(boolValue, 4); +} + +WebGLGetInfo WebGLRenderingContextBase::getFloatParameter(GLenum pname) +{ + GLfloat value = 0; + if (!isContextLost()) + webContext()->getFloatv(pname, &value); + return WebGLGetInfo(value); +} + +WebGLGetInfo WebGLRenderingContextBase::getIntParameter(GLenum pname) +{ + GLint value = 0; + if (!isContextLost()) + webContext()->getIntegerv(pname, &value); + return WebGLGetInfo(value); +} + +WebGLGetInfo WebGLRenderingContextBase::getUnsignedIntParameter(GLenum pname) +{ + GLint value = 0; + if (!isContextLost()) + webContext()->getIntegerv(pname, &value); + return WebGLGetInfo(static_cast<unsigned>(value)); +} + +WebGLGetInfo WebGLRenderingContextBase::getWebGLFloatArrayParameter(GLenum pname) +{ + GLfloat value[4] = {0}; + if (!isContextLost()) + webContext()->getFloatv(pname, value); + unsigned length = 0; + switch (pname) { + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_DEPTH_RANGE: + length = 2; + break; + case GL_BLEND_COLOR: + case GL_COLOR_CLEAR_VALUE: + length = 4; + break; + default: + notImplemented(); + } + return WebGLGetInfo(Float32Array::create(value, length)); +} + +WebGLGetInfo WebGLRenderingContextBase::getWebGLIntArrayParameter(GLenum pname) +{ + GLint value[4] = {0}; + if (!isContextLost()) + webContext()->getIntegerv(pname, value); + unsigned length = 0; + switch (pname) { + case GL_MAX_VIEWPORT_DIMS: + length = 2; + break; + case GL_SCISSOR_BOX: + case GL_VIEWPORT: + length = 4; + break; + default: + notImplemented(); + } + return WebGLGetInfo(Int32Array::create(value, length)); +} + +void WebGLRenderingContextBase::handleTextureCompleteness(const char* functionName, bool prepareToDraw) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + bool resetActiveUnit = false; + WebGLTexture::TextureExtensionFlag flag = static_cast<WebGLTexture::TextureExtensionFlag>((extensionEnabled(OESTextureFloatLinearName) ? WebGLTexture::TextureFloatLinearExtensionEnabled : 0) + | (extensionEnabled(OESTextureHalfFloatLinearName) ? WebGLTexture::TextureHalfFloatLinearExtensionEnabled : 0)); + for (unsigned ii = 0; ii < m_onePlusMaxNonDefaultTextureUnit; ++ii) { + if ((m_textureUnits[ii].m_texture2DBinding.get() && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) + || (m_textureUnits[ii].m_textureCubeMapBinding.get() && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag))) { + if (ii != m_activeTextureUnit) { + webContext()->activeTexture(ii); + resetActiveUnit = true; + } else if (resetActiveUnit) { + webContext()->activeTexture(ii); + resetActiveUnit = false; + } + WebGLTexture* tex2D; + WebGLTexture* texCubeMap; + if (prepareToDraw) { + String msg(String("texture bound to texture unit ") + String::number(ii) + + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'." + + " Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled."); + emitGLWarning(functionName, msg.utf8().data()); + tex2D = m_blackTexture2D.get(); + texCubeMap = m_blackTextureCubeMap.get(); + } else { + tex2D = m_textureUnits[ii].m_texture2DBinding.get(); + texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get(); + } + if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) + webContext()->bindTexture(GL_TEXTURE_2D, objectOrZero(tex2D)); + if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag)) + webContext()->bindTexture(GL_TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); + } + } + if (resetActiveUnit) + webContext()->activeTexture(m_activeTextureUnit); +} + +void WebGLRenderingContextBase::createFallbackBlackTextures1x1() +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + unsigned char black[] = {0, 0, 0, 255}; + m_blackTexture2D = createTexture(); + webContext()->bindTexture(GL_TEXTURE_2D, m_blackTexture2D->object()); + webContext()->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->bindTexture(GL_TEXTURE_2D, 0); + m_blackTextureCubeMap = createTexture(); + webContext()->bindTexture(GL_TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->bindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +bool WebGLRenderingContextBase::isTexInternalFormatColorBufferCombinationValid(GLenum texInternalFormat, GLenum colorBufferFormat) +{ + unsigned need = WebGLImageConversion::getChannelBitsByFormat(texInternalFormat); + unsigned have = WebGLImageConversion::getChannelBitsByFormat(colorBufferFormat); + return (need & have) == need; +} + +GLenum WebGLRenderingContextBase::boundFramebufferColorFormat() +{ + if (m_framebufferBinding && m_framebufferBinding->object()) + return m_framebufferBinding->colorBufferFormat(); + if (m_requestedAttributes->alpha()) + return GL_RGBA; + return GL_RGB; +} + +WebGLTexture* WebGLRenderingContextBase::validateTextureBinding(const char* functionName, GLenum target, bool useSixEnumsForCubeMap) +{ + WebGLTexture* tex = 0; + switch (target) { + case GL_TEXTURE_2D: + tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get(); + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (!useSixEnumsForCubeMap) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); + return 0; + } + tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); + break; + case GL_TEXTURE_CUBE_MAP: + if (useSixEnumsForCubeMap) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); + return 0; + } + tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); + return 0; + } + if (!tex) + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no texture"); + return tex; +} + +bool WebGLRenderingContextBase::validateLocationLength(const char* functionName, const String& string) +{ + const unsigned maxWebGLLocationLength = 256; + if (string.length() > maxWebGLLocationLength) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "location length > 256"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateSize(const char* functionName, GLint x, GLint y) +{ + if (x < 0 || y < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "size < 0"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateString(const char* functionName, const String& string) +{ + for (size_t i = 0; i < string.length(); ++i) { + if (!validateCharacter(string[i])) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "string not ASCII"); + return false; + } + } + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, GLenum format, GLenum type, GLint level) +{ + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_RGB: + case GL_RGBA: + break; + case GL_DEPTH_STENCIL_OES: + case GL_DEPTH_COMPONENT: + if (extensionEnabled(WebGLDepthTextureName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "depth texture formats not enabled"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture format"); + return false; + } + + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + break; + case GL_FLOAT: + if (extensionEnabled(OESTextureFloatName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + case GL_HALF_FLOAT_OES: + if (extensionEnabled(OESTextureHalfFloatName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_24_8_OES: + case GL_UNSIGNED_SHORT: + if (extensionEnabled(WebGLDepthTextureName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + + // Verify that the combination of format and type is supported. + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + if (type != GL_UNSIGNED_BYTE + && type != GL_FLOAT + && type != GL_HALF_FLOAT_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for format"); + return false; + } + break; + case GL_RGB: + if (type != GL_UNSIGNED_BYTE + && type != GL_UNSIGNED_SHORT_5_6_5 + && type != GL_FLOAT + && type != GL_HALF_FLOAT_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGB format"); + return false; + } + break; + case GL_RGBA: + if (type != GL_UNSIGNED_BYTE + && type != GL_UNSIGNED_SHORT_4_4_4_4 + && type != GL_UNSIGNED_SHORT_5_5_5_1 + && type != GL_FLOAT + && type != GL_HALF_FLOAT_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGBA format"); + return false; + } + break; + case GL_DEPTH_COMPONENT: + if (!extensionEnabled(WebGLDepthTextureName)) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled"); + return false; + } + if (type != GL_UNSIGNED_SHORT + && type != GL_UNSIGNED_INT) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format"); + return false; + } + if (level > 0) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format"); + return false; + } + break; + case GL_DEPTH_STENCIL_OES: + if (!extensionEnabled(WebGLDepthTextureName)) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled"); + return false; + } + if (type != GL_UNSIGNED_INT_24_8_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format"); + return false; + } + if (level > 0) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format"); + return false; + } + break; + default: + ASSERT_NOT_REACHED(); + } + + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncLevel(const char* functionName, GLenum target, GLint level) +{ + if (level < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "level < 0"); + return false; + } + switch (target) { + case GL_TEXTURE_2D: + if (level >= m_maxTextureLevel) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "level out of range"); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (level >= m_maxCubeMapTextureLevel) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "level out of range"); + return false; + } + break; + } + // This function only checks if level is legal, so we return true and don't + // generate INVALID_ENUM if target is illegal. + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType functionType, + GLenum target, GLint level, GLsizei width, GLsizei height) +{ + if (width < 0 || height < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + switch (target) { + case GL_TEXTURE_2D: + if (width > (m_maxTextureSize >> level) || height > (m_maxTextureSize >> level)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range"); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (functionType != TexSubImage2D && width != height) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width != height for cube map"); + return false; + } + // No need to check height here. For texImage width == height. + // For texSubImage that will be checked when checking yoffset + height is in range. + if (width > (m_maxCubeMapTextureSize >> level)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range for cube map"); + return false; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType functionType, GLenum target, + GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type) +{ + // We absolutely have to validate the format and type combination. + // The texImage2D entry points taking HTMLImage, etc. will produce + // temporary data based on this combination, so it must be legal. + if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level)) + return false; + + if (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) + return false; + + if (format != internalformat) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "format != internalformat"); + return false; + } + + if (border) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "border != 0"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView* pixels, NullDisposition disposition) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + if (!pixels) { + if (disposition == NullAllowed) + return true; + synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); + return false; + } + + if (!validateTexFuncFormatAndType(functionName, format, type, level)) + return false; + if (!validateSettableTexFormat(functionName, format)) + return false; + + switch (type) { + case GL_UNSIGNED_BYTE: + if (pixels->type() != ArrayBufferView::TypeUint8) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array"); + return false; + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + if (pixels->type() != ArrayBufferView::TypeUint16) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array"); + return false; + } + break; + case GL_FLOAT: // OES_texture_float + if (pixels->type() != ArrayBufferView::TypeFloat32) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array"); + return false; + } + break; + case GL_HALF_FLOAT_OES: // OES_texture_half_float + // As per the specification, ArrayBufferView should be null or a Uint16Array when + // OES_texture_half_float is enabled. + if (pixels && pixels->type() != ArrayBufferView::TypeUint16) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL and not Uint16Array"); + return false; + } + break; + default: + ASSERT_NOT_REACHED(); + } + + unsigned totalBytesRequired; + GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0); + if (error != GL_NO_ERROR) { + synthesizeGLError(error, functionName, "invalid texture dimensions"); + return false; + } + if (pixels->byteLength() < totalBytesRequired) { + if (m_unpackAlignment != 1) { + error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0); + if (pixels->byteLength() == totalBytesRequired) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1"); + return false; + } + } + synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexFormat(GLenum format) +{ + return m_compressedTextureFormats.contains(format); +} + +bool WebGLRenderingContextBase::validateCompressedTexFuncData(const char* functionName, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* pixels) +{ + if (!pixels) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); + return false; + } + if (width < 0 || height < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + unsigned bytesRequired = 0; + + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + const int kBlockSize = 8; + int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; + int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; + int numBlocks = numBlocksAcross * numBlocksDown; + bytesRequired = numBlocks * kBlockSize; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + const int kBlockSize = 16; + int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; + int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; + int numBlocks = numBlocksAcross * numBlocksDown; + bytesRequired = numBlocks * kBlockSize; + } + break; + case GC3D_COMPRESSED_ATC_RGB_AMD: + case GL_ETC1_RGB8_OES: + { + bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 8; + } + break; + case GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + { + bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 16; + } + break; + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + { + bytesRequired = (max(width, 8) * max(height, 8) * 4 + 7) / 8; + } + break; + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: + { + bytesRequired = (max(width, 16) * max(height, 8) * 2 + 7) / 8; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format"); + return false; + } + + if (pixels->byteLength() != bytesRequired) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType functionType, GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format) +{ + if (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) + return false; + + bool widthValid = false; + bool heightValid = false; + + switch (format) { + case GC3D_COMPRESSED_ATC_RGB_AMD: + case GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + widthValid = (level && width == 1) || (level && width == 2) || !(width % kBlockWidth); + heightValid = (level && height == 1) || (level && height == 2) || !(height % kBlockHeight); + break; + } + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + // Must be a power of two + widthValid = (width & (width - 1)) == 0; + heightValid = (height & (height - 1)) == 0; + break; + } + case GL_ETC1_RGB8_OES: { + widthValid = true; + heightValid = true; + break; + } + default: + return false; + } + + if (!widthValid || !heightValid) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "width or height invalid for level"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* functionName, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, WebGLTexture* tex) +{ + if (xoffset < 0 || yoffset < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "xoffset or yoffset < 0"); + return false; + } + + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4"); + return false; + } + if (width - xoffset > tex->getWidth(target, level) + || height - yoffset > tex->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "dimensions out of range"); + return false; + } + return validateCompressedTexDimensions(functionName, TexSubImage2D, target, level, width, height, format); + } + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + if ((xoffset != 0) || (yoffset != 0)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset and yoffset must be zero"); + return false; + } + if (width != tex->getWidth(target, level) + || height != tex->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "dimensions must match existing level"); + return false; + } + return validateCompressedTexDimensions(functionName, TexSubImage2D, target, level, width, height, format); + } + case GC3D_COMPRESSED_ATC_RGB_AMD: + case GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + case GL_ETC1_RGB8_OES: { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "unable to update sub-images with this format"); + return false; + } + default: + return false; + } +} + +bool WebGLRenderingContextBase::validateDrawMode(const char* functionName, GLenum mode) +{ + switch (mode) { + case GL_POINTS: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + case GL_LINES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + case GL_TRIANGLES: + return true; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid draw mode"); + return false; + } +} + +bool WebGLRenderingContextBase::validateStencilSettings(const char* functionName) +{ + if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "front and back stencils settings do not match"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateStencilOrDepthFunc(const char* functionName, GLenum func) +{ + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_LEQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + return true; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid function"); + return false; + } +} + +void WebGLRenderingContextBase::printGLErrorToConsole(const String& message) +{ + if (!m_numGLErrorsToConsoleAllowed) + return; + + --m_numGLErrorsToConsoleAllowed; + printWarningToConsole(message); + + if (!m_numGLErrorsToConsoleAllowed) + printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context."); + + return; +} + +void WebGLRenderingContextBase::printWarningToConsole(const String& message) +{ + if (!canvas()) + return; + canvas()->document().addConsoleMessage(RenderingMessageSource, WarningMessageLevel, message); +} + +bool WebGLRenderingContextBase::validateFramebufferFuncParameters(const char* functionName, GLenum target, GLenum attachment) +{ + if (target != GL_FRAMEBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); + return false; + } + switch (attachment) { + case GL_COLOR_ATTACHMENT0: + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: + break; + default: + if (extensionEnabled(WebGLDrawBuffersName) + && attachment > GL_COLOR_ATTACHMENT0 + && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + maxColorAttachments())) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid attachment"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateBlendEquation(const char* functionName, GLenum mode) +{ + switch (mode) { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + return true; + case GL_MIN_EXT: + case GL_MAX_EXT: + if (extensionEnabled(EXTBlendMinMaxName)) + return true; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid mode"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid mode"); + return false; + } +} + +bool WebGLRenderingContextBase::validateBlendFuncFactors(const char* functionName, GLenum src, GLenum dst) +{ + if (((src == GL_CONSTANT_COLOR || src == GL_ONE_MINUS_CONSTANT_COLOR) + && (dst == GL_CONSTANT_ALPHA || dst == GL_ONE_MINUS_CONSTANT_ALPHA)) + || ((dst == GL_CONSTANT_COLOR || dst == GL_ONE_MINUS_CONSTANT_COLOR) + && (src == GL_CONSTANT_ALPHA || src == GL_ONE_MINUS_CONSTANT_ALPHA))) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "incompatible src and dst"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateCapability(const char* functionName, GLenum cap) +{ + switch (cap) { + case GL_BLEND: + case GL_CULL_FACE: + case GL_DEPTH_TEST: + case GL_DITHER: + case GL_POLYGON_OFFSET_FILL: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + return true; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid capability"); + return false; + } +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GLsizei requiredMinSize) +{ + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GLsizei requiredMinSize) +{ + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GLsizei size, GLsizei requiredMinSize) +{ + return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v, GLsizei requiredMinSize) +{ + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GLboolean transpose, void* v, GLsizei size, GLsizei requiredMinSize) +{ + if (!location) + return false; + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "location is not from current program"); + return false; + } + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + if (transpose) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "transpose not FALSE"); + return false; + } + if (size < requiredMinSize || (size % requiredMinSize)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); + return false; + } + return true; +} + +WebGLBuffer* WebGLRenderingContextBase::validateBufferDataTarget(const char* functionName, GLenum target) +{ + WebGLBuffer* buffer = 0; + switch (target) { + case GL_ELEMENT_ARRAY_BUFFER: + buffer = m_boundVertexArrayObject->boundElementArrayBuffer().get(); + break; + case GL_ARRAY_BUFFER: + buffer = m_boundArrayBuffer.get(); + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); + return 0; + } + if (!buffer) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no buffer"); + return 0; + } + return buffer; +} + +bool WebGLRenderingContextBase::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionState& exceptionState) +{ + if (!image || !image->cachedImage()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no image"); + return false; + } + const KURL& url = image->cachedImage()->response().url(); + if (url.isNull() || url.isEmpty() || !url.isValid()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid image"); + return false; + } + + if (wouldTaintOrigin(image)) { + exceptionState.throwSecurityError("The cross-origin image at " + url.elidedString() + " may not be loaded."); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +{ + if (!canvas || !canvas->buffer()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no canvas"); + return false; + } + if (wouldTaintOrigin(canvas)) { + exceptionState.throwSecurityError("Tainted canvases may not be loaded."); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionState& exceptionState) +{ + if (!video || !video->videoWidth() || !video->videoHeight()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no video"); + return false; + } + + if (wouldTaintOrigin(video)) { + exceptionState.throwSecurityError("The video element contains cross-origin data, and may not be loaded."); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateDrawArrays(const char* functionName, GLenum mode, GLint first, GLsizei count) +{ + if (isContextLost() || !validateDrawMode(functionName, mode)) + return false; + + if (!validateStencilSettings(functionName)) + return false; + + if (first < 0 || count < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "first or count < 0"); + return false; + } + + if (!count) { + markContextChanged(CanvasChanged); + return false; + } + + if (!validateRenderingState(functionName)) { + return false; + } + + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateDrawElements(const char* functionName, GLenum mode, GLsizei count, GLenum type, long long offset) +{ + if (isContextLost() || !validateDrawMode(functionName, mode)) + return false; + + if (!validateStencilSettings(functionName)) + return false; + + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + case GL_UNSIGNED_INT: + if (extensionEnabled(OESElementIndexUintName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); + return false; + } + + if (count < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "count < 0"); + return false; + } + if (!validateValueFitNonNegInt32(functionName, "offset", offset)) + return false; + + if (!count) { + markContextChanged(CanvasChanged); + return false; + } + + if (!m_boundVertexArrayObject->boundElementArrayBuffer()) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound"); + return false; + } + + if (!validateRenderingState(functionName)) { + return false; + } + + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); + return false; + } + + return true; +} + +// Helper function to validate draw*Instanced calls +bool WebGLRenderingContextBase::validateDrawInstanced(const char* functionName, GLsizei primcount) +{ + if (primcount < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "primcount < 0"); + return false; + } + + // Ensure at least one enabled vertex attrib has a divisor of 0. + for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { + const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); + if (state.enabled && !state.divisor) + return true; + } + + synthesizeGLError(GL_INVALID_OPERATION, functionName, "at least one enabled attribute must have a divisor of 0"); + return false; +} + +void WebGLRenderingContextBase::vertexAttribfImpl(const char* functionName, GLuint index, GLsizei expectedSize, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + if (isContextLost()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); + return; + } + // In GL, we skip setting vertexAttrib0 values. + switch (expectedSize) { + case 1: + webContext()->vertexAttrib1f(index, v0); + break; + case 2: + webContext()->vertexAttrib2f(index, v0, v1); + break; + case 3: + webContext()->vertexAttrib3f(index, v0, v1, v2); + break; + case 4: + webContext()->vertexAttrib4f(index, v0, v1, v2, v3); + break; + } + VertexAttribValue& attribValue = m_vertexAttribValue[index]; + attribValue.value[0] = v0; + attribValue.value[1] = v1; + attribValue.value[2] = v2; + attribValue.value[3] = v3; +} + +void WebGLRenderingContextBase::vertexAttribfvImpl(const char* functionName, GLuint index, Float32Array* v, GLsizei expectedSize) +{ + if (isContextLost()) + return; + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return; + } + vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize); +} + +void WebGLRenderingContextBase::vertexAttribfvImpl(const char* functionName, GLuint index, GLfloat* v, GLsizei size, GLsizei expectedSize) +{ + if (isContextLost()) + return; + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return; + } + if (size < expectedSize) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); + return; + } + // In GL, we skip setting vertexAttrib0 values. + switch (expectedSize) { + case 1: + webContext()->vertexAttrib1fv(index, v); + break; + case 2: + webContext()->vertexAttrib2fv(index, v); + break; + case 3: + webContext()->vertexAttrib3fv(index, v); + break; + case 4: + webContext()->vertexAttrib4fv(index, v); + break; + } + VertexAttribValue& attribValue = m_vertexAttribValue[index]; + attribValue.initValue(); + for (int ii = 0; ii < expectedSize; ++ii) + attribValue.value[ii] = v[ii]; +} + +void WebGLRenderingContextBase::dispatchContextLostEvent(Timer<WebGLRenderingContextBase>*) +{ + RefPtrWillBeRawPtr<WebGLContextEvent> event = WebGLContextEvent::create(EventTypeNames::webglcontextlost, false, true, ""); + canvas()->dispatchEvent(event); + m_restoreAllowed = event->defaultPrevented(); + deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAllowed); + if ((m_contextLostMode == RealLostContext || m_contextLostMode == AutoRecoverSyntheticLostContext) && m_restoreAllowed) + m_restoreTimer.startOneShot(0, FROM_HERE); +} + +void WebGLRenderingContextBase::maybeRestoreContext(Timer<WebGLRenderingContextBase>*) +{ +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): begin"); +#endif + ASSERT(isContextLost()); + + // The rendering context is not restored unless the default behavior of the + // webglcontextlost event was prevented earlier. + // + // Because of the way m_restoreTimer is set up for real vs. synthetic lost + // context events, we don't have to worry about this test short-circuiting + // the retry loop for real context lost events. + if (!m_restoreAllowed) + return; + + LocalFrame* frame = canvas()->document().frame(); + if (!frame) + return; + + Settings* settings = frame->settings(); + + if (!frame->loader().client()->allowWebGL(settings && settings->webGLEnabled())) + return; + + // If the context was lost due to RealLostContext, we need to destroy the old DrawingBuffer before creating new DrawingBuffer to ensure resource budget enough. + if (m_drawingBuffer) { + m_drawingBuffer->beginDestruction(); + m_drawingBuffer.clear(); + } +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): destroyed old DrawingBuffer"); +#endif + + blink::WebGraphicsContext3D::Attributes attributes = m_requestedAttributes->attributes(canvas()->document().topDocument().url().string(), settings); + OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(attributes, 0)); + RefPtr<DrawingBuffer> drawingBuffer; + // Even if a non-null WebGraphicsContext3D is created, until it's made current, it isn't known whether the context is still lost. + if (context) { + // Construct a new drawing buffer with the new WebGraphicsContext3D. + drawingBuffer = createDrawingBuffer(context.release()); + // If DrawingBuffer::create() fails to allocate a fbo, |drawingBuffer| is set to null. + } + if (!drawingBuffer) { + if (m_contextLostMode == RealLostContext) { + m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts, FROM_HERE); + } else { + // This likely shouldn't happen but is the best way to report it to the WebGL app. + synthesizeGLError(GL_INVALID_OPERATION, "", "error restoring context"); + } + return; + } +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): created new DrawingBuffer"); +#endif + + m_drawingBuffer = drawingBuffer.release(); + m_drawingBuffer->bind(); + m_lostContextErrors.clear(); + m_contextLost = false; + + setupFlags(); + initializeNewContext(); + markContextChanged(CanvasContextChanged); +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): before dispatchEvent"); +#endif + canvas()->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextrestored, false, true, "")); +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): end"); +#endif +} + +String WebGLRenderingContextBase::ensureNotNull(const String& text) const +{ + if (text.isNull()) + return WTF::emptyString(); + return text; +} + +WebGLRenderingContextBase::LRUImageBufferCache::LRUImageBufferCache(int capacity) + : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity])) + , m_capacity(capacity) +{ +} + +ImageBuffer* WebGLRenderingContextBase::LRUImageBufferCache::imageBuffer(const IntSize& size) +{ + int i; + for (i = 0; i < m_capacity; ++i) { + ImageBuffer* buf = m_buffers[i].get(); + if (!buf) + break; + if (buf->size() != size) + continue; + bubbleToFront(i); + return buf; + } + + OwnPtr<ImageBuffer> temp(ImageBuffer::create(size)); + if (!temp) + return 0; + i = std::min(m_capacity - 1, i); + m_buffers[i] = temp.release(); + + ImageBuffer* buf = m_buffers[i].get(); + bubbleToFront(i); + return buf; +} + +void WebGLRenderingContextBase::LRUImageBufferCache::bubbleToFront(int idx) +{ + for (int i = idx; i > 0; --i) + m_buffers[i].swap(m_buffers[i-1]); +} + +namespace { + + String GetErrorString(GLenum error) + { + switch (error) { + case GL_INVALID_ENUM: + return "INVALID_ENUM"; + case GL_INVALID_VALUE: + return "INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "INVALID_OPERATION"; + case GL_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case GL_INVALID_FRAMEBUFFER_OPERATION: + return "INVALID_FRAMEBUFFER_OPERATION"; + case GC3D_CONTEXT_LOST_WEBGL: + return "CONTEXT_LOST_WEBGL"; + default: + return String::format("WebGL ERROR(0x%04X)", error); + } + } + +} // namespace anonymous + +void WebGLRenderingContextBase::synthesizeGLError(GLenum error, const char* functionName, const char* description, ConsoleDisplayPreference display) +{ + String errorType = GetErrorString(error); + if (m_synthesizedErrorsToConsole && display == DisplayInConsole) { + String message = String("WebGL: ") + errorType + ": " + String(functionName) + ": " + String(description); + printGLErrorToConsole(message); + } + if (!isContextLost()) + webContext()->synthesizeGLError(error); + else { + if (m_lostContextErrors.find(error) == WTF::kNotFound) + m_lostContextErrors.append(error); + } + InspectorInstrumentation::didFireWebGLError(canvas(), errorType); +} + +void WebGLRenderingContextBase::emitGLWarning(const char* functionName, const char* description) +{ + if (m_synthesizedErrorsToConsole) { + String message = String("WebGL: ") + String(functionName) + ": " + String(description); + printGLErrorToConsole(message); + } + InspectorInstrumentation::didFireWebGLWarning(canvas()); +} + +void WebGLRenderingContextBase::applyStencilTest() +{ + bool haveStencilBuffer = false; + + if (m_framebufferBinding) + haveStencilBuffer = m_framebufferBinding->hasStencilBuffer(); + else { + RefPtr<WebGLContextAttributes> attributes = getContextAttributes(); + haveStencilBuffer = attributes->stencil(); + } + enableOrDisable(GL_STENCIL_TEST, + m_stencilEnabled && haveStencilBuffer); +} + +void WebGLRenderingContextBase::enableOrDisable(GLenum capability, bool enable) +{ + if (isContextLost()) + return; + if (enable) + webContext()->enable(capability); + else + webContext()->disable(capability); +} + +IntSize WebGLRenderingContextBase::clampedCanvasSize() +{ + return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]), + clamp(canvas()->height(), 1, m_maxViewportDims[1])); +} + +GLint WebGLRenderingContextBase::maxDrawBuffers() +{ + if (isContextLost() || !extensionEnabled(WebGLDrawBuffersName)) + return 0; + if (!m_maxDrawBuffers) + webContext()->getIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers); + if (!m_maxColorAttachments) + webContext()->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS. + return std::min(m_maxDrawBuffers, m_maxColorAttachments); +} + +GLint WebGLRenderingContextBase::maxColorAttachments() +{ + if (isContextLost() || !extensionEnabled(WebGLDrawBuffersName)) + return 0; + if (!m_maxColorAttachments) + webContext()->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + return m_maxColorAttachments; +} + +void WebGLRenderingContextBase::setBackDrawBuffer(GLenum buf) +{ + m_backDrawBuffer = buf; +} + +void WebGLRenderingContextBase::restoreCurrentFramebuffer() +{ + bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding.get()); +} + +void WebGLRenderingContextBase::restoreCurrentTexture2D() +{ + bindTexture(GL_TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()); +} + +void WebGLRenderingContextBase::multisamplingChanged(bool enabled) +{ + if (m_multisamplingAllowed != enabled) { + m_multisamplingAllowed = enabled; + forceLostContext(WebGLRenderingContextBase::AutoRecoverSyntheticLostContext); + } +} + +void WebGLRenderingContextBase::findNewMaxEnabledAttribIndex() +{ + // Trace backwards from the current max to find the new max enabled attrib index + int startIndex = m_onePlusMaxEnabledAttribIndex - 1; + for (int i = startIndex; i >= 0; --i) { + if (m_boundVertexArrayObject->getVertexAttribState(i).enabled) { + m_onePlusMaxEnabledAttribIndex = i + 1; + return; + } + } + m_onePlusMaxEnabledAttribIndex = 0; +} + +void WebGLRenderingContextBase::findNewMaxNonDefaultTextureUnit() +{ + // Trace backwards from the current max to find the new max non-default texture unit + int startIndex = m_onePlusMaxNonDefaultTextureUnit - 1; + for (int i = startIndex; i >= 0; --i) { + if (m_textureUnits[i].m_texture2DBinding + || m_textureUnits[i].m_textureCubeMapBinding) { + m_onePlusMaxNonDefaultTextureUnit = i + 1; + return; + } + } + m_onePlusMaxNonDefaultTextureUnit = 0; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.h new file mode 100644 index 00000000000..ca08a621efc --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.h @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebGLRenderingContextBase_h +#define WebGLRenderingContextBase_h + +#include "core/dom/ActiveDOMObject.h" +#include "core/html/canvas/CanvasRenderingContext.h" +#include "core/html/canvas/WebGLExtensionName.h" +#include "core/html/canvas/WebGLGetInfo.h" +#include "core/page/Page.h" +#include "core/rendering/RenderBoxModelObject.h" +#include "platform/Timer.h" +#include "platform/graphics/GraphicsTypes3D.h" +#include "platform/graphics/ImageBuffer.h" +#include "platform/graphics/gpu/DrawingBuffer.h" +#include "platform/graphics/gpu/Extensions3DUtil.h" +#include "platform/graphics/gpu/WebGLImageConversion.h" +#include "public/platform/WebGraphicsContext3D.h" +#include "wtf/Float32Array.h" +#include "wtf/Int32Array.h" +#include "wtf/OwnPtr.h" +#include "wtf/text/WTFString.h" + +namespace blink { +class WebLayer; +} + +namespace WebCore { + +class ANGLEInstancedArrays; +class EXTBlendMinMax; +class EXTFragDepth; +class EXTShaderTextureLOD; +class EXTTextureFilterAnisotropic; +class ExceptionState; +class HTMLImageElement; +class HTMLVideoElement; +class ImageBuffer; +class ImageData; +class IntSize; +class OESElementIndexUint; +class OESStandardDerivatives; +class OESTextureFloat; +class OESTextureFloatLinear; +class OESTextureHalfFloat; +class OESTextureHalfFloatLinear; +class OESVertexArrayObject; +class WebGLActiveInfo; +class WebGLBuffer; +class WebGLCompressedTextureATC; +class WebGLCompressedTextureETC1; +class WebGLCompressedTexturePVRTC; +class WebGLCompressedTextureS3TC; +class WebGLContextAttributes; +class WebGLContextGroup; +class WebGLContextObject; +class WebGLDebugRendererInfo; +class WebGLDebugShaders; +class WebGLDepthTexture; +class WebGLDrawBuffers; +class WebGLExtension; +class WebGLFramebuffer; +class WebGLLoseContext; +class WebGLObject; +class WebGLProgram; +class WebGLRenderbuffer; +class WebGLShader; +class WebGLShaderPrecisionFormat; +class WebGLSharedObject; +class WebGLTexture; +class WebGLUniformLocation; +class WebGLVertexArrayObjectOES; + +class WebGLRenderingContextLostCallback; +class WebGLRenderingContextErrorMessageCallback; + +class WebGLRenderingContextBase: public CanvasRenderingContext, public ActiveDOMObject, public Page::MultisamplingChangedObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WebGLRenderingContextBase); +public: + virtual ~WebGLRenderingContextBase(); + + virtual bool is3d() const OVERRIDE { return true; } + virtual bool isAccelerated() const OVERRIDE { return true; } + virtual unsigned version() const = 0; + virtual String contextName() const = 0; + virtual void registerContextExtensions() = 0; + + static unsigned getWebGLVersion(const CanvasRenderingContext*); + + int drawingBufferWidth() const; + int drawingBufferHeight() const; + + void activeTexture(GLenum texture); + void attachShader(WebGLProgram*, WebGLShader*); + void bindAttribLocation(WebGLProgram*, GLuint index, const String& name); + void bindBuffer(GLenum target, WebGLBuffer*); + void bindFramebuffer(GLenum target, WebGLFramebuffer*); + void bindRenderbuffer(GLenum target, WebGLRenderbuffer*); + void bindTexture(GLenum target, WebGLTexture*); + void blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + void blendEquation(GLenum mode); + void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + void blendFunc(GLenum sfactor, GLenum dfactor); + void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + + void bufferData(GLenum target, long long size, GLenum usage); + void bufferData(GLenum target, ArrayBuffer* data, GLenum usage); + void bufferData(GLenum target, ArrayBufferView* data, GLenum usage); + void bufferSubData(GLenum target, long long offset, ArrayBuffer* data); + void bufferSubData(GLenum target, long long offset, ArrayBufferView* data); + + GLenum checkFramebufferStatus(GLenum target); + void clear(GLbitfield mask); + void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + void clearDepth(GLfloat); + void clearStencil(GLint); + void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void compileShader(WebGLShader*); + + void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, ArrayBufferView* data); + void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* data); + + void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + + PassRefPtr<WebGLBuffer> createBuffer(); + PassRefPtr<WebGLFramebuffer> createFramebuffer(); + PassRefPtr<WebGLProgram> createProgram(); + PassRefPtr<WebGLRenderbuffer> createRenderbuffer(); + PassRefPtr<WebGLShader> createShader(GLenum type); + PassRefPtr<WebGLTexture> createTexture(); + + void cullFace(GLenum mode); + + void deleteBuffer(WebGLBuffer*); + void deleteFramebuffer(WebGLFramebuffer*); + void deleteProgram(WebGLProgram*); + void deleteRenderbuffer(WebGLRenderbuffer*); + void deleteShader(WebGLShader*); + void deleteTexture(WebGLTexture*); + + void depthFunc(GLenum); + void depthMask(GLboolean); + void depthRange(GLfloat zNear, GLfloat zFar); + void detachShader(WebGLProgram*, WebGLShader*); + void disable(GLenum cap); + void disableVertexAttribArray(GLuint index); + void drawArrays(GLenum mode, GLint first, GLsizei count); + void drawElements(GLenum mode, GLsizei count, GLenum type, long long offset); + + void drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); + void drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount); + + void enable(GLenum cap); + void enableVertexAttribArray(GLuint index); + void finish(); + void flush(); + void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer*); + void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture*, GLint level); + void frontFace(GLenum mode); + void generateMipmap(GLenum target); + + PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GLuint index); + PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GLuint index); + bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader> >&); + GLint getAttribLocation(WebGLProgram*, const String& name); + WebGLGetInfo getBufferParameter(GLenum target, GLenum pname); + PassRefPtr<WebGLContextAttributes> getContextAttributes(); + GLenum getError(); + PassRefPtr<WebGLExtension> getExtension(const String& name); + WebGLGetInfo getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); + WebGLGetInfo getParameter(GLenum pname); + WebGLGetInfo getProgramParameter(WebGLProgram*, GLenum pname); + String getProgramInfoLog(WebGLProgram*); + WebGLGetInfo getRenderbufferParameter(GLenum target, GLenum pname); + WebGLGetInfo getShaderParameter(WebGLShader*, GLenum pname); + String getShaderInfoLog(WebGLShader*); + PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GLenum shaderType, GLenum precisionType); + String getShaderSource(WebGLShader*); + Vector<String> getSupportedExtensions(); + WebGLGetInfo getTexParameter(GLenum target, GLenum pname); + WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*); + PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&); + WebGLGetInfo getVertexAttrib(GLuint index, GLenum pname); + long long getVertexAttribOffset(GLuint index, GLenum pname); + + void hint(GLenum target, GLenum mode); + GLboolean isBuffer(WebGLBuffer*); + bool isContextLost() const; + GLboolean isEnabled(GLenum cap); + GLboolean isFramebuffer(WebGLFramebuffer*); + GLboolean isProgram(WebGLProgram*); + GLboolean isRenderbuffer(WebGLRenderbuffer*); + GLboolean isShader(WebGLShader*); + GLboolean isTexture(WebGLTexture*); + + void lineWidth(GLfloat); + void linkProgram(WebGLProgram*); + void pixelStorei(GLenum pname, GLint param); + void polygonOffset(GLfloat factor, GLfloat units); + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView* pixels); + void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void sampleCoverage(GLfloat value, GLboolean invert); + void scissor(GLint x, GLint y, GLsizei width, GLsizei height); + void shaderSource(WebGLShader*, const String&); + void stencilFunc(GLenum func, GLint ref, GLuint mask); + void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void stencilMask(GLuint); + void stencilMaskSeparate(GLenum face, GLuint mask); + void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); + void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, ArrayBufferView*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, ImageData*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLImageElement*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLCanvasElement*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLVideoElement*, ExceptionState&); + + void texParameterf(GLenum target, GLenum pname, GLfloat param); + void texParameteri(GLenum target, GLenum pname, GLint param); + + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, ArrayBufferView*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, ImageData*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLImageElement*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLCanvasElement*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLVideoElement*, ExceptionState&); + + void uniform1f(const WebGLUniformLocation*, GLfloat x); + void uniform1fv(const WebGLUniformLocation*, Float32Array* v); + void uniform1fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform1i(const WebGLUniformLocation*, GLint x); + void uniform1iv(const WebGLUniformLocation*, Int32Array* v); + void uniform1iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniform2f(const WebGLUniformLocation*, GLfloat x, GLfloat y); + void uniform2fv(const WebGLUniformLocation*, Float32Array* v); + void uniform2fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform2i(const WebGLUniformLocation*, GLint x, GLint y); + void uniform2iv(const WebGLUniformLocation*, Int32Array* v); + void uniform2iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniform3f(const WebGLUniformLocation*, GLfloat x, GLfloat y, GLfloat z); + void uniform3fv(const WebGLUniformLocation*, Float32Array* v); + void uniform3fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform3i(const WebGLUniformLocation*, GLint x, GLint y, GLint z); + void uniform3iv(const WebGLUniformLocation*, Int32Array* v); + void uniform3iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniform4f(const WebGLUniformLocation*, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform4fv(const WebGLUniformLocation*, Float32Array* v); + void uniform4fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform4i(const WebGLUniformLocation*, GLint x, GLint y, GLint z, GLint w); + void uniform4iv(const WebGLUniformLocation*, Int32Array* v); + void uniform4iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniformMatrix2fv(const WebGLUniformLocation*, GLboolean transpose, Float32Array* value); + void uniformMatrix2fv(const WebGLUniformLocation*, GLboolean transpose, GLfloat* value, GLsizei); + void uniformMatrix3fv(const WebGLUniformLocation*, GLboolean transpose, Float32Array* value); + void uniformMatrix3fv(const WebGLUniformLocation*, GLboolean transpose, GLfloat* value, GLsizei); + void uniformMatrix4fv(const WebGLUniformLocation*, GLboolean transpose, Float32Array* value); + void uniformMatrix4fv(const WebGLUniformLocation*, GLboolean transpose, GLfloat* value, GLsizei); + + void useProgram(WebGLProgram*); + void validateProgram(WebGLProgram*); + + void vertexAttrib1f(GLuint index, GLfloat x); + void vertexAttrib1fv(GLuint index, Float32Array* values); + void vertexAttrib1fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y); + void vertexAttrib2fv(GLuint index, Float32Array* values); + void vertexAttrib2fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z); + void vertexAttrib3fv(GLuint index, Float32Array* values); + void vertexAttrib3fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void vertexAttrib4fv(GLuint index, Float32Array* values); + void vertexAttrib4fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, + GLsizei stride, long long offset); + + void vertexAttribDivisorANGLE(GLuint index, GLuint divisor); + + void viewport(GLint x, GLint y, GLsizei width, GLsizei height); + + // WEBKIT_lose_context support + enum LostContextMode { + // Lost context occurred at the graphics system level. + RealLostContext, + + // Lost context provoked by WEBKIT_lose_context. + SyntheticLostContext, + + // A synthetic lost context that should attempt to recover automatically + AutoRecoverSyntheticLostContext + }; + void forceLostContext(LostContextMode); + void forceRestoreContext(); + void loseContextImpl(LostContextMode); + + blink::WebGraphicsContext3D* webContext() const { return m_drawingBuffer->context(); } + WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } + virtual blink::WebLayer* platformLayer() const OVERRIDE; + Extensions3DUtil* extensionsUtil(); + + void reshape(int width, int height); + + void markLayerComposited(); + virtual void paintRenderingResultsToCanvas() OVERRIDE; + PassRefPtrWillBeRawPtr<ImageData> paintRenderingResultsToImageData(); + + void removeSharedObject(WebGLSharedObject*); + void removeContextObject(WebGLContextObject*); + + unsigned maxVertexAttribs() const { return m_maxVertexAttribs; } + + // ActiveDOMObject notifications + virtual bool hasPendingActivity() const OVERRIDE; + virtual void stop() OVERRIDE; + + void setSavingImage(bool isSaving) { m_savingImage = isSaving; } +protected: + friend class WebGLDrawBuffers; + friend class WebGLFramebuffer; + friend class WebGLObject; + friend class OESVertexArrayObject; + friend class WebGLDebugShaders; + friend class WebGLCompressedTextureATC; + friend class WebGLCompressedTextureETC1; + friend class WebGLCompressedTexturePVRTC; + friend class WebGLCompressedTextureS3TC; + friend class WebGLRenderingContextErrorMessageCallback; + friend class WebGLVertexArrayObjectOES; + friend class ScopedTexture2DRestorer; + + WebGLRenderingContextBase(HTMLCanvasElement*, PassOwnPtr<blink::WebGraphicsContext3D>, WebGLContextAttributes*); + PassRefPtr<DrawingBuffer> createDrawingBuffer(PassOwnPtr<blink::WebGraphicsContext3D>); + void initializeNewContext(); + void setupFlags(); + + void addSharedObject(WebGLSharedObject*); + void addContextObject(WebGLContextObject*); + void detachAndRemoveAllObjects(); + + void destroyContext(); + void markContextChanged(ContentChangeType); + + // Query if the GL implementation is NPOT strict. + bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; } + // Query if depth_stencil buffer is supported. + bool isDepthStencilSupported() { return m_isDepthStencilSupported; } + + // Helper to return the size in bytes of OpenGL data types + // like GL_FLOAT, GL_INT, etc. + unsigned sizeInBytes(GLenum type); + + // Check if each enabled vertex attribute is bound to a buffer. + bool validateRenderingState(const char*); + + bool validateWebGLObject(const char*, WebGLObject*); + + // Adds a compressed texture format. + void addCompressedTextureFormat(GLenum); + void removeAllCompressedTextureFormats(); + + PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, const char* functionName); + + PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy); + + WebGLRenderbuffer* ensureEmulatedStencilBuffer(GLenum target, WebGLRenderbuffer*); + + // Structure for rendering to a DrawingBuffer, instead of directly + // to the back-buffer of m_context. + RefPtr<DrawingBuffer> m_drawingBuffer; + RefPtr<WebGLContextGroup> m_contextGroup; + + // Dispatches a context lost event once it is determined that one is needed. + // This is used both for synthetic and real context losses. For real ones, it's + // likely that there's no JavaScript on the stack, but that might be dependent + // on how exactly the platform discovers that the context was lost. For better + // portability we always defer the dispatch of the event. + Timer<WebGLRenderingContextBase> m_dispatchContextLostEventTimer; + bool m_restoreAllowed; + Timer<WebGLRenderingContextBase> m_restoreTimer; + + bool m_needsUpdate; + bool m_markedCanvasDirty; + HashSet<WebGLContextObject*> m_contextObjects; + + OwnPtr<WebGLRenderingContextLostCallback> m_contextLostCallbackAdapter; + OwnPtr<WebGLRenderingContextErrorMessageCallback> m_errorMessageCallbackAdapter; + + // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER + RefPtr<WebGLBuffer> m_boundArrayBuffer; + + RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject; + RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject; + void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject) + { + if (arrayObject) + m_boundVertexArrayObject = arrayObject; + else + m_boundVertexArrayObject = m_defaultVertexArrayObject; + } + + class VertexAttribValue { + public: + VertexAttribValue() + { + initValue(); + } + + void initValue() + { + value[0] = 0.0f; + value[1] = 0.0f; + value[2] = 0.0f; + value[3] = 1.0f; + } + + GLfloat value[4]; + }; + Vector<VertexAttribValue> m_vertexAttribValue; + unsigned m_maxVertexAttribs; + RefPtr<WebGLBuffer> m_vertexAttrib0Buffer; + long m_vertexAttrib0BufferSize; + GLfloat m_vertexAttrib0BufferValue[4]; + bool m_forceAttrib0BufferRefill; + bool m_vertexAttrib0UsedBefore; + + RefPtr<WebGLProgram> m_currentProgram; + RefPtr<WebGLFramebuffer> m_framebufferBinding; + RefPtr<WebGLRenderbuffer> m_renderbufferBinding; + class TextureUnitState { + public: + RefPtr<WebGLTexture> m_texture2DBinding; + RefPtr<WebGLTexture> m_textureCubeMapBinding; + }; + Vector<TextureUnitState> m_textureUnits; + unsigned long m_activeTextureUnit; + + RefPtr<WebGLTexture> m_blackTexture2D; + RefPtr<WebGLTexture> m_blackTextureCubeMap; + + Vector<GLenum> m_compressedTextureFormats; + + // Fixed-size cache of reusable image buffers for video texImage2D calls. + class LRUImageBufferCache { + public: + LRUImageBufferCache(int capacity); + // The pointer returned is owned by the image buffer map. + ImageBuffer* imageBuffer(const IntSize& size); + private: + void bubbleToFront(int idx); + OwnPtr<OwnPtr<ImageBuffer>[]> m_buffers; + int m_capacity; + }; + LRUImageBufferCache m_generatedImageCache; + + GLint m_maxTextureSize; + GLint m_maxCubeMapTextureSize; + GLint m_maxRenderbufferSize; + GLint m_maxViewportDims[2]; + GLint m_maxTextureLevel; + GLint m_maxCubeMapTextureLevel; + + GLint m_maxDrawBuffers; + GLint m_maxColorAttachments; + GLenum m_backDrawBuffer; + bool m_drawBuffersWebGLRequirementsChecked; + bool m_drawBuffersSupported; + + GLint m_packAlignment; + GLint m_unpackAlignment; + bool m_unpackFlipY; + bool m_unpackPremultiplyAlpha; + GLenum m_unpackColorspaceConversion; + bool m_contextLost; + LostContextMode m_contextLostMode; + RefPtr<WebGLContextAttributes> m_requestedAttributes; + + bool m_layerCleared; + GLfloat m_clearColor[4]; + bool m_scissorEnabled; + GLfloat m_clearDepth; + GLint m_clearStencil; + GLboolean m_colorMask[4]; + GLboolean m_depthMask; + + bool m_stencilEnabled; + GLuint m_stencilMask, m_stencilMaskBack; + GLint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value. + GLuint m_stencilFuncMask, m_stencilFuncMaskBack; + + bool m_isGLES2NPOTStrict; + bool m_isDepthStencilSupported; + + bool m_synthesizedErrorsToConsole; + int m_numGLErrorsToConsoleAllowed; + + bool m_multisamplingAllowed; + bool m_multisamplingObserverRegistered; + + GLuint m_onePlusMaxEnabledAttribIndex; + unsigned long m_onePlusMaxNonDefaultTextureUnit; + + OwnPtr<Extensions3DUtil> m_extensionsUtil; + + bool m_savingImage; + + enum ExtensionFlags { + ApprovedExtension = 0x00, + // Extension that is behind the draft extensions runtime flag: + DraftExtension = 0x01, + // Extension that is still in draft state, but has been selectively enabled by default under a prefix. Do not use + // this for enabling new draft extensions; use the DraftExtension flag instead, and do not use vendor prefixes: + EnabledDraftExtension = 0x04, + }; + + class ExtensionTracker { + public: + ExtensionTracker(ExtensionFlags flags, const char* const* prefixes) + : m_draft(flags & DraftExtension) + , m_prefixes(prefixes) + { + } + + virtual ~ExtensionTracker() + { + } + + bool draft() const + { + return m_draft; + } + + const char* const* prefixes() const; + bool matchesNameWithPrefixes(const String&) const; + + virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContextBase*) = 0; + virtual bool supported(WebGLRenderingContextBase*) const = 0; + virtual const char* extensionName() const = 0; + virtual void loseExtension() = 0; + + private: + bool m_draft; + const char* const* m_prefixes; + }; + + template <typename T> + class TypedExtensionTracker FINAL : public ExtensionTracker { + public: + TypedExtensionTracker(RefPtr<T>& extensionField, ExtensionFlags flags, const char* const* prefixes) + : ExtensionTracker(flags, prefixes) + , m_extensionField(extensionField) + , m_extension(nullptr) + { + } + + virtual ~TypedExtensionTracker() + { + if (m_extension) { + m_extension->lose(true); + m_extension = nullptr; + } + } + + virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContextBase* context) OVERRIDE + { + if (!m_extension) { + m_extension = T::create(context); + m_extensionField = m_extension; + } + + return m_extension; + } + + virtual bool supported(WebGLRenderingContextBase* context) const OVERRIDE + { + return T::supported(context); + } + + virtual const char* extensionName() const OVERRIDE + { + return T::extensionName(); + } + + virtual void loseExtension() OVERRIDE + { + if (m_extension) { + m_extension->lose(false); + if (m_extension->isLost()) + m_extension = nullptr; + } + } + + private: + RefPtr<T>& m_extensionField; + // ExtensionTracker holds it's own reference to the extension to ensure + // that it is not deleted before this object's destructor is called + RefPtr<T> m_extension; + }; + + bool m_extensionEnabled[WebGLExtensionNameCount]; + Vector<ExtensionTracker*> m_extensions; + + template <typename T> + void registerExtension(RefPtr<T>& extensionPtr, ExtensionFlags flags = ApprovedExtension, const char* const* prefixes = 0) + { + m_extensions.append(new TypedExtensionTracker<T>(extensionPtr, flags, prefixes)); + } + + bool extensionSupportedAndAllowed(const ExtensionTracker*); + + inline bool extensionEnabled(WebGLExtensionName name) + { + return m_extensionEnabled[name]; + } + + // Errors raised by synthesizeGLError() while the context is lost. + Vector<GLenum> m_lostContextErrors; + + // Helpers for getParameter and others + WebGLGetInfo getBooleanParameter(GLenum); + WebGLGetInfo getBooleanArrayParameter(GLenum); + WebGLGetInfo getFloatParameter(GLenum); + WebGLGetInfo getIntParameter(GLenum); + WebGLGetInfo getUnsignedIntParameter(GLenum); + WebGLGetInfo getWebGLFloatArrayParameter(GLenum); + WebGLGetInfo getWebGLIntArrayParameter(GLenum); + + // Clear the backbuffer if it was composited since the last operation. + // clearMask is set to the bitfield of any clear that would happen anyway at this time + // and the function returns true if that clear is now unnecessary. + bool clearIfComposited(GLbitfield clearMask = 0); + + // Helper to restore state that clearing the framebuffer may destroy. + void restoreStateAfterClear(); + + // Convert texture internal format. + GLenum convertTexInternalFormat(GLenum internalformat, GLenum type); + + void texImage2DBase(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels, ExceptionState&); + void texImage2DImpl(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); + void texSubImage2DBase(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels, ExceptionState&); + void texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); + + void handleTextureCompleteness(const char*, bool); + void createFallbackBlackTextures1x1(); + + // Helper function for copyTex{Sub}Image, check whether the internalformat + // and the color buffer format of the current bound framebuffer combination + // is valid. + bool isTexInternalFormatColorBufferCombinationValid(GLenum texInternalFormat, GLenum colorBufferFormat); + + // Helper function to get the bound framebuffer's color buffer format. + GLenum boundFramebufferColorFormat(); + + // Helper function to verify limits on the length of uniform and attribute locations. + bool validateLocationLength(const char* functionName, const String&); + + // Helper function to check if size is non-negative. + // Generate GL error and return false for negative inputs; otherwise, return true. + bool validateSize(const char* functionName, GLint x, GLint y); + + // Helper function to check if all characters in the string belong to the + // ASCII subset as defined in GLSL ES 1.0 spec section 3.1. + bool validateString(const char* functionName, const String&); + + // Helper function to check target and texture bound to the target. + // Generate GL errors and return 0 if target is invalid or texture bound is + // null. Otherwise, return the texture bound to the target. + WebGLTexture* validateTextureBinding(const char* functionName, GLenum target, bool useSixEnumsForCubeMap); + + // Helper function to check input format/type for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncFormatAndType(const char* functionName, GLenum format, GLenum type, GLint level); + + // Helper function to check input level for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if level is invalid. + bool validateTexFuncLevel(const char* functionName, GLenum target, GLint level); + + // Helper function to check if a 64-bit value is non-negative and can fit into a 32-bit integer. + // Generates GL error and returns false if not. + bool validateValueFitNonNegInt32(const char* functionName, const char* paramName, long long value); + + enum TexFuncValidationFunctionType { + NotTexSubImage2D, + TexSubImage2D, + }; + + enum TexFuncValidationSourceType { + SourceArrayBufferView, + SourceImageData, + SourceHTMLImageElement, + SourceHTMLCanvasElement, + SourceHTMLVideoElement, + }; + + // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid. + // Otherwise, it would return quickly without doing other work. + bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLint border, GLenum format, GLenum type, GLint xoffset, GLint yoffset); + + // Helper function to check input width and height for functions {copy, compressed}Tex{Sub}Image. + // Generates GL error and returns false if width or height is invalid. + bool validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType, GLenum target, GLint level, GLsizei width, GLsizei height); + + // Helper function to check input parameters for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type); + + enum NullDisposition { + NullAllowed, + NullNotAllowed + }; + + // Helper function to validate that the given ArrayBufferView + // is of the correct type and contains enough data for the texImage call. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncData(const char* functionName, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView* pixels, NullDisposition); + + // Helper function to validate a given texture format is settable as in + // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and + // copyTexSubImage2D. + // Generates GL error and returns false if the format is not settable. + bool validateSettableTexFormat(const char* functionName, GLenum format); + + // Helper function to validate compressed texture data is correct size + // for the given format and dimensions. + bool validateCompressedTexFuncData(const char* functionName, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* pixels); + + // Helper function for validating compressed texture formats. + bool validateCompressedTexFormat(GLenum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType, GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexSubDimensions(const char* functionName, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, WebGLTexture*); + + // Helper function to validate mode for draw{Arrays/Elements}. + bool validateDrawMode(const char* functionName, GLenum); + + // Helper function to validate if front/back stencilMask and stencilFunc settings are the same. + bool validateStencilSettings(const char* functionName); + + // Helper function to validate stencil or depth func. + bool validateStencilOrDepthFunc(const char* functionName, GLenum); + + // Helper function for texParameterf and texParameteri. + void texParameter(GLenum target, GLenum pname, GLfloat parami, GLint paramf, bool isFloat); + + // Helper function to print GL errors to console. + void printGLErrorToConsole(const String&); + + // Helper function to print warnings to console. Currently + // used only to warn about use of obsolete functions. + void printWarningToConsole(const String&); + + // Helper function to validate input parameters for framebuffer functions. + // Generate GL error if parameters are illegal. + bool validateFramebufferFuncParameters(const char* functionName, GLenum target, GLenum attachment); + + // Helper function to validate blend equation mode. + bool validateBlendEquation(const char* functionName, GLenum); + + // Helper function to validate blend func factors. + bool validateBlendFuncFactors(const char* functionName, GLenum src, GLenum dst); + + // Helper function to validate a GL capability. + bool validateCapability(const char* functionName, GLenum); + + // Helper function to validate input parameters for uniform functions. + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GLsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GLsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GLsizei, GLsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GLboolean transpose, Float32Array*, GLsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GLboolean transpose, void*, GLsizei, GLsizei mod); + + // Helper function to validate the target for bufferData. + // Return the current bound buffer to target, or 0 if the target is invalid. + WebGLBuffer* validateBufferDataTarget(const char* functionName, GLenum target); + + // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin. + bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionState&); + + // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin. + bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionState&); + + // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin. + bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionState&); + + // Helper function to validate drawArrays(Instanced) calls + bool validateDrawArrays(const char* functionName, GLenum mode, GLint first, GLsizei count); + + // Helper function to validate drawElements(Instanced) calls + bool validateDrawElements(const char* functionName, GLenum mode, GLsizei count, GLenum type, long long offset); + + // Helper function to validate draw*Instanced calls + bool validateDrawInstanced(const char* functionName, GLsizei primcount); + + // Helper functions for vertexAttribNf{v}. + void vertexAttribfImpl(const char* functionName, GLuint index, GLsizei expectedSize, GLfloat, GLfloat, GLfloat, GLfloat); + void vertexAttribfvImpl(const char* functionName, GLuint index, Float32Array*, GLsizei expectedSize); + void vertexAttribfvImpl(const char* functionName, GLuint index, GLfloat*, GLsizei, GLsizei expectedSize); + + // Helper functions to bufferData() and bufferSubData(). + void bufferDataImpl(GLenum target, long long size, const void* data, GLenum usage); + void bufferSubDataImpl(GLenum target, long long offset, GLsizeiptr size, const void* data); + + // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions. + // Return false if caller should return without further processing. + bool deleteObject(WebGLObject*); + + // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram. + // If the object has already been deleted, set deleted to true upon return. + // Return false if caller should return without further processing. + bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted); + + void dispatchContextLostEvent(Timer<WebGLRenderingContextBase>*); + // Helper for restoration after context lost. + void maybeRestoreContext(Timer<WebGLRenderingContextBase>*); + + enum ConsoleDisplayPreference { + DisplayInConsole, + DontDisplayInConsole + }; + + // Wrapper for WebGraphicsContext3D::synthesizeGLError that sends a message + // to the JavaScript console. + void synthesizeGLError(GLenum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole); + void emitGLWarning(const char* function, const char* reason); + + String ensureNotNull(const String&) const; + + // Enable or disable stencil test based on user setting and + // whether the current FBO has a stencil buffer. + void applyStencilTest(); + + // Helper for enabling or disabling a capability. + void enableOrDisable(GLenum capability, bool enable); + + // Clamp the width and height to GL_MAX_VIEWPORT_DIMS. + IntSize clampedCanvasSize(); + + // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0. + // Later, return the cached value. + GLint maxDrawBuffers(); + GLint maxColorAttachments(); + + void setBackDrawBuffer(GLenum); + + void restoreCurrentFramebuffer(); + void restoreCurrentTexture2D(); + + virtual void multisamplingChanged(bool) OVERRIDE; + + void findNewMaxEnabledAttribIndex(); + void findNewMaxNonDefaultTextureUnit(); + + friend class WebGLStateRestorer; + friend class WebGLRenderingContextEvictionManager; + + static Vector<WebGLRenderingContextBase*>& activeContexts(); + static Vector<WebGLRenderingContextBase*>& forciblyEvictedContexts(); + + static void activateContext(WebGLRenderingContextBase*); + static void deactivateContext(WebGLRenderingContextBase*, bool addToInactiveList); + static void willDestroyContext(WebGLRenderingContextBase*); + static void forciblyLoseOldestContext(const String& reason); + // Return the least recently used context's position in the active context vector. + // If the vector is empty, return the maximum allowed active context number. + static size_t oldestContextIndex(); + static IntSize oldestContextSize(); +}; + +DEFINE_TYPE_CASTS(WebGLRenderingContextBase, CanvasRenderingContext, context, context->is3d(), context.is3d()); + +} // namespace WebCore + +#endif // WebGLRenderingContextBase_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.idl new file mode 100644 index 00000000000..4f0de43de88 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.idl @@ -0,0 +1,689 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// http://www.khronos.org/registry/webgl/specs/latest/1.0/#WebGLRenderingContextBase + +typedef unsigned long GLenum; +typedef boolean GLboolean; +typedef unsigned long GLbitfield; +typedef byte GLbyte; // 'byte' should be a signed 8 bit type. +typedef short GLshort; +typedef long GLint; +typedef long GLsizei; +typedef long long GLintptr; +typedef long long GLsizeiptr; +typedef octet GLubyte; // 'octet' should be an unsigned 8 bit type. +typedef unsigned short GLushort; +typedef unsigned long GLuint; +typedef unrestricted float GLfloat; +typedef unrestricted float GLclampf; + +[ + // FIXME: [DoNotCheckConstants] and [TypeChecking=Interface|Nullable] should be applied + // to members and not need to be put on implementing interface + // DoNotCheckConstants, // need to put on implementing interface + NoInterfaceObject, // Always used on target of 'implements' + // TypeChecking=Interface|Nullable|Unrestricted, // need to put on implementing interface +] interface WebGLRenderingContextBase { + + readonly attribute HTMLCanvasElement canvas; + + /* ClearBufferMask */ + const GLenum DEPTH_BUFFER_BIT = 0x00000100; + const GLenum STENCIL_BUFFER_BIT = 0x00000400; + const GLenum COLOR_BUFFER_BIT = 0x00004000; + + /* BeginMode */ + const GLenum POINTS = 0x0000; + const GLenum LINES = 0x0001; + const GLenum LINE_LOOP = 0x0002; + const GLenum LINE_STRIP = 0x0003; + const GLenum TRIANGLES = 0x0004; + const GLenum TRIANGLE_STRIP = 0x0005; + const GLenum TRIANGLE_FAN = 0x0006; + + /* AlphaFunction (not supported in ES20) */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* BlendingFactorDest */ + const GLenum ZERO = 0; + const GLenum ONE = 1; + const GLenum SRC_COLOR = 0x0300; + const GLenum ONE_MINUS_SRC_COLOR = 0x0301; + const GLenum SRC_ALPHA = 0x0302; + const GLenum ONE_MINUS_SRC_ALPHA = 0x0303; + const GLenum DST_ALPHA = 0x0304; + const GLenum ONE_MINUS_DST_ALPHA = 0x0305; + + /* BlendingFactorSrc */ + /* ZERO */ + /* ONE */ + const GLenum DST_COLOR = 0x0306; + const GLenum ONE_MINUS_DST_COLOR = 0x0307; + const GLenum SRC_ALPHA_SATURATE = 0x0308; + /* SRC_ALPHA */ + /* ONE_MINUS_SRC_ALPHA */ + /* DST_ALPHA */ + /* ONE_MINUS_DST_ALPHA */ + + /* BlendEquationSeparate */ + const GLenum FUNC_ADD = 0x8006; + const GLenum BLEND_EQUATION = 0x8009; + const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */ + const GLenum BLEND_EQUATION_ALPHA = 0x883D; + + /* BlendSubtract */ + const GLenum FUNC_SUBTRACT = 0x800A; + const GLenum FUNC_REVERSE_SUBTRACT = 0x800B; + + /* Separate Blend Functions */ + const GLenum BLEND_DST_RGB = 0x80C8; + const GLenum BLEND_SRC_RGB = 0x80C9; + const GLenum BLEND_DST_ALPHA = 0x80CA; + const GLenum BLEND_SRC_ALPHA = 0x80CB; + const GLenum CONSTANT_COLOR = 0x8001; + const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002; + const GLenum CONSTANT_ALPHA = 0x8003; + const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004; + const GLenum BLEND_COLOR = 0x8005; + + /* Buffer Objects */ + const GLenum ARRAY_BUFFER = 0x8892; + const GLenum ELEMENT_ARRAY_BUFFER = 0x8893; + const GLenum ARRAY_BUFFER_BINDING = 0x8894; + const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895; + + const GLenum STREAM_DRAW = 0x88E0; + const GLenum STATIC_DRAW = 0x88E4; + const GLenum DYNAMIC_DRAW = 0x88E8; + + const GLenum BUFFER_SIZE = 0x8764; + const GLenum BUFFER_USAGE = 0x8765; + + const GLenum CURRENT_VERTEX_ATTRIB = 0x8626; + + /* CullFaceMode */ + const GLenum FRONT = 0x0404; + const GLenum BACK = 0x0405; + const GLenum FRONT_AND_BACK = 0x0408; + + /* DepthFunction */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* EnableCap */ + const GLenum TEXTURE_2D = 0x0DE1; + const GLenum CULL_FACE = 0x0B44; + const GLenum BLEND = 0x0BE2; + const GLenum DITHER = 0x0BD0; + const GLenum STENCIL_TEST = 0x0B90; + const GLenum DEPTH_TEST = 0x0B71; + const GLenum SCISSOR_TEST = 0x0C11; + const GLenum POLYGON_OFFSET_FILL = 0x8037; + const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E; + const GLenum SAMPLE_COVERAGE = 0x80A0; + + /* ErrorCode */ + const GLenum NO_ERROR = 0; + const GLenum INVALID_ENUM = 0x0500; + const GLenum INVALID_VALUE = 0x0501; + const GLenum INVALID_OPERATION = 0x0502; + const GLenum OUT_OF_MEMORY = 0x0505; + + /* FrontFaceDirection */ + const GLenum CW = 0x0900; + const GLenum CCW = 0x0901; + + /* GetPName */ + const GLenum LINE_WIDTH = 0x0B21; + const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D; + const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E; + const GLenum CULL_FACE_MODE = 0x0B45; + const GLenum FRONT_FACE = 0x0B46; + const GLenum DEPTH_RANGE = 0x0B70; + const GLenum DEPTH_WRITEMASK = 0x0B72; + const GLenum DEPTH_CLEAR_VALUE = 0x0B73; + const GLenum DEPTH_FUNC = 0x0B74; + const GLenum STENCIL_CLEAR_VALUE = 0x0B91; + const GLenum STENCIL_FUNC = 0x0B92; + const GLenum STENCIL_FAIL = 0x0B94; + const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95; + const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96; + const GLenum STENCIL_REF = 0x0B97; + const GLenum STENCIL_VALUE_MASK = 0x0B93; + const GLenum STENCIL_WRITEMASK = 0x0B98; + const GLenum STENCIL_BACK_FUNC = 0x8800; + const GLenum STENCIL_BACK_FAIL = 0x8801; + const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802; + const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803; + const GLenum STENCIL_BACK_REF = 0x8CA3; + const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4; + const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5; + const GLenum VIEWPORT = 0x0BA2; + const GLenum SCISSOR_BOX = 0x0C10; + /* SCISSOR_TEST */ + const GLenum COLOR_CLEAR_VALUE = 0x0C22; + const GLenum COLOR_WRITEMASK = 0x0C23; + const GLenum UNPACK_ALIGNMENT = 0x0CF5; + const GLenum PACK_ALIGNMENT = 0x0D05; + const GLenum MAX_TEXTURE_SIZE = 0x0D33; + const GLenum MAX_VIEWPORT_DIMS = 0x0D3A; + const GLenum SUBPIXEL_BITS = 0x0D50; + const GLenum RED_BITS = 0x0D52; + const GLenum GREEN_BITS = 0x0D53; + const GLenum BLUE_BITS = 0x0D54; + const GLenum ALPHA_BITS = 0x0D55; + const GLenum DEPTH_BITS = 0x0D56; + const GLenum STENCIL_BITS = 0x0D57; + const GLenum POLYGON_OFFSET_UNITS = 0x2A00; + /* POLYGON_OFFSET_FILL */ + const GLenum POLYGON_OFFSET_FACTOR = 0x8038; + const GLenum TEXTURE_BINDING_2D = 0x8069; + const GLenum SAMPLE_BUFFERS = 0x80A8; + const GLenum SAMPLES = 0x80A9; + const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA; + const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB; + + /* GetTextureParameter */ + /* TEXTURE_MAG_FILTER */ + /* TEXTURE_MIN_FILTER */ + /* TEXTURE_WRAP_S */ + /* TEXTURE_WRAP_T */ + + const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3; + + /* HintMode */ + const GLenum DONT_CARE = 0x1100; + const GLenum FASTEST = 0x1101; + const GLenum NICEST = 0x1102; + + /* HintTarget */ + const GLenum GENERATE_MIPMAP_HINT = 0x8192; + + /* DataType */ + const GLenum BYTE = 0x1400; + const GLenum UNSIGNED_BYTE = 0x1401; + const GLenum SHORT = 0x1402; + const GLenum UNSIGNED_SHORT = 0x1403; + const GLenum INT = 0x1404; + const GLenum UNSIGNED_INT = 0x1405; + const GLenum FLOAT = 0x1406; + + /* PixelFormat */ + const GLenum DEPTH_COMPONENT = 0x1902; + const GLenum ALPHA = 0x1906; + const GLenum RGB = 0x1907; + const GLenum RGBA = 0x1908; + const GLenum LUMINANCE = 0x1909; + const GLenum LUMINANCE_ALPHA = 0x190A; + + /* PixelType */ + /* UNSIGNED_BYTE */ + const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033; + const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034; + const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363; + + /* Shaders */ + const GLenum FRAGMENT_SHADER = 0x8B30; + const GLenum VERTEX_SHADER = 0x8B31; + const GLenum MAX_VERTEX_ATTRIBS = 0x8869; + const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; + const GLenum MAX_VARYING_VECTORS = 0x8DFC; + const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D; + const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; + const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872; + const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD; + const GLenum SHADER_TYPE = 0x8B4F; + const GLenum DELETE_STATUS = 0x8B80; + const GLenum LINK_STATUS = 0x8B82; + const GLenum VALIDATE_STATUS = 0x8B83; + const GLenum ATTACHED_SHADERS = 0x8B85; + const GLenum ACTIVE_UNIFORMS = 0x8B86; + const GLenum ACTIVE_ATTRIBUTES = 0x8B89; + const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C; + const GLenum CURRENT_PROGRAM = 0x8B8D; + + /* StencilFunction */ + const GLenum NEVER = 0x0200; + const GLenum LESS = 0x0201; + const GLenum EQUAL = 0x0202; + const GLenum LEQUAL = 0x0203; + const GLenum GREATER = 0x0204; + const GLenum NOTEQUAL = 0x0205; + const GLenum GEQUAL = 0x0206; + const GLenum ALWAYS = 0x0207; + + /* StencilOp */ + /* ZERO */ + const GLenum KEEP = 0x1E00; + const GLenum REPLACE = 0x1E01; + const GLenum INCR = 0x1E02; + const GLenum DECR = 0x1E03; + const GLenum INVERT = 0x150A; + const GLenum INCR_WRAP = 0x8507; + const GLenum DECR_WRAP = 0x8508; + + /* StringName */ + const GLenum VENDOR = 0x1F00; + const GLenum RENDERER = 0x1F01; + const GLenum VERSION = 0x1F02; + + /* TextureMagFilter */ + const GLenum NEAREST = 0x2600; + const GLenum LINEAR = 0x2601; + + /* TextureMinFilter */ + /* NEAREST */ + /* LINEAR */ + const GLenum NEAREST_MIPMAP_NEAREST = 0x2700; + const GLenum LINEAR_MIPMAP_NEAREST = 0x2701; + const GLenum NEAREST_MIPMAP_LINEAR = 0x2702; + const GLenum LINEAR_MIPMAP_LINEAR = 0x2703; + + /* TextureParameterName */ + const GLenum TEXTURE_MAG_FILTER = 0x2800; + const GLenum TEXTURE_MIN_FILTER = 0x2801; + const GLenum TEXTURE_WRAP_S = 0x2802; + const GLenum TEXTURE_WRAP_T = 0x2803; + + /* TextureTarget */ + /* TEXTURE_2D */ + const GLenum TEXTURE = 0x1702; + + const GLenum TEXTURE_CUBE_MAP = 0x8513; + const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514; + const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; + + /* TextureUnit */ + const GLenum TEXTURE0 = 0x84C0; + const GLenum TEXTURE1 = 0x84C1; + const GLenum TEXTURE2 = 0x84C2; + const GLenum TEXTURE3 = 0x84C3; + const GLenum TEXTURE4 = 0x84C4; + const GLenum TEXTURE5 = 0x84C5; + const GLenum TEXTURE6 = 0x84C6; + const GLenum TEXTURE7 = 0x84C7; + const GLenum TEXTURE8 = 0x84C8; + const GLenum TEXTURE9 = 0x84C9; + const GLenum TEXTURE10 = 0x84CA; + const GLenum TEXTURE11 = 0x84CB; + const GLenum TEXTURE12 = 0x84CC; + const GLenum TEXTURE13 = 0x84CD; + const GLenum TEXTURE14 = 0x84CE; + const GLenum TEXTURE15 = 0x84CF; + const GLenum TEXTURE16 = 0x84D0; + const GLenum TEXTURE17 = 0x84D1; + const GLenum TEXTURE18 = 0x84D2; + const GLenum TEXTURE19 = 0x84D3; + const GLenum TEXTURE20 = 0x84D4; + const GLenum TEXTURE21 = 0x84D5; + const GLenum TEXTURE22 = 0x84D6; + const GLenum TEXTURE23 = 0x84D7; + const GLenum TEXTURE24 = 0x84D8; + const GLenum TEXTURE25 = 0x84D9; + const GLenum TEXTURE26 = 0x84DA; + const GLenum TEXTURE27 = 0x84DB; + const GLenum TEXTURE28 = 0x84DC; + const GLenum TEXTURE29 = 0x84DD; + const GLenum TEXTURE30 = 0x84DE; + const GLenum TEXTURE31 = 0x84DF; + const GLenum ACTIVE_TEXTURE = 0x84E0; + + /* TextureWrapMode */ + const GLenum REPEAT = 0x2901; + const GLenum CLAMP_TO_EDGE = 0x812F; + const GLenum MIRRORED_REPEAT = 0x8370; + + /* Uniform Types */ + const GLenum FLOAT_VEC2 = 0x8B50; + const GLenum FLOAT_VEC3 = 0x8B51; + const GLenum FLOAT_VEC4 = 0x8B52; + const GLenum INT_VEC2 = 0x8B53; + const GLenum INT_VEC3 = 0x8B54; + const GLenum INT_VEC4 = 0x8B55; + const GLenum BOOL = 0x8B56; + const GLenum BOOL_VEC2 = 0x8B57; + const GLenum BOOL_VEC3 = 0x8B58; + const GLenum BOOL_VEC4 = 0x8B59; + const GLenum FLOAT_MAT2 = 0x8B5A; + const GLenum FLOAT_MAT3 = 0x8B5B; + const GLenum FLOAT_MAT4 = 0x8B5C; + const GLenum SAMPLER_2D = 0x8B5E; + const GLenum SAMPLER_CUBE = 0x8B60; + + /* Vertex Arrays */ + const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622; + const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623; + const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624; + const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625; + const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A; + const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645; + const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F; + + /* Read Format */ + const GLenum IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A; + const GLenum IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B; + + /* Shader Source */ + const GLenum COMPILE_STATUS = 0x8B81; + + /* Shader Precision-Specified Types */ + const GLenum LOW_FLOAT = 0x8DF0; + const GLenum MEDIUM_FLOAT = 0x8DF1; + const GLenum HIGH_FLOAT = 0x8DF2; + const GLenum LOW_INT = 0x8DF3; + const GLenum MEDIUM_INT = 0x8DF4; + const GLenum HIGH_INT = 0x8DF5; + + /* Framebuffer Object. */ + const GLenum FRAMEBUFFER = 0x8D40; + const GLenum RENDERBUFFER = 0x8D41; + + const GLenum RGBA4 = 0x8056; + const GLenum RGB5_A1 = 0x8057; + const GLenum RGB565 = 0x8D62; + const GLenum DEPTH_COMPONENT16 = 0x81A5; + const GLenum STENCIL_INDEX = 0x1901; + const GLenum STENCIL_INDEX8 = 0x8D48; + const GLenum DEPTH_STENCIL = 0x84F9; + + const GLenum RENDERBUFFER_WIDTH = 0x8D42; + const GLenum RENDERBUFFER_HEIGHT = 0x8D43; + const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44; + const GLenum RENDERBUFFER_RED_SIZE = 0x8D50; + const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51; + const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52; + const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53; + const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54; + const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55; + + const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0; + const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1; + const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2; + const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3; + + const GLenum COLOR_ATTACHMENT0 = 0x8CE0; + const GLenum DEPTH_ATTACHMENT = 0x8D00; + const GLenum STENCIL_ATTACHMENT = 0x8D20; + const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; + + const GLenum NONE = 0; + + const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5; + const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6; + const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7; + const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9; + const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD; + + const GLenum FRAMEBUFFER_BINDING = 0x8CA6; + const GLenum RENDERBUFFER_BINDING = 0x8CA7; + const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8; + + const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506; + + /* WebGL-specific enums */ + const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240; + const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; + const GLenum CONTEXT_LOST_WEBGL = 0x9242; + const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; + const GLenum BROWSER_DEFAULT_WEBGL = 0x9244; + + readonly attribute GLsizei drawingBufferWidth; + readonly attribute GLsizei drawingBufferHeight; + + void activeTexture(GLenum texture); + void attachShader(WebGLProgram? program, WebGLShader? shader); + void bindAttribLocation(WebGLProgram? program, GLuint index, DOMString name); + void bindBuffer(GLenum target, WebGLBuffer? buffer); + void bindFramebuffer(GLenum target, WebGLFramebuffer? framebuffer); + void bindRenderbuffer(GLenum target, WebGLRenderbuffer? renderbuffer); + void bindTexture(GLenum target, WebGLTexture? texture); + void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void blendEquation(GLenum mode); + void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + void blendFunc(GLenum sfactor, GLenum dfactor); + void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + // FIXME: should be union type + // https://www.khronos.org/bugzilla/show_bug.cgi?id=1172 + void bufferData(GLenum target, GLsizeiptr size, GLenum usage); + void bufferData(GLenum target, ArrayBufferView data, GLenum usage); + void bufferData(GLenum target, ArrayBuffer? data, GLenum usage); + void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView data); + void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data); + + GLenum checkFramebufferStatus(GLenum target); + void clear(GLbitfield mask); + void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void clearDepth(GLclampf depth); + void clearStencil(GLint s); + void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void compileShader(WebGLShader? shader); + + void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, ArrayBufferView? data); + void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, ArrayBufferView? data); + + void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + + WebGLBuffer createBuffer(); + WebGLFramebuffer createFramebuffer(); + WebGLProgram createProgram(); + WebGLRenderbuffer createRenderbuffer(); + WebGLShader createShader(GLenum type); + WebGLTexture createTexture(); + + void cullFace(GLenum mode); + + void deleteBuffer(WebGLBuffer? buffer); + void deleteFramebuffer(WebGLFramebuffer? framebuffer); + void deleteProgram(WebGLProgram? program); + void deleteRenderbuffer(WebGLRenderbuffer? renderbuffer); + void deleteShader(WebGLShader? shader); + void deleteTexture(WebGLTexture? texture); + + void depthFunc(GLenum func); + void depthMask(GLboolean flag); + void depthRange(GLclampf zNear, GLclampf zFar); + void detachShader(WebGLProgram? program, WebGLShader? shader); + void disable(GLenum cap); + void disableVertexAttribArray(GLuint index); + void drawArrays(GLenum mode, GLint first, GLsizei count); + void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset); + + void enable(GLenum cap); + void enableVertexAttribArray(GLuint index); + void finish(); + void flush(); + void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer? renderbuffer); + void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture? texture, GLint level); + void frontFace(GLenum mode); + void generateMipmap(GLenum target); + + WebGLActiveInfo getActiveAttrib(WebGLProgram? program, GLuint index); + WebGLActiveInfo getActiveUniform(WebGLProgram? program, GLuint index); + + [Custom] void getAttachedShaders(WebGLProgram? program); + + GLint getAttribLocation(WebGLProgram? program, DOMString name); + + [Custom] any getBufferParameter(GLenum target, GLenum pname); + + WebGLContextAttributes getContextAttributes(); + + GLenum getError(); + + // object getExtension(DOMString name); + [Custom] any getExtension(DOMString name); + + [Custom] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); + [Custom] any getParameter(GLenum pname); + [Custom] any getProgramParameter(WebGLProgram? program, GLenum pname); + [TreatReturnedNullStringAs=Null] DOMString getProgramInfoLog(WebGLProgram? program); + [Custom] any getRenderbufferParameter(GLenum target, GLenum pname); + [Custom] any getShaderParameter(WebGLShader? shader, GLenum pname); + + [TreatReturnedNullStringAs=Null] DOMString getShaderInfoLog(WebGLShader? shader); + + WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); + + [TreatReturnedNullStringAs=Null] DOMString getShaderSource(WebGLShader? shader); + + [Custom] sequence<DOMString> getSupportedExtensions(); + + [Custom] any getTexParameter(GLenum target, GLenum pname); + + [Custom] any getUniform(WebGLProgram? program, WebGLUniformLocation location); + + WebGLUniformLocation getUniformLocation(WebGLProgram? program, DOMString name); + + [Custom] any getVertexAttrib(GLuint index, GLenum pname); + + GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); + + void hint(GLenum target, GLenum mode); + GLboolean isBuffer(WebGLBuffer? buffer); + GLboolean isContextLost(); + GLboolean isEnabled(GLenum cap); + GLboolean isFramebuffer(WebGLFramebuffer? framebuffer); + GLboolean isProgram(WebGLProgram? program); + GLboolean isRenderbuffer(WebGLRenderbuffer? renderbuffer); + GLboolean isShader(WebGLShader? shader); + GLboolean isTexture(WebGLTexture? texture); + void lineWidth(GLfloat width); + void linkProgram(WebGLProgram? program); + void pixelStorei(GLenum pname, GLint param); + void polygonOffset(GLfloat factor, GLfloat units); + + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView? pixels); + + void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void sampleCoverage(GLclampf value, GLboolean invert); + void scissor(GLint x, GLint y, GLsizei width, GLsizei height); + void shaderSource(WebGLShader? shader, DOMString string); + void stencilFunc(GLenum func, GLint ref, GLuint mask); + void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void stencilMask(GLuint mask); + void stencilMaskSeparate(GLenum face, GLuint mask); + void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); + void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + void texParameterf(GLenum target, GLenum pname, GLfloat param); + void texParameteri(GLenum target, GLenum pname, GLint param); + + // Supported forms: + // FIXME: should be union type + // https://www.khronos.org/bugzilla/show_bug.cgi?id=1172 + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, ArrayBufferView? pixels); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, ImageData? pixels); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLImageElement image); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLCanvasElement canvas); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLVideoElement video); + + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, ArrayBufferView? pixels); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, ImageData? pixels); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLImageElement image); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLCanvasElement canvas); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLVideoElement video); + + void uniform1f(WebGLUniformLocation? location, GLfloat x); + [Custom] void uniform1fv(WebGLUniformLocation? location, Float32Array v); + void uniform1i(WebGLUniformLocation? location, GLint x); + [Custom] void uniform1iv(WebGLUniformLocation? location, Int32Array v); + void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); + [Custom] void uniform2fv(WebGLUniformLocation? location, Float32Array v); + void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); + [Custom] void uniform2iv(WebGLUniformLocation? location, Int32Array v); + void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); + [Custom] void uniform3fv(WebGLUniformLocation? location, Float32Array v); + void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); + [Custom] void uniform3iv(WebGLUniformLocation? location, Int32Array v); + void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + [Custom] void uniform4fv(WebGLUniformLocation? location, Float32Array v); + void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); + [Custom] void uniform4iv(WebGLUniformLocation? location, Int32Array v); + + [Custom] void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array array); + [Custom] void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array array); + [Custom] void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array array); + + void useProgram(WebGLProgram? program); + void validateProgram(WebGLProgram? program); + + void vertexAttrib1f(GLuint indx, GLfloat x); + [Custom] void vertexAttrib1fv(GLuint indx, Float32Array values); + void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); + [Custom] void vertexAttrib2fv(GLuint indx, Float32Array values); + void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + [Custom] void vertexAttrib3fv(GLuint indx, Float32Array values); + void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + [Custom] void vertexAttrib4fv(GLuint indx, Float32Array values); + void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, + GLsizei stride, GLintptr offset); + + void viewport(GLint x, GLint y, GLsizei width, GLsizei height); +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp index 0920fc9043e..203041e85cf 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp @@ -27,22 +27,22 @@ #include "core/html/canvas/WebGLShader.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContext* ctx, GC3Denum type) +PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContextBase* ctx, GLenum type) { return adoptRef(new WebGLShader(ctx, type)); } -WebGLShader::WebGLShader(WebGLRenderingContext* ctx, GC3Denum type) +WebGLShader::WebGLShader(WebGLRenderingContextBase* ctx, GLenum type) : WebGLSharedObject(ctx) , m_type(type) , m_source("") { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createShader(type)); + setObject(ctx->webContext()->createShader(type)); } WebGLShader::~WebGLShader() @@ -50,7 +50,7 @@ WebGLShader::~WebGLShader() deleteObject(0); } -void WebGLShader::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLShader::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteShader(object); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h index 6c776afc281..2d2fc23be20 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h @@ -29,28 +29,29 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/WebGLSharedObject.h" #include "wtf/PassRefPtr.h" +#include "wtf/text/WTFString.h" namespace WebCore { -class WebGLShader : public WebGLSharedObject, public ScriptWrappable { +class WebGLShader FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLShader(); - static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GC3Denum); + static PassRefPtr<WebGLShader> create(WebGLRenderingContextBase*, GLenum); - GC3Denum type() const { return m_type; } + GLenum type() const { return m_type; } const String& source() const { return m_source; } void setSource(const String& source) { m_source = source; } private: - WebGLShader(WebGLRenderingContext*, GC3Denum); + WebGLShader(WebGLRenderingContextBase*, GLenum); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; - virtual bool isShader() const { return true; } + virtual bool isShader() const OVERRIDE { return true; } - GC3Denum m_type; + GLenum m_type; String m_source; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp index 288468f37ce..8fb4bb1c9af 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp @@ -31,27 +31,27 @@ namespace WebCore { // static -PassRefPtr<WebGLShaderPrecisionFormat> WebGLShaderPrecisionFormat::create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision) +PassRefPtr<WebGLShaderPrecisionFormat> WebGLShaderPrecisionFormat::create(GLint rangeMin, GLint rangeMax, GLint precision) { return adoptRef(new WebGLShaderPrecisionFormat(rangeMin, rangeMax, precision)); } -GC3Dint WebGLShaderPrecisionFormat::rangeMin() const +GLint WebGLShaderPrecisionFormat::rangeMin() const { return m_rangeMin; } -GC3Dint WebGLShaderPrecisionFormat::rangeMax() const +GLint WebGLShaderPrecisionFormat::rangeMax() const { return m_rangeMax; } -GC3Dint WebGLShaderPrecisionFormat::precision() const +GLint WebGLShaderPrecisionFormat::precision() const { return m_precision; } -WebGLShaderPrecisionFormat::WebGLShaderPrecisionFormat(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision) +WebGLShaderPrecisionFormat::WebGLShaderPrecisionFormat(GLint rangeMin, GLint rangeMax, GLint precision) : m_rangeMin(rangeMin) , m_rangeMax(rangeMax) , m_precision(precision) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h index b59acc052a5..bd363bb232b 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h @@ -28,7 +28,7 @@ #define WebGLShaderPrecisionFormat_h #include "bindings/v8/ScriptWrappable.h" -#include "platform/graphics/GraphicsContext3D.h" +#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -36,18 +36,18 @@ namespace WebCore { class WebGLShaderPrecisionFormat : public RefCounted<WebGLShaderPrecisionFormat>, public ScriptWrappable { public: - static PassRefPtr<WebGLShaderPrecisionFormat> create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision); + static PassRefPtr<WebGLShaderPrecisionFormat> create(GLint rangeMin, GLint rangeMax, GLint precision); - GC3Dint rangeMin() const; - GC3Dint rangeMax() const; - GC3Dint precision() const; + GLint rangeMin() const; + GLint rangeMax() const; + GLint precision() const; private: - WebGLShaderPrecisionFormat(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision); + WebGLShaderPrecisionFormat(GLint rangeMin, GLint rangeMax, GLint precision); - GC3Dint m_rangeMin; - GC3Dint m_rangeMax; - GC3Dint m_precision; + GLint m_rangeMin; + GLint m_rangeMax; + GLint m_precision; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp index f5d63651ff5..94f1db80baf 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp @@ -28,11 +28,11 @@ #include "core/html/canvas/WebGLSharedObject.h" #include "core/html/canvas/WebGLContextGroup.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context) +WebGLSharedObject::WebGLSharedObject(WebGLRenderingContextBase* context) : WebGLObject(context), m_contextGroup(context->contextGroup()) { @@ -54,9 +54,9 @@ void WebGLSharedObject::detachContextGroup() } } -GraphicsContext3D* WebGLSharedObject::getAGraphicsContext3D() const +blink::WebGraphicsContext3D* WebGLSharedObject::getAWebGraphicsContext3D() const { - return m_contextGroup ? m_contextGroup->getAGraphicsContext3D() : 0; + return m_contextGroup ? m_contextGroup->getAWebGraphicsContext3D() : 0; } } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h index 6c33471ba7f..990c8ae1565 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h @@ -30,9 +30,8 @@ namespace WebCore { -class GraphicsContext3D; class WebGLContextGroup; -class WebGLRenderingContext; +class WebGLRenderingContextBase; // WebGLSharedObject the base class for objects that can be shared by multiple // WebGLRenderingContexts. @@ -43,13 +42,12 @@ public: WebGLContextGroup* contextGroup() const { return m_contextGroup; } virtual bool isBuffer() const { return false; } - virtual bool isFramebuffer() const { return false; } virtual bool isProgram() const { return false; } virtual bool isRenderbuffer() const { return false; } virtual bool isShader() const { return false; } virtual bool isTexture() const { return false; } - virtual bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContext*) const + virtual bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContextBase*) const OVERRIDE FINAL { return contextGroup == m_contextGroup; } @@ -57,14 +55,14 @@ public: void detachContextGroup(); protected: - WebGLSharedObject(WebGLRenderingContext*); + WebGLSharedObject(WebGLRenderingContextBase*); - virtual bool hasGroupOrContext() const + virtual bool hasGroupOrContext() const OVERRIDE FINAL { return m_contextGroup; } - virtual GraphicsContext3D* getAGraphicsContext3D() const; + virtual blink::WebGraphicsContext3D* getAWebGraphicsContext3D() const OVERRIDE FINAL; private: WebGLContextGroup* m_contextGroup; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp index 804547e1b0e..292974230ea 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp @@ -27,16 +27,16 @@ #include "core/html/canvas/WebGLTexture.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLTexture(ctx)); } -WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) +WebGLTexture::WebGLTexture(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_target(0) , m_minFilter(GL_NEAREST_MIPMAP_LINEAR) @@ -51,7 +51,7 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) , m_isHalfFloatType(false) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createTexture()); + setObject(ctx->webContext()->createTexture()); } WebGLTexture::~WebGLTexture() @@ -59,7 +59,7 @@ WebGLTexture::~WebGLTexture() deleteObject(0); } -void WebGLTexture::setTarget(GC3Denum target, GC3Dint maxLevel) +void WebGLTexture::setTarget(GLenum target, GLint maxLevel) { if (!object()) return; @@ -81,7 +81,7 @@ void WebGLTexture::setTarget(GC3Denum target, GC3Dint maxLevel) } } -void WebGLTexture::setParameteri(GC3Denum pname, GC3Dint param) +void WebGLTexture::setParameteri(GLenum pname, GLint param) { if (!object() || !m_target) return; @@ -130,15 +130,15 @@ void WebGLTexture::setParameteri(GC3Denum pname, GC3Dint param) update(); } -void WebGLTexture::setParameterf(GC3Denum pname, GC3Dfloat param) +void WebGLTexture::setParameterf(GLenum pname, GLfloat param) { if (!object() || !m_target) return; - GC3Dint iparam = static_cast<GC3Dint>(param); + GLint iparam = static_cast<GLint>(param); setParameteri(pname, iparam); } -void WebGLTexture::setLevelInfo(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type) +void WebGLTexture::setLevelInfo(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type) { if (!object() || !m_target) return; @@ -160,10 +160,10 @@ void WebGLTexture::generateMipmapLevelInfo() if (!m_isComplete) { for (size_t ii = 0; ii < m_info.size(); ++ii) { const LevelInfo& info0 = m_info[ii][0]; - GC3Dsizei width = info0.width; - GC3Dsizei height = info0.height; - GC3Dint levelCount = computeLevelCount(width, height); - for (GC3Dint level = 1; level < levelCount; ++level) { + GLsizei width = info0.width; + GLsizei height = info0.height; + GLint levelCount = computeLevelCount(width, height); + for (GLint level = 1; level < levelCount; ++level) { width = std::max(1, width >> 1); height = std::max(1, height >> 1); LevelInfo& info = m_info[ii][level]; @@ -175,7 +175,7 @@ void WebGLTexture::generateMipmapLevelInfo() m_needToUseBlackTexture = false; } -GC3Denum WebGLTexture::getInternalFormat(GC3Denum target, GC3Dint level) const +GLenum WebGLTexture::getInternalFormat(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -183,7 +183,7 @@ GC3Denum WebGLTexture::getInternalFormat(GC3Denum target, GC3Dint level) const return info->internalFormat; } -GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const +GLenum WebGLTexture::getType(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -191,7 +191,7 @@ GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const return info->type; } -GC3Dsizei WebGLTexture::getWidth(GC3Denum target, GC3Dint level) const +GLsizei WebGLTexture::getWidth(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -199,7 +199,7 @@ GC3Dsizei WebGLTexture::getWidth(GC3Denum target, GC3Dint level) const return info->width; } -GC3Dsizei WebGLTexture::getHeight(GC3Denum target, GC3Dint level) const +GLsizei WebGLTexture::getHeight(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -207,7 +207,7 @@ GC3Dsizei WebGLTexture::getHeight(GC3Denum target, GC3Dint level) const return info->height; } -bool WebGLTexture::isValid(GC3Denum target, GC3Dint level) const +bool WebGLTexture::isValid(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -215,7 +215,7 @@ bool WebGLTexture::isValid(GC3Denum target, GC3Dint level) const return info->valid; } -bool WebGLTexture::isNPOT(GC3Dsizei width, GC3Dsizei height) +bool WebGLTexture::isNPOT(GLsizei width, GLsizei height) { ASSERT(width >= 0 && height >= 0); if (!width || !height) @@ -245,12 +245,12 @@ bool WebGLTexture::needToUseBlackTexture(TextureExtensionFlag flag) const return false; } -void WebGLTexture::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLTexture::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteTexture(object); } -int WebGLTexture::mapTargetToIndex(GC3Denum target) const +int WebGLTexture::mapTargetToIndex(GLenum target) const { if (m_target == GL_TEXTURE_2D) { if (target == GL_TEXTURE_2D) @@ -290,17 +290,17 @@ bool WebGLTexture::canGenerateMipmaps() return true; } -GC3Dint WebGLTexture::computeLevelCount(GC3Dsizei width, GC3Dsizei height) +GLint WebGLTexture::computeLevelCount(GLsizei width, GLsizei height) { // return 1 + log2Floor(std::max(width, height)); - GC3Dsizei n = std::max(width, height); + GLsizei n = std::max(width, height); if (n <= 0) return 0; - GC3Dint log = 0; - GC3Dsizei value = n; + GLint log = 0; + GLsizei value = n; for (int ii = 4; ii >= 0; --ii) { int shift = (1 << ii); - GC3Dsizei x = (value >> shift); + GLsizei x = (value >> shift); if (x) { value = x; log += shift; @@ -322,7 +322,7 @@ void WebGLTexture::update() m_isComplete = true; m_isCubeComplete = true; const LevelInfo& first = m_info[0][0]; - GC3Dint levelCount = computeLevelCount(first.width, first.height); + GLint levelCount = computeLevelCount(first.width, first.height); if (levelCount < 1) m_isComplete = false; else { @@ -337,9 +337,9 @@ void WebGLTexture::update() m_isComplete = false; break; } - GC3Dsizei width = info0.width; - GC3Dsizei height = info0.height; - for (GC3Dint level = 1; level < levelCount; ++level) { + GLsizei width = info0.width; + GLsizei height = info0.height; + for (GLint level = 1; level < levelCount; ++level) { width = std::max(1, width >> 1); height = std::max(1, height >> 1); const LevelInfo& info = m_info[ii][level]; @@ -369,14 +369,14 @@ void WebGLTexture::update() m_needToUseBlackTexture = true; } -const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GC3Denum target, GC3Dint level) const +const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GLenum target, GLint level) const { if (!object() || !m_target) return 0; int targetIndex = mapTargetToIndex(target); if (targetIndex < 0 || targetIndex >= static_cast<int>(m_info.size())) return 0; - if (level < 0 || level >= static_cast<GC3Dint>(m_info[targetIndex].size())) + if (level < 0 || level >= static_cast<GLint>(m_info[targetIndex].size())) return 0; return &(m_info[targetIndex][level]); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h index 67f1fdce86c..bb086c08a10 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h @@ -33,7 +33,7 @@ namespace WebCore { -class WebGLTexture : public WebGLSharedObject, public ScriptWrappable { +class WebGLTexture FINAL : public WebGLSharedObject, public ScriptWrappable { public: enum TextureExtensionFlag { NoTextureExtensionEnabled = 0, @@ -42,30 +42,30 @@ public: }; virtual ~WebGLTexture(); - static PassRefPtr<WebGLTexture> create(WebGLRenderingContext*); + static PassRefPtr<WebGLTexture> create(WebGLRenderingContextBase*); - void setTarget(GC3Denum target, GC3Dint maxLevel); - void setParameteri(GC3Denum pname, GC3Dint param); - void setParameterf(GC3Denum pname, GC3Dfloat param); + void setTarget(GLenum target, GLint maxLevel); + void setParameteri(GLenum pname, GLint param); + void setParameterf(GLenum pname, GLfloat param); - GC3Denum getTarget() const { return m_target; } + GLenum getTarget() const { return m_target; } int getMinFilter() const { return m_minFilter; } - void setLevelInfo(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type); + void setLevelInfo(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type); bool canGenerateMipmaps(); // Generate all level information. void generateMipmapLevelInfo(); - GC3Denum getInternalFormat(GC3Denum target, GC3Dint level) const; - GC3Denum getType(GC3Denum target, GC3Dint level) const; - GC3Dsizei getWidth(GC3Denum target, GC3Dint level) const; - GC3Dsizei getHeight(GC3Denum target, GC3Dint level) const; - bool isValid(GC3Denum target, GC3Dint level) const; + GLenum getInternalFormat(GLenum target, GLint level) const; + GLenum getType(GLenum target, GLint level) const; + GLsizei getWidth(GLenum target, GLint level) const; + GLsizei getHeight(GLenum target, GLint level) const; + bool isValid(GLenum target, GLint level) const; // Whether width/height is NotPowerOfTwo. - static bool isNPOT(GC3Dsizei, GC3Dsizei); + static bool isNPOT(GLsizei, GLsizei); bool isNPOT() const; // Determine if texture sampling should always return [0, 0, 0, 1] (OpenGL ES 2.0 Sec 3.8.2). @@ -73,12 +73,12 @@ public: bool hasEverBeenBound() const { return object() && m_target; } - static GC3Dint computeLevelCount(GC3Dsizei width, GC3Dsizei height); + static GLint computeLevelCount(GLsizei width, GLsizei height); protected: - WebGLTexture(WebGLRenderingContext*); + WebGLTexture(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: class LevelInfo { @@ -92,7 +92,7 @@ private: { } - void setInfo(GC3Denum internalFmt, GC3Dsizei w, GC3Dsizei h, GC3Denum tp) + void setInfo(GLenum internalFmt, GLsizei w, GLsizei h, GLenum tp) { valid = true; internalFormat = internalFmt; @@ -102,26 +102,26 @@ private: } bool valid; - GC3Denum internalFormat; - GC3Dsizei width; - GC3Dsizei height; - GC3Denum type; + GLenum internalFormat; + GLsizei width; + GLsizei height; + GLenum type; }; - virtual bool isTexture() const { return true; } + virtual bool isTexture() const OVERRIDE { return true; } void update(); - int mapTargetToIndex(GC3Denum) const; + int mapTargetToIndex(GLenum) const; - const LevelInfo* getLevelInfo(GC3Denum target, GC3Dint level) const; + const LevelInfo* getLevelInfo(GLenum target, GLint level) const; - GC3Denum m_target; + GLenum m_target; - GC3Denum m_minFilter; - GC3Denum m_magFilter; - GC3Denum m_wrapS; - GC3Denum m_wrapT; + GLenum m_minFilter; + GLenum m_magFilter; + GLenum m_wrapS; + GLenum m_wrapT; Vector<Vector<LevelInfo> > m_info; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp index 2790c7eb70c..cd1eb95593a 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp @@ -30,12 +30,12 @@ namespace WebCore { -PassRefPtr<WebGLUniformLocation> WebGLUniformLocation::create(WebGLProgram* program, GC3Dint location) +PassRefPtr<WebGLUniformLocation> WebGLUniformLocation::create(WebGLProgram* program, GLint location) { return adoptRef(new WebGLUniformLocation(program, location)); } -WebGLUniformLocation::WebGLUniformLocation(WebGLProgram* program, GC3Dint location) +WebGLUniformLocation::WebGLUniformLocation(WebGLProgram* program, GLint location) : m_program(program) , m_location(location) { @@ -53,7 +53,7 @@ WebGLProgram* WebGLUniformLocation::program() const return m_program.get(); } -GC3Dint WebGLUniformLocation::location() const +GLint WebGLUniformLocation::location() const { // If the program has been linked again, then this UniformLocation is no // longer valid. diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h index 34e0480c126..76e98b3e359 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h @@ -36,18 +36,18 @@ namespace WebCore { class WebGLUniformLocation FINAL : public RefCounted<WebGLUniformLocation>, public ScriptWrappable { public: - static PassRefPtr<WebGLUniformLocation> create(WebGLProgram*, GC3Dint location); + static PassRefPtr<WebGLUniformLocation> create(WebGLProgram*, GLint location); WebGLProgram* program() const; - GC3Dint location() const; + GLint location() const; protected: - WebGLUniformLocation(WebGLProgram*, GC3Dint location); + WebGLUniformLocation(WebGLProgram*, GLint location); private: RefPtr<WebGLProgram> m_program; - GC3Dint m_location; + GLint m_location; unsigned m_linkCount; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp index 1d54886af8a..6c12bccb704 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp @@ -27,31 +27,29 @@ #include "core/html/canvas/WebGLVertexArrayObjectOES.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContext* ctx, VaoType type) +PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContextBase* ctx, VaoType type) { return adoptRef(new WebGLVertexArrayObjectOES(ctx, type)); } -WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContext* ctx, VaoType type) +WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContextBase* ctx, VaoType type) : WebGLContextObject(ctx) , m_type(type) , m_hasEverBeenBound(false) - , m_boundElementArrayBuffer(0) + , m_boundElementArrayBuffer(nullptr) { ScriptWrappable::init(this); m_vertexAttribState.resize(ctx->maxVertexAttribs()); - Extensions3D* extensions = context()->graphicsContext3D()->extensions(); switch (m_type) { case VaoTypeDefault: break; default: - setObject(extensions->createVertexArrayOES()); + setObject(context()->webContext()->createVertexArrayOES()); break; } } @@ -61,14 +59,13 @@ WebGLVertexArrayObjectOES::~WebGLVertexArrayObjectOES() deleteObject(0); } -void WebGLVertexArrayObjectOES::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLVertexArrayObjectOES::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { - Extensions3D* extensions = context3d->extensions(); switch (m_type) { case VaoTypeDefault: break; default: - extensions->deleteVertexArrayOES(object); + context()->webContext()->deleteVertexArrayOES(object); break; } @@ -87,22 +84,22 @@ void WebGLVertexArrayObjectOES::setElementArrayBuffer(PassRefPtr<WebGLBuffer> bu if (buffer) buffer->onAttached(); if (m_boundElementArrayBuffer) - m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); + m_boundElementArrayBuffer->onDetached(context()->webContext()); m_boundElementArrayBuffer = buffer; } void WebGLVertexArrayObjectOES::setVertexAttribState( - GC3Duint index, GC3Dsizei bytesPerElement, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, PassRefPtr<WebGLBuffer> buffer) + GLuint index, GLsizei bytesPerElement, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset, PassRefPtr<WebGLBuffer> buffer) { - GC3Dsizei validatedStride = stride ? stride : bytesPerElement; + GLsizei validatedStride = stride ? stride : bytesPerElement; VertexAttribState& state = m_vertexAttribState[index]; if (buffer) buffer->onAttached(); if (state.bufferBinding) - state.bufferBinding->onDetached(context()->graphicsContext3D()); + state.bufferBinding->onDetached(context()->webContext()); state.bufferBinding = buffer; state.bytesPerElement = bytesPerElement; @@ -117,20 +114,20 @@ void WebGLVertexArrayObjectOES::setVertexAttribState( void WebGLVertexArrayObjectOES::unbindBuffer(PassRefPtr<WebGLBuffer> buffer) { if (m_boundElementArrayBuffer == buffer) { - m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); - m_boundElementArrayBuffer = 0; + m_boundElementArrayBuffer->onDetached(context()->webContext()); + m_boundElementArrayBuffer = nullptr; } for (size_t i = 0; i < m_vertexAttribState.size(); ++i) { VertexAttribState& state = m_vertexAttribState[i]; if (state.bufferBinding == buffer) { - buffer->onDetached(context()->graphicsContext3D()); - state.bufferBinding = 0; + buffer->onDetached(context()->webContext()); + state.bufferBinding = nullptr; } } } -void WebGLVertexArrayObjectOES::setVertexAttribDivisor(GC3Duint index, GC3Duint divisor) +void WebGLVertexArrayObjectOES::setVertexAttribDivisor(GLuint index, GLuint divisor) { VertexAttribState& state = m_vertexAttribState[index]; state.divisor = divisor; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h index 8b1fd6ee063..e54ef0a36a9 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h @@ -33,7 +33,7 @@ namespace WebCore { -class WebGLVertexArrayObjectOES : public WebGLContextObject, public ScriptWrappable { +class WebGLVertexArrayObjectOES FINAL : public WebGLContextObject, public ScriptWrappable { public: enum VaoType { VaoTypeDefault, @@ -42,7 +42,7 @@ public: virtual ~WebGLVertexArrayObjectOES(); - static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContext*, VaoType); + static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContextBase*, VaoType); // Cached values for vertex attrib range checks struct VertexAttribState { @@ -61,14 +61,14 @@ public: bool enabled; RefPtr<WebGLBuffer> bufferBinding; - GC3Dsizei bytesPerElement; - GC3Dint size; - GC3Denum type; + GLsizei bytesPerElement; + GLint size; + GLenum type; bool normalized; - GC3Dsizei stride; - GC3Dsizei originalStride; - GC3Dintptr offset; - GC3Duint divisor; + GLsizei stride; + GLsizei originalStride; + GLintptr offset; + GLuint divisor; }; bool isDefaultObject() const { return m_type == VaoTypeDefault; } @@ -80,16 +80,14 @@ public: void setElementArrayBuffer(PassRefPtr<WebGLBuffer>); VertexAttribState& getVertexAttribState(int index) { return m_vertexAttribState[index]; } - void setVertexAttribState(GC3Duint, GC3Dsizei, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr, PassRefPtr<WebGLBuffer>); + void setVertexAttribState(GLuint, GLsizei, GLint, GLenum, GLboolean, GLsizei, GLintptr, PassRefPtr<WebGLBuffer>); void unbindBuffer(PassRefPtr<WebGLBuffer>); - void setVertexAttribDivisor(GC3Duint index, GC3Duint divisor); + void setVertexAttribDivisor(GLuint index, GLuint divisor); private: - WebGLVertexArrayObjectOES(WebGLRenderingContext*, VaoType); + WebGLVertexArrayObjectOES(WebGLRenderingContextBase*, VaoType); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); - - virtual bool isVertexArray() const { return true; } + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; VaoType m_type; bool m_hasEverBeenBound; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseButtonInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseButtonInputType.cpp index a41645c2428..63fed8c3512 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseButtonInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseButtonInputType.cpp @@ -32,7 +32,7 @@ #include "config.h" #include "core/html/forms/BaseButtonInputType.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Text.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLInputElement.h" diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.cpp index 7ffe40b29da..d40d965acb2 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.cpp @@ -32,7 +32,7 @@ #include "config.h" #include "core/html/forms/BaseCheckableInputType.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/events/KeyboardEvent.h" #include "core/html/FormDataList.h" #include "core/html/HTMLInputElement.h" @@ -111,4 +111,9 @@ bool BaseCheckableInputType::isCheckable() return true; } +bool BaseCheckableInputType::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue) +{ + return oldValue != newValue; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.h index fdb2fa006ec..aeb6ee2e462 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseCheckableInputType.h @@ -42,16 +42,17 @@ protected: virtual void handleKeydownEvent(KeyboardEvent*); private: - virtual FormControlState saveFormControlState() const OVERRIDE; - virtual void restoreFormControlState(const FormControlState&) OVERRIDE; - virtual bool appendFormData(FormDataList&, bool) const OVERRIDE; - virtual void handleKeypressEvent(KeyboardEvent*) OVERRIDE; - virtual bool canSetStringValue() const OVERRIDE; - virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; - virtual String fallbackValue() const OVERRIDE; - virtual bool storesValueSeparateFromAttribute() OVERRIDE; - virtual void setValue(const String&, bool, TextFieldEventBehavior) OVERRIDE; - virtual bool isCheckable() OVERRIDE; + virtual FormControlState saveFormControlState() const OVERRIDE FINAL; + virtual void restoreFormControlState(const FormControlState&) OVERRIDE FINAL; + virtual bool appendFormData(FormDataList&, bool) const OVERRIDE FINAL; + virtual void handleKeypressEvent(KeyboardEvent*) OVERRIDE FINAL; + virtual bool canSetStringValue() const OVERRIDE FINAL; + virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE FINAL; + virtual String fallbackValue() const OVERRIDE FINAL; + virtual bool storesValueSeparateFromAttribute() OVERRIDE FINAL; + virtual void setValue(const String&, bool, TextFieldEventBehavior) OVERRIDE FINAL; + virtual bool isCheckable() OVERRIDE FINAL; + virtual bool shouldDispatchFormControlChangeEvent(String&, String&) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.cpp index 3967a8ac871..76f32aba3de 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.cpp @@ -29,17 +29,16 @@ #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/dom/shadow/ShadowRoot.h" +#include "core/frame/FrameHost.h" #include "core/html/HTMLDivElement.h" #include "core/html/HTMLInputElement.h" #include "core/page/Chrome.h" -#include "core/page/Page.h" #include "platform/UserGestureIndicator.h" namespace WebCore { BaseChooserOnlyDateAndTimeInputType::~BaseChooserOnlyDateAndTimeInputType() { - closeDateTimeChooser(); } void BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent(Event*) @@ -54,25 +53,29 @@ void BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent(Event*) DateTimeChooserParameters parameters; if (!element().setupDateTimeChooserParameters(parameters)) return; - m_dateTimeChooser = element().document().page()->chrome().openDateTimeChooser(this, parameters); + m_dateTimeChooser = element().document().frameHost()->chrome().openDateTimeChooser(this, parameters); } void BaseChooserOnlyDateAndTimeInputType::createShadowSubtree() { DEFINE_STATIC_LOCAL(AtomicString, valueContainerPseudo, ("-webkit-date-and-time-value", AtomicString::ConstructFromLiteral)); - RefPtr<HTMLDivElement> valueContainer = HTMLDivElement::create(element().document()); - valueContainer->setPseudo(valueContainerPseudo); + RefPtrWillBeRawPtr<HTMLDivElement> valueContainer = HTMLDivElement::create(element().document()); + valueContainer->setShadowPseudoId(valueContainerPseudo); element().userAgentShadowRoot()->appendChild(valueContainer.get()); - updateAppearance(); + updateView(); } -void BaseChooserOnlyDateAndTimeInputType::updateAppearance() +void BaseChooserOnlyDateAndTimeInputType::updateView() { Node* node = element().userAgentShadowRoot()->firstChild(); if (!node || !node->isHTMLElement()) return; - String displayValue = visibleValue(); + String displayValue; + if (!element().suggestedValue().isNull()) + displayValue = element().suggestedValue(); + else + displayValue = visibleValue(); if (displayValue.isEmpty()) { // Need to put something to keep text baseline. displayValue = " "; @@ -84,7 +87,7 @@ void BaseChooserOnlyDateAndTimeInputType::setValue(const String& value, bool val { BaseDateAndTimeInputType::setValue(value, valueChanged, eventBehavior); if (valueChanged) - updateAppearance(); + updateView(); } void BaseChooserOnlyDateAndTimeInputType::closePopupView() @@ -138,5 +141,12 @@ void BaseChooserOnlyDateAndTimeInputType::accessKeyAction(bool sendMouseEvents) BaseClickableWithKeyInputType::accessKeyAction(element(), sendMouseEvents); } +void BaseChooserOnlyDateAndTimeInputType::trace(Visitor* visitor) +{ + visitor->trace(m_dateTimeChooser); + BaseDateAndTimeInputType::trace(visitor); + DateTimeChooserClient::trace(visitor); +} + } #endif diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.h index 4ba1f878ce5..92e1764fb80 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseChooserOnlyDateAndTimeInputType.h @@ -35,12 +35,14 @@ namespace WebCore { class BaseChooserOnlyDateAndTimeInputType : public BaseDateAndTimeInputType, public DateTimeChooserClient { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(BaseChooserOnlyDateAndTimeInputType); protected: - BaseChooserOnlyDateAndTimeInputType(HTMLInputElement& element) : BaseDateAndTimeInputType(element) { } + explicit BaseChooserOnlyDateAndTimeInputType(HTMLInputElement& element) : BaseDateAndTimeInputType(element) { } virtual ~BaseChooserOnlyDateAndTimeInputType(); + virtual void trace(Visitor*) OVERRIDE; + private: - void updateAppearance(); void closeDateTimeChooser(); // InputType functions: @@ -52,13 +54,14 @@ private: virtual void handleKeypressEvent(KeyboardEvent*) OVERRIDE; virtual void handleKeyupEvent(KeyboardEvent*) OVERRIDE; virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; + virtual void updateView() OVERRIDE; // DateTimeChooserClient functions: virtual void didChooseValue(const String&) OVERRIDE; virtual void didChooseValue(double) OVERRIDE; virtual void didEndChooser() OVERRIDE; - RefPtr<DateTimeChooser> m_dateTimeChooser; + RefPtrWillBeMember<DateTimeChooser> m_dateTimeChooser; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp index bf87e948cc0..662f4e6a4cd 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.cpp @@ -43,7 +43,6 @@ namespace WebCore { using blink::WebLocalizedString; using namespace HTMLNames; -using namespace std; static const int msecPerMinute = 60 * 1000; static const int msecPerSecond = 1000; @@ -64,9 +63,9 @@ double BaseDateAndTimeInputType::valueAsDouble() const return value.isFinite() ? value.toDouble() : DateComponents::invalidMilliseconds(); } -void BaseDateAndTimeInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState&) const +void BaseDateAndTimeInputType::setValueAsDouble(double newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const { - element().setValue(serialize(newValue), eventBehavior); + setValueAsDecimal(Decimal::fromDouble(newValue), eventBehavior, exceptionState); } bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const @@ -177,7 +176,7 @@ bool BaseDateAndTimeInputType::supportsReadOnly() const bool BaseDateAndTimeInputType::shouldRespectListAttribute() { - return InputType::themeSupportsDataListUI(this); + return true; } bool BaseDateAndTimeInputType::valueMissing(const String& value) const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h index 0bdf559b0f2..bf5c8bf895a 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseDateAndTimeInputType.h @@ -43,7 +43,11 @@ class BaseDateAndTimeInputType : public InputType { protected: BaseDateAndTimeInputType(HTMLInputElement& element) : InputType(element) { } virtual Decimal parseToNumber(const String&, const Decimal&) const OVERRIDE; - virtual bool parseToDateComponents(const String&, DateComponents*) const OVERRIDE; + // Parses the specified string for this InputType, and returns true if it + // is successfully parsed. An instance pointed by the DateComponents* + // parameter will have parsed values and be modified even if the parsing + // fails. The DateComponents* parameter may be 0. + bool parseToDateComponents(const String&, DateComponents*) const; virtual String sanitizeValue(const String&) const OVERRIDE; virtual String serialize(const Decimal&) const OVERRIDE; String serializeWithComponents(const DateComponents&) const; @@ -55,7 +59,7 @@ private: virtual double valueAsDate() const OVERRIDE; virtual void setValueAsDate(double, ExceptionState&) const OVERRIDE; virtual double valueAsDouble() const OVERRIDE; - virtual void setValueAsDecimal(const Decimal&, TextFieldEventBehavior, ExceptionState&) const OVERRIDE; + virtual void setValueAsDouble(double, TextFieldEventBehavior, ExceptionState&) const OVERRIDE; virtual bool typeMismatchFor(const String&) const OVERRIDE; virtual bool typeMismatch() const OVERRIDE; virtual bool valueMissing(const String&) const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp index 3fbe6236e7b..4f8b9eb59ce 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp @@ -32,10 +32,10 @@ #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h" -#include "CSSValueKeywords.h" -#include "RuntimeEnabledFeatures.h" +#include "core/CSSValueKeywords.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/events/KeyboardEvent.h" +#include "core/events/ScopedEventQueue.h" #include "core/html/HTMLDataListElement.h" #include "core/html/HTMLInputElement.h" #include "core/html/HTMLOptionElement.h" @@ -46,6 +46,7 @@ #include "core/page/Page.h" #include "core/rendering/RenderTheme.h" #include "platform/DateComponents.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/text/DateTimeFormat.h" #include "platform/text/PlatformLocale.h" #include "wtf/DateMath.h" @@ -158,9 +159,12 @@ void BaseMultipleFieldsDateAndTimeInputType::didBlurFromControl() if (containsFocusedShadowElement()) return; - RefPtr<HTMLInputElement> protector(element()); + EventQueueScope scope; + RefPtrWillBeRawPtr<HTMLInputElement> protector(element()); // Remove focus ring by CSS "focus" pseudo class. element().setFocus(false); + if (SpinButtonElement *spinButton = spinButtonElement()) + spinButton->releaseCapture(); } void BaseMultipleFieldsDateAndTimeInputType::didFocusOnControl() @@ -177,7 +181,7 @@ void BaseMultipleFieldsDateAndTimeInputType::didFocusOnControl() void BaseMultipleFieldsDateAndTimeInputType::editControlValueChanged() { - RefPtr<HTMLInputElement> input(element()); + RefPtrWillBeRawPtr<HTMLInputElement> input(element()); String oldValue = input->value(); String newValue = sanitizeValue(dateTimeEditElement()->value()); // Even if oldValue is null and newValue is "", we should assume they are same. @@ -185,9 +189,8 @@ void BaseMultipleFieldsDateAndTimeInputType::editControlValueChanged() input->setNeedsValidityCheck(); } else { input->setValueInternal(newValue, DispatchNoEvent); - input->setNeedsStyleRecalc(); + input->setNeedsStyleRecalc(SubtreeStyleChange); input->dispatchFormControlInputEvent(); - input->dispatchFormControlChangeEvent(); } input->notifyFormStateChanged(); input->updateClearButtonVisibility(); @@ -240,6 +243,12 @@ void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepUp() edit->stepUp(); } +void BaseMultipleFieldsDateAndTimeInputType::spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch eventDispatch) +{ + if (eventDispatch == SpinButtonElement::EventDispatchAllowed) + element().dispatchFormControlChangeEvent(); +} + bool BaseMultipleFieldsDateAndTimeInputType::isPickerIndicatorOwnerDisabledOrReadOnly() const { return element().isDisabledOrReadOnly(); @@ -259,6 +268,7 @@ void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(const St unsigned end; if (date.parseDate(value, 0, end) && end == value.length()) edit->setOnlyYearMonthDay(date); + element().dispatchFormControlChangeEvent(); } void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(double value) @@ -285,6 +295,7 @@ BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(H BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType() { +#if !ENABLE(OILPAN) if (SpinButtonElement* element = spinButtonElement()) element->removeSpinButtonOwner(); if (ClearButtonElement* element = clearButtonElement()) @@ -293,6 +304,7 @@ BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType( element->removeEditControlOwner(); if (PickerIndicatorElement* element = pickerIndicatorElement()) element->removePickerIndicatorOwner(); +#endif } String BaseMultipleFieldsDateAndTimeInputType::badInputText() const @@ -339,22 +351,15 @@ void BaseMultipleFieldsDateAndTimeInputType::createShadowSubtree() ContainerNode* container = element().userAgentShadowRoot(); container->appendChild(DateTimeEditElement::create(document, *this)); - updateView(); + element().updateView(); container->appendChild(ClearButtonElement::create(document, *this)); container->appendChild(SpinButtonElement::create(document, *this)); - bool shouldAddPickerIndicator = false; - if (InputType::themeSupportsDataListUI(this)) - shouldAddPickerIndicator = true; - if (RenderTheme::theme().supportsCalendarPicker(formControlType())) { - shouldAddPickerIndicator = true; + if (RenderTheme::theme().supportsCalendarPicker(formControlType())) m_pickerIndicatorIsAlwaysVisible = true; - } - if (shouldAddPickerIndicator) { - container->appendChild(PickerIndicatorElement::create(document, *this)); - m_pickerIndicatorIsVisible = true; - updatePickerIndicatorVisibility(); - } + container->appendChild(PickerIndicatorElement::create(document, *this)); + m_pickerIndicatorIsVisible = true; + updatePickerIndicatorVisibility(); } void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree() @@ -379,15 +384,15 @@ void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree() m_isDestroyingShadowSubtree = false; } -void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction) +void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Element* oldFocusedElement, FocusType type) { DateTimeEditElement* edit = dateTimeEditElement(); if (!edit || m_isDestroyingShadowSubtree) return; - if (direction == FocusDirectionBackward) { + if (type == FocusTypeBackward) { if (element().document().page()) - element().document().page()->focusController().advanceFocus(direction); - } else if (direction == FocusDirectionNone || direction == FocusDirectionMouse || direction == FocusDirectionPage) { + element().document().page()->focusController().advanceFocus(type); + } else if (type == FocusTypeNone || type == FocusTypeMouse || type == FocusTypePage) { edit->focusByOwner(oldFocusedElement); } else { edit->focusByOwner(); @@ -443,6 +448,11 @@ AtomicString BaseMultipleFieldsDateAndTimeInputType::localeIdentifier() const return element().computeInheritedLanguage(); } +void BaseMultipleFieldsDateAndTimeInputType::editControlDidChangeValueByKeyboard() +{ + element().dispatchFormControlChangeEvent(); +} + void BaseMultipleFieldsDateAndTimeInputType::minOrMaxAttributeChanged() { updateView(); @@ -479,7 +489,7 @@ void BaseMultipleFieldsDateAndTimeInputType::setValue(const String& sanitizedVal InputType::setValue(sanitizedValue, valueChanged, eventBehavior); DateTimeEditElement* edit = dateTimeEditElement(); if (valueChanged || (sanitizedValue.isEmpty() && edit && edit->anyEditableFieldsHaveValues())) { - updateView(); + element().updateView(); element().setNeedsValidityCheck(); } } @@ -503,12 +513,18 @@ void BaseMultipleFieldsDateAndTimeInputType::updateView() DateTimeEditElement::LayoutParameters layoutParameters(element().locale(), createStepRange(AnyIsDefaultStep)); DateComponents date; - const bool hasValue = parseToDateComponents(element().value(), &date); + bool hasValue = false; + if (!element().suggestedValue().isNull()) + hasValue = parseToDateComponents(element().suggestedValue(), &date); + else + hasValue = parseToDateComponents(element().value(), &date); if (!hasValue) setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date); setupLayoutParameters(layoutParameters, date); + DEFINE_STATIC_LOCAL(AtomicString, datetimeformatAttr, ("datetimeformat", AtomicString::ConstructFromLiteral)); + edit->setAttribute(datetimeformatAttr, AtomicString(layoutParameters.dateTimeFormat), ASSERT_NO_EXCEPTION); const AtomicString pattern = edit->fastGetAttribute(HTMLNames::patternAttr); if (!pattern.isEmpty()) layoutParameters.dateTimeFormat = pattern; @@ -540,12 +556,10 @@ void BaseMultipleFieldsDateAndTimeInputType::updatePickerIndicatorVisibility() showPickerIndicator(); return; } - if (RuntimeEnabledFeatures::dataListElementEnabled()) { - if (element().hasValidDataListOptions()) - showPickerIndicator(); - else - hidePickerIndicator(); - } + if (element().hasValidDataListOptions()) + showPickerIndicator(); + else + hidePickerIndicator(); } void BaseMultipleFieldsDateAndTimeInputType::hidePickerIndicator() @@ -586,7 +600,7 @@ bool BaseMultipleFieldsDateAndTimeInputType::shouldClearButtonRespondToMouseEven void BaseMultipleFieldsDateAndTimeInputType::clearValue() { - RefPtr<HTMLInputElement> input(element()); + RefPtrWillBeRawPtr<HTMLInputElement> input(element()); input->setValue("", DispatchInputAndChangeEvent); input->updateClearButtonVisibility(); } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h index 14a0a2c8171..4867175784d 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h @@ -49,6 +49,8 @@ class BaseMultipleFieldsDateAndTimeInputType , protected PickerIndicatorElement::PickerIndicatorOwner , protected SpinButtonElement::SpinButtonOwner , protected ClearButtonElement::ClearButtonOwner { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(BaseMultipleFieldsDateAndTimeInputType); + public: virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const = 0; @@ -67,6 +69,7 @@ private: virtual bool isEditControlOwnerDisabled() const OVERRIDE FINAL; virtual bool isEditControlOwnerReadOnly() const OVERRIDE FINAL; virtual AtomicString localeIdentifier() const OVERRIDE FINAL; + virtual void editControlDidChangeValueByKeyboard() OVERRIDE FINAL; // SpinButtonElement::SpinButtonOwner functions. virtual void focusAndSelectSpinButtonOwner() OVERRIDE; @@ -74,6 +77,7 @@ private: virtual bool shouldSpinButtonRespondToWheelEvents() OVERRIDE; virtual void spinButtonStepDown() OVERRIDE; virtual void spinButtonStepUp() OVERRIDE; + virtual void spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch) OVERRIDE; // PickerIndicatorElement::PickerIndicatorOwner functions virtual bool isPickerIndicatorOwnerDisabledOrReadOnly() const OVERRIDE FINAL; @@ -94,7 +98,7 @@ private: virtual void destroyShadowSubtree() OVERRIDE FINAL; virtual void disabledAttributeChanged() OVERRIDE FINAL; virtual void forwardEvent(Event*) OVERRIDE FINAL; - virtual void handleFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE; + virtual void handleFocusEvent(Element* oldFocusedElement, FocusType) OVERRIDE; virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE FINAL; virtual bool hasBadInput() const OVERRIDE; virtual bool hasCustomFocusLogic() const OVERRIDE FINAL; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp index d00d21e98cb..cc531a12091 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp @@ -24,8 +24,8 @@ #include "config.h" #include "core/html/forms/BaseTextInputType.h" -#include "HTMLNames.h" #include "bindings/v8/ScriptRegexp.h" +#include "core/HTMLNames.h" #include "core/html/HTMLInputElement.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h index 8c917a0b616..c2743688571 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h @@ -42,9 +42,9 @@ protected: BaseTextInputType(HTMLInputElement& element) : TextFieldInputType(element) { } private: - virtual bool isTextType() const OVERRIDE; - virtual bool patternMismatch(const String&) const OVERRIDE; - virtual bool supportsPlaceholder() const OVERRIDE; + virtual bool isTextType() const OVERRIDE FINAL; + virtual bool patternMismatch(const String&) const OVERRIDE FINAL; + virtual bool supportsPlaceholder() const OVERRIDE FINAL; virtual bool supportsSelectionAPI() const OVERRIDE; }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.cpp index 39e112c03fe..7ecf1cbf1d4 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.cpp @@ -31,14 +31,14 @@ #include "config.h" #include "core/html/forms/ButtonInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "wtf/PassOwnPtr.h" namespace WebCore { -PassRefPtr<InputType> ButtonInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> ButtonInputType::create(HTMLInputElement& element) { - return adoptRef(new ButtonInputType(element)); + return adoptRefWillBeNoop(new ButtonInputType(element)); } const AtomicString& ButtonInputType::formControlType() const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.h index aa31135602b..5b187710d3a 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/ButtonInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class ButtonInputType : public BaseButtonInputType { +class ButtonInputType FINAL : public BaseButtonInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: ButtonInputType(HTMLInputElement& element) : BaseButtonInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp index 738f9d58b9b..9a77643e431 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp @@ -32,7 +32,7 @@ #include "config.h" #include "core/html/forms/CheckboxInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "core/events/KeyboardEvent.h" #include "core/html/HTMLInputElement.h" #include "platform/text/PlatformLocale.h" @@ -40,9 +40,9 @@ namespace WebCore { -PassRefPtr<InputType> CheckboxInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> CheckboxInputType::create(HTMLInputElement& element) { - return adoptRef(new CheckboxInputType(element)); + return adoptRefWillBeNoop(new CheckboxInputType(element)); } const AtomicString& CheckboxInputType::formControlType() const @@ -68,12 +68,12 @@ void CheckboxInputType::handleKeyupEvent(KeyboardEvent* event) dispatchSimulatedClickIfActive(event); } -PassOwnPtr<ClickHandlingState> CheckboxInputType::willDispatchClick() +PassOwnPtrWillBeRawPtr<ClickHandlingState> CheckboxInputType::willDispatchClick() { // An event handler can use preventDefault or "return false" to reverse the checking we do here. // The ClickHandlingState object contains what we need to undo what we did here in didDispatchClick. - OwnPtr<ClickHandlingState> state = adoptPtr(new ClickHandlingState); + OwnPtrWillBeRawPtr<ClickHandlingState> state = adoptPtrWillBeNoop(new ClickHandlingState); state->checked = element().checked(); state->indeterminate = element().indeterminate(); diff --git a/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.h index 9299018f6b5..06e4c516750 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/CheckboxInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class CheckboxInputType : public BaseCheckableInputType { +class CheckboxInputType FINAL : public BaseCheckableInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: CheckboxInputType(HTMLInputElement& element) : BaseCheckableInputType(element) { } @@ -45,7 +45,7 @@ private: virtual bool valueMissing(const String&) const OVERRIDE; virtual String valueMissingText() const OVERRIDE; virtual void handleKeyupEvent(KeyboardEvent*) OVERRIDE; - virtual PassOwnPtr<ClickHandlingState> willDispatchClick() OVERRIDE; + virtual PassOwnPtrWillBeRawPtr<ClickHandlingState> willDispatchClick() OVERRIDE; virtual void didDispatchClick(Event*, const ClickHandlingState&) OVERRIDE; virtual bool isCheckbox() const OVERRIDE; virtual bool supportsIndeterminateAppearance() const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.cpp index 304504bdfc3..ae4bd2d7677 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.cpp @@ -31,11 +31,10 @@ #include "config.h" #include "core/html/forms/ColorInputType.h" -#include "CSSPropertyNames.h" -#include "InputTypeNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "bindings/v8/ScriptController.h" +#include "core/CSSPropertyNames.h" +#include "core/InputTypeNames.h" #include "core/events/MouseEvent.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLDataListElement.h" @@ -44,6 +43,8 @@ #include "core/html/HTMLOptionElement.h" #include "core/page/Chrome.h" #include "core/rendering/RenderView.h" +#include "platform/ColorChooser.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/UserGestureIndicator.h" #include "platform/graphics/Color.h" #include "wtf/PassOwnPtr.h" @@ -68,13 +69,13 @@ static bool isValidColorString(const String& value) // We don't accept #rgb and #aarrggbb formats. if (value.length() != 7) return false; - Color color(value); - return color.isValid() && !color.hasAlpha(); + Color color; + return color.setFromString(value) && !color.hasAlpha(); } -PassRefPtr<InputType> ColorInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> ColorInputType::create(HTMLInputElement& element) { - return adoptRef(new ColorInputType(element)); + return adoptRefWillBeNoop(new ColorInputType(element)); } ColorInputType::~ColorInputType() @@ -117,7 +118,10 @@ String ColorInputType::sanitizeValue(const String& proposedValue) const Color ColorInputType::valueAsColor() const { - return Color(element().value()); + Color color; + bool success = color.setFromString(element().value()); + ASSERT_UNUSED(success, success); + return color; } void ColorInputType::createShadowSubtree() @@ -125,14 +129,14 @@ void ColorInputType::createShadowSubtree() ASSERT(element().shadow()); Document& document = element().document(); - RefPtr<HTMLDivElement> wrapperElement = HTMLDivElement::create(document); - wrapperElement->setPseudo(AtomicString("-webkit-color-swatch-wrapper", AtomicString::ConstructFromLiteral)); - RefPtr<HTMLDivElement> colorSwatch = HTMLDivElement::create(document); - colorSwatch->setPseudo(AtomicString("-webkit-color-swatch", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<HTMLDivElement> wrapperElement = HTMLDivElement::create(document); + wrapperElement->setShadowPseudoId(AtomicString("-webkit-color-swatch-wrapper", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<HTMLDivElement> colorSwatch = HTMLDivElement::create(document); + colorSwatch->setShadowPseudoId(AtomicString("-webkit-color-swatch", AtomicString::ConstructFromLiteral)); wrapperElement->appendChild(colorSwatch.release()); element().userAgentShadowRoot()->appendChild(wrapperElement.release()); - updateColorSwatch(); + element().updateView(); } void ColorInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior) @@ -142,7 +146,7 @@ void ColorInputType::setValue(const String& value, bool valueChanged, TextFieldE if (!valueChanged) return; - updateColorSwatch(); + element().updateView(); if (m_chooser) m_chooser->setSelectedColor(valueAsColor()); } @@ -157,7 +161,7 @@ void ColorInputType::handleDOMActivateEvent(Event* event) Chrome* chrome = this->chrome(); if (chrome && !m_chooser) - m_chooser = chrome->createColorChooser(this, valueAsColor()); + m_chooser = chrome->createColorChooser(element().document().frame(), this, valueAsColor()); event->setDefaultHandled(); } @@ -169,7 +173,7 @@ void ColorInputType::closePopupView() bool ColorInputType::shouldRespectListAttribute() { - return InputType::themeSupportsDataListUI(this); + return true; } bool ColorInputType::typeMismatchFor(const String& value) const @@ -182,7 +186,7 @@ void ColorInputType::didChooseColor(const Color& color) if (element().isDisabledFormControl() || color == valueAsColor()) return; element().setValueFromRenderer(color.serialized()); - updateColorSwatch(); + element().updateView(); element().dispatchFormControlChangeEvent(); } @@ -197,7 +201,7 @@ void ColorInputType::endColorChooser() m_chooser->endChooser(); } -void ColorInputType::updateColorSwatch() +void ColorInputType::updateView() { HTMLElement* colorSwatch = shadowColorSwatch(); if (!colorSwatch) @@ -224,30 +228,25 @@ Color ColorInputType::currentColor() bool ColorInputType::shouldShowSuggestions() const { - if (RuntimeEnabledFeatures::dataListElementEnabled()) - return element().fastHasAttribute(listAttr); - - return false; + return element().fastHasAttribute(listAttr); } Vector<ColorSuggestion> ColorInputType::suggestions() const { Vector<ColorSuggestion> suggestions; - if (RuntimeEnabledFeatures::dataListElementEnabled()) { - HTMLDataListElement* dataList = element().dataList(); - if (dataList) { - RefPtr<HTMLCollection> options = dataList->options(); - for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); i++) { - if (!element().isValidValue(option->value())) - continue; - Color color(option->value()); - if (!color.isValid()) - continue; - ColorSuggestion suggestion(color, option->label().left(maxSuggestionLabelLength)); - suggestions.append(suggestion); - if (suggestions.size() >= maxSuggestions) - break; - } + HTMLDataListElement* dataList = element().dataList(); + if (dataList) { + RefPtrWillBeRawPtr<HTMLCollection> options = dataList->options(); + for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); i++) { + if (!element().isValidValue(option->value())) + continue; + Color color; + if (!color.setFromString(option->value())) + continue; + ColorSuggestion suggestion(color, option->label().left(maxSuggestionLabelLength)); + suggestions.append(suggestion); + if (suggestions.size() >= maxSuggestions) + break; } } return suggestions; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.h index b0f7ba3d02b..366451bddd2 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/ColorInputType.h @@ -36,9 +36,11 @@ namespace WebCore { -class ColorInputType : public BaseClickableWithKeyInputType, public ColorChooserClient { +class ColorChooser; + +class ColorInputType FINAL : public BaseClickableWithKeyInputType, public ColorChooserClient { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); virtual ~ColorInputType(); // ColorChooserClient implementation. @@ -63,10 +65,10 @@ private: virtual void closePopupView() OVERRIDE; virtual bool shouldRespectListAttribute() OVERRIDE; virtual bool typeMismatchFor(const String&) const OVERRIDE; + virtual void updateView() OVERRIDE; Color valueAsColor() const; void endColorChooser(); - void updateColorSwatch(); HTMLElement* shadowColorSwatch() const; OwnPtr<ColorChooser> m_chooser; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.cpp index a820bc8f97b..6f3cbef7a8e 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "core/html/forms/DateInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/DateTimeFieldsState.h" #include "platform/DateComponents.h" @@ -53,9 +53,9 @@ inline DateInputType::DateInputType(HTMLInputElement& element) { } -PassRefPtr<InputType> DateInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> DateInputType::create(HTMLInputElement& element) { - return adoptRef(new DateInputType(element)); + return adoptRefWillBeNoop(new DateInputType(element)); } void DateInputType::countUsage() @@ -72,7 +72,7 @@ StepRange DateInputType::createStepRange(AnyStepHandling anyStepHandling) const { DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (dateDefaultStep, dateDefaultStepBase, dateStepScaleFactor, StepRange::ParsedStepValueShouldBeInteger)); - return InputType::createStepRange(anyStepHandling, 0, Decimal::fromDouble(DateComponents::minimumDate()), Decimal::fromDouble(DateComponents::maximumDate()), stepDescription); + return InputType::createStepRange(anyStepHandling, dateDefaultStepBase, Decimal::fromDouble(DateComponents::minimumDate()), Decimal::fromDouble(DateComponents::maximumDate()), stepDescription); } bool DateInputType::parseToDateComponentsInternal(const String& string, DateComponents* out) const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.h index 2688adf1d93..1583a2b46c5 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/DateInputType.h @@ -44,9 +44,9 @@ typedef BaseMultipleFieldsDateAndTimeInputType BaseDateInputType; typedef BaseChooserOnlyDateAndTimeInputType BaseDateInputType; #endif -class DateInputType : public BaseDateInputType { +class DateInputType FINAL : public BaseDateInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: DateInputType(HTMLInputElement&); @@ -61,7 +61,7 @@ private: // BaseMultipleFieldsDateAndTimeInputType functions virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE; virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE; - virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const; + virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const OVERRIDE; #endif }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp index 60c162dc247..76c733f43c2 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "core/html/forms/DateTimeLocalInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/DateTimeFieldsState.h" #include "platform/DateComponents.h" @@ -50,9 +50,9 @@ static const int dateTimeLocalDefaultStep = 60; static const int dateTimeLocalDefaultStepBase = 0; static const int dateTimeLocalStepScaleFactor = 1000; -PassRefPtr<InputType> DateTimeLocalInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> DateTimeLocalInputType::create(HTMLInputElement& element) { - return adoptRef(new DateTimeLocalInputType(element)); + return adoptRefWillBeNoop(new DateTimeLocalInputType(element)); } void DateTimeLocalInputType::countUsage() @@ -81,7 +81,7 @@ StepRange DateTimeLocalInputType::createStepRange(AnyStepHandling anyStepHandlin { DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (dateTimeLocalDefaultStep, dateTimeLocalDefaultStepBase, dateTimeLocalStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); - return InputType::createStepRange(anyStepHandling, 0, Decimal::fromDouble(DateComponents::minimumDateTime()), Decimal::fromDouble(DateComponents::maximumDateTime()), stepDescription); + return InputType::createStepRange(anyStepHandling, dateTimeLocalDefaultStepBase, Decimal::fromDouble(DateComponents::minimumDateTime()), Decimal::fromDouble(DateComponents::maximumDateTime()), stepDescription); } bool DateTimeLocalInputType::parseToDateComponentsInternal(const String& string, DateComponents* out) const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h index ade5ac0f8e4..8fb2f5e637b 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/DateTimeLocalInputType.h @@ -44,9 +44,9 @@ typedef BaseMultipleFieldsDateAndTimeInputType BaseDateTimeLocalInputType; typedef BaseChooserOnlyDateAndTimeInputType BaseDateTimeLocalInputType; #endif -class DateTimeLocalInputType : public BaseDateTimeLocalInputType { +class DateTimeLocalInputType FINAL : public BaseDateTimeLocalInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: DateTimeLocalInputType(HTMLInputElement& element) : BaseDateTimeLocalInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.cpp index 20db60bf5f2..727bdb478e4 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.cpp @@ -24,8 +24,8 @@ #include "config.h" #include "core/html/forms/EmailInputType.h" -#include "InputTypeNames.h" #include "bindings/v8/ScriptRegexp.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/page/Chrome.h" @@ -34,7 +34,8 @@ #include "public/platform/Platform.h" #include "wtf/PassOwnPtr.h" #include "wtf/text/StringBuilder.h" -#include <unicode/uidna.h> +#include <unicode/idna.h> +#include <unicode/unistr.h> namespace WebCore { @@ -45,11 +46,13 @@ static const char localPartCharacters[] = "abcdefghijklmnopqrstuvwxyz0123456789! static const char emailPattern[] = "[a-z0-9!#$%&'*+/=?^_`{|}~.-]+" // local part "@" - "[a-z0-9-]+(\\.[a-z0-9-]+)*"; // domain part + "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?" // domain part + "(?:\\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*"; // RFC5321 says the maximum total length of a domain name is 255 octets. -static const size_t maximumDomainNameLength = 255; -static const int32_t idnaConversionOption = UIDNA_ALLOW_UNASSIGNED; +static const int32_t maximumDomainNameLength = 255; +// Use the same option as in url/url_canon_icu.cc +static const int32_t idnaConversionOption = UIDNA_CHECK_BIDI; static String convertEmailAddressToASCII(const String& address) { @@ -60,15 +63,24 @@ static String convertEmailAddressToASCII(const String& address) if (atPosition == kNotFound) return address; - UErrorCode error = U_ZERO_ERROR; - UChar domainNameBuffer[maximumDomainNameLength]; - int32_t domainNameLength = uidna_IDNToASCII(address.charactersWithNullTermination().data() + atPosition + 1, address.length() - atPosition - 1, domainNameBuffer, WTF_ARRAY_LENGTH(domainNameBuffer), idnaConversionOption, 0, &error); - if (error != U_ZERO_ERROR || domainNameLength <= 0) + // UnicodeString ctor for copy-on-write does not work reliably (in debug + // build.) TODO(jshin): In an unlikely case this is a perf-issue, treat + // 8bit and non-8bit strings separately. + icu::UnicodeString idnDomainName(address.charactersWithNullTermination().data() + atPosition + 1, address.length() - atPosition - 1); + icu::UnicodeString domainName; + + // Leak |idna| at the end. + UErrorCode errorCode = U_ZERO_ERROR; + static icu::IDNA *idna = icu::IDNA::createUTS46Instance(idnaConversionOption, errorCode); + ASSERT(idna); + icu::IDNAInfo idnaInfo; + idna->nameToASCII(idnDomainName, domainName, idnaInfo, errorCode); + if (U_FAILURE(errorCode) || idnaInfo.hasErrors() || domainName.length() > maximumDomainNameLength) return address; StringBuilder builder; builder.append(address, 0, atPosition + 1); - builder.append(domainNameBuffer, domainNameLength); + builder.append(domainName.getBuffer(), domainName.length()); return builder.toString(); } @@ -133,9 +145,9 @@ static bool isValidEmailAddress(const String& address) return !matchOffset && matchLength == addressLength; } -PassRefPtr<InputType> EmailInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> EmailInputType::create(HTMLInputElement& element) { - return adoptRef(new EmailInputType(element)); + return adoptRefWillBeNoop(new EmailInputType(element)); } void EmailInputType::countUsage() diff --git a/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.h index 82bd153a780..230586f9d47 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/EmailInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class EmailInputType : public BaseTextInputType { +class EmailInputType FINAL : public BaseTextInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: EmailInputType(HTMLInputElement& element) : BaseTextInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.cpp index 64338a6849d..f63368f318d 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.cpp @@ -22,10 +22,9 @@ #include "config.h" #include "core/html/forms/FileInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/events/Event.h" #include "core/fileapi/File.h" @@ -37,6 +36,7 @@ #include "core/page/DragData.h" #include "core/rendering/RenderFileUploadControl.h" #include "platform/FileMetadata.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/UserGestureIndicator.h" #include "platform/text/PlatformLocale.h" #include "wtf/PassOwnPtr.h" @@ -54,9 +54,15 @@ inline FileInputType::FileInputType(HTMLInputElement& element) { } -PassRefPtr<InputType> FileInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> FileInputType::create(HTMLInputElement& element) { - return adoptRef(new FileInputType(element)); + return adoptRefWillBeNoop(new FileInputType(element)); +} + +void FileInputType::trace(Visitor* visitor) +{ + visitor->trace(m_fileList); + BaseClickableWithKeyInputType::trace(visitor); } Vector<FileChooserFileInfo> FileInputType::filesFromFormControlState(const FormControlState& state) @@ -146,13 +152,13 @@ void FileInputType::handleDOMActivateEvent(Event* event) if (Chrome* chrome = this->chrome()) { FileChooserSettings settings; HTMLInputElement& input = element(); - settings.allowsDirectoryUpload = RuntimeEnabledFeatures::directoryUploadEnabled() && input.fastHasAttribute(webkitdirectoryAttr); + settings.allowsDirectoryUpload = input.fastHasAttribute(webkitdirectoryAttr); settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input.fastHasAttribute(multipleAttr); settings.acceptMIMETypes = input.acceptMIMETypes(); settings.acceptFileExtensions = input.acceptFileExtensions(); settings.selectedFiles = m_fileList->paths(); #if ENABLE(MEDIA_CAPTURE) - settings.useMediaCapture = input.capture(); + settings.useMediaCapture = input.isFileUpload() && input.fastHasAttribute(captureAttr); #endif chrome->runOpenPanel(input.document().frame(), newFileChooser(settings)); } @@ -200,21 +206,25 @@ bool FileInputType::getTypeSpecificValue(String& value) return true; } -void FileInputType::setValue(const String&, bool, TextFieldEventBehavior) +void FileInputType::setValue(const String&, bool valueChanged, TextFieldEventBehavior) { + if (!valueChanged) + return; + m_fileList->clear(); - element().setNeedsStyleRecalc(); + element().setNeedsStyleRecalc(SubtreeStyleChange); + element().setNeedsValidityCheck(); } -PassRefPtr<FileList> FileInputType::createFileList(const Vector<FileChooserFileInfo>& files) const +PassRefPtrWillBeRawPtr<FileList> FileInputType::createFileList(const Vector<FileChooserFileInfo>& files) const { - RefPtr<FileList> fileList(FileList::create()); + RefPtrWillBeRawPtr<FileList> fileList(FileList::create()); size_t size = files.size(); // If a directory is being selected, the UI allows a directory to be chosen // and the paths provided here share a root directory somewhere up the tree; // we want to store only the relative paths from that point. - if (size && element().fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::directoryUploadEnabled()) { + if (size && element().fastHasAttribute(webkitdirectoryAttr)) { // Find the common root path. String rootPath = directoryName(files[0].path); for (size_t i = 1; i < size; i++) { @@ -247,10 +257,10 @@ bool FileInputType::isFileUpload() const void FileInputType::createShadowSubtree() { ASSERT(element().shadow()); - RefPtr<HTMLInputElement> button = HTMLInputElement::create(element().document(), 0, false); + RefPtrWillBeRawPtr<HTMLInputElement> button = HTMLInputElement::create(element().document(), 0, false); button->setType(InputTypeNames::button); - button->setAttribute(valueAttr, locale().queryString(element().multiple() ? WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString::FileButtonChooseFileLabel)); - button->setPseudo(AtomicString("-webkit-file-upload-button", AtomicString::ConstructFromLiteral)); + button->setAttribute(valueAttr, AtomicString(locale().queryString(element().multiple() ? WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString::FileButtonChooseFileLabel))); + button->setShadowPseudoId(AtomicString("-webkit-file-upload-button", AtomicString::ConstructFromLiteral)); element().userAgentShadowRoot()->appendChild(button.release()); } @@ -265,15 +275,15 @@ void FileInputType::multipleAttributeChanged() { ASSERT(element().shadow()); if (Element* button = toElement(element().userAgentShadowRoot()->firstChild())) - button->setAttribute(valueAttr, locale().queryString(element().multiple() ? WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString::FileButtonChooseFileLabel)); + button->setAttribute(valueAttr, AtomicString(locale().queryString(element().multiple() ? WebLocalizedString::FileButtonChooseMultipleFilesLabel : WebLocalizedString::FileButtonChooseFileLabel))); } -void FileInputType::setFiles(PassRefPtr<FileList> files) +void FileInputType::setFiles(PassRefPtrWillBeRawPtr<FileList> files) { if (!files) return; - RefPtr<HTMLInputElement> input(element()); + RefPtrWillBeRawPtr<HTMLInputElement> input(element()); bool pathsChanged = false; if (files->length() != m_fileList->length()) { @@ -289,21 +299,16 @@ void FileInputType::setFiles(PassRefPtr<FileList> files) m_fileList = files; - input->setFormControlValueMatchesRenderer(true); input->notifyFormStateChanged(); input->setNeedsValidityCheck(); - Vector<String> paths; - for (unsigned i = 0; i < m_fileList->length(); ++i) - paths.append(m_fileList->item(i)->path()); - if (input->renderer()) - input->renderer()->repaint(); + input->renderer()->paintInvalidationForWholeRenderer(); if (pathsChanged) { // This call may cause destruction of this instance. // input instance is safe since it is ref-counted. - input->HTMLElement::dispatchChangeEvent(); + input->dispatchChangeEvent(); } input->setChangedSinceLastFormControlChangeEvent(false); } @@ -335,7 +340,7 @@ bool FileInputType::receiveDroppedFiles(const DragData* dragData) return false; HTMLInputElement& input = element(); - if (input.fastHasAttribute(webkitdirectoryAttr) && RuntimeEnabledFeatures::directoryUploadEnabled()) { + if (input.fastHasAttribute(webkitdirectoryAttr)) { receiveDropForDirectoryUpload(paths); return true; } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.h index a91ba75e2be..68fc3342045 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/FileInputType.h @@ -34,6 +34,7 @@ #include "core/html/forms/BaseClickableWithKeyInputType.h" #include "platform/FileChooser.h" +#include "platform/heap/Handle.h" #include "wtf/RefPtr.h" namespace WebCore { @@ -41,9 +42,10 @@ namespace WebCore { class DragData; class FileList; -class FileInputType : public BaseClickableWithKeyInputType, private FileChooserClient { +class FileInputType FINAL : public BaseClickableWithKeyInputType, private FileChooserClient { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); + virtual void trace(Visitor*) OVERRIDE; static Vector<FileChooserFileInfo> filesFromFormControlState(const FormControlState&); private: @@ -58,7 +60,7 @@ private: virtual RenderObject* createRenderer(RenderStyle*) const OVERRIDE; virtual bool canSetStringValue() const OVERRIDE; virtual FileList* files() OVERRIDE; - virtual void setFiles(PassRefPtr<FileList>) OVERRIDE; + virtual void setFiles(PassRefPtrWillBeRawPtr<FileList>) OVERRIDE; virtual bool canSetValue(const String&) OVERRIDE; virtual bool getTypeSpecificValue(String&) OVERRIDE; // Checked first, before internal storage or the value attribute. virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE; @@ -73,10 +75,10 @@ private: // FileChooserClient implementation. virtual void filesChosen(const Vector<FileChooserFileInfo>&) OVERRIDE; - PassRefPtr<FileList> createFileList(const Vector<FileChooserFileInfo>& files) const; + PassRefPtrWillBeRawPtr<FileList> createFileList(const Vector<FileChooserFileInfo>& files) const; void receiveDropForDirectoryUpload(const Vector<String>&); - RefPtr<FileList> m_fileList; + RefPtrWillBeMember<FileList> m_fileList; String m_droppedFileSystemId; }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/FormController.cpp b/chromium/third_party/WebKit/Source/core/html/forms/FormController.cpp index a3cd9b02100..e4125bb7ed5 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/FormController.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/FormController.cpp @@ -221,7 +221,7 @@ PassOwnPtr<SavedFormState> SavedFormState::deserialize(const Vector<String>& sta FormControlState state = FormControlState::deserialize(stateVector, index); if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != kNotFound || state.isFailure()) return nullptr; - savedFormState->appendControlState(name, type, state); + savedFormState->appendControlState(AtomicString(name), AtomicString(type), state); } return savedFormState.release(); } @@ -288,19 +288,20 @@ Vector<String> SavedFormState::getReferencedFilePaths() const // ---------------------------------------------------------------------------- -class FormKeyGenerator { +class FormKeyGenerator FINAL : public NoBaseWillBeGarbageCollectedFinalized<FormKeyGenerator> { WTF_MAKE_NONCOPYABLE(FormKeyGenerator); - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<FormKeyGenerator> create() { return adoptPtr(new FormKeyGenerator); } + static PassOwnPtrWillBeRawPtr<FormKeyGenerator> create() { return adoptPtrWillBeNoop(new FormKeyGenerator); } + void trace(Visitor* visitor) { visitor->trace(m_formToKeyMap); } const AtomicString& formKey(const HTMLFormControlElementWithState&); void willDeleteForm(HTMLFormElement*); private: FormKeyGenerator() { } - typedef HashMap<HTMLFormElement*, AtomicString> FormToKeyMap; + typedef WillBeHeapHashMap<RawPtrWillBeMember<HTMLFormElement>, AtomicString> FormToKeyMap; typedef HashMap<String, unsigned> FormSignatureToNextIndexMap; FormToKeyMap m_formToKeyMap; FormSignatureToNextIndexMap m_formSignatureToNextIndexMap; @@ -310,7 +311,7 @@ static inline void recordFormStructure(const HTMLFormElement& form, StringBuilde { // 2 is enough to distinguish forms in webkit.org/b/91209#c0 const size_t namedControlsToBeRecorded = 2; - const Vector<FormAssociatedElement*>& controls = form.associatedElements(); + const FormAssociatedElement::List& controls = form.associatedElements(); builder.append(" ["); for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) { if (!controls[i]->isFormControlElementWithState()) @@ -333,7 +334,9 @@ static inline String formSignature(const HTMLFormElement& form) KURL actionURL = form.getURLAttribute(actionAttr); // Remove the query part because it might contain volatile parameters such // as a session key. - actionURL.setQuery(String()); + if (!actionURL.isEmpty()) + actionURL.setQuery(String()); + StringBuilder builder; if (!actionURL.isEmpty()) builder.append(actionURL.string()); @@ -356,14 +359,14 @@ const AtomicString& FormKeyGenerator::formKey(const HTMLFormControlElementWithSt String signature = formSignature(*form); ASSERT(!signature.isNull()); FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMap.add(signature, 0); - unsigned nextIndex = result.iterator->value++; + unsigned nextIndex = result.storedValue->value++; StringBuilder formKeyBuilder; formKeyBuilder.append(signature); formKeyBuilder.appendLiteral(" #"); formKeyBuilder.appendNumber(nextIndex); FormToKeyMap::AddResult addFormKeyresult = m_formToKeyMap.add(form, formKeyBuilder.toAtomicString()); - return addFormKeyresult.iterator->value; + return addFormKeyresult.storedValue->value; } void FormKeyGenerator::willDeleteForm(HTMLFormElement* form) @@ -374,12 +377,28 @@ void FormKeyGenerator::willDeleteForm(HTMLFormElement* form) // ---------------------------------------------------------------------------- -FormController::FormController() +PassRefPtrWillBeRawPtr<DocumentState> DocumentState::create() { + return adoptRefWillBeNoop(new DocumentState); } -FormController::~FormController() +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentState) + +void DocumentState::trace(Visitor* visitor) { + visitor->trace(m_formControls); +} + +void DocumentState::addControl(HTMLFormControlElementWithState* control) +{ + ASSERT(!m_formControls.contains(control)); + m_formControls.add(control); +} + +void DocumentState::removeControl(HTMLFormControlElementWithState* control) +{ + RELEASE_ASSERT(m_formControls.contains(control)); + m_formControls.remove(control); } static String formStateSignature() @@ -391,28 +410,23 @@ static String formStateSignature() return signature; } -PassOwnPtr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList) +Vector<String> DocumentState::toStateVector() { - OwnPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create(); + OwnPtrWillBeRawPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create(); OwnPtr<SavedFormStateMap> stateMap = adoptPtr(new SavedFormStateMap); - for (FormElementListHashSet::const_iterator it = controlList.begin(); it != controlList.end(); ++it) { - HTMLFormControlElementWithState* control = (*it).get(); + for (FormElementListHashSet::const_iterator it = m_formControls.begin(); it != m_formControls.end(); ++it) { + HTMLFormControlElementWithState* control = it->get(); ASSERT(control->inDocument()); if (!control->shouldSaveAndRestoreFormControlState()) continue; SavedFormStateMap::AddResult result = stateMap->add(keyGenerator->formKey(*control), nullptr); if (result.isNewEntry) - result.iterator->value = SavedFormState::create(); - result.iterator->value->appendControlState(control->name(), control->type(), control->saveFormControlState()); + result.storedValue->value = SavedFormState::create(); + result.storedValue->value->appendControlState(control->name(), control->type(), control->saveFormControlState()); } - return stateMap.release(); -} -Vector<String> FormController::formElementsState() const -{ - OwnPtr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState); Vector<String> stateVector; - stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4); + stateVector.reserveInitialCapacity(m_formControls.size() * 4); stateVector.append(formStateSignature()); for (SavedFormStateMap::const_iterator it = stateMap->begin(); it != stateMap->end(); ++it) { stateVector.append(it->key); @@ -424,6 +438,29 @@ Vector<String> FormController::formElementsState() const return stateVector; } +// ---------------------------------------------------------------------------- + +FormController::FormController() + : m_documentState(DocumentState::create()) +{ +} + +FormController::~FormController() +{ +} + +void FormController::trace(Visitor* visitor) +{ + visitor->trace(m_radioButtonGroupScope); + visitor->trace(m_documentState); + visitor->trace(m_formKeyGenerator); +} + +DocumentState* FormController::formElementsState() const +{ + return m_documentState.get(); +} + void FormController::setStateForNewFormElements(const Vector<String>& stateVector) { formStatesFromStateVector(stateVector, m_savedFormStateMap); @@ -453,7 +490,7 @@ void FormController::formStatesFromStateVector(const Vector<String>& stateVector return; while (i + 1 < stateVector.size()) { - AtomicString formKey = stateVector[i++]; + AtomicString formKey = AtomicString(stateVector[i++]); OwnPtr<SavedFormState> state = SavedFormState::deserialize(stateVector, i); if (!state) { i = 0; @@ -487,7 +524,7 @@ void FormController::restoreControlStateFor(HTMLFormControlElementWithState& con void FormController::restoreControlStateIn(HTMLFormElement& form) { - const Vector<FormAssociatedElement*>& elements = form.associatedElements(); + const FormAssociatedElement::List& elements = form.associatedElements(); for (size_t i = 0; i < elements.size(); ++i) { if (!elements[i]->isFormControlElementWithState()) continue; @@ -508,20 +545,18 @@ Vector<String> FormController::getReferencedFilePaths(const Vector<String>& stat SavedFormStateMap map; formStatesFromStateVector(stateVector, map); for (SavedFormStateMap::const_iterator it = map.begin(); it != map.end(); ++it) - toReturn.append(it->value->getReferencedFilePaths()); + toReturn.appendVector(it->value->getReferencedFilePaths()); return toReturn; } -void FormController::registerFormElementWithState(HTMLFormControlElementWithState* control) +void FormController::registerStatefulFormControl(HTMLFormControlElementWithState& control) { - ASSERT(!m_formElementsWithState.contains(control)); - m_formElementsWithState.add(control); + m_documentState->addControl(&control); } -void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState* control) +void FormController::unregisterStatefulFormControl(HTMLFormControlElementWithState& control) { - RELEASE_ASSERT(m_formElementsWithState.contains(control)); - m_formElementsWithState.remove(control); + m_documentState->removeControl(&control); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/FormController.h b/chromium/third_party/WebKit/Source/core/html/forms/FormController.h index 40799358d55..0671fe8a2b5 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/FormController.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/FormController.h @@ -22,7 +22,8 @@ #ifndef FormController_h #define FormController_h -#include "core/html/forms/CheckedRadioButtons.h" +#include "core/html/forms/RadioButtonGroupScope.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/ListHashSet.h" #include "wtf/Vector.h" @@ -71,21 +72,39 @@ inline void FormControlState::append(const String& value) m_values.append(value); } -class FormController { - WTF_MAKE_FAST_ALLOCATED; +typedef HashMap<AtomicString, OwnPtr<SavedFormState> > SavedFormStateMap; + +class DocumentState FINAL : public RefCountedWillBeGarbageCollected<DocumentState> { + DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentState); +public: + static PassRefPtrWillBeRawPtr<DocumentState> create(); + void trace(Visitor*); + + void addControl(HTMLFormControlElementWithState*); + void removeControl(HTMLFormControlElementWithState*); + Vector<String> toStateVector(); + +private: + typedef WillBeHeapListHashSet<RefPtrWillBeMember<HTMLFormControlElementWithState>, 64> FormElementListHashSet; + FormElementListHashSet m_formControls; +}; + +class FormController FINAL : public NoBaseWillBeGarbageCollectedFinalized<FormController> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<FormController> create() + static PassOwnPtrWillBeRawPtr<FormController> create() { - return adoptPtr(new FormController); + return adoptPtrWillBeNoop(new FormController); } ~FormController(); + void trace(Visitor*); - CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; } + RadioButtonGroupScope& radioButtonGroupScope() { return m_radioButtonGroupScope; } - void registerFormElementWithState(HTMLFormControlElementWithState*); - void unregisterFormElementWithState(HTMLFormControlElementWithState*); + void registerStatefulFormControl(HTMLFormControlElementWithState&); + void unregisterStatefulFormControl(HTMLFormControlElementWithState&); // This should be callled only by Document::formElementsState(). - Vector<String> formElementsState() const; + DocumentState* formElementsState() const; // This should be callled only by Document::setStateForNewFormElements(). void setStateForNewFormElements(const Vector<String>&); void willDeleteForm(HTMLFormElement*); @@ -95,18 +114,14 @@ public: static Vector<String> getReferencedFilePaths(const Vector<String>& stateVector); private: - typedef ListHashSet<RefPtr<HTMLFormControlElementWithState>, 64> FormElementListHashSet; - typedef HashMap<AtomicString, OwnPtr<SavedFormState> > SavedFormStateMap; - FormController(); - static PassOwnPtr<SavedFormStateMap> createSavedFormStateMap(const FormElementListHashSet&); FormControlState takeStateForFormElement(const HTMLFormControlElementWithState&); static void formStatesFromStateVector(const Vector<String>&, SavedFormStateMap&); - CheckedRadioButtons m_checkedRadioButtons; - FormElementListHashSet m_formElementsWithState; + RadioButtonGroupScope m_radioButtonGroupScope; + RefPtrWillBeMember<DocumentState> m_documentState; SavedFormStateMap m_savedFormStateMap; - OwnPtr<FormKeyGenerator> m_formKeyGenerator; + OwnPtrWillBeMember<FormKeyGenerator> m_formKeyGenerator; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.cpp index 7609742da68..abfbb551ab6 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.cpp @@ -32,8 +32,8 @@ #include "config.h" #include "core/html/forms/HiddenInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/html/FormDataList.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/FormController.h" @@ -43,9 +43,9 @@ namespace WebCore { using namespace HTMLNames; -PassRefPtr<InputType> HiddenInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> HiddenInputType::create(HTMLInputElement& element) { - return adoptRef(new HiddenInputType(element)); + return adoptRefWillBeNoop(new HiddenInputType(element)); } const AtomicString& HiddenInputType::formControlType() const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.h index a93b5c34fa7..70eeeb84e74 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/HiddenInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class HiddenInputType : public InputType { +class HiddenInputType FINAL : public InputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: HiddenInputType(HTMLInputElement& element) : InputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.cpp index a8a8d5143ca..e10beef9621 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.cpp @@ -23,8 +23,8 @@ #include "config.h" #include "core/html/forms/ImageInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/events/MouseEvent.h" #include "core/fetch/ImageResource.h" #include "core/html/FormDataList.h" @@ -45,9 +45,9 @@ inline ImageInputType::ImageInputType(HTMLInputElement& element) { } -PassRefPtr<InputType> ImageInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> ImageInputType::create(HTMLInputElement& element) { - return adoptRef(new ImageInputType(element)); + return adoptRefWillBeNoop(new ImageInputType(element)); } const AtomicString& ImageInputType::formControlType() const @@ -107,7 +107,7 @@ static IntPoint extractClickLocation(Event* event) void ImageInputType::handleDOMActivateEvent(Event* event) { - RefPtr<HTMLInputElement> element(this->element()); + RefPtrWillBeRawPtr<HTMLInputElement> element(this->element()); if (element->isDisabledFormControl() || !element->form()) return; element->setActivatedSubmit(true); @@ -150,9 +150,6 @@ void ImageInputType::startResourceLoading() if (!renderer) return; - if (imageLoader->hasPendingBeforeLoadEvent()) - return; - RenderImageResource* imageResource = renderer->imageResource(); imageResource->setImageResource(imageLoader->image()); @@ -189,7 +186,7 @@ bool ImageInputType::shouldRespectHeightAndWidthAttributes() unsigned ImageInputType::height() const { - RefPtr<HTMLInputElement> element(this->element()); + RefPtrWillBeRawPtr<HTMLInputElement> element(this->element()); if (!element->renderer()) { // Check the attribute first for an explicit pixel value. @@ -213,7 +210,7 @@ unsigned ImageInputType::height() const unsigned ImageInputType::width() const { - RefPtr<HTMLInputElement> element(this->element()); + RefPtrWillBeRawPtr<HTMLInputElement> element(this->element()); if (!element->renderer()) { // Check the attribute first for an explicit pixel value. @@ -235,4 +232,14 @@ unsigned ImageInputType::width() const return box ? adjustForAbsoluteZoom(box->contentWidth(), box) : 0; } +bool ImageInputType::hasLegalLinkAttribute(const QualifiedName& name) const +{ + return name == srcAttr || BaseButtonInputType::hasLegalLinkAttribute(name); +} + +const QualifiedName& ImageInputType::subResourceAttributeName() const +{ + return srcAttr; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.h index d033e2a61c2..a81356d09f4 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/ImageInputType.h @@ -38,9 +38,9 @@ namespace WebCore { -class ImageInputType : public BaseButtonInputType { +class ImageInputType FINAL : public BaseButtonInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: ImageInputType(HTMLInputElement&); @@ -61,6 +61,8 @@ private: virtual bool shouldRespectHeightAndWidthAttributes() OVERRIDE; virtual unsigned height() const OVERRIDE; virtual unsigned width() const OVERRIDE; + virtual bool hasLegalLinkAttribute(const QualifiedName&) const OVERRIDE; + virtual const QualifiedName& subResourceAttributeName() const OVERRIDE; IntPoint m_clickLocation; // Valid only during HTMLFormElement::prepareForSubmission(). }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/InputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/InputType.cpp index c443f6d2025..f06d4056f52 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/InputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/InputType.cpp @@ -28,15 +28,18 @@ #include "config.h" #include "core/html/forms/InputType.h" -#include "InputTypeNames.h" -#include "RuntimeEnabledFeatures.h" +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "core/InputTypeNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/dom/NodeRenderStyle.h" #include "core/events/KeyboardEvent.h" #include "core/events/ScopedEventQueue.h" #include "core/fileapi/FileList.h" +#include "core/frame/FrameHost.h" #include "core/html/FormDataList.h" #include "core/html/HTMLInputElement.h" +#include "core/html/HTMLShadowElement.h" #include "core/html/forms/ButtonInputType.h" #include "core/html/forms/CheckboxInputType.h" #include "core/html/forms/ColorInputType.h" @@ -61,9 +64,9 @@ #include "core/html/forms/URLInputType.h" #include "core/html/forms/WeekInputType.h" #include "core/html/parser/HTMLParserIdioms.h" -#include "core/html/shadow/HTMLShadowElement.h" -#include "core/page/Page.h" #include "core/rendering/RenderTheme.h" +#include "platform/ColorChooser.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/text/PlatformLocale.h" #include "platform/text/TextBreakIterator.h" @@ -71,9 +74,8 @@ namespace WebCore { using blink::WebLocalizedString; using namespace HTMLNames; -using namespace std; -typedef PassRefPtr<InputType> (*InputTypeFactoryFunction)(HTMLInputElement&); +typedef PassRefPtrWillBeRawPtr<InputType> (*InputTypeFactoryFunction)(HTMLInputElement&); typedef HashMap<AtomicString, InputTypeFactoryFunction, CaseFoldingHash> InputTypeFactoryMap; static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap() @@ -81,8 +83,7 @@ static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap() OwnPtr<InputTypeFactoryMap> map = adoptPtr(new InputTypeFactoryMap); map->add(InputTypeNames::button, ButtonInputType::create); map->add(InputTypeNames::checkbox, CheckboxInputType::create); - if (RuntimeEnabledFeatures::inputTypeColorEnabled()) - map->add(InputTypeNames::color, ColorInputType::create); + map->add(InputTypeNames::color, ColorInputType::create); map->add(InputTypeNames::date, DateInputType::create); map->add(InputTypeNames::datetime_local, DateTimeLocalInputType::create); map->add(InputTypeNames::email, EmailInputType::create); @@ -100,8 +101,7 @@ static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap() map->add(InputTypeNames::tel, TelephoneInputType::create); map->add(InputTypeNames::time, TimeInputType::create); map->add(InputTypeNames::url, URLInputType::create); - if (RuntimeEnabledFeatures::inputTypeWeekEnabled()) - map->add(InputTypeNames::week, WeekInputType::create); + map->add(InputTypeNames::week, WeekInputType::create); // No need to register "text" because it is the default type. return map.release(); } @@ -112,7 +112,7 @@ static const InputTypeFactoryMap* factoryMap() return factoryMap; } -PassRefPtr<InputType> InputType::create(HTMLInputElement& element, const AtomicString& typeName) +PassRefPtrWillBeRawPtr<InputType> InputType::create(HTMLInputElement& element, const AtomicString& typeName) { InputTypeFactoryFunction factory = typeName.isEmpty() ? 0 : factoryMap()->get(typeName); if (!factory) @@ -120,7 +120,7 @@ PassRefPtr<InputType> InputType::create(HTMLInputElement& element, const AtomicS return factory(element); } -PassRefPtr<InputType> InputType::createText(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> InputType::createText(HTMLInputElement& element) { return TextInputType::create(element); } @@ -133,25 +133,10 @@ const AtomicString& InputType::normalizeTypeName(const AtomicString& typeName) return it == factoryMap()->end() ? InputTypeNames::text : it->key; } -bool InputType::canChangeFromAnotherType(const AtomicString& normalizedTypeName) -{ - // Don't allow the type to be changed to file after the first type change. - // In other engines this might mean a JavaScript programmer could set a text - // field's value to something like /etc/passwd and then change it to a file - // input. I don't think this would actually occur in Blink, but this rule - // still may be important for compatibility. - return normalizedTypeName != InputTypeNames::file; -} - InputType::~InputType() { } -bool InputType::themeSupportsDataListUI(InputType* type) -{ - return RenderTheme::theme().supportsDataListUI(type->formControlType()); -} - bool InputType::isTextField() const { return false; @@ -210,22 +195,22 @@ double InputType::valueAsDate() const void InputType::setValueAsDate(double, ExceptionState& exceptionState) const { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "This input element does not support Date values."); } double InputType::valueAsDouble() const { - return numeric_limits<double>::quiet_NaN(); + return std::numeric_limits<double>::quiet_NaN(); } void InputType::setValueAsDouble(double doubleValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const { - setValueAsDecimal(Decimal::fromDouble(doubleValue), eventBehavior, exceptionState); + exceptionState.throwDOMException(InvalidStateError, "This input element does not support Number values."); } -void InputType::setValueAsDecimal(const Decimal&, TextFieldEventBehavior, ExceptionState& exceptionState) const +void InputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState&) const { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + element().setValue(serialize(newValue), eventBehavior); } bool InputType::supportsValidation() const @@ -437,12 +422,6 @@ Decimal InputType::parseToNumberOrNaN(const String& string) const return parseToNumber(string, Decimal::nan()); } -bool InputType::parseToDateComponents(const String&, DateComponents*) const -{ - ASSERT_NOT_REACHED(); - return false; -} - String InputType::serialize(const Decimal&) const { ASSERT_NOT_REACHED(); @@ -458,8 +437,8 @@ void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const Chrome* InputType::chrome() const { - if (Page* page = element().document().page()) - return &page->chrome(); + if (FrameHost* host = element().document().frameHost()) + return &host->chrome(); return 0; } @@ -534,7 +513,7 @@ FileList* InputType::files() return 0; } -void InputType::setFiles(PassRefPtr<FileList>) +void InputType::setFiles(PassRefPtrWillBeRawPtr<FileList>) { } @@ -568,10 +547,15 @@ bool InputType::storesValueSeparateFromAttribute() return true; } +bool InputType::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue) +{ + return !equalIgnoringNullity(oldValue, newValue); +} + void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior) { element().setValueInternal(sanitizedValue, eventBehavior); - element().setNeedsStyleRecalc(); + element().setNeedsStyleRecalc(SubtreeStyleChange); if (!valueChanged) return; switch (eventBehavior) { @@ -619,11 +603,6 @@ String InputType::droppedFileSystemId() return String(); } -bool InputType::shouldResetOnDocumentActivation() -{ - return false; -} - bool InputType::shouldRespectListAttribute() { return false; @@ -689,11 +668,6 @@ bool InputType::isNumberField() const return false; } -bool InputType::isSubmitButton() const -{ - return false; -} - bool InputType::isTelephoneField() const { return false; @@ -764,10 +738,6 @@ bool InputType::supportsReadOnly() const return false; } -void InputType::updatePlaceholderText() -{ -} - String InputType::defaultToolTip() const { return String(); @@ -783,6 +753,16 @@ void InputType::handleDOMActivateEvent(Event*) { } +bool InputType::hasLegalLinkAttribute(const QualifiedName&) const +{ + return false; +} + +const QualifiedName& InputType::subResourceAttributeName() const +{ + return QualifiedName::null(); +} + bool InputType::supportsIndeterminateAppearance() const { return false; @@ -808,46 +788,64 @@ unsigned InputType::width() const return 0; } -void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) +void InputType::applyStep(const Decimal& current, int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) { StepRange stepRange(createStepRange(anyStepHandling)); if (!stepRange.hasStep()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "This form element does not have an allowed value step."); return; } - const Decimal current = parseToNumberOrNaN(element().value()); - if (!current.isFinite()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - Decimal newValue = current + stepRange.step() * count; - if (!newValue.isFinite()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - const Decimal acceptableErrorValue = stepRange.acceptableError(); - if (newValue - stepRange.minimum() < -acceptableErrorValue) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - if (newValue < stepRange.minimum()) - newValue = stepRange.minimum(); + EventQueueScope scope; + const Decimal step = stepRange.step(); const AtomicString& stepString = element().fastGetAttribute(stepAttr); - if (!equalIgnoringCase(stepString, "any")) - newValue = stepRange.alignValueForStep(current, newValue); + if (!equalIgnoringCase(stepString, "any") && stepRange.stepMismatch(current)) { + // Snap-to-step / clamping steps + // If the current value is not matched to step value: + // - The value should be the larger matched value nearest to 0 if count > 0 + // e.g. <input type=number value=3 min=-100 step=3> -> 5 + // - The value should be the smaller matched value nearest to 0 if count < 0 + // e.g. <input type=number value=3 min=-100 step=3> -> 2 + // + + ASSERT(!step.isZero()); + Decimal newValue; + const Decimal base = stepRange.stepBase(); + if (count < 0) + newValue = base + ((current - base) / step).floor() * step; + else if (count > 0) + newValue = base + ((current - base) / step).ceiling() * step; + else + newValue = current; + + if (newValue < stepRange.minimum()) + newValue = stepRange.minimum(); + if (newValue > stepRange.maximum()) + newValue = stepRange.maximum(); + + setValueAsDecimal(newValue, count == 1 || count == -1 ? DispatchChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION); + if (count > 1) { + applyStep(newValue, count - 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION); + return; + } + if (count < -1) { + applyStep(newValue, count + 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION); + return; + } + } else { + Decimal newValue = current + stepRange.step() * count; - if (newValue - stepRange.maximum() > acceptableErrorValue) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - if (newValue > stepRange.maximum()) - newValue = stepRange.maximum(); + if (!equalIgnoringCase(stepString, "any")) + newValue = stepRange.alignValueForStep(current, newValue); - setValueAsDecimal(newValue, eventBehavior, exceptionState); + if (newValue > stepRange.maximum()) + newValue = newValue - stepRange.step(); + else if (newValue < stepRange.minimum()) + newValue = newValue + stepRange.step(); + setValueAsDecimal(newValue, eventBehavior, exceptionState); + } if (AXObjectCache* cache = element().document().existingAXObjectCache()) cache->postNotification(&element(), AXObjectCache::AXValueChanged, true); } @@ -868,17 +866,18 @@ StepRange InputType::createStepRange(AnyStepHandling) const void InputType::stepUp(int n, ExceptionState& exceptionState) { if (!isSteppable()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "This form element is not steppable."); return; } - applyStep(n, RejectAny, DispatchNoEvent, exceptionState); + const Decimal current = parseToNumber(element().value(), 0); + applyStep(current, n, RejectAny, DispatchNoEvent, exceptionState); } void InputType::stepUpFromRenderer(int n) { - // The differences from stepUp()/stepDown(): + // The only difference from stepUp()/stepDown() is the extra treatment + // of the current value before applying the step: // - // Difference 1: the current value // If the current value is not a number, including empty, the current value is assumed as 0. // * If 0 is in-range, and matches to step value // - The value should be the +step if n > 0 @@ -902,13 +901,6 @@ void InputType::stepUpFromRenderer(int n) // - The value should be the maximum value if n < 0 // - Nothing should happen if n > 0 // - // Difference 2: clamping steps - // If the current value is not matched to step value: - // - The value should be the larger matched value nearest to 0 if n > 0 - // e.g. <input type=number value=3 min=-100 step=3> -> 5 - // - The value should be the smaler matched value nearest to 0 if n < 0 - // e.g. <input type=number value=3 min=-100 step=3> -> 2 - // // n is assumed as -n if step < 0. ASSERT(isSteppable()); @@ -936,8 +928,7 @@ void InputType::stepUpFromRenderer(int n) else sign = 0; - String currentStringValue = element().value(); - Decimal current = parseToNumberOrNaN(currentStringValue); + Decimal current = parseToNumberOrNaN(element().value()); if (!current.isFinite()) { current = defaultValueForStepUp(); const Decimal nextDiff = step * n; @@ -948,33 +939,10 @@ void InputType::stepUpFromRenderer(int n) setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); } if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) { - setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchInputAndChangeEvent, IGNORE_EXCEPTION); - } else { - if (stepMismatch(element().value())) { - ASSERT(!step.isZero()); - const Decimal base = stepRange.stepBase(); - Decimal newValue; - if (sign < 0) - newValue = base + ((current - base) / step).floor() * step; - else if (sign > 0) - newValue = base + ((current - base) / step).ceiling() * step; - else - newValue = current; - - if (newValue < stepRange.minimum()) - newValue = stepRange.minimum(); - if (newValue > stepRange.maximum()) - newValue = stepRange.maximum(); - - setValueAsDecimal(newValue, n == 1 || n == -1 ? DispatchInputAndChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION); - if (n > 1) - applyStep(n - 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION); - else if (n < -1) - applyStep(n + 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION); - } else { - applyStep(n, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION); - } + setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION); + return; } + applyStep(current, n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION); } void InputType::countUsageIfVisible(UseCounter::Feature feature) const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/InputType.h b/chromium/third_party/WebKit/Source/core/html/forms/InputType.h index 207abd8f305..fe0f4d33311 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/InputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/InputType.h @@ -55,17 +55,14 @@ class Node; // FIXME: InputType should not inherit InputTypeView. It's conceptually wrong. class InputType : public InputTypeView { WTF_MAKE_NONCOPYABLE(InputType); - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<InputType> create(HTMLInputElement&, const AtomicString&); - static PassRefPtr<InputType> createText(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&, const AtomicString&); + static PassRefPtrWillBeRawPtr<InputType> createText(HTMLInputElement&); static const AtomicString& normalizeTypeName(const AtomicString&); virtual ~InputType(); - static bool canChangeFromAnotherType(const AtomicString& normalizedTypeName); - static bool themeSupportsDataListUI(InputType*); - virtual const AtomicString& formControlType() const = 0; // Type query functions @@ -92,7 +89,6 @@ public: virtual bool isRadioButton() const; virtual bool isRangeControl() const; virtual bool isSearchField() const; - virtual bool isSubmitButton() const; virtual bool isTelephoneField() const; virtual bool isTextButton() const; virtual bool isTextField() const; @@ -172,7 +168,7 @@ public: virtual void sanitizeValueInResponseToMinOrMaxAttributeChange(); virtual bool shouldRespectAlignAttribute(); virtual FileList* files(); - virtual void setFiles(PassRefPtr<FileList>); + virtual void setFiles(PassRefPtrWillBeRawPtr<FileList>); // Should return true if the given DragData has more than one dropped files. virtual bool receiveDroppedFiles(const DragData*); virtual String droppedFileSystemId(); @@ -182,7 +178,6 @@ public: virtual bool canSetValue(const String&); virtual bool storesValueSeparateFromAttribute(); virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior); - virtual bool shouldResetOnDocumentActivation(); virtual bool shouldRespectListAttribute(); virtual bool shouldRespectSpeechAttribute(); virtual bool isEnumeratable(); @@ -191,10 +186,11 @@ public: virtual bool shouldRespectHeightAndWidthAttributes(); virtual bool supportsPlaceholder() const; virtual bool supportsReadOnly() const; - virtual void updatePlaceholderText(); virtual String defaultToolTip() const; virtual Decimal findClosestTickMarkValue(const Decimal&); virtual void handleDOMActivateEvent(Event*); + virtual bool hasLegalLinkAttribute(const QualifiedName&) const; + virtual const QualifiedName& subResourceAttributeName() const; // Parses the specified string for the type, and return // the Decimal value for the parsing result if the parsing @@ -202,12 +198,6 @@ public: // return NaN or Infinity only if defaultValue is NaN or Infinity. virtual Decimal parseToNumber(const String&, const Decimal& defaultValue) const; - // Parses the specified string for this InputType, and returns true if it - // is successfully parsed. An instance pointed by the DateComponents* - // parameter will have parsed values and be modified even if the parsing - // fails. The DateComponents* parameter may be 0. - virtual bool parseToDateComponents(const String&, DateComponents*) const; - // Create a string representation of the specified Decimal value for the // input type. If NaN or Infinity is specified, this returns an empty // string. This should not be called for types without valueAsNumber. @@ -230,6 +220,8 @@ public: virtual bool shouldSubmitImplicitly(Event*) OVERRIDE; virtual bool hasCustomFocusLogic() const OVERRIDE; + virtual bool shouldDispatchFormControlChangeEvent(String&, String&); + protected: InputType(HTMLInputElement& element) : InputTypeView(element) { } Chrome* chrome() const; @@ -244,7 +236,7 @@ protected: private: // Helper for stepUp()/stepDown(). Adds step value * count to the current value. - void applyStep(int count, AnyStepHandling, TextFieldEventBehavior, ExceptionState&); + void applyStep(const Decimal&, int count, AnyStepHandling, TextFieldEventBehavior, ExceptionState&); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp b/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp index d8c49395104..8e8aee3e27f 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp @@ -35,15 +35,20 @@ namespace WebCore { -PassRefPtr<InputTypeView> InputTypeView::create(HTMLInputElement& input) +PassRefPtrWillBeRawPtr<InputTypeView> InputTypeView::create(HTMLInputElement& input) { - return adoptRef(new InputTypeView(input)); + return adoptRefWillBeNoop(new InputTypeView(input)); } InputTypeView::~InputTypeView() { } +void InputTypeView::trace(Visitor* visitor) +{ + visitor->trace(m_element); +} + bool InputTypeView::sizeShouldIncludeDecoration(int, int& preferredSize) const { preferredSize = element().size(); @@ -87,7 +92,7 @@ bool InputTypeView::shouldSubmitImplicitly(Event* event) return false; } -PassRefPtr<HTMLFormElement> InputTypeView::formForSubmission() const +PassRefPtrWillBeRawPtr<HTMLFormElement> InputTypeView::formForSubmission() const { return element().form(); } @@ -112,7 +117,7 @@ bool InputTypeView::hasCustomFocusLogic() const return false; } -void InputTypeView::handleFocusEvent(Element*, FocusDirection) +void InputTypeView::handleFocusEvent(Element*, FocusType) { } @@ -154,7 +159,7 @@ void InputTypeView::stepAttributeChanged() { } -PassOwnPtr<ClickHandlingState> InputTypeView::willDispatchClick() +PassOwnPtrWillBeRawPtr<ClickHandlingState> InputTypeView::willDispatchClick() { return nullptr; } @@ -209,4 +214,13 @@ void InputTypeView::updateClearButtonVisibility() { } +void InputTypeView::updatePlaceholderText() +{ +} + +void ClickHandlingState::trace(Visitor* visitor) +{ + visitor->trace(checkedRadioButton); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.h b/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.h index 1e4aec4f20a..808fde90803 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/InputTypeView.h @@ -33,7 +33,8 @@ #ifndef InputTypeView_h #define InputTypeView_h -#include "core/page/FocusDirection.h" +#include "core/page/FocusType.h" +#include "platform/heap/Handle.h" #include "wtf/FastAllocBase.h" #include "wtf/Forward.h" #include "wtf/Noncopyable.h" @@ -53,30 +54,33 @@ class RenderObject; class RenderStyle; class TouchEvent; -struct ClickHandlingState { - WTF_MAKE_FAST_ALLOCATED; +struct ClickHandlingState FINAL : public NoBaseWillBeGarbageCollected<ClickHandlingState> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: + void trace(Visitor*); + bool checked; bool indeterminate; - RefPtr<HTMLInputElement> checkedRadioButton; + RefPtrWillBeMember<HTMLInputElement> checkedRadioButton; }; // An InputTypeView object represents the UI-specific part of an // HTMLInputElement. Do not expose instances of InputTypeView and classes // derived from it to classes other than HTMLInputElement. -class InputTypeView : public RefCounted<InputTypeView> { +class InputTypeView : public RefCountedWillBeGarbageCollectedFinalized<InputTypeView> { WTF_MAKE_NONCOPYABLE(InputTypeView); - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<InputTypeView> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputTypeView> create(HTMLInputElement&); virtual ~InputTypeView(); + virtual void trace(Visitor*); virtual bool sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const; virtual void handleClickEvent(MouseEvent*); virtual void handleMouseDownEvent(MouseEvent*); - virtual PassOwnPtr<ClickHandlingState> willDispatchClick(); + virtual PassOwnPtrWillBeRawPtr<ClickHandlingState> willDispatchClick(); virtual void didDispatchClick(Event*, const ClickHandlingState&); virtual void handleKeydownEvent(KeyboardEvent*); virtual void handleKeypressEvent(KeyboardEvent*); @@ -85,9 +89,9 @@ public: virtual void handleTouchEvent(TouchEvent*); virtual void forwardEvent(Event*); virtual bool shouldSubmitImplicitly(Event*); - virtual PassRefPtr<HTMLFormElement> formForSubmission() const; + virtual PassRefPtrWillBeRawPtr<HTMLFormElement> formForSubmission() const; virtual bool hasCustomFocusLogic() const; - virtual void handleFocusEvent(Element* oldFocusedElement, FocusDirection); + virtual void handleFocusEvent(Element* oldFocusedElement, FocusType); virtual void handleBlurEvent(); virtual void subtreeHasChanged(); virtual bool hasTouchEventHandler() const; @@ -111,15 +115,16 @@ public: virtual void valueAttributeChanged(); virtual void listAttributeTargetChanged(); virtual void updateClearButtonVisibility(); + virtual void updatePlaceholderText(); protected: - InputTypeView(HTMLInputElement& element) : m_element(element) { } - HTMLInputElement& element() const { return m_element; } + InputTypeView(HTMLInputElement& element) : m_element(&element) { } + HTMLInputElement& element() const { return *m_element; } private: // Not a RefPtr because the HTMLInputElement object owns this InputTypeView // object. - HTMLInputElement& m_element; + RawPtrWillBeMember<HTMLInputElement> m_element; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp index 647ac351770..27800a016ba 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "core/html/forms/MonthInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/DateTimeFieldsState.h" #include "platform/DateComponents.h" @@ -51,9 +51,9 @@ static const int monthDefaultStep = 1; static const int monthDefaultStepBase = 0; static const int monthStepScaleFactor = 1; -PassRefPtr<InputType> MonthInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> MonthInputType::create(HTMLInputElement& element) { - return adoptRef(new MonthInputType(element)); + return adoptRefWillBeNoop(new MonthInputType(element)); } void MonthInputType::countUsage() @@ -134,6 +134,11 @@ bool MonthInputType::isMonthField() const return true; } +bool MonthInputType::canSetSuggestedValue() +{ + return true; +} + #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) String MonthInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const { diff --git a/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.h index ee2bbf2bf24..34fd57227a7 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/MonthInputType.h @@ -42,9 +42,9 @@ typedef BaseMultipleFieldsDateAndTimeInputType BaseMonthInputType; typedef BaseChooserOnlyDateAndTimeInputType BaseMonthInputType; #endif -class MonthInputType : public BaseMonthInputType { +class MonthInputType FINAL : public BaseMonthInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: MonthInputType(HTMLInputElement& element) : BaseMonthInputType(element) { } @@ -58,12 +58,13 @@ private: virtual bool parseToDateComponentsInternal(const String&, DateComponents*) const OVERRIDE; virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; virtual bool isMonthField() const OVERRIDE; + virtual bool canSetSuggestedValue() OVERRIDE; #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) // BaseMultipleFieldsDateAndTimeInputType functions - virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE FINAL; - virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE FINAL; - virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const; + virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE; + virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE; + virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const OVERRIDE; #endif }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.cpp index e2d90015378..a1a3eed20a9 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.cpp @@ -32,9 +32,9 @@ #include "config.h" #include "core/html/forms/NumberInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" #include "bindings/v8/ExceptionState.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/dom/ExceptionCode.h" #include "core/events/KeyboardEvent.h" #include "core/html/HTMLInputElement.h" @@ -49,7 +49,6 @@ namespace WebCore { using blink::WebLocalizedString; using namespace HTMLNames; -using namespace std; static const int numberDefaultStep = 1; static const int numberDefaultStepBase = 0; @@ -94,9 +93,9 @@ static RealNumberRenderSize calculateRenderSize(const Decimal& value) return RealNumberRenderSize(sizeOfSign + sizeOfZero , numberOfZeroAfterDecimalPoint + sizeOfDigits); } -PassRefPtr<InputType> NumberInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> NumberInputType::create(HTMLInputElement& element) { - return adoptRef(new NumberInputType(element)); + return adoptRefWillBeNoop(new NumberInputType(element)); } void NumberInputType::countUsage() @@ -111,8 +110,8 @@ const AtomicString& NumberInputType::formControlType() const void NumberInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior) { - if (!valueChanged && sanitizedValue.isEmpty() && !element().innerTextValue().isEmpty()) - updateView(); + if (!valueChanged && sanitizedValue.isEmpty() && !element().innerEditorValue().isEmpty()) + element().updateView(); TextFieldInputType::setValue(sanitizedValue, valueChanged, eventBehavior); } @@ -123,23 +122,11 @@ double NumberInputType::valueAsDouble() const void NumberInputType::setValueAsDouble(double newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const { - // FIXME: We should use numeric_limits<double>::max for number input type. - const double floatMax = numeric_limits<float>::max(); - if (newValue < -floatMax || newValue > floatMax) { - exceptionState.throwDOMException(InvalidStateError, "The value provided (" + String::number(newValue) + ") is outside the range (" + String::number(-floatMax) + ", " + String::number(floatMax) + ")."); - return; - } element().setValue(serializeForNumberType(newValue), eventBehavior); } void NumberInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const { - // FIXME: We should use numeric_limits<double>::max for number input type. - const Decimal floatMax = Decimal::fromDouble(numeric_limits<float>::max()); - if (newValue < -floatMax || newValue > floatMax) { - exceptionState.throwDOMException(InvalidStateError, "The value provided (" + newValue.toString() + ") is outside the range (-" + floatMax.toString() + ", " + floatMax.toString() + ")."); - return; - } element().setValue(serializeForNumberType(newValue), eventBehavior); } @@ -157,10 +144,8 @@ bool NumberInputType::typeMismatch() const StepRange NumberInputType::createStepRange(AnyStepHandling anyStepHandling) const { DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (numberDefaultStep, numberDefaultStepBase, numberStepScaleFactor)); - - // FIXME: We should use numeric_limits<double>::max for number input type. - const Decimal floatMax = Decimal::fromDouble(numeric_limits<float>::max()); - return InputType::createStepRange(anyStepHandling, numberDefaultStepBase, -floatMax, floatMax, stepDescription); + const Decimal doubleMax = Decimal::fromDouble(std::numeric_limits<double>::max()); + return InputType::createStepRange(anyStepHandling, numberDefaultStepBase, -doubleMax, doubleMax, stepDescription); } bool NumberInputType::sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const @@ -252,7 +237,7 @@ String NumberInputType::sanitizeValue(const String& proposedValue) const bool NumberInputType::hasBadInput() const { - String standardValue = convertFromVisibleValue(element().innerTextValue()); + String standardValue = convertFromVisibleValue(element().innerEditorValue()); return !standardValue.isEmpty() && !std::isfinite(parseToDoubleForNumberType(standardValue)); } @@ -291,7 +276,7 @@ void NumberInputType::minOrMaxAttributeChanged() InputType::minOrMaxAttributeChanged(); if (element().renderer()) - element().renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + element().renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } void NumberInputType::stepAttributeChanged() @@ -299,7 +284,7 @@ void NumberInputType::stepAttributeChanged() InputType::stepAttributeChanged(); if (element().renderer()) - element().renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + element().renderer()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } bool NumberInputType::supportsSelectionAPI() const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.h index 35711e3f9f6..be04ad8b53f 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/NumberInputType.h @@ -37,9 +37,9 @@ namespace WebCore { class ExceptionState; -class NumberInputType : public TextFieldInputType { +class NumberInputType FINAL : public TextFieldInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: NumberInputType(HTMLInputElement& element) : TextFieldInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.cpp index 6da205be0cc..4c974f03c21 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.cpp @@ -32,24 +32,18 @@ #include "config.h" #include "core/html/forms/PasswordInputType.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "InputTypeNames.h" -#include "core/dom/shadow/ShadowRoot.h" +#include "core/InputTypeNames.h" +#include "core/dom/Document.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/FormController.h" -#include "core/page/Chrome.h" -#include "core/page/ChromeClient.h" -#include "core/page/Page.h" -#include "core/frame/Settings.h" #include "wtf/Assertions.h" -#include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" namespace WebCore { -PassRefPtr<InputType> PasswordInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> PasswordInputType::create(HTMLInputElement& element) { - return adoptRef(new PasswordInputType(element)); + return adoptRefWillBeNoop(new PasswordInputType(element)); } void PasswordInputType::countUsage() @@ -59,38 +53,6 @@ void PasswordInputType::countUsage() countUsageIfVisible(UseCounter::InputTypePasswordMaxLength); } -bool PasswordInputType::isPasswordGenerationEnabled() const -{ - if (isPasswordGenerationDecorationEnabled()) - return true; - if (Page* page = element().document().page()) - return page->chrome().client().isPasswordGenerationEnabled(); - return false; -} - -bool PasswordInputType::isPasswordGenerationDecorationEnabled() const -{ - if (Page* page = element().document().page()) - return page->settings().passwordGenerationDecorationEnabled(); - return false; -} - -bool PasswordInputType::needsContainer() const -{ - return BaseTextInputType::needsContainer() || isPasswordGenerationEnabled(); -} - -void PasswordInputType::createShadowSubtree() -{ - BaseTextInputType::createShadowSubtree(); - if (!isPasswordGenerationEnabled()) - return; - RefPtr<PasswordGeneratorButtonElement> generatorButton = PasswordGeneratorButtonElement::create(element().document()); - if (!isPasswordGenerationDecorationEnabled()) - generatorButton->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); - containerElement()->appendChild(generatorButton.release()); -} - const AtomicString& PasswordInputType::formControlType() const { return InputTypeNames::password; @@ -121,11 +83,6 @@ bool PasswordInputType::shouldUseInputMethod() const return false; } -bool PasswordInputType::shouldResetOnDocumentActivation() -{ - return true; -} - bool PasswordInputType::shouldRespectListAttribute() { return false; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.h index 50f36691e0d..441cd99a171 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/PasswordInputType.h @@ -32,34 +32,26 @@ #define PasswordInputType_h #include "core/html/forms/BaseTextInputType.h" -#include "core/html/shadow/PasswordGeneratorButtonElement.h" namespace WebCore { class PasswordInputType FINAL : public BaseTextInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: PasswordInputType(HTMLInputElement& element) : BaseTextInputType(element) { } - virtual bool needsContainer() const OVERRIDE; - virtual void createShadowSubtree() OVERRIDE; virtual void countUsage() OVERRIDE; virtual const AtomicString& formControlType() const OVERRIDE; virtual bool shouldSaveAndRestoreFormControlState() const OVERRIDE; virtual FormControlState saveFormControlState() const OVERRIDE; virtual void restoreFormControlState(const FormControlState&) OVERRIDE; virtual bool shouldUseInputMethod() const OVERRIDE; - virtual bool shouldResetOnDocumentActivation() OVERRIDE; virtual bool shouldRespectListAttribute() OVERRIDE; virtual bool shouldRespectSpeechAttribute() OVERRIDE; virtual bool isPasswordField() const OVERRIDE; virtual void enableSecureTextInput() OVERRIDE; virtual void disableSecureTextInput() OVERRIDE; - - bool isPasswordGenerationEnabled() const; - // For testing. - bool isPasswordGenerationDecorationEnabled() const; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/CheckedRadioButtons.cpp b/chromium/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp index 58850fb8e11..92909e3a87a 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/CheckedRadioButtons.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp @@ -19,17 +19,17 @@ */ #include "config.h" -#include "core/html/forms/CheckedRadioButtons.h" +#include "core/html/forms/RadioButtonGroupScope.h" #include "core/html/HTMLInputElement.h" #include "wtf/HashSet.h" namespace WebCore { -class RadioButtonGroup { - WTF_MAKE_FAST_ALLOCATED; +class RadioButtonGroup : public NoBaseWillBeGarbageCollected<RadioButtonGroup> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<RadioButtonGroup> create(); + static PassOwnPtrWillBeRawPtr<RadioButtonGroup> create(); bool isEmpty() const { return m_members.isEmpty(); } bool isRequired() const { return m_requiredCount; } HTMLInputElement* checkedButton() const { return m_checkedButton; } @@ -39,26 +39,28 @@ public: void remove(HTMLInputElement*); bool contains(HTMLInputElement*) const; + void trace(Visitor*); + private: RadioButtonGroup(); void setNeedsValidityCheckForAllButtons(); bool isValid() const; void setCheckedButton(HTMLInputElement*); - HashSet<HTMLInputElement*> m_members; - HTMLInputElement* m_checkedButton; + WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> > m_members; + RawPtrWillBeMember<HTMLInputElement> m_checkedButton; size_t m_requiredCount; }; RadioButtonGroup::RadioButtonGroup() - : m_checkedButton(0) + : m_checkedButton(nullptr) , m_requiredCount(0) { } -PassOwnPtr<RadioButtonGroup> RadioButtonGroup::create() +PassOwnPtrWillBeRawPtr<RadioButtonGroup> RadioButtonGroup::create() { - return adoptPtr(new RadioButtonGroup); + return adoptPtrWillBeNoop(new RadioButtonGroup); } inline bool RadioButtonGroup::isValid() const @@ -106,7 +108,7 @@ void RadioButtonGroup::updateCheckedState(HTMLInputElement* button) setCheckedButton(button); } else { if (m_checkedButton == button) - m_checkedButton = 0; + m_checkedButton = nullptr; } if (wasValid != isValid()) setNeedsValidityCheckForAllButtons(); @@ -130,7 +132,7 @@ void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button) void RadioButtonGroup::remove(HTMLInputElement* button) { ASSERT(button->isRadioButton()); - HashSet<HTMLInputElement*>::iterator it = m_members.find(button); + WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::iterator it = m_members.find(button); if (it == m_members.end()) return; bool wasValid = isValid(); @@ -140,7 +142,7 @@ void RadioButtonGroup::remove(HTMLInputElement* button) --m_requiredCount; } if (m_checkedButton == button) - m_checkedButton = 0; + m_checkedButton = nullptr; if (m_members.isEmpty()) { ASSERT(!m_requiredCount); @@ -157,7 +159,7 @@ void RadioButtonGroup::remove(HTMLInputElement* button) void RadioButtonGroup::setNeedsValidityCheckForAllButtons() { - typedef HashSet<HTMLInputElement*>::const_iterator Iterator; + typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iterator Iterator; Iterator end = m_members.end(); for (Iterator it = m_members.begin(); it != end; ++it) { HTMLInputElement* button = *it; @@ -171,35 +173,41 @@ bool RadioButtonGroup::contains(HTMLInputElement* button) const return m_members.contains(button); } +void RadioButtonGroup::trace(Visitor* visitor) +{ + visitor->trace(m_members); + visitor->trace(m_checkedButton); +} + // ---------------------------------------------------------------- // Explicity define empty constructor and destructor in order to prevent the // compiler from generating them as inlines. So we don't need to to define // RadioButtonGroup in the header. -CheckedRadioButtons::CheckedRadioButtons() +RadioButtonGroupScope::RadioButtonGroupScope() { } -CheckedRadioButtons::~CheckedRadioButtons() +RadioButtonGroupScope::~RadioButtonGroupScope() { } -void CheckedRadioButtons::addButton(HTMLInputElement* element) +void RadioButtonGroupScope::addButton(HTMLInputElement* element) { ASSERT(element->isRadioButton()); if (element->name().isEmpty()) return; if (!m_nameToGroupMap) - m_nameToGroupMap = adoptPtr(new NameToGroupMap); + m_nameToGroupMap = adoptPtrWillBeNoop(new NameToGroupMap); - OwnPtr<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name().impl(), PassOwnPtr<RadioButtonGroup>()).iterator->value; + OwnPtrWillBeMember<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name(), nullptr).storedValue->value; if (!group) group = RadioButtonGroup::create(); group->add(element); } -void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element) +void RadioButtonGroupScope::updateCheckedState(HTMLInputElement* element) { ASSERT(element->isRadioButton()); if (element->name().isEmpty()) @@ -207,12 +215,12 @@ void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element) ASSERT(m_nameToGroupMap); if (!m_nameToGroupMap) return; - RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl()); + RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); ASSERT(group); group->updateCheckedState(element); } -void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element) +void RadioButtonGroupScope::requiredAttributeChanged(HTMLInputElement* element) { ASSERT(element->isRadioButton()); if (element->name().isEmpty()) @@ -220,31 +228,31 @@ void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element) ASSERT(m_nameToGroupMap); if (!m_nameToGroupMap) return; - RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl()); + RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); ASSERT(group); group->requiredAttributeChanged(element); } -HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const +HTMLInputElement* RadioButtonGroupScope::checkedButtonForGroup(const AtomicString& name) const { if (!m_nameToGroupMap) return 0; - RadioButtonGroup* group = m_nameToGroupMap->get(name.impl()); + RadioButtonGroup* group = m_nameToGroupMap->get(name); return group ? group->checkedButton() : 0; } -bool CheckedRadioButtons::isInRequiredGroup(HTMLInputElement* element) const +bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const { ASSERT(element->isRadioButton()); if (element->name().isEmpty()) return false; if (!m_nameToGroupMap) return false; - RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl()); + RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); return group && group->isRequired() && group->contains(element); } -void CheckedRadioButtons::removeButton(HTMLInputElement* element) +void RadioButtonGroupScope::removeButton(HTMLInputElement* element) { ASSERT(element->isRadioButton()); if (element->name().isEmpty()) @@ -252,18 +260,23 @@ void CheckedRadioButtons::removeButton(HTMLInputElement* element) if (!m_nameToGroupMap) return; - NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl()); - if (it == m_nameToGroupMap->end()) + RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); + if (!group) return; - it->value->remove(element); - if (it->value->isEmpty()) { - // FIXME: We may skip deallocating the empty RadioButtonGroup for - // performance improvement. If we do so, we need to change the key type - // of m_nameToGroupMap from StringImpl* to AtomicString. - m_nameToGroupMap->remove(it); - if (m_nameToGroupMap->isEmpty()) - m_nameToGroupMap.clear(); + group->remove(element); + if (group->isEmpty()) { + // We don't remove an empty RadioButtonGroup from m_nameToGroupMap for + // better performance. + ASSERT(!group->isRequired()); + ASSERT_WITH_SECURITY_IMPLICATION(!group->checkedButton()); } } +void RadioButtonGroupScope::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_nameToGroupMap); +#endif +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/forms/CheckedRadioButtons.h b/chromium/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.h index 6a1585bd5aa..41f9bbc7696 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/CheckedRadioButtons.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.h @@ -18,9 +18,10 @@ * */ -#ifndef CheckedRadioButtons_h -#define CheckedRadioButtons_h +#ifndef RadioButtonGroupScope_h +#define RadioButtonGroupScope_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" #include "wtf/OwnPtr.h" @@ -31,12 +32,12 @@ namespace WebCore { class HTMLInputElement; class RadioButtonGroup; -// FIXME: Rename the class. The class was a simple map from a name to a checked -// radio button. It manages RadioButtonGroup objects now. -class CheckedRadioButtons { +class RadioButtonGroupScope { + DISALLOW_ALLOCATION(); public: - CheckedRadioButtons(); - ~CheckedRadioButtons(); + RadioButtonGroupScope(); + ~RadioButtonGroupScope(); + void trace(Visitor*); void addButton(HTMLInputElement*); void updateCheckedState(HTMLInputElement*); void requiredAttributeChanged(HTMLInputElement*); @@ -45,10 +46,10 @@ public: bool isInRequiredGroup(HTMLInputElement*) const; private: - typedef HashMap<StringImpl*, OwnPtr<RadioButtonGroup> > NameToGroupMap; - OwnPtr<NameToGroupMap> m_nameToGroupMap; + typedef WillBeHeapHashMap<AtomicString, OwnPtrWillBeMember<RadioButtonGroup>, CaseFoldingHash> NameToGroupMap; + OwnPtrWillBeMember<NameToGroupMap> m_nameToGroupMap; }; } // namespace WebCore -#endif // CheckedRadioButtons_h +#endif // RadioButtonGroupScope_h diff --git a/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp index fc6da4939fa..9a495ce2446 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.cpp @@ -22,9 +22,10 @@ #include "config.h" #include "core/html/forms/RadioInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" -#include "core/dom/NodeTraversal.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" +#include "core/dom/Document.h" +#include "core/dom/ElementTraversal.h" #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" #include "core/html/HTMLInputElement.h" @@ -36,9 +37,9 @@ namespace WebCore { using namespace HTMLNames; -PassRefPtr<InputType> RadioInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> RadioInputType::create(HTMLInputElement& element) { - return adoptRef(new RadioInputType(element)); + return adoptRefWillBeNoop(new RadioInputType(element)); } const AtomicString& RadioInputType::formControlType() const @@ -83,19 +84,19 @@ void RadioInputType::handleKeydownEvent(KeyboardEvent* event) // We can only stay within the form's children if the form hasn't been demoted to a leaf because // of malformed HTML. - Node* node = &element(); - while ((node = (forward ? NodeTraversal::next(*node) : NodeTraversal::previous(*node)))) { + HTMLElement* htmlElement = &element(); + while ((htmlElement = (forward ? Traversal<HTMLElement>::next(*htmlElement) : Traversal<HTMLElement>::previous(*htmlElement)))) { // Once we encounter a form element, we know we're through. - if (node->hasTagName(formTag)) + if (isHTMLFormElement(*htmlElement)) break; // Look for more radio buttons. - if (!node->hasTagName(inputTag)) + if (!isHTMLInputElement(*htmlElement)) continue; - HTMLInputElement* inputElement = toHTMLInputElement(node); + HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); if (inputElement->form() != element().form()) break; if (inputElement->isRadioButton() && inputElement->name() == element().name() && inputElement->isFocusable()) { - RefPtr<HTMLInputElement> protector(inputElement); + RefPtrWillBeRawPtr<HTMLInputElement> protector(inputElement); document.setFocusedElement(inputElement); inputElement->dispatchSimulatedClick(event, SendNoEvents); event->setDefaultHandled(); @@ -128,9 +129,9 @@ bool RadioInputType::isKeyboardFocusable() const // Never allow keyboard tabbing to leave you in the same radio group. Always // skip any other elements in the group. Element* currentFocusedElement = element().document().focusedElement(); - if (currentFocusedElement && currentFocusedElement->hasTagName(inputTag)) { - HTMLInputElement* focusedInput = toHTMLInputElement(currentFocusedElement); - if (focusedInput->isRadioButton() && focusedInput->form() == element().form() && focusedInput->name() == element().name()) + if (isHTMLInputElement(currentFocusedElement)) { + HTMLInputElement& focusedInput = toHTMLInputElement(*currentFocusedElement); + if (focusedInput.isRadioButton() && focusedInput.form() == element().form() && focusedInput.name() == element().name()) return false; } @@ -145,7 +146,7 @@ bool RadioInputType::shouldSendChangeEventAfterCheckedChanged() return element().checked(); } -PassOwnPtr<ClickHandlingState> RadioInputType::willDispatchClick() +PassOwnPtrWillBeRawPtr<ClickHandlingState> RadioInputType::willDispatchClick() { // An event handler can use preventDefault or "return false" to reverse the selection we do here. // The ClickHandlingState object contains what we need to undo what we did here in didDispatchClick. @@ -154,7 +155,7 @@ PassOwnPtr<ClickHandlingState> RadioInputType::willDispatchClick() // Therefore if nothing is currently selected, we won't allow the upcoming action to be "undone", since // we want some object in the radio group to actually get selected. - OwnPtr<ClickHandlingState> state = adoptPtr(new ClickHandlingState); + OwnPtrWillBeRawPtr<ClickHandlingState> state = adoptPtrWillBeNoop(new ClickHandlingState); state->checked = element().checked(); state->checkedRadioButton = element().checkedRadioButtonForGroup(); diff --git a/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.h index 09788e2033a..2f965eeef20 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/RadioInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class RadioInputType : public BaseCheckableInputType { +class RadioInputType FINAL : public BaseCheckableInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: RadioInputType(HTMLInputElement& element) : BaseCheckableInputType(element) { } @@ -49,7 +49,7 @@ private: virtual void handleKeyupEvent(KeyboardEvent*) OVERRIDE; virtual bool isKeyboardFocusable() const OVERRIDE; virtual bool shouldSendChangeEventAfterCheckedChanged() OVERRIDE; - virtual PassOwnPtr<ClickHandlingState> willDispatchClick() OVERRIDE; + virtual PassOwnPtrWillBeRawPtr<ClickHandlingState> willDispatchClick() OVERRIDE; virtual void didDispatchClick(Event*, const ClickHandlingState&) OVERRIDE; virtual bool isRadioButton() const OVERRIDE; virtual bool supportsIndeterminateAppearance() const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp index 561a6504777..a6c0d34b3b9 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp @@ -32,9 +32,9 @@ #include "config.h" #include "core/html/forms/RangeInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/events/KeyboardEvent.h" #include "core/events/MouseEvent.h" @@ -61,7 +61,6 @@ namespace WebCore { using namespace HTMLNames; -using namespace std; static const int rangeDefaultMinimum = 0; static const int rangeDefaultMaximum = 100; @@ -74,9 +73,9 @@ static Decimal ensureMaximum(const Decimal& proposedValue, const Decimal& minimu return proposedValue >= minimum ? proposedValue : std::max(minimum, fallbackValue); } -PassRefPtr<InputType> RangeInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> RangeInputType::create(HTMLInputElement& element) { - return adoptRef(new RangeInputType(element)); + return adoptRefWillBeNoop(new RangeInputType(element)); } RangeInputType::RangeInputType(HTMLInputElement& element) @@ -105,9 +104,9 @@ double RangeInputType::valueAsDouble() const return parseToDoubleForNumberType(element().value()); } -void RangeInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState&) const +void RangeInputType::setValueAsDouble(double newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const { - element().setValue(serialize(newValue), eventBehavior); + setValueAsDecimal(Decimal::fromDouble(newValue), eventBehavior, exceptionState); } bool RangeInputType::typeMismatchFor(const String& value) const @@ -124,17 +123,12 @@ StepRange RangeInputType::createStepRange(AnyStepHandling anyStepHandling) const { DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (rangeDefaultStep, rangeDefaultStepBase, rangeStepScaleFactor)); + const Decimal stepBase = findStepBase(rangeDefaultStepBase); const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), rangeDefaultMinimum); const Decimal maximum = ensureMaximum(parseToNumber(element().fastGetAttribute(maxAttr), rangeDefaultMaximum), minimum, rangeDefaultMaximum); - const AtomicString& precisionValue = element().fastGetAttribute(precisionAttr); - if (!precisionValue.isNull()) { - const Decimal step = equalIgnoringCase(precisionValue, "float") ? Decimal::nan() : 1; - return StepRange(minimum, minimum, maximum, step, stepDescription); - } - const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr)); - return StepRange(minimum, minimum, maximum, step, stepDescription); + return StepRange(stepBase, minimum, maximum, step, stepDescription); } bool RangeInputType::isSteppable() const @@ -165,6 +159,7 @@ void RangeInputType::handleTouchEvent(TouchEvent* event) return; if (event->type() == EventTypeNames::touchend) { + element().dispatchFormControlChangeEvent(); event->setDefaultHandled(); return; } @@ -197,12 +192,12 @@ void RangeInputType::handleKeydownEvent(KeyboardEvent* event) // FIXME: We can't use stepUp() for the step value "any". So, we increase // or decrease the value by 1/100 of the value range. Is it reasonable? const Decimal step = equalIgnoringCase(element().fastGetAttribute(stepAttr), "any") ? (stepRange.maximum() - stepRange.minimum()) / 100 : stepRange.step(); - const Decimal bigStep = max((stepRange.maximum() - stepRange.minimum()) / 10, step); + const Decimal bigStep = std::max((stepRange.maximum() - stepRange.minimum()) / 10, step); bool isVertical = false; if (element().renderer()) { ControlPart part = element().renderer()->style()->appearance(); - isVertical = part == SliderVerticalPart || part == MediaVolumeSliderPart; + isVertical = part == SliderVerticalPart; } Decimal newValue; @@ -229,12 +224,11 @@ void RangeInputType::handleKeydownEvent(KeyboardEvent* event) if (newValue != current) { EventQueueScope scope; - TextFieldEventBehavior eventBehavior = DispatchChangeEvent; + TextFieldEventBehavior eventBehavior = DispatchInputAndChangeEvent; setValueAsDecimal(newValue, eventBehavior, IGNORE_EXCEPTION); if (AXObjectCache* cache = element().document().existingAXObjectCache()) cache->postNotification(&element(), AXObjectCache::AXValueChanged, true); - element().dispatchFormControlChangeEvent(); } event->setDefaultHandled(); @@ -245,11 +239,11 @@ void RangeInputType::createShadowSubtree() ASSERT(element().shadow()); Document& document = element().document(); - RefPtr<HTMLDivElement> track = HTMLDivElement::create(document); - track->setPseudo(AtomicString("-webkit-slider-runnable-track", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<HTMLDivElement> track = HTMLDivElement::create(document); + track->setShadowPseudoId(AtomicString("-webkit-slider-runnable-track", AtomicString::ConstructFromLiteral)); track->setAttribute(idAttr, ShadowElementNames::sliderTrack()); track->appendChild(SliderThumbElement::create(document)); - RefPtr<HTMLElement> container = SliderContainerElement::create(document); + RefPtrWillBeRawPtr<HTMLElement> container = SliderContainerElement::create(document); container->appendChild(track.release()); element().userAgentShadowRoot()->appendChild(container.release()); } @@ -317,7 +311,7 @@ void RangeInputType::disabledAttributeChanged() bool RangeInputType::shouldRespectListAttribute() { - return InputType::themeSupportsDataListUI(this); + return true; } inline SliderThumbElement* RangeInputType::sliderThumbElement() const @@ -335,7 +329,7 @@ void RangeInputType::listAttributeTargetChanged() m_tickMarkValuesDirty = true; Element* sliderTrackElement = this->sliderTrackElement(); if (sliderTrackElement->renderer()) - sliderTrackElement->renderer()->setNeedsLayout(); + sliderTrackElement->renderer()->setNeedsLayoutAndFullPaintInvalidation(); } static bool decimalCompare(const Decimal& a, const Decimal& b) @@ -352,13 +346,13 @@ void RangeInputType::updateTickMarkValues() HTMLDataListElement* dataList = element().dataList(); if (!dataList) return; - RefPtr<HTMLCollection> options = dataList->options(); + RefPtrWillBeRawPtr<HTMLCollection> options = dataList->options(); m_tickMarkValues.reserveCapacity(options->length()); for (unsigned i = 0; i < options->length(); ++i) { - Node* node = options->item(i); - HTMLOptionElement* optionElement = toHTMLOptionElement(node); + Element* element = options->item(i); + HTMLOptionElement* optionElement = toHTMLOptionElement(element); String optionValue = optionElement->value(); - if (!element().isValidValue(optionValue)) + if (!this->element().isValidValue(optionValue)) continue; m_tickMarkValues.append(parseToNumber(optionValue, Decimal::nan())); } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.h index cb10f784e3e..2cd9f71892a 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/RangeInputType.h @@ -38,9 +38,9 @@ namespace WebCore { class ExceptionState; class SliderThumbElement; -class RangeInputType : public InputType { +class RangeInputType FINAL : public InputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: RangeInputType(HTMLInputElement&); @@ -48,7 +48,7 @@ private: virtual bool isRangeControl() const OVERRIDE; virtual const AtomicString& formControlType() const OVERRIDE; virtual double valueAsDouble() const OVERRIDE; - virtual void setValueAsDecimal(const Decimal&, TextFieldEventBehavior, ExceptionState&) const OVERRIDE; + virtual void setValueAsDouble(double, TextFieldEventBehavior, ExceptionState&) const OVERRIDE; virtual bool typeMismatchFor(const String&) const OVERRIDE; virtual bool supportsRequired() const OVERRIDE; virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.cpp index 6175a6c95e9..bb9de0774fc 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.cpp @@ -32,7 +32,7 @@ #include "config.h" #include "core/html/forms/ResetInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "core/events/Event.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLInputElement.h" @@ -41,9 +41,9 @@ namespace WebCore { -PassRefPtr<InputType> ResetInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> ResetInputType::create(HTMLInputElement& element) { - return adoptRef(new ResetInputType(element)); + return adoptRefWillBeNoop(new ResetInputType(element)); } const AtomicString& ResetInputType::formControlType() const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.h index 8837400b86e..e30b91cd6fc 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/ResetInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class ResetInputType : public BaseButtonInputType { +class ResetInputType FINAL : public BaseButtonInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: ResetInputType(HTMLInputElement& element) : BaseButtonInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp index ba6e85aab40..a5563cee2d5 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "core/html/forms/SearchInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/events/KeyboardEvent.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLInputElement.h" @@ -52,9 +52,9 @@ inline SearchInputType::SearchInputType(HTMLInputElement& element) { } -PassRefPtr<InputType> SearchInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> SearchInputType::create(HTMLInputElement& element) { - return adoptRef(new SearchInputType(element)); + return adoptRefWillBeNoop(new SearchInputType(element)); } void SearchInputType::countUsage() @@ -108,7 +108,7 @@ void SearchInputType::handleKeydownEvent(KeyboardEvent* event) const String& key = event->keyIdentifier(); if (key == "U+001B") { - RefPtr<HTMLInputElement> input(element()); + RefPtrWillBeRawPtr<HTMLInputElement> input(element()); input->setValueForUser(""); input->onSearch(); event->setDefaultHandled(); @@ -120,7 +120,7 @@ void SearchInputType::handleKeydownEvent(KeyboardEvent* event) void SearchInputType::startSearchEventTimer() { ASSERT(element().renderer()); - unsigned length = element().innerTextValue().length(); + unsigned length = element().innerEditorValue().length(); if (!length) { stopSearchEventTimer(); @@ -130,7 +130,7 @@ void SearchInputType::startSearchEventTimer() // After typing the first key, we wait 0.5 seconds. // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on. - m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length)); + m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length), FROM_HERE); } void SearchInputType::stopSearchEventTimer() diff --git a/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.h index d13c0f94c42..6687f6d6901 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/SearchInputType.h @@ -39,9 +39,9 @@ namespace WebCore { class SearchFieldCancelButtonElement; class SearchFieldDecorationElement; -class SearchInputType : public BaseTextInputType { +class SearchInputType FINAL : public BaseTextInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); void stopSearchEventTimer(); diff --git a/chromium/third_party/WebKit/Source/core/html/forms/StepRange.cpp b/chromium/third_party/WebKit/Source/core/html/forms/StepRange.cpp index 0e10a5f162f..32761459cd1 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/StepRange.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/StepRange.cpp @@ -21,14 +21,12 @@ #include "config.h" #include "core/html/forms/StepRange.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/parser/HTMLParserIdioms.h" #include "wtf/MathExtras.h" #include "wtf/text/WTFString.h" #include <float.h> -using namespace std; - namespace WebCore { using namespace HTMLNames; @@ -84,12 +82,12 @@ Decimal StepRange::alignValueForStep(const Decimal& currentValue, const Decimal& Decimal StepRange::clampValue(const Decimal& value) const { - const Decimal inRangeValue = max(m_minimum, min(value, m_maximum)); + const Decimal inRangeValue = std::max(m_minimum, std::min(value, m_maximum)); if (!m_hasStep) return inRangeValue; - // Rounds inRangeValue to minimum + N * step. - const Decimal roundedValue = roundByStep(inRangeValue, m_minimum); - const Decimal clampedValue = roundedValue > m_maximum ? roundedValue - m_step : roundedValue; + // Rounds inRangeValue to stepBase + N * step. + const Decimal roundedValue = roundByStep(inRangeValue, m_stepBase); + const Decimal clampedValue = roundedValue > m_maximum ? roundedValue - m_step : (roundedValue < m_minimum ? roundedValue + m_step : roundedValue); ASSERT(clampedValue >= m_minimum); ASSERT(clampedValue <= m_maximum); return clampedValue; @@ -121,13 +119,13 @@ Decimal StepRange::parseStep(AnyStepHandling anyStepHandling, const StepDescript break; case ParsedStepValueShouldBeInteger: // For date, month, and week, the parsed value should be an integer for some types. - step = max(step.round(), Decimal(1)); + step = std::max(step.round(), Decimal(1)); step *= stepDescription.stepScaleFactor; break; case ScaledStepValueShouldBeInteger: // For datetime, datetime-local, time, the result should be an integer. step *= stepDescription.stepScaleFactor; - step = max(step.round(), Decimal(1)); + step = std::max(step.round(), Decimal(1)); break; default: ASSERT_NOT_REACHED(); @@ -161,7 +159,7 @@ bool StepRange::stepMismatch(const Decimal& valueForCheck) const // ... that number subtracted from the step base is not an integral multiple // of the allowed value step, the element is suffering from a step mismatch. const Decimal remainder = (value - m_step * (value / m_step).round()).abs(); - // Accepts erros in lower fractional part which IEEE 754 single-precision + // Accepts errors in lower fractional part which IEEE 754 single-precision // can't represent. const Decimal computedAcceptableError = acceptableError(); return computedAcceptableError < remainder && remainder < (m_step - computedAcceptableError); diff --git a/chromium/third_party/WebKit/Source/core/html/forms/StepRange.h b/chromium/third_party/WebKit/Source/core/html/forms/StepRange.h index a31e264c281..f2fdbb2dfde 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/StepRange.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/StepRange.h @@ -71,7 +71,6 @@ public: StepRange(); StepRange(const StepRange&); StepRange(const Decimal& stepBase, const Decimal& minimum, const Decimal& maximum, const Decimal& step, const StepDescription&); - Decimal acceptableError() const; Decimal alignValueForStep(const Decimal& currentValue, const Decimal& newValue) const; Decimal clampValue(const Decimal& value) const; bool hasStep() const { return m_hasStep; } @@ -80,7 +79,6 @@ public: static Decimal parseStep(AnyStepHandling, const StepDescription&, const String&); Decimal step() const { return m_step; } Decimal stepBase() const { return m_stepBase; } - int stepScaleFactor() const { return m_stepDescription.stepScaleFactor; } bool stepMismatch(const Decimal&) const; // Clamp the middle value according to the step @@ -106,6 +104,7 @@ public: private: StepRange& operator =(const StepRange&); + Decimal acceptableError() const; Decimal roundByStep(const Decimal& value, const Decimal& base) const; const Decimal m_maximum; // maximum must be >= minimum. diff --git a/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.cpp index 3b25b468ec1..8ef131314a5 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.cpp @@ -32,7 +32,7 @@ #include "config.h" #include "core/html/forms/SubmitInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "core/events/Event.h" #include "core/html/FormDataList.h" #include "core/html/HTMLFormElement.h" @@ -42,9 +42,9 @@ namespace WebCore { -PassRefPtr<InputType> SubmitInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> SubmitInputType::create(HTMLInputElement& element) { - return adoptRef(new SubmitInputType(element)); + return adoptRefWillBeNoop(new SubmitInputType(element)); } const AtomicString& SubmitInputType::formControlType() const @@ -67,7 +67,7 @@ bool SubmitInputType::supportsRequired() const void SubmitInputType::handleDOMActivateEvent(Event* event) { - RefPtr<HTMLInputElement> element(this->element()); + RefPtrWillBeRawPtr<HTMLInputElement> element(this->element()); if (element->isDisabledFormControl() || !element->form()) return; element->setActivatedSubmit(true); @@ -86,11 +86,6 @@ String SubmitInputType::defaultValue() const return locale().queryString(blink::WebLocalizedString::SubmitButtonDefaultLabel); } -bool SubmitInputType::isSubmitButton() const -{ - return true; -} - bool SubmitInputType::isTextButton() const { return true; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.h index ea88704fe9e..169117c2155 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/SubmitInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class SubmitInputType : public BaseButtonInputType { +class SubmitInputType FINAL : public BaseButtonInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: SubmitInputType(HTMLInputElement& element) : BaseButtonInputType(element) { } @@ -47,7 +47,6 @@ private: virtual void handleDOMActivateEvent(Event*) OVERRIDE; virtual bool canBeSuccessfulSubmitButton() OVERRIDE; virtual String defaultValue() const OVERRIDE; - virtual bool isSubmitButton() const OVERRIDE; virtual bool isTextButton() const OVERRIDE; }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.cpp index 4b5e2edbd48..4d11d9e896a 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.cpp @@ -31,14 +31,14 @@ #include "config.h" #include "core/html/forms/TelephoneInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "wtf/PassOwnPtr.h" namespace WebCore { -PassRefPtr<InputType> TelephoneInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> TelephoneInputType::create(HTMLInputElement& element) { - return adoptRef(new TelephoneInputType(element)); + return adoptRefWillBeNoop(new TelephoneInputType(element)); } void TelephoneInputType::countUsage() diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.h index d636ee2bff6..dca6c4fc39a 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/TelephoneInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class TelephoneInputType : public BaseTextInputType { +class TelephoneInputType FINAL : public BaseTextInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: TelephoneInputType(HTMLInputElement& element) : BaseTextInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp index 0114adab3e8..2b61994d4a8 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp @@ -32,24 +32,23 @@ #include "config.h" #include "core/html/forms/TextFieldInputType.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" -#include "core/events/BeforeTextInsertedEvent.h" -#include "core/events/KeyboardEvent.h" +#include "core/HTMLNames.h" #include "core/dom/NodeRenderStyle.h" -#include "core/events/TextEvent.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/editing/FrameSelection.h" #include "core/editing/TextIterator.h" +#include "core/events/BeforeTextInsertedEvent.h" +#include "core/events/KeyboardEvent.h" +#include "core/events/TextEvent.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/html/FormDataList.h" #include "core/html/HTMLInputElement.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/html/shadow/TextControlInnerElements.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/page/Chrome.h" #include "core/page/ChromeClient.h" -#include "core/page/Page.h" #include "core/rendering/RenderDetailsMarker.h" #include "core/rendering/RenderLayer.h" #include "core/rendering/RenderTextControlSingleLine.h" @@ -83,25 +82,26 @@ private: virtual void defaultEventHandler(Event* event) OVERRIDE { + ASSERT(document().isActive()); if (event->type() != EventTypeNames::click) return; HTMLInputElement* host = hostInput(); - if (host && !host->isDisabledOrReadOnly() && document().page()) { - document().page()->chrome().openTextDataListChooser(*host); + if (host && !host->isDisabledOrReadOnly()) { + document().frameHost()->chrome().openTextDataListChooser(*host); event->setDefaultHandled(); } } virtual bool willRespondToMouseClickEvents() OVERRIDE { - return hostInput() && !hostInput()->isDisabledOrReadOnly() && document().page(); + return hostInput() && !hostInput()->isDisabledOrReadOnly() && document().isActive(); } public: - static PassRefPtr<DataListIndicatorElement> create(Document& document) + static PassRefPtrWillBeRawPtr<DataListIndicatorElement> create(Document& document) { - RefPtr<DataListIndicatorElement> element = adoptRef(new DataListIndicatorElement(document)); - element->setPseudo(AtomicString("-webkit-calendar-picker-indicator", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<DataListIndicatorElement> element = adoptRefWillBeNoop(new DataListIndicatorElement(document)); + element->setShadowPseudoId(AtomicString("-webkit-calendar-picker-indicator", AtomicString::ConstructFromLiteral)); element->setAttribute(idAttr, ShadowElementNames::pickerIndicator()); return element.release(); } @@ -115,8 +115,10 @@ TextFieldInputType::TextFieldInputType(HTMLInputElement& element) TextFieldInputType::~TextFieldInputType() { +#if !ENABLE(OILPAN) if (SpinButtonElement* spinButton = spinButtonElement()) spinButton->removeSpinButtonOwner(); +#endif } SpinButtonElement* TextFieldInputType::spinButtonElement() const @@ -134,18 +136,9 @@ bool TextFieldInputType::isTextField() const return true; } -static inline bool shouldIgnoreRequiredAttribute(const HTMLInputElement& input) -{ - if (!input.document().settings() || !input.document().settings()->needsSiteSpecificQuirks()) - return false; - if (!equalIgnoringCase(input.document().url().host(), "egov.uscis.gov")) - return false; - return input.fastGetAttribute(requiredAttr) == "no"; -} - bool TextFieldInputType::valueMissing(const String& value) const { - return !shouldIgnoreRequiredAttribute(element()) && element().isRequired() && value.isEmpty(); + return element().isRequired() && value.isEmpty(); } bool TextFieldInputType::canSetSuggestedValue() @@ -157,14 +150,14 @@ void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChange { // Grab this input element to keep reference even if JS event handler // changes input type. - RefPtr<HTMLInputElement> input(element()); + RefPtrWillBeRawPtr<HTMLInputElement> input(element()); // We don't ask InputType::setValue to dispatch events because // TextFieldInputType dispatches events different way from InputType. InputType::setValue(sanitizedValue, valueChanged, DispatchNoEvent); if (valueChanged) - updateView(); + input->updateView(); unsigned max = visibleValue().length(); if (input->focused()) @@ -217,10 +210,11 @@ void TextFieldInputType::handleKeydownEventForSpinButton(KeyboardEvent* event) const String& key = event->keyIdentifier(); if (key == "Up") spinButtonStepUp(); - else if (key == "Down") + else if (key == "Down" && !event->altKey()) spinButtonStepDown(); else return; + element().dispatchFormControlChangeEvent(); event->setDefaultHandled(); } @@ -235,12 +229,13 @@ void TextFieldInputType::forwardEvent(Event* event) if (element().renderer() && (event->isMouseEvent() || event->isDragEvent() || event->hasInterface(EventNames::WheelEvent) || event->type() == EventTypeNames::blur || event->type() == EventTypeNames::focus)) { RenderTextControlSingleLine* renderTextControl = toRenderTextControlSingleLine(element().renderer()); if (event->type() == EventTypeNames::blur) { - if (RenderBox* innerTextRenderer = element().innerTextElement()->renderBox()) { + if (RenderBox* innerEditorRenderer = element().innerEditorElement()->renderBox()) { // FIXME: This class has no need to know about RenderLayer! - if (RenderLayer* innerLayer = innerTextRenderer->layer()) { - RenderLayerScrollableArea* innerScrollableArea = innerLayer->scrollableArea(); - IntSize scrollOffset(!renderTextControl->style()->isLeftToRightDirection() ? innerScrollableArea->scrollWidth() : 0, 0); - innerScrollableArea->scrollToOffset(scrollOffset, ScrollOffsetClamped); + if (RenderLayer* innerLayer = innerEditorRenderer->layer()) { + if (RenderLayerScrollableArea* innerScrollableArea = innerLayer->scrollableArea()) { + IntSize scrollOffset(!renderTextControl->style()->isLeftToRightDirection() ? innerScrollableArea->scrollWidth().toInt() : 0, 0); + innerScrollableArea->scrollToOffset(scrollOffset, ScrollOffsetClamped); + } } } @@ -253,9 +248,9 @@ void TextFieldInputType::forwardEvent(Event* event) } } -void TextFieldInputType::handleFocusEvent(Element* oldFocusedNode, FocusDirection focusDirection) +void TextFieldInputType::handleFocusEvent(Element* oldFocusedNode, FocusType focusType) { - InputType::handleFocusEvent(oldFocusedNode, focusDirection); + InputType::handleFocusEvent(oldFocusedNode, focusType); element().beginEditing(); } @@ -263,6 +258,8 @@ void TextFieldInputType::handleBlurEvent() { InputType::handleBlurEvent(); element().endEditing(); + if (SpinButtonElement *spinButton = spinButtonElement()) + spinButton->releaseCapture(); } bool TextFieldInputType::shouldSubmitImplicitly(Event* event) @@ -275,15 +272,6 @@ RenderObject* TextFieldInputType::createRenderer(RenderStyle*) const return new RenderTextControlSingleLine(&element()); } -bool TextFieldInputType::needsContainer() const -{ -#if ENABLE(INPUT_SPEECH) - return element().isSpeechEnabled(); -#else - return false; -#endif -} - bool TextFieldInputType::shouldHaveSpinButton() const { return RenderTheme::theme().shouldHaveSpinButton(&element()); @@ -293,32 +281,27 @@ void TextFieldInputType::createShadowSubtree() { ASSERT(element().shadow()); ShadowRoot* shadowRoot = element().userAgentShadowRoot(); - ASSERT(!shadowRoot->hasChildNodes()); + ASSERT(!shadowRoot->hasChildren()); Document& document = element().document(); bool shouldHaveSpinButton = this->shouldHaveSpinButton(); bool shouldHaveDataListIndicator = element().hasValidDataListOptions(); bool createsContainer = shouldHaveSpinButton || shouldHaveDataListIndicator || needsContainer(); - RefPtr<TextControlInnerTextElement> innerEditor = TextControlInnerTextElement::create(document); + RefPtrWillBeRawPtr<TextControlInnerEditorElement> innerEditor = TextControlInnerEditorElement::create(document); if (!createsContainer) { shadowRoot->appendChild(innerEditor.release()); return; } - RefPtr<TextControlInnerContainer> container = TextControlInnerContainer::create(document); - container->setPseudo(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<TextControlInnerContainer> container = TextControlInnerContainer::create(document); + container->setShadowPseudoId(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral)); shadowRoot->appendChild(container); - RefPtr<EditingViewPortElement> editingViewPort = EditingViewPortElement::create(document); + RefPtrWillBeRawPtr<EditingViewPortElement> editingViewPort = EditingViewPortElement::create(document); editingViewPort->appendChild(innerEditor.release()); container->appendChild(editingViewPort.release()); -#if ENABLE(INPUT_SPEECH) - if (element().isSpeechEnabled()) - container->appendChild(InputFieldSpeechButtonElement::create(document)); -#endif - if (shouldHaveDataListIndicator) container->appendChild(DataListIndicatorElement::create(document)); // FIXME: Because of a special handling for a spin button in @@ -357,14 +340,16 @@ void TextFieldInputType::listAttributeTargetChanged() // FIXME: The following code is similar to createShadowSubtree(), // but they are different. We should simplify the code by making // containerElement mandatory. - RefPtr<Element> rpContainer = TextControlInnerContainer::create(document); - rpContainer->setPseudo(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral)); - RefPtr<Element> innerEditor = element().innerTextElement(); + RefPtrWillBeRawPtr<Element> rpContainer = TextControlInnerContainer::create(document); + rpContainer->setShadowPseudoId(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<Element> innerEditor = element().innerEditorElement(); innerEditor->parentNode()->replaceChild(rpContainer.get(), innerEditor.get()); - RefPtr<Element> editingViewPort = EditingViewPortElement::create(document); + RefPtrWillBeRawPtr<Element> editingViewPort = EditingViewPortElement::create(document); editingViewPort->appendChild(innerEditor.release()); rpContainer->appendChild(editingViewPort.release()); rpContainer->appendChild(DataListIndicatorElement::create(document)); + if (element().document().focusedElement() == element()) + element().updateFocusAppearance(true /* restore selection */); } } else { picker->remove(ASSERT_NO_EXCEPTION); @@ -408,15 +393,6 @@ static bool isASCIILineBreak(UChar c) static String limitLength(const String& string, unsigned maxLength) { unsigned newLength = std::min(maxLength, string.length()); - // FIXME: We should not truncate the string at a control character. It's not - // compatible with IE and Firefox. - for (unsigned i = 0; i < newLength; ++i) { - const UChar current = string[i]; - if (current < ' ' && current != '\t') { - newLength = i; - break; - } - } if (newLength == string.length()) return string; if (newLength > 0 && U16_IS_LEAD(string[newLength - 1])) @@ -433,10 +409,10 @@ void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* { // Make sure that the text to be inserted will not violate the maxLength. - // We use HTMLInputElement::innerTextValue() instead of + // We use HTMLInputElement::innerEditorValue() instead of // HTMLInputElement::value() because they can be mismatched by // sanitizeValue() in HTMLInputElement::subtreeHasChanged() in some cases. - unsigned oldLength = element().innerTextValue().length(); + unsigned oldLength = element().innerEditorValue().length(); // selectionLength represents the selection length of this text field to be // removed by this insertion. @@ -466,7 +442,7 @@ void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* bool TextFieldInputType::shouldRespectListAttribute() { - return InputType::themeSupportsDataListUI(this); + return true; } void TextFieldInputType::updatePlaceholderText() @@ -481,12 +457,12 @@ void TextFieldInputType::updatePlaceholderText() return; } if (!placeholder) { - RefPtr<HTMLElement> newElement = HTMLDivElement::create(element().document()); + RefPtrWillBeRawPtr<HTMLElement> newElement = HTMLDivElement::create(element().document()); placeholder = newElement.get(); - placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral)); + placeholder->setShadowPseudoId(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral)); placeholder->setAttribute(idAttr, ShadowElementNames::placeholder()); Element* container = containerElement(); - Node* previous = container ? container : element().innerTextElement(); + Node* previous = container ? container : element().innerEditorElement(); previous->parentNode()->insertBefore(placeholder, previous->nextSibling()); ASSERT_WITH_SECURITY_IMPLICATION(placeholder->parentNode() == previous->parentNode()); } @@ -518,10 +494,10 @@ void TextFieldInputType::subtreeHasChanged() // HTMLInputElement::handleBeforeTextInsertedEvent() has already called // sanitizeUserInputValue(). // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent. - element().setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element().innerTextValue()))); + element().setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element().innerEditorValue()))); element().updatePlaceholderVisibility(false); // Recalc for :invalid change. - element().setNeedsStyleRecalc(); + element().setNeedsStyleRecalc(SubtreeStyleChange); didSetValueByUserEdit(wasChanged ? ValueChangeStateChanged : ValueChangeStateNone); } @@ -547,19 +523,23 @@ void TextFieldInputType::spinButtonStepUp() void TextFieldInputType::updateView() { if (!element().suggestedValue().isNull()) { - element().setInnerTextValue(element().suggestedValue()); + element().setInnerEditorValue(element().suggestedValue()); element().updatePlaceholderVisibility(false); - } else if (!element().formControlValueMatchesRenderer()) { - // Update the renderer value if the formControlValueMatchesRenderer() flag is false. - // It protects an unacceptable renderer value from being overwritten with the DOM value. - element().setInnerTextValue(visibleValue()); + } else if (element().needsToUpdateViewValue()) { + // Update the view only if needsToUpdateViewValue is true. It protects + // an unacceptable view value from being overwritten with the DOM value. + // + // e.g. <input type=number> has a view value "abc", and input.max is + // updated. In this case, updateView() is called but we should not + // update the view value. + element().setInnerEditorValue(visibleValue()); element().updatePlaceholderVisibility(false); } } void TextFieldInputType::focusAndSelectSpinButtonOwner() { - RefPtr<HTMLInputElement> input(element()); + RefPtrWillBeRawPtr<HTMLInputElement> input(element()); input->focus(); input->select(); } @@ -574,4 +554,10 @@ bool TextFieldInputType::shouldSpinButtonRespondToWheelEvents() return shouldSpinButtonRespondToMouseEvents() && element().focused(); } +void TextFieldInputType::spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch eventDispatch) +{ + if (eventDispatch == SpinButtonElement::EventDispatchAllowed) + element().dispatchFormControlChangeEvent(); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.h index 38d5d9ed57f..0eb1fda2d4c 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/TextFieldInputType.h @@ -41,6 +41,7 @@ class FormDataList; // The class represents types of which UI contain text fields. // It supports not only the types for BaseTextInputType but also type=number. class TextFieldInputType : public InputType, protected SpinButtonElement::SpinButtonOwner { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TextFieldInputType); protected: TextFieldInputType(HTMLInputElement&); virtual ~TextFieldInputType(); @@ -49,16 +50,16 @@ protected: void handleKeydownEventForSpinButton(KeyboardEvent*); protected: - virtual bool needsContainer() const; - virtual bool shouldHaveSpinButton() const; + virtual bool needsContainer() const { return false; } + bool shouldHaveSpinButton() const; virtual void createShadowSubtree() OVERRIDE; virtual void destroyShadowSubtree() OVERRIDE; virtual void attributeChanged() OVERRIDE; virtual void disabledAttributeChanged() OVERRIDE; virtual void readonlyAttributeChanged() OVERRIDE; virtual bool supportsReadOnly() const OVERRIDE; - virtual void handleFocusEvent(Element* oldFocusedNode, FocusDirection) OVERRIDE; - virtual void handleBlurEvent() OVERRIDE; + virtual void handleFocusEvent(Element* oldFocusedNode, FocusType) OVERRIDE FINAL; + virtual void handleBlurEvent() OVERRIDE FINAL; virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE; virtual void updateView() OVERRIDE; @@ -72,27 +73,28 @@ protected: Element* containerElement() const; private: - virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE; - virtual bool isTextField() const OVERRIDE; + virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE FINAL; + virtual bool isTextField() const OVERRIDE FINAL; virtual bool valueMissing(const String&) const OVERRIDE; virtual void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) OVERRIDE; - virtual void forwardEvent(Event*) OVERRIDE; - virtual bool shouldSubmitImplicitly(Event*) OVERRIDE; + virtual void forwardEvent(Event*) OVERRIDE FINAL; + virtual bool shouldSubmitImplicitly(Event*) OVERRIDE FINAL; virtual RenderObject* createRenderer(RenderStyle*) const OVERRIDE; virtual bool shouldUseInputMethod() const OVERRIDE; virtual String sanitizeValue(const String&) const OVERRIDE; virtual bool shouldRespectListAttribute() OVERRIDE; virtual void listAttributeTargetChanged() OVERRIDE; - virtual void updatePlaceholderText() OVERRIDE; + virtual void updatePlaceholderText() OVERRIDE FINAL; virtual bool appendFormData(FormDataList&, bool multipart) const OVERRIDE; - virtual void subtreeHasChanged() OVERRIDE; + virtual void subtreeHasChanged() OVERRIDE FINAL; // SpinButtonElement::SpinButtonOwner functions. - virtual void focusAndSelectSpinButtonOwner() OVERRIDE; - virtual bool shouldSpinButtonRespondToMouseEvents() OVERRIDE; - virtual bool shouldSpinButtonRespondToWheelEvents() OVERRIDE; - virtual void spinButtonStepDown() OVERRIDE; - virtual void spinButtonStepUp() OVERRIDE; + virtual void focusAndSelectSpinButtonOwner() OVERRIDE FINAL; + virtual bool shouldSpinButtonRespondToMouseEvents() OVERRIDE FINAL; + virtual bool shouldSpinButtonRespondToWheelEvents() OVERRIDE FINAL; + virtual void spinButtonStepDown() OVERRIDE FINAL; + virtual void spinButtonStepUp() OVERRIDE FINAL; + virtual void spinButtonDidReleaseMouseCapture(SpinButtonElement::EventDispatch) OVERRIDE FINAL; SpinButtonElement* spinButtonElement() const; }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.cpp index a5e9db19398..b39a4ccbcd0 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "core/html/forms/TextInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "wtf/PassOwnPtr.h" @@ -39,9 +39,9 @@ namespace WebCore { using namespace HTMLNames; -PassRefPtr<InputType> TextInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> TextInputType::create(HTMLInputElement& element) { - return adoptRef(new TextInputType(element)); + return adoptRefWillBeNoop(new TextInputType(element)); } void TextInputType::countUsage() diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.h index 8fb1e8c2447..75608bd2ee2 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/TextInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class TextInputType : public BaseTextInputType { +class TextInputType FINAL : public BaseTextInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: TextInputType(HTMLInputElement& element) : BaseTextInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp index 22d80ef7e1e..ae3203eabc8 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "core/html/forms/TimeInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/DateTimeFieldsState.h" #include "platform/DateComponents.h" @@ -56,9 +56,9 @@ TimeInputType::TimeInputType(HTMLInputElement& element) { } -PassRefPtr<InputType> TimeInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> TimeInputType::create(HTMLInputElement& element) { - return adoptRef(new TimeInputType(element)); + return adoptRefWillBeNoop(new TimeInputType(element)); } void TimeInputType::countUsage() @@ -90,7 +90,7 @@ StepRange TimeInputType::createStepRange(AnyStepHandling anyStepHandling) const { DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (timeDefaultStep, timeDefaultStepBase, timeStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); - return InputType::createStepRange(anyStepHandling, 0, Decimal::fromDouble(DateComponents::minimumTime()), Decimal::fromDouble(DateComponents::maximumTime()), stepDescription); + return InputType::createStepRange(anyStepHandling, timeDefaultStepBase, Decimal::fromDouble(DateComponents::minimumTime()), Decimal::fromDouble(DateComponents::maximumTime()), stepDescription); } bool TimeInputType::parseToDateComponentsInternal(const String& string, DateComponents* out) const diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.h index 82a540d52f6..b8d3f111ca3 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/TimeInputType.h @@ -42,9 +42,9 @@ typedef BaseMultipleFieldsDateAndTimeInputType BaseTimeInputType; typedef BaseChooserOnlyDateAndTimeInputType BaseTimeInputType; #endif -class TimeInputType : public BaseTimeInputType { +class TimeInputType FINAL : public BaseTimeInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: TimeInputType(HTMLInputElement&); @@ -59,9 +59,9 @@ private: virtual String localizeValue(const String&) const OVERRIDE; // BaseMultipleFieldsDateAndTimeInputType functions - virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE FINAL; - virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE FINAL; - virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const; + virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE; + virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE; + virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const OVERRIDE; #endif }; diff --git a/chromium/third_party/WebKit/Source/core/html/forms/TypeAhead.cpp b/chromium/third_party/WebKit/Source/core/html/forms/TypeAhead.cpp index e9a0052edad..673b88956ce 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/TypeAhead.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/TypeAhead.cpp @@ -50,7 +50,7 @@ static String stripLeadingWhiteSpace(const String& string) unsigned i; for (i = 0; i < length; ++i) { - if (string[i] != noBreakSpace && (string[i] <= 0x7F ? !isASCIISpace(string[i]) : (direction(string[i]) != WhiteSpaceNeutral))) + if (string[i] != noBreakSpace && !isSpaceOrNewline(string[i])) break; } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.cpp index 33017eb34c7..c39d40c5301 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.cpp @@ -31,16 +31,16 @@ #include "config.h" #include "core/html/forms/URLInputType.h" -#include "InputTypeNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "platform/text/PlatformLocale.h" #include "wtf/PassOwnPtr.h" namespace WebCore { -PassRefPtr<InputType> URLInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> URLInputType::create(HTMLInputElement& element) { - return adoptRef(new URLInputType(element)); + return adoptRefWillBeNoop(new URLInputType(element)); } void URLInputType::countUsage() diff --git a/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.h index 98f53f21b38..e11143fc6c4 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/URLInputType.h @@ -35,9 +35,9 @@ namespace WebCore { -class URLInputType : public BaseTextInputType { +class URLInputType FINAL : public BaseTextInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: URLInputType(HTMLInputElement& element) : BaseTextInputType(element) { } diff --git a/chromium/third_party/WebKit/Source/core/html/forms/ValidationMessage.cpp b/chromium/third_party/WebKit/Source/core/html/forms/ValidationMessage.cpp index 57ee0eb6b8f..df7475f4c3e 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/ValidationMessage.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/ValidationMessage.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "core/html/forms/ValidationMessage.h" +#include "core/dom/Document.h" #include "core/html/HTMLFormControlElement.h" #include "core/page/Page.h" #include "core/page/ValidationMessageClient.h" @@ -46,8 +47,6 @@ ALWAYS_INLINE ValidationMessage::ValidationMessage(HTMLFormControlElement* eleme ValidationMessage::~ValidationMessage() { - if (ValidationMessageClient* client = validationMessageClient()) - client->hideValidationMessage(*m_element); } PassOwnPtr<ValidationMessage> ValidationMessage::create(HTMLFormControlElement* element) @@ -60,9 +59,8 @@ ValidationMessageClient* ValidationMessage::validationMessageClient() const Page* page = m_element->document().page(); if (!page) return 0; - // The form valdiation feature requires ValidationMessageClient. - ASSERT(page->validationMessageClient()); - return page->validationMessageClient(); + + return &page->validationMessageClient(); } void ValidationMessage::updateValidationMessage(const String& message) diff --git a/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp b/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp index 419b1603ddc..e49651ed71e 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp +++ b/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "core/html/forms/WeekInputType.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/DateTimeFieldsState.h" #include "platform/DateComponents.h" @@ -48,9 +48,9 @@ static const int weekDefaultStepBase = -259200000; // The first day of 1970-W01. static const int weekDefaultStep = 1; static const int weekStepScaleFactor = 604800000; -PassRefPtr<InputType> WeekInputType::create(HTMLInputElement& element) +PassRefPtrWillBeRawPtr<InputType> WeekInputType::create(HTMLInputElement& element) { - return adoptRef(new WeekInputType(element)); + return adoptRefWillBeNoop(new WeekInputType(element)); } void WeekInputType::countUsage() diff --git a/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.h b/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.h index 9455039c61a..f3360f27404 100644 --- a/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.h +++ b/chromium/third_party/WebKit/Source/core/html/forms/WeekInputType.h @@ -42,9 +42,9 @@ typedef BaseMultipleFieldsDateAndTimeInputType BaseWeekInputType; typedef BaseChooserOnlyDateAndTimeInputType BaseWeekInputType; #endif -class WeekInputType : public BaseWeekInputType { +class WeekInputType FINAL : public BaseWeekInputType { public: - static PassRefPtr<InputType> create(HTMLInputElement&); + static PassRefPtrWillBeRawPtr<InputType> create(HTMLInputElement&); private: WeekInputType(HTMLInputElement& element) : BaseWeekInputType(element) { } @@ -57,9 +57,9 @@ private: #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) // BaseMultipleFieldsDateAndTimeInputType functions - virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE FINAL; - virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE FINAL; - virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const; + virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE; + virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE; + virtual bool isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const OVERRIDE; #endif }; diff --git a/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.cpp b/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.cpp index 74643ac6db0..e497b047ff3 100644 --- a/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.cpp @@ -31,16 +31,16 @@ #include "config.h" #include "core/html/ime/InputMethodContext.h" +#include "core/dom/Document.h" #include "core/dom/Text.h" #include "core/editing/InputMethodController.h" -#include "core/html/ime/Composition.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -PassOwnPtr<InputMethodContext> InputMethodContext::create(HTMLElement* element) +PassOwnPtrWillBeRawPtr<InputMethodContext> InputMethodContext::create(HTMLElement* element) { - return adoptPtr(new InputMethodContext(element)); + return adoptPtrWillBeRefCountedGarbageCollected(new InputMethodContext(element)); } InputMethodContext::InputMethodContext(HTMLElement* element) @@ -53,13 +53,6 @@ InputMethodContext::~InputMethodContext() { } -Composition* InputMethodContext::composition() -{ - if (!m_composition) - m_composition = Composition::create(this); - return m_composition.get(); -} - String InputMethodContext::locale() const { // FIXME: Implement this. @@ -93,7 +86,7 @@ void InputMethodContext::confirmComposition() bool InputMethodContext::hasFocus() const { - Frame* frame = m_element->document().frame(); + LocalFrame* frame = m_element->document().frame(); if (!frame) return false; @@ -193,4 +186,10 @@ void InputMethodContext::dispatchCandidateWindowHideEvent() dispatchEvent(Event::create(EventTypeNames::candidatewindowhide)); } +void InputMethodContext::trace(Visitor* visitor) +{ + visitor->trace(m_element); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.h b/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.h index 16bb6ffe17a..d2b7978bc40 100644 --- a/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.h +++ b/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.h @@ -42,20 +42,21 @@ namespace WebCore { -class Composition; class ExecutionContext; class InputMethodController; class Node; -class InputMethodContext : public ScriptWrappable, public EventTargetWithInlineData { +class InputMethodContext FINAL : public NoBaseWillBeRefCountedGarbageCollected<InputMethodContext>, public ScriptWrappable, public EventTargetWithInlineData { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(InputMethodContext); public: - static PassOwnPtr<InputMethodContext> create(HTMLElement*); - ~InputMethodContext(); + static PassOwnPtrWillBeRawPtr<InputMethodContext> create(HTMLElement*); + virtual ~InputMethodContext(); +#if !ENABLE(OILPAN) void ref() { m_element->ref(); } void deref() { m_element->deref(); } +#endif - Composition* composition(); String locale() const; HTMLElement* target() const; unsigned compositionStartOffset(); @@ -78,17 +79,20 @@ public: void dispatchCandidateWindowUpdateEvent(); void dispatchCandidateWindowHideEvent(); + virtual void trace(Visitor*) OVERRIDE; + private: InputMethodContext(HTMLElement*); bool hasFocus() const; CompositionUnderline selectedSegment() const; InputMethodController& inputMethodController() const; +#if !ENABLE(OILPAN) virtual void refEventTarget() OVERRIDE { ref(); } virtual void derefEventTarget() OVERRIDE { deref(); } +#endif - HTMLElement* m_element; - OwnPtr<Composition> m_composition; + RawPtrWillBeMember<HTMLElement> m_element; Vector<unsigned> m_segments; }; diff --git a/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.idl b/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.idl index 8ce8c4a43d6..043feed06ba 100644 --- a/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.idl +++ b/chromium/third_party/WebKit/Source/core/html/ime/InputMethodContext.idl @@ -30,7 +30,6 @@ // http://www.w3.org/TR/ime-api/ interface InputMethodContext : EventTarget { - readonly attribute Composition composition; readonly attribute DOMString locale; readonly attribute HTMLElement target; readonly attribute unsigned long compositionStartOffset; diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp new file mode 100644 index 00000000000..4726f713235 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImport.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/html/imports/HTMLImport.h" + +#include "core/dom/Document.h" +#include "core/html/imports/HTMLImportStateResolver.h" + +namespace WebCore { + +HTMLImport* HTMLImport::root() +{ + HTMLImport* i = this; + while (i->parent()) + i = i->parent(); + return i; +} + +bool HTMLImport::precedes(HTMLImport* import) +{ + for (HTMLImport* i = this; i; i = traverseNext(i)) { + if (i == import) + return true; + } + + return false; +} + +bool HTMLImport::formsCycle() const +{ + for (const HTMLImport* i = this->parent(); i; i = i->parent()) { + if (i->document() == this->document()) + return true; + } + + return false; + +} + +void HTMLImport::appendImport(HTMLImport* child) +{ + appendChild(child); + + // This prevents HTML parser from going beyond the + // blockage line before the precise state is computed by recalcState(). + if (child->isSync()) + m_state = HTMLImportState::blockedState(); + + stateWillChange(); +} + +void HTMLImport::stateDidChange() +{ + if (!state().shouldBlockScriptExecution()) { + if (Document* document = this->document()) + document->didLoadAllImports(); + } +} + +void HTMLImport::recalcTreeState(HTMLImport* root) +{ + HashMap<HTMLImport*, HTMLImportState> snapshot; + Vector<HTMLImport*> updated; + + for (HTMLImport* i = root; i; i = traverseNext(i)) { + snapshot.add(i, i->state()); + i->m_state = HTMLImportState::invalidState(); + } + + // The post-visit DFS order matters here because + // HTMLImportStateResolver in recalcState() Depends on + // |m_state| of its children and precedents of ancestors. + // Accidental cycle dependency of state computation is prevented + // by invalidateCachedState() and isStateCacheValid() check. + for (HTMLImport* i = traverseFirstPostOrder(root); i; i = traverseNextPostOrder(i)) { + ASSERT(!i->m_state.isValid()); + i->m_state = HTMLImportStateResolver(i).resolve(); + + HTMLImportState newState = i->state(); + HTMLImportState oldState = snapshot.get(i); + // Once the state reaches Ready, it shouldn't go back. + ASSERT(!oldState.isReady() || oldState <= newState); + if (newState != oldState) + updated.append(i); + } + + for (size_t i = 0; i < updated.size(); ++i) + updated[i]->stateDidChange(); +} + +#if !defined(NDEBUG) +void HTMLImport::show() +{ + root()->showTree(this, 0); +} + +void HTMLImport::showTree(HTMLImport* highlight, unsigned depth) +{ + for (unsigned i = 0; i < depth*4; ++i) + fprintf(stderr, " "); + + fprintf(stderr, "%s", this == highlight ? "*" : " "); + showThis(); + fprintf(stderr, "\n"); + for (HTMLImport* child = firstChild(); child; child = child->next()) + child->showTree(highlight, depth + 1); +} + +void HTMLImport::showThis() +{ + fprintf(stderr, "%p state=%d", this, m_state.peekValueForDebug()); +} +#endif + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImport.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImport.h new file mode 100644 index 00000000000..0a7e35a7392 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImport.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLImport_h +#define HTMLImport_h + +#include "core/html/imports/HTMLImportState.h" +#include "platform/heap/Handle.h" +#include "wtf/TreeNode.h" +#include "wtf/Vector.h" + +namespace WebCore { + +class Document; +class LocalFrame; +class HTMLImportChild; +class HTMLImportLoader; +class HTMLImportsController; +class KURL; + +// +// # Basic Data Structure and Algorithms of HTML Imports implemenation. +// +// ## The Import Tree +// +// HTML Imports form a tree: +// +// * The root of the tree is HTMLImportTreeRoot. +// +// * The HTMLImportTreeRoot is owned HTMLImportsController, which is owned by the master +// document as a DocumentSupplement. +// +// * The non-root nodes are HTMLImportChild. They are all owned by HTMLImporTreeRoot. +// LinkStyle is wired into HTMLImportChild by implementing HTMLImportChildClient interface +// +// * Both HTMLImportTreeRoot and HTMLImportChild are derived from HTMLImport superclass +// that models the tree data structure using WTF::TreeNode and provides a set of +// virtual functions. +// +// HTMLImportsController also owns all loaders in the tree and manages their lifetime through it. +// One assumption is that the tree is append-only and nodes are never inserted in the middle of the tree nor removed. +// +// Full diagram is here: +// https://docs.google.com/drawings/d/1jFQrO0IupWrlykTNzQ3Nv2SdiBiSz4UE9-V3-vDgBb0/ +// +// # Import Sharing and HTMLImportLoader +// +// The HTML Imports spec calls for de-dup mechanism to share already loaded imports. +// To implement this, the actual loading machinery is split out from HTMLImportChild to +// HTMLImportLoader, and each loader shares HTMLImportLoader with other loader if the URL is same. +// Check around HTMLImportsController::findLink() for more detail. +// +// HTMLImportLoader can be shared by multiple imports. +// +// HTMLImportChild (1)-->(*) HTMLImportLoader +// +// +// # Script Blocking +// +// - An import blocks the HTML parser of its own imported document from running <script> +// until all of its children are loaded. +// Note that dynamically added import won't block the parser. +// +// - An import under loading also blocks imported documents that follow from being created. +// This is because an import can include another import that has same URLs of following ones. +// In such case, the preceding import should be loaded and following ones should be de-duped. +// + +// The superclass of HTMLImportTreeRoot and HTMLImportChild +// This represents the import tree data structure. +class HTMLImport : public NoBaseWillBeGarbageCollectedFinalized<HTMLImport>, public TreeNode<HTMLImport> { +public: + enum SyncMode { + Sync = 0, + Async = 1 + }; + + virtual ~HTMLImport() { } + + // FIXME: Consider returning HTMLImportTreeRoot. + HTMLImport* root(); + bool precedes(HTMLImport*); + bool isRoot() const { return !parent(); } + bool isSync() const { return SyncMode(m_sync) == Sync; } + bool formsCycle() const; + const HTMLImportState& state() const { return m_state; } + + void appendImport(HTMLImport*); + + virtual Document* document() const = 0; + virtual bool isDone() const = 0; // FIXME: Should be renamed to haveFinishedLoading() + virtual HTMLImportLoader* loader() const { return 0; } + virtual void stateWillChange() { } + virtual void stateDidChange(); + + virtual void trace(Visitor*) { } + +protected: + // Stating from most conservative state. + // It will be corrected through state update flow. + explicit HTMLImport(SyncMode sync) + : m_sync(sync) + { } + + static void recalcTreeState(HTMLImport* root); + +#if !defined(NDEBUG) + void show(); + void showTree(HTMLImport* highlight, unsigned depth); + virtual void showThis(); +#endif + +private: + HTMLImportState m_state; + unsigned m_sync : 1; +}; + +} // namespace WebCore + +#endif // HTMLImport_h diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp new file mode 100644 index 00000000000..91b1b87f5ab --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChild.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/html/imports/HTMLImportChild.h" + +#include "core/dom/Document.h" +#include "core/dom/custom/CustomElement.h" +#include "core/dom/custom/CustomElementMicrotaskDispatcher.h" +#include "core/dom/custom/CustomElementMicrotaskImportStep.h" +#include "core/dom/custom/CustomElementSyncMicrotaskQueue.h" +#include "core/html/imports/HTMLImportChildClient.h" +#include "core/html/imports/HTMLImportLoader.h" +#include "core/html/imports/HTMLImportTreeRoot.h" +#include "core/html/imports/HTMLImportsController.h" + +namespace WebCore { + +HTMLImportChild::HTMLImportChild(const KURL& url, HTMLImportLoader* loader, SyncMode sync) + : HTMLImport(sync) + , m_url(url) +#if !ENABLE(OILPAN) + , m_weakFactory(this) +#endif + , m_loader(loader) + , m_client(nullptr) +{ +} + +HTMLImportChild::~HTMLImportChild() +{ +#if !ENABLE(OILPAN) + // importDestroyed() should be called before the destruction. + ASSERT(!m_loader); + + if (m_client) + m_client->importChildWasDestroyed(this); +#endif +} + +void HTMLImportChild::ownerInserted() +{ + if (!m_loader->isDone()) + return; + root()->document()->styleResolverChanged(); +} + +void HTMLImportChild::didShareLoader() +{ + createCustomElementMicrotaskStepIfNeeded(); + stateWillChange(); +} + +void HTMLImportChild::didStartLoading() +{ + createCustomElementMicrotaskStepIfNeeded(); +} + +void HTMLImportChild::didFinish() +{ + if (m_client) + m_client->didFinish(); +} + +void HTMLImportChild::didFinishLoading() +{ + stateWillChange(); + if (m_customElementMicrotaskStep) + CustomElementMicrotaskDispatcher::instance().importDidFinish(m_customElementMicrotaskStep.get()); +} + +void HTMLImportChild::didFinishUpgradingCustomElements() +{ + stateWillChange(); + m_customElementMicrotaskStep.clear(); +} + +#if !ENABLE(OILPAN) +void HTMLImportChild::importDestroyed() +{ + if (parent()) + parent()->removeChild(this); + + ASSERT(m_loader); + m_loader->removeImport(this); + m_loader = nullptr; +} +#endif + +Document* HTMLImportChild::document() const +{ + ASSERT(m_loader); + return m_loader->document(); +} + +void HTMLImportChild::stateWillChange() +{ + toHTMLImportTreeRoot(root())->scheduleRecalcState(); +} + +void HTMLImportChild::stateDidChange() +{ + HTMLImport::stateDidChange(); + + if (state().isReady()) + didFinish(); +} + +void HTMLImportChild::createCustomElementMicrotaskStepIfNeeded() +{ + // HTMLImportChild::normalize(), which is called from HTMLImportLoader::addImport(), + // can move import children to new parents. So their microtask steps should be updated as well, + // to let the steps be in the new parent queues.This method handles such migration. + // For implementation simplicity, outdated step objects that are owned by moved children + // aren't removed from the (now wrong) queues. Instead, each step invalidates its content so that + // it is removed from the wrong queue during the next traversal. See parentWasChanged() for the detail. + + if (m_customElementMicrotaskStep) { + m_customElementMicrotaskStep->parentWasChanged(); + m_customElementMicrotaskStep.clear(); + } + + if (!isDone() && !formsCycle()) { +#if ENABLE(OILPAN) + m_customElementMicrotaskStep = CustomElement::didCreateImport(this); +#else + m_customElementMicrotaskStep = CustomElement::didCreateImport(this)->weakPtr(); +#endif + } + + for (HTMLImport* child = firstChild(); child; child = child->next()) + toHTMLImportChild(child)->createCustomElementMicrotaskStepIfNeeded(); +} + +bool HTMLImportChild::isDone() const +{ + ASSERT(m_loader); + + return m_loader->isDone() && m_loader->microtaskQueue()->isEmpty() && !m_customElementMicrotaskStep; +} + +HTMLImportLoader* HTMLImportChild::loader() const +{ + // This should never be called after importDestroyed. + ASSERT(m_loader); + return m_loader; +} + +void HTMLImportChild::setClient(HTMLImportChildClient* client) +{ + ASSERT(client); + ASSERT(!m_client); + m_client = client; +} + +#if !ENABLE(OILPAN) +void HTMLImportChild::clearClient() +{ + // Doesn't check m_client nullity because we allow + // clearClient() to reenter. + m_client = nullptr; +} +#endif + +HTMLLinkElement* HTMLImportChild::link() const +{ + if (!m_client) + return 0; + return m_client->link(); +} + +// Ensuring following invariants against the import tree: +// - HTMLImportChild::firstImport() is the "first import" of the DFS order of the import tree. +// - The "first import" manages all the children that is loaded by the document. +void HTMLImportChild::normalize() +{ + if (!loader()->isFirstImport(this) && this->precedes(loader()->firstImport())) { + HTMLImportChild* oldFirst = loader()->firstImport(); + loader()->moveToFirst(this); + takeChildrenFrom(oldFirst); + } + + for (HTMLImport* child = firstChild(); child; child = child->next()) + toHTMLImportChild(child)->normalize(); +} + +#if !defined(NDEBUG) +void HTMLImportChild::showThis() +{ + bool isFirst = loader() ? loader()->isFirstImport(this) : false; + HTMLImport::showThis(); + fprintf(stderr, " loader=%p first=%d, step=%p sync=%s url=%s", + m_loader.get(), + isFirst, + m_customElementMicrotaskStep.get(), + isSync() ? "Y" : "N", + url().string().utf8().data()); +} +#endif + +void HTMLImportChild::trace(Visitor* visitor) +{ + visitor->trace(m_customElementMicrotaskStep); + visitor->trace(m_loader); + visitor->trace(m_client); + HTMLImport::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportChild.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChild.h index 72f0329c2c5..aafc6ebcec1 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportChild.h +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChild.h @@ -31,67 +31,82 @@ #ifndef HTMLImportChild_h #define HTMLImportChild_h -#include "core/html/HTMLImport.h" -#include "core/html/HTMLImportLoaderClient.h" -#include "core/html/HTMLImportResourceOwner.h" +#include "core/html/imports/HTMLImport.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" +#include "wtf/Vector.h" +#include "wtf/WeakPtr.h" namespace WebCore { +class CustomElementMicrotaskImportStep; class HTMLImportLoader; class HTMLImportChildClient; +class HTMLLinkElement; // // An import tree node subclas to encapsulate imported document -// lifecycle. This class is owned by LinkStyle. The actual loading +// lifecycle. This class is owned by HTMLImportsController. The actual loading // is done by HTMLImportLoader, which can be shared among multiple // HTMLImportChild of same link URL. // -// HTMLImportChild implements ResourceClient through HTMLImportResourceOwner -// so that it can speculatively request linked resources while it is unblocked. -// -class HTMLImportChild : public HTMLImport, public HTMLImportLoaderClient, public HTMLImportResourceOwner { +class HTMLImportChild FINAL : public HTMLImport { public: - HTMLImportChild(const KURL&, HTMLImportChildClient*); + HTMLImportChild(const KURL&, HTMLImportLoader*, SyncMode); virtual ~HTMLImportChild(); - Document* importedDocument() const; + HTMLLinkElement* link() const; const KURL& url() const { return m_url; } - void wasAlreadyLoadedAs(HTMLImportChild* found); - void startLoading(const ResourcePtr<RawResource>&); + void ownerInserted(); + void didShareLoader(); + void didStartLoading(); +#if !ENABLE(OILPAN) void importDestroyed(); - bool isLoaded() const; + WeakPtr<HTMLImportChild> weakPtr() { return m_weakFactory.createWeakPtr(); } +#endif // HTMLImport - virtual HTMLImportRoot* root() OVERRIDE; virtual Document* document() const OVERRIDE; - virtual void wasDetachedFromDocument() OVERRIDE; - virtual void didFinishParsing() OVERRIDE; - virtual bool isProcessing() const OVERRIDE; virtual bool isDone() const OVERRIDE; - virtual void didUnblockDocument() OVERRIDE; + virtual HTMLImportLoader* loader() const OVERRIDE; + virtual void stateWillChange() OVERRIDE; + virtual void stateDidChange() OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; - void clearClient() { m_client = 0; } +#if !defined(NDEBUG) + virtual void showThis() OVERRIDE; +#endif -private: - // RawResourceOwner doing nothing. - // HTMLImportChild owns the resource so that the contents of prefetched Resource doesn't go away. - virtual void responseReceived(Resource*, const ResourceResponse&) OVERRIDE { } - virtual void dataReceived(Resource*, const char*, int) OVERRIDE { } - virtual void notifyFinished(Resource*) OVERRIDE { } + void setClient(HTMLImportChildClient*); +#if !ENABLE(OILPAN) + void clearClient(); +#endif - // HTMLImportLoaderClient - virtual void didFinish() OVERRIDE; + void didFinishLoading(); + void didFinishUpgradingCustomElements(); + void normalize(); - void createLoader(); - void shareLoader(HTMLImportChild*); +private: + void didFinish(); + void shareLoader(); + void createCustomElementMicrotaskStepIfNeeded(); KURL m_url; - HTMLImportChildClient* m_client; - RefPtr<HTMLImportLoader> m_loader; + WeakPtrWillBeWeakMember<CustomElementMicrotaskImportStep> m_customElementMicrotaskStep; +#if !ENABLE(OILPAN) + WeakPtrFactory<HTMLImportChild> m_weakFactory; +#endif + RawPtrWillBeMember<HTMLImportLoader> m_loader; + RawPtrWillBeMember<HTMLImportChildClient> m_client; }; +inline HTMLImportChild* toHTMLImportChild(HTMLImport* import) +{ + ASSERT(!import || !import->isRoot()); + return static_cast<HTMLImportChild*>(import); +} + } // namespace WebCore #endif // HTMLImportChild_h diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportChildClient.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChildClient.h index 62866e8c4f7..67d0b65d4d3 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportChildClient.h +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportChildClient.h @@ -33,11 +33,19 @@ namespace WebCore { -class HTMLImportChildClient { +class HTMLImportChild; +class HTMLLinkElement; + +class HTMLImportChildClient : public WillBeGarbageCollectedMixin { public: virtual ~HTMLImportChildClient() { } virtual void didFinish() = 0; - virtual void loaderWillBeDestroyed() = 0; +#if !ENABLE(OILPAN) + virtual void importChildWasDestroyed(HTMLImportChild*) = 0; +#endif + virtual bool isSync() const = 0; + virtual HTMLLinkElement* link() = 0; + virtual void trace(Visitor*) { } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp new file mode 100644 index 00000000000..3b4d138babe --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/html/imports/HTMLImportLoader.h" + +#include "core/dom/Document.h" +#include "core/dom/StyleEngine.h" +#include "core/dom/custom/CustomElementSyncMicrotaskQueue.h" +#include "core/html/HTMLDocument.h" +#include "core/html/imports/HTMLImportChild.h" +#include "core/html/imports/HTMLImportsController.h" +#include "core/loader/DocumentWriter.h" +#include "platform/network/ContentSecurityPolicyResponseHeaders.h" + + +namespace WebCore { + +HTMLImportLoader::HTMLImportLoader(HTMLImportsController* controller) + : m_controller(controller) + , m_state(StateLoading) + , m_microtaskQueue(CustomElementSyncMicrotaskQueue::create()) +{ +} + +HTMLImportLoader::~HTMLImportLoader() +{ +#if !ENABLE(OILPAN) + clear(); +#endif +} + +#if !ENABLE(OILPAN) +void HTMLImportLoader::importDestroyed() +{ + clear(); +} + +void HTMLImportLoader::clear() +{ + m_controller = nullptr; + if (m_document) { + m_document->setImportsController(0); + m_document->cancelParsing(); + m_document.clear(); + } +} +#endif + +void HTMLImportLoader::startLoading(const ResourcePtr<RawResource>& resource) +{ + setResource(resource); +} + +void HTMLImportLoader::responseReceived(Resource* resource, const ResourceResponse& response) +{ + // Resource may already have been loaded with the import loader + // being added as a client later & now being notified. Fail early. + if (resource->loadFailedOrCanceled() || response.httpStatusCode() >= 400) { + setState(StateError); + return; + } + setState(startWritingAndParsing(response)); +} + +void HTMLImportLoader::dataReceived(Resource*, const char* data, int length) +{ + RefPtrWillBeRawPtr<DocumentWriter> protectingWriter(m_writer.get()); + m_writer->addData(data, length); +} + +void HTMLImportLoader::notifyFinished(Resource* resource) +{ + // The writer instance indicates that a part of the document can be already loaded. + // We don't take such a case as an error because the partially-loaded document has been visible from script at this point. + if (resource->loadFailedOrCanceled() && !m_writer) { + setState(StateError); + return; + } + + setState(finishWriting()); +} + +HTMLImportLoader::State HTMLImportLoader::startWritingAndParsing(const ResourceResponse& response) +{ + ASSERT(!m_imports.isEmpty()); + DocumentInit init = DocumentInit(response.url(), 0, m_controller->master()->contextDocument(), m_controller) + .withRegistrationContext(m_controller->master()->registrationContext()); + m_document = HTMLDocument::create(init); + m_writer = DocumentWriter::create(m_document.get(), response.mimeType(), "UTF-8"); + + return StateLoading; +} + +HTMLImportLoader::State HTMLImportLoader::finishWriting() +{ + return StateWritten; +} + +HTMLImportLoader::State HTMLImportLoader::finishParsing() +{ + return StateParsed; +} + +HTMLImportLoader::State HTMLImportLoader::finishLoading() +{ + return StateLoaded; +} + +void HTMLImportLoader::setState(State state) +{ + if (m_state == state) + return; + + m_state = state; + + if (m_state == StateParsed || m_state == StateError || m_state == StateWritten) { + if (RefPtrWillBeRawPtr<DocumentWriter> writer = m_writer.release()) + writer->end(); + } + + // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here. + if (state == StateLoaded || state == StateError) + didFinishLoading(); +} + +void HTMLImportLoader::didFinishParsing() +{ + setState(finishParsing()); + if (!hasPendingResources()) + setState(finishLoading()); +} + +void HTMLImportLoader::didRemoveAllPendingStylesheet() +{ + if (m_state == StateParsed) + setState(finishLoading()); +} + +bool HTMLImportLoader::hasPendingResources() const +{ + return m_document && m_document->styleEngine()->hasPendingSheets(); +} + +void HTMLImportLoader::didFinishLoading() +{ + for (size_t i = 0; i < m_imports.size(); ++i) + m_imports[i]->didFinishLoading(); + + clearResource(); + + ASSERT(!m_document || !m_document->parsing()); +} + +void HTMLImportLoader::moveToFirst(HTMLImportChild* import) +{ + size_t position = m_imports.find(import); + ASSERT(kNotFound != position); + m_imports.remove(position); + m_imports.insert(0, import); +} + +void HTMLImportLoader::addImport(HTMLImportChild* import) +{ + ASSERT(kNotFound == m_imports.find(import)); + + m_imports.append(import); + import->normalize(); + if (isDone()) + import->didFinishLoading(); +} + +#if !ENABLE(OILPAN) +void HTMLImportLoader::removeImport(HTMLImportChild* client) +{ + ASSERT(kNotFound != m_imports.find(client)); + m_imports.remove(m_imports.find(client)); +} +#endif + +bool HTMLImportLoader::shouldBlockScriptExecution() const +{ + return firstImport()->state().shouldBlockScriptExecution(); +} + +PassRefPtrWillBeRawPtr<CustomElementSyncMicrotaskQueue> HTMLImportLoader::microtaskQueue() const +{ + return m_microtaskQueue; +} + +void HTMLImportLoader::trace(Visitor* visitor) +{ + visitor->trace(m_controller); +#if ENABLE(OILPAN) + visitor->trace(m_imports); +#endif + visitor->trace(m_document); + visitor->trace(m_writer); + visitor->trace(m_microtaskQueue); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportLoader.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.h index 83ea998e310..45d05e38469 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportLoader.h +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.h @@ -31,50 +31,77 @@ #ifndef HTMLImportLoader_h #define HTMLImportLoader_h -#include "core/html/HTMLImportResourceOwner.h" +#include "core/fetch/RawResource.h" +#include "core/fetch/ResourceOwner.h" +#include "platform/heap/Handle.h" +#include "wtf/OwnPtr.h" +#include "wtf/PassOwnPtr.h" #include "wtf/Vector.h" namespace WebCore { +class CustomElementSyncMicrotaskQueue; class Document; class DocumentWriter; -class HTMLImport; -class HTMLImportLoaderClient; +class HTMLImportChild; +class HTMLImportsController; + // -// Owning imported Document lifetime. It also implements ResourceClient through HTMLImportResourceOwner +// Owning imported Document lifetime. It also implements ResourceClient through ResourceOwner // to feed fetched bytes to the DocumentWriter of the imported document. -// HTMLImportLoader is owned by and shared between HTMLImportChild. +// HTMLImportLoader is owned by HTMLImportsController. // // -class HTMLImportLoader : public RefCounted<HTMLImportLoader>, public HTMLImportResourceOwner { +class HTMLImportLoader FINAL : public NoBaseWillBeGarbageCollectedFinalized<HTMLImportLoader>, public ResourceOwner<RawResource> { public: enum State { StateLoading, StateWritten, - StateError, - StateReady + StateParsed, + StateLoaded, + StateError }; - static PassRefPtr<HTMLImportLoader> create(HTMLImport*, ResourceFetcher*); + static PassOwnPtrWillBeRawPtr<HTMLImportLoader> create(HTMLImportsController* controller) + { + return adoptPtrWillBeNoop(new HTMLImportLoader(controller)); + } virtual ~HTMLImportLoader(); - Document* document() const { return m_importedDocument.get(); } - Document* importedDocument() const; - void addClient(HTMLImportLoaderClient*); - void removeClient(HTMLImportLoaderClient*); - - bool isDone() const { return m_state == StateReady || m_state == StateError; } - bool isLoaded() const { return m_state == StateReady; } - bool isProcessing() const; - + Document* document() const { return m_document.get(); } + void addImport(HTMLImportChild*); +#if !ENABLE(OILPAN) + void removeImport(HTMLImportChild*); +#endif + void moveToFirst(HTMLImportChild*); + HTMLImportChild* firstImport() const { return m_imports[0]; } + bool isFirstImport(const HTMLImportChild* child) const { return m_imports.size() ? firstImport() == child : false; } + + bool isDone() const { return m_state == StateLoaded || m_state == StateError; } + bool hasError() const { return m_state == StateError; } + bool shouldBlockScriptExecution() const; + +#if !ENABLE(OILPAN) + void importDestroyed(); +#endif void startLoading(const ResourcePtr<RawResource>&); + + // Tells the loader that the parser is done with this import. + // Called by Document::finishedParsing, after DOMContentLoaded was dispatched. void didFinishParsing(); - bool isOwnedBy(const HTMLImport* import) const { return m_import == import; } + // Tells the loader that all of the import's stylesheets finished + // loading. + // Called by Document::didRemoveAllPendingStylesheet. + void didRemoveAllPendingStylesheet(); + + PassRefPtrWillBeRawPtr<CustomElementSyncMicrotaskQueue> microtaskQueue() const; + + virtual void trace(Visitor*); private: - HTMLImportLoader(HTMLImport*, ResourceFetcher*); + HTMLImportLoader(HTMLImportsController*); // RawResourceClient virtual void responseReceived(Resource*, const ResourceResponse&) OVERRIDE; @@ -84,16 +111,21 @@ private: State startWritingAndParsing(const ResourceResponse&); State finishWriting(); State finishParsing(); + State finishLoading(); void setState(State); - void didFinish(); - - HTMLImport* m_import; - ResourceFetcher* m_fetcher; - Vector<HTMLImportLoaderClient*> m_clients; + void didFinishLoading(); + bool hasPendingResources() const; +#if !ENABLE(OILPAN) + void clear(); +#endif + + RawPtrWillBeMember<HTMLImportsController> m_controller; + WillBeHeapVector<RawPtrWillBeMember<HTMLImportChild> > m_imports; State m_state; - RefPtr<Document> m_importedDocument; - RefPtr<DocumentWriter> m_writer; + RefPtrWillBeMember<Document> m_document; + RefPtrWillBeMember<DocumentWriter> m_writer; + RefPtrWillBeMember<CustomElementSyncMicrotaskQueue> m_microtaskQueue; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLShadowElement.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportState.h index 77741ecc588..356a40df39b 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLShadowElement.h +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportState.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -28,35 +28,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HTMLShadowElement_h -#define HTMLShadowElement_h +#ifndef HTMLImportState_h +#define HTMLImportState_h -#include "core/dom/shadow/InsertionPoint.h" -#include "wtf/Forward.h" +#include "wtf/Assertions.h" namespace WebCore { -class HTMLShadowElement FINAL : public InsertionPoint { +class HTMLImportState { public: - static PassRefPtr<HTMLShadowElement> create(Document&); + enum Value { + BlockingScriptExecution = 0, + Active, + Ready, + Invalid + }; - virtual ~HTMLShadowElement(); + explicit HTMLImportState(Value value = BlockingScriptExecution) + : m_value(value) + { } - ShadowRoot* olderShadowRoot(); + bool shouldBlockScriptExecution() const { return checkedValue() <= BlockingScriptExecution; } + bool isReady() const { return checkedValue() == Ready; } + bool isValid() const { return m_value != Invalid; } + bool operator==(const HTMLImportState& other) const { return m_value == other.m_value; } + bool operator!=(const HTMLImportState& other) const { return !(*this == other); } + bool operator<=(const HTMLImportState& other) const { return m_value <= other.m_value; } +#if !defined(NDEBUG) + Value peekValueForDebug() const { return m_value; } +#endif + + static HTMLImportState invalidState() { return HTMLImportState(Invalid); } + static HTMLImportState blockedState() { return HTMLImportState(BlockingScriptExecution); } private: - explicit HTMLShadowElement(Document&); - virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint) OVERRIDE; + Value checkedValue() const; + Value m_value; }; -inline bool isHTMLShadowElement(const Node* node) +inline HTMLImportState::Value HTMLImportState::checkedValue() const { - ASSERT(node); - return node->hasTagName(HTMLNames::shadowTag); + ASSERT(isValid()); + return m_value; } -DEFINE_NODE_TYPE_CASTS(HTMLShadowElement, hasTagName(HTMLNames::shadowTag)); - -} // namespace WebCore +} -#endif // HTMLShadowElement_h +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportStateResolver.cpp b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportStateResolver.cpp new file mode 100644 index 00000000000..9a1f2bfa534 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportStateResolver.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/html/imports/HTMLImportStateResolver.h" + +#include "core/html/imports/HTMLImport.h" +#include "core/html/imports/HTMLImportChild.h" +#include "core/html/imports/HTMLImportLoader.h" + +namespace WebCore { + +inline bool HTMLImportStateResolver::isBlockingFollowers(HTMLImport* import) +{ + if (!import->isSync()) + return false; + HTMLImportChild* child = toHTMLImportChild(import); + if (!child->loader()->isFirstImport(child)) + return false; + return !import->state().isReady(); +} + +inline bool HTMLImportStateResolver::shouldBlockScriptExecution() const +{ + // FIXME: Memoize to make this faster. + for (HTMLImport* ancestor = m_import; ancestor; ancestor = ancestor->parent()) { + for (HTMLImport* predecessor = ancestor->previous(); predecessor; predecessor = predecessor->previous()) { + if (isBlockingFollowers(predecessor)) + return true; + } + } + + for (HTMLImport* child = m_import->firstChild(); child; child = child->next()) { + if (isBlockingFollowers(child)) + return true; + } + + return false; +} + +inline bool HTMLImportStateResolver::isActive() const +{ + return !m_import->isDone(); +} + +HTMLImportState HTMLImportStateResolver::resolve() const +{ + if (shouldBlockScriptExecution()) + return HTMLImportState(HTMLImportState::BlockingScriptExecution); + if (isActive()) + return HTMLImportState(HTMLImportState::Active); + return HTMLImportState(HTMLImportState::Ready); +} + +} + diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportStateResolver.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportStateResolver.h new file mode 100644 index 00000000000..0850380bf62 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportStateResolver.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLImportStateResolver_h +#define HTMLImportStateResolver_h + +#include "core/html/imports/HTMLImportState.h" + +namespace WebCore { + +class HTMLImport; + +class HTMLImportStateResolver { +public: + explicit HTMLImportStateResolver(HTMLImport* import) + : m_import(import) + { } + + HTMLImportState resolve() const; + +private: + static bool isBlockingFollowers(HTMLImport*); + + bool shouldBlockScriptExecution() const; + bool isActive() const; + + HTMLImport* m_import; +}; + +} + +#endif // HTMLImportStateResolver_h + diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp new file mode 100644 index 00000000000..bfe0beded33 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp @@ -0,0 +1,110 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/imports/HTMLImportTreeRoot.h" + +#include "core/dom/Document.h" +#include "core/dom/StyleEngine.h" +#include "core/frame/LocalFrame.h" +#include "core/html/imports/HTMLImportChild.h" + +namespace WebCore { + +PassOwnPtrWillBeRawPtr<HTMLImportTreeRoot> HTMLImportTreeRoot::create(Document* document) +{ + return adoptPtrWillBeNoop(new HTMLImportTreeRoot(document)); +} + +HTMLImportTreeRoot::HTMLImportTreeRoot(Document* document) + : HTMLImport(HTMLImport::Sync) + , m_document(document) + , m_recalcTimer(this, &HTMLImportTreeRoot::recalcTimerFired) +{ + recalcTreeState(this); // This recomputes initial state. +} + +HTMLImportTreeRoot::~HTMLImportTreeRoot() +{ +#if !ENABLE(OILPAN) + for (size_t i = 0; i < m_imports.size(); ++i) + m_imports[i]->importDestroyed(); + m_imports.clear(); + m_document = nullptr; +#endif +} + +Document* HTMLImportTreeRoot::document() const +{ + return m_document; +} + +bool HTMLImportTreeRoot::isDone() const +{ + return !m_document->parsing() && m_document->styleEngine()->haveStylesheetsLoaded(); +} + +void HTMLImportTreeRoot::stateWillChange() +{ + scheduleRecalcState(); +} + +void HTMLImportTreeRoot::stateDidChange() +{ + HTMLImport::stateDidChange(); + + if (!state().isReady()) + return; + if (LocalFrame* frame = m_document->frame()) + frame->loader().checkCompleted(); +} + +void HTMLImportTreeRoot::scheduleRecalcState() +{ +#if ENABLE(OILPAN) + ASSERT(m_document); + if (m_recalcTimer.isActive() || !m_document->isActive()) + return; +#else + if (m_recalcTimer.isActive() || !m_document) + return; +#endif + m_recalcTimer.startOneShot(0, FROM_HERE); +} + +HTMLImportChild* HTMLImportTreeRoot::add(PassOwnPtrWillBeRawPtr<HTMLImportChild> child) +{ + m_imports.append(child); + return m_imports.last().get(); +} + +HTMLImportChild* HTMLImportTreeRoot::find(const KURL& url) const +{ + for (size_t i = 0; i < m_imports.size(); ++i) { + HTMLImportChild* candidate = m_imports[i].get(); + if (equalIgnoringFragmentIdentifier(candidate->url(), url)) + return candidate; + } + + return 0; +} + +void HTMLImportTreeRoot::recalcTimerFired(Timer<HTMLImportTreeRoot>*) +{ + ASSERT(m_document); + + do { + m_recalcTimer.stop(); + HTMLImport::recalcTreeState(this); + } while (m_recalcTimer.isActive()); +} + +void HTMLImportTreeRoot::trace(Visitor* visitor) +{ + visitor->trace(m_document); + visitor->trace(m_imports); + HTMLImport::trace(visitor); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h new file mode 100644 index 00000000000..6cd31168fd0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HTMLImportTreeRoot_h +#define HTMLImportTreeRoot_h + +#include "core/html/imports/HTMLImport.h" +#include "platform/Timer.h" +#include "wtf/PassOwnPtr.h" + +namespace WebCore { + +class HTMLImportChild; + +class HTMLImportTreeRoot : public HTMLImport { +public: + static PassOwnPtrWillBeRawPtr<HTMLImportTreeRoot> create(Document*); + + virtual ~HTMLImportTreeRoot(); + + // HTMLImport + virtual Document* document() const OVERRIDE; + virtual bool isDone() const OVERRIDE; + virtual void stateWillChange() OVERRIDE; + virtual void stateDidChange() OVERRIDE; + + void scheduleRecalcState(); + + HTMLImportChild* add(PassOwnPtrWillBeRawPtr<HTMLImportChild>); + HTMLImportChild* find(const KURL&) const; + + virtual void trace(Visitor*) OVERRIDE; + +private: + explicit HTMLImportTreeRoot(Document*); + + void recalcTimerFired(Timer<HTMLImportTreeRoot>*); + + RawPtrWillBeMember<Document> m_document; + Timer<HTMLImportTreeRoot> m_recalcTimer; + + // List of import which has been loaded or being loaded. + typedef WillBeHeapVector<OwnPtrWillBeMember<HTMLImportChild> > ImportList; + ImportList m_imports; +}; + +DEFINE_TYPE_CASTS(HTMLImportTreeRoot, HTMLImport, import, import->isRoot(), import.isRoot()); + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp new file mode 100644 index 00000000000..8afd0dd7449 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/html/imports/HTMLImportsController.h" + +#include "core/dom/Document.h" +#include "core/fetch/ResourceFetcher.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" +#include "core/html/imports/HTMLImportChild.h" +#include "core/html/imports/HTMLImportChildClient.h" +#include "core/html/imports/HTMLImportLoader.h" +#include "core/html/imports/HTMLImportTreeRoot.h" + +namespace WebCore { + +void HTMLImportsController::provideTo(Document& master) +{ + DEFINE_STATIC_LOCAL(const char*, name, ("HTMLImportsController")); + OwnPtrWillBeRawPtr<HTMLImportsController> controller = adoptPtrWillBeNoop(new HTMLImportsController(master)); + master.setImportsController(controller.get()); + DocumentSupplement::provideTo(master, name, controller.release()); +} + +HTMLImportsController::HTMLImportsController(Document& master) + : m_root(HTMLImportTreeRoot::create(&master)) +{ + UseCounter::count(master, UseCounter::HTMLImports); +} + +HTMLImportsController::~HTMLImportsController() +{ +#if !ENABLE(OILPAN) + ASSERT(!m_root); +#endif +} + +#if !ENABLE(OILPAN) +void HTMLImportsController::clear() +{ + Document* master = root()->document(); + m_root.clear(); + + for (size_t i = 0; i < m_loaders.size(); ++i) + m_loaders[i]->importDestroyed(); + m_loaders.clear(); + + if (master) + master->setImportsController(0); +} +#endif + +static bool makesCycle(HTMLImport* parent, const KURL& url) +{ + for (HTMLImport* ancestor = parent; ancestor; ancestor = ancestor->parent()) { + if (!ancestor->isRoot() && equalIgnoringFragmentIdentifier(toHTMLImportChild(parent)->url(), url)) + return true; + } + + return false; +} + +HTMLImportChild* HTMLImportsController::createChild(const KURL& url, HTMLImportLoader* loader, HTMLImport* parent, HTMLImportChildClient* client) +{ + HTMLImport::SyncMode mode = client->isSync() && !makesCycle(parent, url) ? HTMLImport::Sync : HTMLImport::Async; + if (mode == HTMLImport::Async) + UseCounter::count(root()->document(), UseCounter::HTMLImportsAsyncAttribute); + + OwnPtrWillBeRawPtr<HTMLImportChild> child = adoptPtrWillBeNoop(new HTMLImportChild(url, loader, mode)); + child->setClient(client); + parent->appendImport(child.get()); + loader->addImport(child.get()); + return root()->add(child.release()); +} + +HTMLImportChild* HTMLImportsController::load(HTMLImport* parent, HTMLImportChildClient* client, FetchRequest request) +{ + ASSERT(!request.url().isEmpty() && request.url().isValid()); + ASSERT(parent == root() || toHTMLImportChild(parent)->loader()->isFirstImport(toHTMLImportChild(parent))); + + if (HTMLImportChild* childToShareWith = root()->find(request.url())) { + HTMLImportLoader* loader = childToShareWith->loader(); + ASSERT(loader); + HTMLImportChild* child = createChild(request.url(), loader, parent, client); + child->didShareLoader(); + return child; + } + + bool sameOriginRequest = master()->securityOrigin()->canRequest(request.url()); + request.setCrossOriginAccessControl( + master()->securityOrigin(), sameOriginRequest ? AllowStoredCredentials : DoNotAllowStoredCredentials, + ClientDidNotRequestCredentials); + ResourcePtr<RawResource> resource = parent->document()->fetcher()->fetchImport(request); + if (!resource) + return 0; + + HTMLImportLoader* loader = createLoader(); + HTMLImportChild* child = createChild(request.url(), loader, parent, client); + // We set resource after the import tree is built since + // Resource::addClient() immediately calls back to feed the bytes when the resource is cached. + loader->startLoading(resource); + child->didStartLoading(); + return child; +} + +Document* HTMLImportsController::master() const +{ + return root()->document(); +} + +bool HTMLImportsController::shouldBlockScriptExecution(const Document& document) const +{ + ASSERT(document.importsController() == this); + if (HTMLImportLoader* loader = loaderFor(document)) + return loader->shouldBlockScriptExecution(); + return root()->state().shouldBlockScriptExecution(); +} + +#if !ENABLE(OILPAN) +void HTMLImportsController::wasDetachedFrom(const Document& document) +{ + ASSERT(document.importsController() == this); + if (master() == &document) + clear(); +} +#endif + +HTMLImportLoader* HTMLImportsController::createLoader() +{ + m_loaders.append(HTMLImportLoader::create(this)); + return m_loaders.last().get(); +} + +HTMLImportLoader* HTMLImportsController::loaderFor(const Document& document) const +{ + for (size_t i = 0; i < m_loaders.size(); ++i) { + if (m_loaders[i]->document() == &document) + return m_loaders[i].get(); + } + + return 0; +} + +Document* HTMLImportsController::loaderDocumentAt(size_t i) const +{ + return loaderAt(i)->document(); +} + +void HTMLImportsController::trace(Visitor* visitor) +{ + visitor->trace(m_root); + visitor->trace(m_loaders); + DocumentSupplement::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/HTMLImportsController.h b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h index 7cc1b92ea08..414fe464396 100644 --- a/chromium/third_party/WebKit/Source/core/html/HTMLImportsController.h +++ b/chromium/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h @@ -31,9 +31,10 @@ #ifndef HTMLImportsController_h #define HTMLImportsController_h +#include "core/dom/DocumentSupplementable.h" #include "core/fetch/RawResource.h" -#include "core/html/HTMLImport.h" #include "core/html/LinkResource.h" +#include "core/html/imports/HTMLImport.h" #include "platform/Supplementable.h" #include "platform/Timer.h" #include "wtf/FastAllocBase.h" @@ -47,47 +48,46 @@ class ExecutionContext; class ResourceFetcher; class HTMLImportChild; class HTMLImportChildClient; +class HTMLImportLoader; +class HTMLImportTreeRoot; -class HTMLImportsController : public HTMLImportRoot, public DocumentSupplement { - WTF_MAKE_FAST_ALLOCATED; +class HTMLImportsController FINAL : public NoBaseWillBeGarbageCollectedFinalized<HTMLImportsController>, public DocumentSupplement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLImportsController); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static void provideTo(Document*); + static void provideTo(Document&); - explicit HTMLImportsController(Document*); + explicit HTMLImportsController(Document&); virtual ~HTMLImportsController(); - // HTMLImport - virtual HTMLImportRoot* root() OVERRIDE; - virtual Document* document() const OVERRIDE; - virtual void wasDetachedFromDocument() OVERRIDE; - virtual void didFinishParsing() OVERRIDE; - virtual bool isProcessing() const OVERRIDE; - virtual bool isDone() const OVERRIDE; - - // HTMLImportRoot - virtual void blockerGone() OVERRIDE; - virtual HTMLImportsController* toController() OVERRIDE { return this; } - virtual HTMLImportChild* findLinkFor(const KURL&, HTMLImport* excluding = 0) const OVERRIDE; + HTMLImportTreeRoot* root() const { return m_root.get(); } + bool shouldBlockScriptExecution(const Document&) const; +#if !ENABLE(OILPAN) + void wasDetachedFrom(const Document&); +#endif HTMLImportChild* load(HTMLImport* parent, HTMLImportChildClient*, FetchRequest); - void showSecurityErrorMessage(const String&); - SecurityOrigin* securityOrigin() const; - ResourceFetcher* fetcher() const; + Document* master() const; + + HTMLImportLoader* createLoader(); - void scheduleUnblock(); - void unblockTimerFired(Timer<HTMLImportsController>*); + size_t loaderCount() const { return m_loaders.size(); } + HTMLImportLoader* loaderAt(size_t i) const { return m_loaders[i].get(); } + Document* loaderDocumentAt(size_t) const; + HTMLImportLoader* loaderFor(const Document&) const; + + virtual void trace(Visitor*); private: - HTMLImportChild* createChild(const KURL&, HTMLImport* parent, HTMLImportChildClient*); + HTMLImportChild* createChild(const KURL&, HTMLImportLoader*, HTMLImport* parent, HTMLImportChildClient*); +#if !ENABLE(OILPAN) void clear(); +#endif - Document* m_master; - Timer<HTMLImportsController> m_unblockTimer; - - // List of import which has been loaded or being loaded. - typedef Vector<OwnPtr<HTMLImportChild> > ImportList; - ImportList m_imports; + OwnPtrWillBeMember<HTMLImportTreeRoot> m_root; + typedef WillBeHeapVector<OwnPtrWillBeMember<HTMLImportLoader> > LoaderList; + LoaderList m_loaders; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/LinkImport.cpp b/chromium/third_party/WebKit/Source/core/html/imports/LinkImport.cpp index 18e5d4a51a7..0f5a9840211 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkImport.cpp +++ b/chromium/third_party/WebKit/Source/core/html/imports/LinkImport.cpp @@ -29,52 +29,60 @@ */ #include "config.h" -#include "core/html/LinkImport.h" +#include "core/html/imports/LinkImport.h" #include "core/dom/Document.h" #include "core/fetch/CrossOriginAccessControl.h" -#include "core/html/HTMLImportChild.h" -#include "core/html/HTMLImportsController.h" #include "core/html/HTMLLinkElement.h" - +#include "core/html/imports/HTMLImportChild.h" +#include "core/html/imports/HTMLImportLoader.h" +#include "core/html/imports/HTMLImportTreeRoot.h" +#include "core/html/imports/HTMLImportsController.h" namespace WebCore { -PassOwnPtr<LinkImport> LinkImport::create(HTMLLinkElement* owner) +PassOwnPtrWillBeRawPtr<LinkImport> LinkImport::create(HTMLLinkElement* owner) { - return adoptPtr(new LinkImport(owner)); + return adoptPtrWillBeNoop(new LinkImport(owner)); } LinkImport::LinkImport(HTMLLinkElement* owner) : LinkResource(owner) - , m_loader(0) + , m_child(nullptr) { } LinkImport::~LinkImport() { - clear(); +#if !ENABLE(OILPAN) + if (m_child) { + m_child->clearClient(); + m_child = nullptr; + } +#endif } Document* LinkImport::importedDocument() const { - if (!m_loader) + if (!m_child || !m_owner || !m_owner->inDocument()) + return 0; + if (m_child->loader()->hasError()) return 0; - return m_loader->importedDocument(); + return m_child->document(); } void LinkImport::process() { - if (m_loader) + if (m_child) return; if (!m_owner) return; if (!shouldLoadResource()) return; - if (!m_owner->document().import()) { + if (!m_owner->document().importsController()) { ASSERT(m_owner->document().frame()); // The document should be the master. - HTMLImportsController::provideTo(&m_owner->document()); + HTMLImportsController::provideTo(m_owner->document()); } LinkRequestBuilder builder(m_owner); @@ -83,44 +91,60 @@ void LinkImport::process() return; } - HTMLImport* parent = m_owner->document().import(); - HTMLImportsController* controller = parent->controller(); - m_loader = controller->load(parent, this, builder.build(true)); - if (!m_loader) { + HTMLImportsController* controller = m_owner->document().importsController(); + HTMLImportLoader* loader = m_owner->document().importLoader(); + HTMLImport* parent = loader ? static_cast<HTMLImport*>(loader->firstImport()) : static_cast<HTMLImport*>(controller->root()); + m_child = controller->load(parent, this, builder.build(true)); + if (!m_child) { didFinish(); return; } } -void LinkImport::clear() +void LinkImport::didFinish() { - m_owner = 0; - if (m_loader) { - m_loader->clearClient(); - m_loader = 0; - } + if (!m_owner || !m_owner->inDocument()) + return; + m_owner->scheduleEvent(); } -void LinkImport::ownerRemoved() +#if !ENABLE(OILPAN) +void LinkImport::importChildWasDestroyed(HTMLImportChild* child) { - clear(); + ASSERT(m_child == child); + m_child = nullptr; + m_owner = nullptr; } +#endif -void LinkImport::didFinish() +bool LinkImport::isSync() const { - if (!m_owner) - return; - m_owner->scheduleEvent(); + return m_owner && !m_owner->async(); } -void LinkImport::loaderWillBeDestroyed() +HTMLLinkElement* LinkImport::link() { - clear(); + return m_owner; } bool LinkImport::hasLoaded() const { - return m_loader && m_loader->isLoaded(); + // Should never be called after importChildWasDestroyed was called. + ASSERT(m_owner); + return m_child && m_child->isDone() && !m_child->loader()->hasError(); +} + +void LinkImport::ownerInserted() +{ + if (m_child) + m_child->ownerInserted(); +} + +void LinkImport::trace(Visitor* visitor) +{ + visitor->trace(m_child); + HTMLImportChildClient::trace(visitor); + LinkResource::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/LinkImport.h b/chromium/third_party/WebKit/Source/core/html/imports/LinkImport.h index bc2ec95bfb5..e56339f68dc 100644 --- a/chromium/third_party/WebKit/Source/core/html/LinkImport.h +++ b/chromium/third_party/WebKit/Source/core/html/imports/LinkImport.h @@ -31,8 +31,8 @@ #ifndef LinkImport_h #define LinkImport_h -#include "core/html/HTMLImportChildClient.h" #include "core/html/LinkResource.h" +#include "core/html/imports/HTMLImportChildClient.h" #include "wtf/FastAllocBase.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefPtr.h" @@ -45,11 +45,12 @@ class HTMLImportChild; // // A LinkResource subclasss used for @rel=import. // -class LinkImport : public LinkResource, public HTMLImportChildClient { - WTF_MAKE_FAST_ALLOCATED; +class LinkImport FINAL : public LinkResource, public HTMLImportChildClient { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(LinkImport); public: - static PassOwnPtr<LinkImport> create(HTMLLinkElement* owner); + static PassOwnPtrWillBeRawPtr<LinkImport> create(HTMLLinkElement* owner); explicit LinkImport(HTMLLinkElement* owner); virtual ~LinkImport(); @@ -57,19 +58,22 @@ public: // LinkResource virtual void process() OVERRIDE; virtual Type type() const OVERRIDE { return Import; } - virtual void ownerRemoved() OVERRIDE; virtual bool hasLoaded() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + virtual void ownerInserted() OVERRIDE; // HTMLImportChildClient virtual void didFinish() OVERRIDE; - virtual void loaderWillBeDestroyed() OVERRIDE; +#if !ENABLE(OILPAN) + virtual void importChildWasDestroyed(HTMLImportChild*) OVERRIDE; +#endif + virtual bool isSync() const OVERRIDE; + virtual HTMLLinkElement* link() OVERRIDE; Document* importedDocument() const; private: - void clear(); - - HTMLImportChild* m_loader; + RawPtrWillBeMember<HTMLImportChild> m_child; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h b/chromium/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h index 63e8c0c86dc..7254ab88480 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h @@ -26,7 +26,7 @@ #ifndef AtomicHTMLToken_h #define AtomicHTMLToken_h -#include "HTMLElementLookupTrie.h" +#include "core/HTMLElementLookupTrie.h" #include "core/dom/Attribute.h" #include "core/html/parser/CompactHTMLToken.h" #include "core/html/parser/HTMLToken.h" @@ -150,7 +150,7 @@ public: ASSERT_NOT_REACHED(); break; case HTMLToken::DOCTYPE: - m_name = token.data(); + m_name = AtomicString(token.data()); m_doctypeData = adoptPtr(new DoctypeData()); m_doctypeData->m_hasPublicIdentifier = true; append(m_doctypeData->m_publicIdentifier, token.publicIdentifier()); @@ -163,15 +163,15 @@ public: case HTMLToken::StartTag: m_attributes.reserveInitialCapacity(token.attributes().size()); for (Vector<CompactHTMLToken::Attribute>::const_iterator it = token.attributes().begin(); it != token.attributes().end(); ++it) { - QualifiedName name(nullAtom, it->name, nullAtom); + QualifiedName name(nullAtom, AtomicString(it->name), nullAtom); // FIXME: This is N^2 for the number of attributes. if (!findAttributeInVector(m_attributes, name)) - m_attributes.append(Attribute(name, it->value)); + m_attributes.append(Attribute(name, AtomicString(it->value))); } // Fall through! case HTMLToken::EndTag: m_selfClosing = token.selfClosing(); - m_name = token.data(); + m_name = AtomicString(token.data()); break; case HTMLToken::Character: case HTMLToken::Comment: @@ -233,9 +233,7 @@ inline void AtomicHTMLToken::initializeAttributes(const HTMLToken::AttributeList if (attribute.name.isEmpty()) continue; - // FIXME: We should be able to add the following ASSERT once we fix - // https://bugs.webkit.org/show_bug.cgi?id=62971 - // ASSERT(attribute.nameRange.start); + ASSERT(attribute.nameRange.start); ASSERT(attribute.nameRange.end); ASSERT(attribute.valueRange.start); ASSERT(attribute.valueRange.end); diff --git a/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp index b91dafd40b9..66a62b8d1e7 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp @@ -27,7 +27,7 @@ #include "core/html/parser/BackgroundHTMLParser.h" #include "core/html/parser/HTMLDocumentParser.h" -#include "core/html/parser/HTMLParserThread.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/html/parser/XSSAuditor.h" #include "wtf/MainThread.h" #include "wtf/text/TextPosition.h" @@ -76,6 +76,12 @@ static void checkThatXSSInfosAreSafeToSendToAnotherThread(const XSSInfoStream& i #endif +void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config) +{ + new BackgroundHTMLParser(reference, config); + // Caller must free by calling stop(). +} + BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config) : m_weakFactory(reference, this) , m_token(adoptPtr(new HTMLToken)) @@ -86,16 +92,62 @@ BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHT , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream)) , m_xssAuditor(config->xssAuditor.release()) , m_preloadScanner(config->preloadScanner.release()) + , m_decoder(config->decoder.release()) +{ +} + +BackgroundHTMLParser::~BackgroundHTMLParser() +{ +} + +void BackgroundHTMLParser::appendRawBytesFromParserThread(const char* data, int dataLength) { + ASSERT(m_decoder); + updateDocument(m_decoder->decode(data, dataLength)); } -void BackgroundHTMLParser::append(const String& input) +void BackgroundHTMLParser::appendRawBytesFromMainThread(PassOwnPtr<Vector<char> > buffer) +{ + ASSERT(m_decoder); + updateDocument(m_decoder->decode(buffer->data(), buffer->size())); +} + +void BackgroundHTMLParser::appendDecodedBytes(const String& input) { ASSERT(!m_input.current().isClosed()); m_input.append(input); pumpTokenizer(); } +void BackgroundHTMLParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) +{ + ASSERT(decoder); + m_decoder = decoder; +} + +void BackgroundHTMLParser::flush() +{ + ASSERT(m_decoder); + updateDocument(m_decoder->flush()); +} + +void BackgroundHTMLParser::updateDocument(const String& decodedData) +{ + DocumentEncodingData encodingData(*m_decoder.get()); + + if (encodingData != m_lastSeenEncodingData) { + m_lastSeenEncodingData = encodingData; + + m_xssAuditor->setEncoding(encodingData.encoding()); + callOnMainThread(bind(&HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser, m_parser, encodingData)); + } + + if (decodedData.isEmpty()) + return; + + appendDecodedBytes(decodedData); +} + void BackgroundHTMLParser::resumeFrom(PassOwnPtr<Checkpoint> checkpoint) { m_parser = checkpoint->parser; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h b/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h index b9b5a511c49..8d315a8f23e 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h @@ -26,14 +26,14 @@ #ifndef BackgroundHTMLParser_h #define BackgroundHTMLParser_h +#include "core/dom/DocumentEncodingData.h" #include "core/html/parser/BackgroundHTMLInputStream.h" #include "core/html/parser/CompactHTMLToken.h" #include "core/html/parser/HTMLParserOptions.h" #include "core/html/parser/HTMLPreloadScanner.h" #include "core/html/parser/HTMLSourceTracker.h" -#include "core/html/parser/HTMLToken.h" -#include "core/html/parser/HTMLTokenizer.h" #include "core/html/parser/HTMLTreeBuilderSimulator.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/html/parser/XSSAuditorDelegate.h" #include "wtf/PassOwnPtr.h" #include "wtf/WeakPtr.h" @@ -41,6 +41,7 @@ namespace WebCore { class HTMLDocumentParser; +class SharedBuffer; class XSSAuditor; class BackgroundHTMLParser { @@ -51,13 +52,10 @@ public: WeakPtr<HTMLDocumentParser> parser; OwnPtr<XSSAuditor> xssAuditor; OwnPtr<TokenPreloadScanner> preloadScanner; + OwnPtr<TextResourceDecoder> decoder; }; - static void create(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config) - { - new BackgroundHTMLParser(reference, config); - // Caller must free by calling stop(). - } + static void start(PassRefPtr<WeakReference<BackgroundHTMLParser> >, PassOwnPtr<Configuration>); struct Checkpoint { WeakPtr<HTMLDocumentParser> parser; @@ -69,7 +67,11 @@ public: String unparsedInput; }; - void append(const String&); + void appendRawBytesFromParserThread(const char* data, int dataLength); + + void appendRawBytesFromMainThread(PassOwnPtr<Vector<char> >); + void setDecoder(PassOwnPtr<TextResourceDecoder>); + void flush(); void resumeFrom(PassOwnPtr<Checkpoint>); void startedChunkWithCheckpoint(HTMLInputCheckpoint); void finish(); @@ -79,10 +81,13 @@ public: private: BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> >, PassOwnPtr<Configuration>); + ~BackgroundHTMLParser(); + void appendDecodedBytes(const String&); void markEndOfFile(); void pumpTokenizer(); void sendTokensToMainThread(); + void updateDocument(const String& decodedData); WeakPtrFactory<BackgroundHTMLParser> m_weakFactory; BackgroundHTMLInputStream m_input; @@ -99,6 +104,8 @@ private: OwnPtr<XSSAuditor> m_xssAuditor; OwnPtr<TokenPreloadScanner> m_preloadScanner; + OwnPtr<TextResourceDecoder> m_decoder; + DocumentEncodingData m_lastSeenEncodingData; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp b/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp index b1eea275aaa..042c52a86c8 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp @@ -28,7 +28,7 @@ #include "config.h" #include "core/html/parser/CSSPreloadScanner.h" -#include "FetchInitiatorTypeNames.h" +#include "core/FetchInitiatorTypeNames.h" #include "core/html/parser/HTMLParserIdioms.h" #include "platform/text/SegmentedString.h" diff --git a/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h b/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h index 7161a27434e..8c328997553 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.h @@ -33,7 +33,6 @@ namespace WebCore { -class HTMLIdentifier; class SegmentedString; class CSSPreloadScanner { diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp index 96dc2484b4b..71d5b6b14c8 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp @@ -25,19 +25,20 @@ */ #include "config.h" -#include "core/html/parser/HTMLTreeBuilder.h" +#include "core/html/parser/HTMLConstructionSite.h" -#include "HTMLElementFactory.h" -#include "HTMLNames.h" +#include "core/HTMLElementFactory.h" +#include "core/HTMLNames.h" #include "core/dom/Comment.h" #include "core/dom/DocumentFragment.h" #include "core/dom/DocumentType.h" #include "core/dom/Element.h" #include "core/dom/ScriptLoader.h" #include "core/dom/Text.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLHtmlElement.h" -#include "core/html/HTMLOptGroupElement.h" +#include "core/html/HTMLPlugInElement.h" #include "core/html/HTMLScriptElement.h" #include "core/html/HTMLTemplateElement.h" #include "core/html/parser/AtomicHTMLToken.h" @@ -46,7 +47,7 @@ #include "core/html/parser/HTMLToken.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" +#include "core/svg/SVGScriptElement.h" #include "platform/NotImplemented.h" #include "platform/text/TextBreakIterator.h" #include <limits> @@ -70,20 +71,20 @@ static bool hasImpliedEndTag(const HTMLStackItem* item) || item->hasTagName(dtTag) || item->hasTagName(liTag) || item->hasTagName(optionTag) - || isHTMLOptGroupElement(item->node()) + || item->hasTagName(optgroupTag) || item->hasTagName(pTag) || item->hasTagName(rpTag) || item->hasTagName(rtTag); } -static bool shouldUseLengthLimit(const ContainerNode* node) +static bool shouldUseLengthLimit(const ContainerNode& node) { - return !node->hasTagName(scriptTag) - && !node->hasTagName(styleTag) - && !node->hasTagName(SVGNames::scriptTag); + return !isHTMLScriptElement(node) + && !isHTMLStyleElement(node) + && !isSVGScriptElement(node); } -static unsigned textLengthLimitForContainer(const ContainerNode* node) +static unsigned textLengthLimitForContainer(const ContainerNode& node) { return shouldUseLengthLimit(node) ? Text::defaultLengthLimit : std::numeric_limits<unsigned>::max(); } @@ -95,7 +96,7 @@ static inline bool isAllWhitespace(const String& string) static inline void insert(HTMLConstructionSiteTask& task) { - if (task.parent->hasTagName(templateTag)) + if (isHTMLTemplateElement(*task.parent)) task.parent = toHTMLTemplateElement(task.parent.get())->content(); if (ContainerNode* parent = task.child->parentNode()) @@ -113,10 +114,12 @@ static inline void executeInsertTask(HTMLConstructionSiteTask& task) insert(task); - task.child->beginParsingChildren(); - - if (task.selfClosing) - task.child->finishParsingChildren(); + if (task.child->isElementNode()) { + Element& child = toElement(*task.child); + child.beginParsingChildren(); + if (task.selfClosing) + child.finishParsingChildren(); + } } static inline void executeInsertTextTask(HTMLConstructionSiteTask& task) @@ -130,7 +133,7 @@ static inline void executeInsertTextTask(HTMLConstructionSiteTask& task) Node* previousChild = task.nextChild ? task.nextChild->previousSibling() : task.parent->lastChild(); if (previousChild && previousChild->isTextNode()) { Text* previousText = toText(previousChild); - unsigned lengthLimit = textLengthLimitForContainer(task.parent.get()); + unsigned lengthLimit = textLengthLimitForContainer(*task.parent); if (previousText->length() + newText->length() < lengthLimit) { previousText->parserAppendData(newText->data()); return; @@ -238,7 +241,7 @@ void HTMLConstructionSite::flushPendingText() // Splitting text nodes into smaller chunks contradicts HTML5 spec, but is necessary // for performance, see: https://bugs.webkit.org/show_bug.cgi?id=55898 - unsigned lengthLimit = textLengthLimitForContainer(pendingText.parent.get()); + unsigned lengthLimit = textLengthLimitForContainer(*pendingText.parent); unsigned currentPosition = 0; const StringBuilder& string = pendingText.stringBuilder; @@ -269,10 +272,10 @@ void HTMLConstructionSite::queueTask(const HTMLConstructionSiteTask& task) m_taskQueue.append(task); } -void HTMLConstructionSite::attachLater(ContainerNode* parent, PassRefPtr<Node> prpChild, bool selfClosing) +void HTMLConstructionSite::attachLater(ContainerNode* parent, PassRefPtrWillBeRawPtr<Node> prpChild, bool selfClosing) { ASSERT(scriptingContentIsAllowed(m_parserContentPolicy) || !prpChild.get()->isElementNode() || !toScriptLoaderIfPossible(toElement(prpChild.get()))); - ASSERT(pluginContentIsAllowed(m_parserContentPolicy) || !prpChild->isPluginElement()); + ASSERT(pluginContentIsAllowed(m_parserContentPolicy) || !isHTMLPlugInElement(prpChild)); HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Insert); task.parent = parent; @@ -343,14 +346,26 @@ HTMLConstructionSite::~HTMLConstructionSite() ASSERT(m_pendingText.isEmpty()); } +void HTMLConstructionSite::trace(Visitor* visitor) +{ + visitor->trace(m_document); + visitor->trace(m_attachmentRoot); + visitor->trace(m_head); + visitor->trace(m_form); + visitor->trace(m_openElements); + visitor->trace(m_activeFormattingElements); + visitor->trace(m_taskQueue); + visitor->trace(m_pendingText); +} + void HTMLConstructionSite::detach() { // FIXME: We'd like to ASSERT here that we're canceling and not just discarding // text that really should have made it into the DOM earlier, but there // doesn't seem to be a nice way to do that. m_pendingText.discard(); - m_document = 0; - m_attachmentRoot = 0; + m_document = nullptr; + m_attachmentRoot = nullptr; } void HTMLConstructionSite::setForm(HTMLFormElement* form) @@ -360,7 +375,7 @@ void HTMLConstructionSite::setForm(HTMLFormElement* form) m_form = form; } -PassRefPtr<HTMLFormElement> HTMLConstructionSite::takeForm() +PassRefPtrWillBeRawPtr<HTMLFormElement> HTMLConstructionSite::takeForm() { return m_form.release(); } @@ -375,7 +390,7 @@ void HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded() void HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken* token) { ASSERT(m_document); - RefPtr<HTMLHtmlElement> element = HTMLHtmlElement::create(*m_document); + RefPtrWillBeRawPtr<HTMLHtmlElement> element = HTMLHtmlElement::create(*m_document); setAttributes(element.get(), token, m_parserContentPolicy); attachLater(m_attachmentRoot, element); m_openElements.pushHTMLHtmlElement(HTMLStackItem::create(element, token)); @@ -392,7 +407,7 @@ void HTMLConstructionSite::mergeAttributesFromTokenIntoElement(AtomicHTMLToken* for (unsigned i = 0; i < token->attributes().size(); ++i) { const Attribute& tokenAttribute = token->attributes().at(i); - if (!element->elementData() || !element->getAttributeItem(tokenAttribute.name())) + if (!element->elementData() || !element->findAttributeByName(tokenAttribute.name())) element->setAttribute(tokenAttribute.name(), tokenAttribute.value()); } } @@ -416,8 +431,6 @@ void HTMLConstructionSite::setDefaultCompatibilityMode() { if (m_isParsingFragment) return; - if (m_document->isSrcdocDocument()) - return; setCompatibilityMode(Document::QuirksMode); } @@ -536,7 +549,7 @@ void HTMLConstructionSite::insertDoctype(AtomicHTMLToken* token) const String& publicId = StringImpl::create8BitIfPossible(token->publicIdentifier()); const String& systemId = StringImpl::create8BitIfPossible(token->systemIdentifier()); - RefPtr<DocumentType> doctype = DocumentType::create(m_document, token->name(), publicId, systemId); + RefPtrWillBeRawPtr<DocumentType> doctype = DocumentType::create(m_document, token->name(), publicId, systemId); attachLater(m_attachmentRoot, doctype.release()); // DOCTYPE nodes are only processed when parsing fragments w/o contextElements, which @@ -586,26 +599,26 @@ void HTMLConstructionSite::insertHTMLHeadElement(AtomicHTMLToken* token) void HTMLConstructionSite::insertHTMLBodyElement(AtomicHTMLToken* token) { ASSERT(!shouldFosterParent()); - RefPtr<Element> body = createHTMLElement(token); + RefPtrWillBeRawPtr<Element> body = createHTMLElement(token); attachLater(currentNode(), body); m_openElements.pushHTMLBodyElement(HTMLStackItem::create(body.release(), token)); - if (Frame* frame = m_document->frame()) + if (LocalFrame* frame = m_document->frame()) frame->loader().client()->dispatchWillInsertBody(); } void HTMLConstructionSite::insertHTMLFormElement(AtomicHTMLToken* token, bool isDemoted) { - RefPtr<Element> element = createHTMLElement(token); - ASSERT(element->hasTagName(formTag)); + RefPtrWillBeRawPtr<Element> element = createHTMLElement(token); + ASSERT(isHTMLFormElement(element)); m_form = static_pointer_cast<HTMLFormElement>(element.release()); m_form->setDemoted(isDemoted); - attachLater(currentNode(), m_form); - m_openElements.push(HTMLStackItem::create(m_form, token)); + attachLater(currentNode(), m_form.get()); + m_openElements.push(HTMLStackItem::create(m_form.get(), token)); } void HTMLConstructionSite::insertHTMLElement(AtomicHTMLToken* token) { - RefPtr<Element> element = createHTMLElement(token); + RefPtrWillBeRawPtr<Element> element = createHTMLElement(token); attachLater(currentNode(), element); m_openElements.push(HTMLStackItem::create(element.release(), token)); } @@ -639,7 +652,7 @@ void HTMLConstructionSite::insertScriptElement(AtomicHTMLToken* token) // those flags or effects thereof. const bool parserInserted = m_parserContentPolicy != AllowScriptingContentAndDoNotMarkAlreadyStarted; const bool alreadyStarted = m_isParsingFragment && parserInserted; - RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(ownerDocumentForCurrentNode(), parserInserted, alreadyStarted); + RefPtrWillBeRawPtr<HTMLScriptElement> element = HTMLScriptElement::create(ownerDocumentForCurrentNode(), parserInserted, alreadyStarted); setAttributes(element.get(), token, m_parserContentPolicy); if (scriptingContentIsAllowed(m_parserContentPolicy)) attachLater(currentNode(), element); @@ -651,7 +664,7 @@ void HTMLConstructionSite::insertForeignElement(AtomicHTMLToken* token, const At ASSERT(token->type() == HTMLToken::StartTag); notImplemented(); // parseError when xmlns or xmlns:xlink are wrong. - RefPtr<Element> element = createElement(token, namespaceURI); + RefPtrWillBeRawPtr<Element> element = createElement(token, namespaceURI); if (scriptingContentIsAllowed(m_parserContentPolicy) || !toScriptLoaderIfPossible(element.get())) attachLater(currentNode(), element, token->selfClosing()); if (!token->selfClosing()) @@ -667,7 +680,7 @@ void HTMLConstructionSite::insertTextNode(const String& string, WhitespaceMode w findFosterSite(dummyTask); // FIXME: This probably doesn't need to be done both here and in insert(Task). - if (dummyTask.parent->hasTagName(templateTag)) + if (isHTMLTemplateElement(*dummyTask.parent)) dummyTask.parent = toHTMLTemplateElement(dummyTask.parent.get())->content(); // Unclear when parent != case occurs. Somehow we insert text into two separate nodes while processing the same Token. @@ -715,22 +728,22 @@ void HTMLConstructionSite::takeAllChildren(HTMLStackItem* newParent, HTMLElement queueTask(task); } -PassRefPtr<Element> HTMLConstructionSite::createElement(AtomicHTMLToken* token, const AtomicString& namespaceURI) +PassRefPtrWillBeRawPtr<Element> HTMLConstructionSite::createElement(AtomicHTMLToken* token, const AtomicString& namespaceURI) { QualifiedName tagName(nullAtom, token->name(), namespaceURI); - RefPtr<Element> element = ownerDocumentForCurrentNode().createElement(tagName, true); + RefPtrWillBeRawPtr<Element> element = ownerDocumentForCurrentNode().createElement(tagName, true); setAttributes(element.get(), token, m_parserContentPolicy); return element.release(); } inline Document& HTMLConstructionSite::ownerDocumentForCurrentNode() { - if (currentNode()->hasTagName(templateTag)) + if (isHTMLTemplateElement(*currentNode())) return toHTMLTemplateElement(currentElement())->content()->document(); return currentNode()->document(); } -PassRefPtr<Element> HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token) +PassRefPtrWillBeRawPtr<Element> HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token) { Document& document = ownerDocumentForCurrentNode(); // Only associate the element with the current form if we're creating the new element @@ -739,15 +752,15 @@ PassRefPtr<Element> HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* tok // FIXME: This can't use HTMLConstructionSite::createElement because we // have to pass the current form element. We should rework form association // to occur after construction to allow better code sharing here. - RefPtr<Element> element = HTMLElementFactory::createHTMLElement(token->name(), document, form, true); + RefPtrWillBeRawPtr<Element> element = HTMLElementFactory::createHTMLElement(token->name(), document, form, true); setAttributes(element.get(), token, m_parserContentPolicy); ASSERT(element->isHTMLElement()); return element.release(); } -PassRefPtr<HTMLStackItem> HTMLConstructionSite::createElementFromSavedToken(HTMLStackItem* item) +PassRefPtrWillBeRawPtr<HTMLStackItem> HTMLConstructionSite::createElementFromSavedToken(HTMLStackItem* item) { - RefPtr<Element> element; + RefPtrWillBeRawPtr<Element> element; // NOTE: Moving from item -> token -> item copies the Attribute vector twice! AtomicHTMLToken fakeToken(HTMLToken::StartTag, item->localName(), item->attributes()); if (item->namespaceURI() == HTMLNames::xhtmlNamespaceURI) @@ -784,7 +797,7 @@ void HTMLConstructionSite::reconstructTheActiveFormattingElements() ASSERT(unopenEntryIndex < m_activeFormattingElements.size()); for (; unopenEntryIndex < m_activeFormattingElements.size(); ++unopenEntryIndex) { HTMLFormattingElementList::Entry& unopenedEntry = m_activeFormattingElements.at(unopenEntryIndex); - RefPtr<HTMLStackItem> reconstructed = createElementFromSavedToken(unopenedEntry.stackItem().get()); + RefPtrWillBeRawPtr<HTMLStackItem> reconstructed = createElementFromSavedToken(unopenedEntry.stackItem().get()); attachLater(currentNode(), reconstructed->node()); m_openElements.push(reconstructed); unopenedEntry.replaceElement(reconstructed.release()); @@ -847,7 +860,7 @@ bool HTMLConstructionSite::shouldFosterParent() const && currentStackItem()->causesFosterParenting(); } -void HTMLConstructionSite::fosterParent(PassRefPtr<Node> node) +void HTMLConstructionSite::fosterParent(PassRefPtrWillBeRawPtr<Node> node) { HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Insert); findFosterSite(task); @@ -856,4 +869,11 @@ void HTMLConstructionSite::fosterParent(PassRefPtr<Node> node) queueTask(task); } +void HTMLConstructionSite::PendingText::trace(Visitor* visitor) +{ + visitor->trace(parent); + visitor->trace(nextChild); +} + + } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h index d4d812eb109..0bd25a0fa62 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h @@ -27,6 +27,7 @@ #ifndef HTMLConstructionSite_h #define HTMLConstructionSite_h +#include "core/dom/Document.h" #include "core/dom/ParserContentPolicy.h" #include "core/html/parser/HTMLElementStack.h" #include "core/html/parser/HTMLFormattingElementList.h" @@ -39,6 +40,8 @@ namespace WebCore { struct HTMLConstructionSiteTask { + ALLOW_ONLY_INLINE_ALLOCATION(); +public: enum Operation { Insert, InsertText, // Handles possible merging of text nodes. @@ -53,6 +56,13 @@ struct HTMLConstructionSiteTask { { } + void trace(Visitor* visitor) + { + visitor->trace(parent); + visitor->trace(nextChild); + visitor->trace(child); + } + ContainerNode* oldParent() { // It's sort of ugly, but we store the |oldParent| in the |child| field @@ -62,17 +72,15 @@ struct HTMLConstructionSiteTask { } Operation operation; - RefPtr<ContainerNode> parent; - RefPtr<Node> nextChild; - RefPtr<Node> child; + RefPtrWillBeMember<ContainerNode> parent; + RefPtrWillBeMember<Node> nextChild; + RefPtrWillBeMember<Node> child; bool selfClosing; }; } // namespace WebCore -namespace WTF { -template<> struct VectorTraits<WebCore::HTMLConstructionSiteTask> : SimpleClassVectorTraits { }; -} // namespace WTF +WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::HTMLConstructionSiteTask); namespace WebCore { @@ -89,12 +97,14 @@ class Document; class Element; class HTMLFormElement; -class HTMLConstructionSite { +class HTMLConstructionSite FINAL { WTF_MAKE_NONCOPYABLE(HTMLConstructionSite); + DISALLOW_ALLOCATION(); public: HTMLConstructionSite(Document*, ParserContentPolicy); HTMLConstructionSite(DocumentFragment*, ParserContentPolicy); ~HTMLConstructionSite(); + void trace(Visitor*); void detach(); @@ -150,10 +160,10 @@ public: void insertAlreadyParsedChild(HTMLStackItem* newParent, HTMLElementStack::ElementRecord* child); void takeAllChildren(HTMLStackItem* newParent, HTMLElementStack::ElementRecord* oldParent); - PassRefPtr<HTMLStackItem> createElementFromSavedToken(HTMLStackItem*); + PassRefPtrWillBeRawPtr<HTMLStackItem> createElementFromSavedToken(HTMLStackItem*); bool shouldFosterParent() const; - void fosterParent(PassRefPtr<Node>); + void fosterParent(PassRefPtrWillBeRawPtr<Node>); bool indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const; void reconstructTheActiveFormattingElements(); @@ -179,7 +189,7 @@ public: void setForm(HTMLFormElement*); HTMLFormElement* form() const { return m_form.get(); } - PassRefPtr<HTMLFormElement> takeForm(); + PassRefPtrWillBeRawPtr<HTMLFormElement> takeForm(); ParserContentPolicy parserContentPolicy() { return m_parserContentPolicy; } @@ -206,17 +216,17 @@ public: private: // In the common case, this queue will have only one task because most // tokens produce only one DOM mutation. - typedef Vector<HTMLConstructionSiteTask, 1> TaskQueue; + typedef WillBeHeapVector<HTMLConstructionSiteTask, 1> TaskQueue; void setCompatibilityMode(Document::CompatibilityMode); void setCompatibilityModeFromDoctype(const String& name, const String& publicId, const String& systemId); - void attachLater(ContainerNode* parent, PassRefPtr<Node> child, bool selfClosing = false); + void attachLater(ContainerNode* parent, PassRefPtrWillBeRawPtr<Node> child, bool selfClosing = false); void findFosterSite(HTMLConstructionSiteTask&); - PassRefPtr<Element> createHTMLElement(AtomicHTMLToken*); - PassRefPtr<Element> createElement(AtomicHTMLToken*, const AtomicString& namespaceURI); + PassRefPtrWillBeRawPtr<Element> createHTMLElement(AtomicHTMLToken*); + PassRefPtrWillBeRawPtr<Element> createElement(AtomicHTMLToken*, const AtomicString& namespaceURI); void mergeAttributesFromTokenIntoElement(AtomicHTMLToken*, Element*); void dispatchDocumentElementAvailableIfNeeded(); @@ -224,27 +234,29 @@ private: void executeTask(HTMLConstructionSiteTask&); void queueTask(const HTMLConstructionSiteTask&); - Document* m_document; + RawPtrWillBeMember<Document> m_document; // This is the root ContainerNode to which the parser attaches all newly // constructed nodes. It points to a DocumentFragment when parsing fragments // and a Document in all other cases. - ContainerNode* m_attachmentRoot; + RawPtrWillBeMember<ContainerNode> m_attachmentRoot; - RefPtr<HTMLStackItem> m_head; - RefPtr<HTMLFormElement> m_form; + RefPtrWillBeMember<HTMLStackItem> m_head; + RefPtrWillBeMember<HTMLFormElement> m_form; mutable HTMLElementStack m_openElements; mutable HTMLFormattingElementList m_activeFormattingElements; TaskQueue m_taskQueue; - struct PendingText { + class PendingText FINAL { + DISALLOW_ALLOCATION(); + public: PendingText() : whitespaceMode(WhitespaceUnknown) { } - void append(PassRefPtr<ContainerNode> newParent, PassRefPtr<Node> newNextChild, const String& newString, WhitespaceMode newWhitespaceMode) + void append(PassRefPtrWillBeRawPtr<ContainerNode> newParent, PassRefPtrWillBeRawPtr<Node> newNextChild, const String& newString, WhitespaceMode newWhitespaceMode) { ASSERT(!parent || parent == newParent); parent = newParent; @@ -277,8 +289,10 @@ private: return stringBuilder.isEmpty(); } - RefPtr<ContainerNode> parent; - RefPtr<Node> nextChild; + void trace(Visitor*); + + RefPtrWillBeMember<ContainerNode> parent; + RefPtrWillBeMember<Node> nextChild; StringBuilder stringBuilder; WhitespaceMode whitespaceMode; }; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index 2008ae5f0e1..e5a4d251b1c 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp @@ -26,9 +26,11 @@ #include "config.h" #include "core/html/parser/HTMLDocumentParser.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/css/MediaValuesCached.h" #include "core/dom/DocumentFragment.h" #include "core/dom/Element.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLDocument.h" #include "core/html/parser/AtomicHTMLToken.h" #include "core/html/parser/BackgroundHTMLParser.h" @@ -37,8 +39,11 @@ #include "core/html/parser/HTMLScriptRunner.h" #include "core/html/parser/HTMLTreeBuilder.h" #include "core/inspector/InspectorInstrumentation.h" -#include "core/frame/Frame.h" +#include "core/inspector/InspectorTraceEvents.h" +#include "core/loader/DocumentLoader.h" +#include "platform/SharedBuffer.h" #include "platform/TraceEvent.h" +#include "public/platform/WebThreadedDataReceiver.h" #include "wtf/Functional.h" namespace WebCore { @@ -70,17 +75,44 @@ static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem return HTMLTokenizer::DataState; } -HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors) +class ParserDataReceiver : public blink::WebThreadedDataReceiver { +public: + explicit ParserDataReceiver(WeakPtr<BackgroundHTMLParser> backgroundParser) + : m_backgroundParser(backgroundParser) + { + } + + // WebThreadedDataReceiver + virtual void acceptData(const char* data, int dataLength) OVERRIDE FINAL + { + ASSERT(backgroundThread() && backgroundThread()->isCurrentThread()); + if (m_backgroundParser.get()) + m_backgroundParser.get()->appendRawBytesFromParserThread(data, dataLength); + } + + virtual blink::WebThread* backgroundThread() OVERRIDE FINAL + { + if (HTMLParserThread::shared()) + return &HTMLParserThread::shared()->platformThread(); + + return 0; + } + +private: + WeakPtr<BackgroundHTMLParser> m_backgroundParser; +}; + +HTMLDocumentParser::HTMLDocumentParser(HTMLDocument& document, bool reportErrors) : ScriptableDocumentParser(document) - , m_options(document) + , m_options(&document) , m_token(m_options.useThreading ? nullptr : adoptPtr(new HTMLToken)) , m_tokenizer(m_options.useThreading ? nullptr : HTMLTokenizer::create(m_options)) - , m_scriptRunner(HTMLScriptRunner::create(document, this)) - , m_treeBuilder(HTMLTreeBuilder::create(this, document, parserContentPolicy(), reportErrors, m_options)) + , m_scriptRunner(HTMLScriptRunner::create(&document, this)) + , m_treeBuilder(HTMLTreeBuilder::create(this, &document, parserContentPolicy(), reportErrors, m_options)) , m_parserScheduler(HTMLParserScheduler::create(this)) - , m_xssAuditorDelegate(document) + , m_xssAuditorDelegate(&document) , m_weakFactory(this) - , m_preloader(adoptPtr(new HTMLResourcePreloader(document))) + , m_preloader(adoptPtr(new HTMLResourcePreloader(&document))) , m_isPinnedToMainThread(false) , m_endWasDelayed(false) , m_haveBackgroundParser(false) @@ -92,7 +124,7 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors // FIXME: Member variables should be grouped into self-initializing structs to // minimize code duplication between these constructors. HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) - : ScriptableDocumentParser(&fragment->document(), parserContentPolicy) + : ScriptableDocumentParser(fragment->document(), parserContentPolicy) , m_options(&fragment->document()) , m_token(adoptPtr(new HTMLToken)) , m_tokenizer(HTMLTokenizer::create(m_options)) @@ -112,6 +144,12 @@ HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont HTMLDocumentParser::~HTMLDocumentParser() { +#if ENABLE(OILPAN) + if (m_haveBackgroundParser) + stopBackgroundParser(); + // In Oilpan, HTMLDocumentParser can die together with Document, and + // detach() is not called in this case. +#else ASSERT(!m_parserScheduler); ASSERT(!m_pumpSessionNestingLevel); ASSERT(!m_preloadScanner); @@ -120,6 +158,15 @@ HTMLDocumentParser::~HTMLDocumentParser() // FIXME: We should be able to ASSERT(m_speculations.isEmpty()), // but there are cases where that's not true currently. For example, // we we're told to stop parsing before we've consumed all the input. +#endif +} + +void HTMLDocumentParser::trace(Visitor* visitor) +{ + visitor->trace(m_treeBuilder); + visitor->trace(m_scriptRunner); + ScriptableDocumentParser::trace(visitor); + HTMLScriptRunnerHost::trace(visitor); } void HTMLDocumentParser::pinToMainThread() @@ -167,7 +214,7 @@ void HTMLDocumentParser::prepareToStopParsing() // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); // NOTE: This pump should only ever emit buffered character tokens, // so ForceSynchronous vs. AllowYield should be meaningless. @@ -230,7 +277,7 @@ void HTMLDocumentParser::resumeParsingAfterYield() ASSERT(!m_isPinnedToMainThread); // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); if (m_haveBackgroundParser) { pumpPendingSpeculations(); @@ -248,7 +295,7 @@ void HTMLDocumentParser::runScriptsForPausedTreeBuilder() ASSERT(scriptingContentIsAllowed(parserContentPolicy())); TextPosition scriptStartPosition = TextPosition::belowRangePosition(); - RefPtr<Element> scriptElement = m_treeBuilder->takeScriptToProcess(scriptStartPosition); + RefPtrWillBeRawPtr<Element> scriptElement = m_treeBuilder->takeScriptToProcess(scriptStartPosition); // We will not have a scriptRunner when parsing a DocumentFragment. if (m_scriptRunner) m_scriptRunner->execute(scriptElement.release(), scriptStartPosition); @@ -263,7 +310,7 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses if (isWaitingForScripts()) { if (mode == AllowYield) - m_parserScheduler->checkForYieldBeforeScript(session); + session.didSeeScript = true; // If we don't run the script, we cannot allow the next token to be taken. if (session.needsYield) @@ -278,7 +325,7 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses } // FIXME: It's wrong for the HTMLDocumentParser to reach back to the - // Frame, but this approach is how the old parser handled + // LocalFrame, but this approach is how the old parser handled // stopping when the page assigns window.location. What really // should happen is that assigning window.location causes the // parser to stop parsing cleanly. The problem is we're not @@ -308,7 +355,7 @@ void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa // processParsedChunkFromBackgroundParser can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); ASSERT(m_speculations.isEmpty()); chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately. @@ -316,6 +363,11 @@ void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa pumpPendingSpeculations(); } +void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const DocumentEncodingData& data) +{ + document()->setEncodingData(data); +} + void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) { ASSERT(chunk); @@ -382,8 +434,10 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse ASSERT(!isParsingFragment()); ASSERT(!isWaitingForScripts()); ASSERT(!isStopped()); +#if !ENABLE(OILPAN) // ASSERT that this object is both attached to the Document and protected. ASSERT(refCount() >= 2); +#endif ASSERT(shouldUseThreading()); ASSERT(!m_tokenizer); ASSERT(!m_token); @@ -406,8 +460,7 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != tokens->end(); ++it) { ASSERT(!isWaitingForScripts()); - if (!isParsingFragment() - && document()->frame() && document()->frame()->navigationScheduler().locationChangePending()) { + if (document()->frame() && document()->frame()->navigationScheduler().locationChangePending()) { // To match main-thread parser behavior (which never checks locationChangePending on the EOF path) // we peek to see if this chunk has an EOF and process it anyway. @@ -442,6 +495,10 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse ASSERT(!m_tokenizer); ASSERT(!m_token); } + + // Make sure any pending text nodes are emitted before returning. + if (!isStopped()) + m_treeBuilder->flush(); } void HTMLDocumentParser::pumpPendingSpeculations() @@ -449,8 +506,10 @@ void HTMLDocumentParser::pumpPendingSpeculations() // FIXME: Share this constant with the parser scheduler. const double parserTimeLimit = 0.500; +#if !ENABLE(OILPAN) // ASSERT that this object is both attached to the Document and protected. ASSERT(refCount() >= 2); +#endif // If this assert fails, you need to call validateSpeculations to make sure // m_tokenizer and m_token don't have state that invalidates m_speculations. ASSERT(!m_tokenizer); @@ -460,6 +519,9 @@ void HTMLDocumentParser::pumpPendingSpeculations() ASSERT(!isStopped()); // FIXME: Pass in current input length. + TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ParseHTML", "beginData", InspectorParseHtmlEvent::beginData(document(), lineNumber().zeroBasedInt())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willWriteHTML(document(), lineNumber().zeroBasedInt()); double startTime = currentTime(); @@ -467,11 +529,8 @@ void HTMLDocumentParser::pumpPendingSpeculations() while (!m_speculations.isEmpty()) { processParsedChunkFromBackgroundParser(m_speculations.takeFirst()); - // The order matters! If this isStopped(), isWaitingForScripts() can hit and ASSERT since - // m_document can be null which is used to decide the readiness. - if (isStopped()) - break; - if (isWaitingForScripts()) + // Always check isStopped first as m_document may be null. + if (isStopped() || isWaitingForScripts()) break; if (currentTime() - startTime > parserTimeLimit && !m_speculations.isEmpty()) { @@ -480,7 +539,10 @@ void HTMLDocumentParser::pumpPendingSpeculations() } } + TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ParseHTML", "endLine", lineNumber().zeroBasedInt()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didWriteHTML(cookie, lineNumber().zeroBasedInt()); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); } void HTMLDocumentParser::forcePlaintextForTextDocument() @@ -505,12 +567,22 @@ Document* HTMLDocumentParser::contextForParsingSession() return document(); } +static PassRefPtr<MediaValues> createMediaValues(Document* document) +{ + ASSERT(document); + RefPtr<MediaValues> mediaValues = MediaValuesCached::create(*document); + ASSERT(mediaValues->isSafeToSendToAnotherThread()); + return mediaValues; +} + void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) { ASSERT(!isStopped()); ASSERT(!isScheduledForResume()); +#if !ENABLE(OILPAN) // ASSERT that this object is both attached to the Document and protected. ASSERT(refCount() >= 2); +#endif ASSERT(m_tokenizer); ASSERT(m_token); ASSERT(!m_haveBackgroundParser || mode == ForceSynchronous); @@ -522,6 +594,9 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) // FIXME: m_input.current().length() is only accurate if we // end up parsing the whole buffer in this pump. We should pass how // much we parsed as part of didWriteHTML instead of willWriteHTML. + TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ParseHTML", "beginData", InspectorParseHtmlEvent::beginData(document(), m_input.current().currentLine().zeroBasedInt())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willWriteHTML(document(), m_input.current().currentLine().zeroBasedInt()); m_xssAuditor.init(document(), &m_xssAuditorDelegate); @@ -546,9 +621,11 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) ASSERT(token().isUninitialized()); } +#if !ENABLE(OILPAN) // Ensure we haven't been totally deref'ed after pumping. Any caller of this // function should be holding a RefPtr to this to ensure we weren't deleted. ASSERT(refCount() >= 1); +#endif if (isStopped()) return; @@ -565,12 +642,14 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) if (isWaitingForScripts()) { ASSERT(m_tokenizer->state() == HTMLTokenizer::DataState); if (!m_preloadScanner) { - m_preloadScanner = adoptPtr(new HTMLPreloadScanner(m_options, document()->url(), document()->devicePixelRatio())); + m_preloadScanner = adoptPtr(new HTMLPreloadScanner(m_options, document()->url(), createMediaValues(document()))); m_preloadScanner->appendToEnd(m_input.current()); } m_preloadScanner->scan(m_preloader.get(), document()->baseElementURL()); } + TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ParseHTML", "endLine", m_input.current().currentLine().zeroBasedInt()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didWriteHTML(cookie, m_input.current().currentLine().zeroBasedInt()); } @@ -620,11 +699,11 @@ void HTMLDocumentParser::insert(const SegmentedString& source) if (isStopped()) return; - TRACE_EVENT0("webkit", "HTMLDocumentParser::insert"); + TRACE_EVENT1("webkit", "HTMLDocumentParser::insert", "source_length", source.length()); // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); if (!m_tokenizer) { ASSERT(!inPumpSession()); @@ -642,7 +721,7 @@ void HTMLDocumentParser::insert(const SegmentedString& source) // Check the document.write() output with a separate preload scanner as // the main scanner can't deal with insertions. if (!m_insertionPreloadScanner) - m_insertionPreloadScanner = adoptPtr(new HTMLPreloadScanner(m_options, document()->url(), document()->devicePixelRatio())); + m_insertionPreloadScanner = adoptPtr(new HTMLPreloadScanner(m_options, document()->url(), createMediaValues(document()))); m_insertionPreloadScanner->appendToEnd(source); m_insertionPreloadScanner->scan(m_preloader.get(), document()->baseElementURL()); @@ -653,6 +732,7 @@ void HTMLDocumentParser::insert(const SegmentedString& source) void HTMLDocumentParser::startBackgroundParser() { + ASSERT(!isStopped()); ASSERT(shouldUseThreading()); ASSERT(!m_haveBackgroundParser); m_haveBackgroundParser = true; @@ -660,16 +740,21 @@ void HTMLDocumentParser::startBackgroundParser() RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<BackgroundHTMLParser>::createUnbound(); m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); + // TODO(oysteine): Disabled due to crbug.com/398076 until a full fix can be implemented. + if (RuntimeEnabledFeatures::threadedParserDataReceiverEnabled()) + document()->loader()->attachThreadedDataReceiver(adoptPtr(new ParserDataReceiver(m_backgroundParser))); + OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new BackgroundHTMLParser::Configuration); config->options = m_options; config->parser = m_weakFactory.createWeakPtr(); config->xssAuditor = adoptPtr(new XSSAuditor); config->xssAuditor->init(document(), &m_xssAuditorDelegate); - config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().copy(), document()->devicePixelRatio())); + config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().copy(), createMediaValues(document()))); + config->decoder = takeDecoder(); ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); - HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, reference.release(), config.release())); + HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::start, reference.release(), config.release())); } void HTMLDocumentParser::stopBackgroundParser() @@ -687,23 +772,13 @@ void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) if (isStopped()) return; - if (shouldUseThreading()) { - if (!m_haveBackgroundParser) - startBackgroundParser(); - - ASSERT(inputSource->hasOneRef()); - TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->length()); - // NOTE: Important that the String temporary is destroyed before we post the task - // otherwise the String could call deref() on a StringImpl now owned by the background parser. - // We would like to ASSERT(closure.arg3()->hasOneRef()) but sadly the args are private. - Closure closure = bind(&BackgroundHTMLParser::append, m_backgroundParser, String(inputSource)); - HTMLParserThread::shared()->postTask(closure); - return; - } + // We should never reach this point if we're using a parser thread, + // as appendBytes() will directly ship the data to the thread. + ASSERT(!shouldUseThreading()); // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->length()); String source(inputSource); @@ -876,7 +951,7 @@ void HTMLDocumentParser::resumeParsingAfterScriptExecution() ASSERT(!m_lastChunkBeforeScript); // processParsedChunkFromBackgroundParser can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); pumpPendingSpeculations(); return; } @@ -886,20 +961,6 @@ void HTMLDocumentParser::resumeParsingAfterScriptExecution() endIfDelayed(); } -void HTMLDocumentParser::watchForLoad(Resource* resource) -{ - ASSERT(!resource->isLoaded()); - // addClient would call notifyFinished if the load were complete. - // Callers do not expect to be re-entered from this call, so they should - // not an already-loaded Resource. - resource->addClient(this); -} - -void HTMLDocumentParser::stopWatchingForLoad(Resource* resource) -{ - resource->removeClient(this); -} - void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() { ASSERT(m_preloadScanner); @@ -907,11 +968,11 @@ void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() m_preloadScanner->scan(m_preloader.get(), document()->baseElementURL()); } -void HTMLDocumentParser::notifyFinished(Resource* cachedResource) +void HTMLDocumentParser::notifyScriptLoaded(Resource* cachedResource) { // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); ASSERT(m_scriptRunner); ASSERT(!isExecutingScript()); @@ -938,7 +999,7 @@ void HTMLDocumentParser::executeScriptsWaitingForResources() // pumpTokenizer can cause this parser to be detached from the Document, // but we need to ensure it isn't deleted yet. - RefPtr<HTMLDocumentParser> protect(this); + RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); m_scriptRunner->executeScriptsWaitingForResources(); if (!isWaitingForScripts()) resumeParsingAfterScriptExecution(); @@ -946,7 +1007,7 @@ void HTMLDocumentParser::executeScriptsWaitingForResources() void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) { - RefPtr<HTMLDocumentParser> parser = HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); + RefPtrWillBeRawPtr<HTMLDocumentParser> parser = HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); parser->insert(source); // Use insert() so that the parser will not yield. parser->finish(); ASSERT(!parser->processingData()); // Make sure we're done. <rdar://problem/3963151> @@ -965,4 +1026,45 @@ void HTMLDocumentParser::resumeScheduledTasks() m_parserScheduler->resume(); } +void HTMLDocumentParser::appendBytes(const char* data, size_t length) +{ + if (!length || isStopped()) + return; + + if (shouldUseThreading()) { + if (!m_haveBackgroundParser) + startBackgroundParser(); + + OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length)); + memcpy(buffer->data(), data, length); + TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned)length); + + HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::appendRawBytesFromMainThread, m_backgroundParser, buffer.release())); + return; + } + + DecodedDataDocumentParser::appendBytes(data, length); +} + +void HTMLDocumentParser::flush() +{ + // If we've got no decoder, we never received any data. + if (isDetached() || needsDecoder()) + return; + + if (m_haveBackgroundParser) + HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::flush, m_backgroundParser)); + else + DecodedDataDocumentParser::flush(); +} + +void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) +{ + ASSERT(decoder); + DecodedDataDocumentParser::setDecoder(decoder); + + if (m_haveBackgroundParser) + HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, takeDecoder())); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h index 40779561ad3..227cf522507 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h @@ -40,6 +40,7 @@ #include "core/html/parser/HTMLToken.h" #include "core/html/parser/HTMLTokenizer.h" #include "core/html/parser/HTMLTreeBuilderSimulator.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/html/parser/XSSAuditor.h" #include "core/html/parser/XSSAuditorDelegate.h" #include "platform/text/SegmentedString.h" @@ -64,14 +65,16 @@ class ScriptSourceCode; class PumpSession; -class HTMLDocumentParser : public ScriptableDocumentParser, HTMLScriptRunnerHost, ResourceClient { - WTF_MAKE_FAST_ALLOCATED; +class HTMLDocumentParser : public ScriptableDocumentParser, private HTMLScriptRunnerHost { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLDocumentParser); public: - static PassRefPtr<HTMLDocumentParser> create(HTMLDocument* document, bool reportErrors) + static PassRefPtrWillBeRawPtr<HTMLDocumentParser> create(HTMLDocument& document, bool reportErrors) { - return adoptRef(new HTMLDocumentParser(document, reportErrors)); + return adoptRefWillBeNoop(new HTMLDocumentParser(document, reportErrors)); } virtual ~HTMLDocumentParser(); + virtual void trace(Visitor*) OVERRIDE; // Exposed for HTMLParserScheduler void resumeParsingAfterYield(); @@ -80,11 +83,11 @@ public: HTMLTokenizer* tokenizer() const { return m_tokenizer.get(); } - virtual TextPosition textPosition() const; - virtual OrdinalNumber lineNumber() const; + virtual TextPosition textPosition() const OVERRIDE FINAL; + virtual OrdinalNumber lineNumber() const OVERRIDE FINAL; - virtual void suspendScheduledTasks(); - virtual void resumeScheduledTasks(); + virtual void suspendScheduledTasks() OVERRIDE FINAL; + virtual void resumeScheduledTasks() OVERRIDE FINAL; struct ParsedChunk { OwnPtr<CompactHTMLTokenStream> tokens; @@ -96,15 +99,20 @@ public: TokenPreloadScannerCheckpoint preloadScannerCheckpoint; }; void didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk>); + void didReceiveEncodingDataFromBackgroundParser(const DocumentEncodingData&); + + virtual void appendBytes(const char* bytes, size_t length) OVERRIDE; + virtual void flush() OVERRIDE FINAL; + virtual void setDecoder(PassOwnPtr<TextResourceDecoder>) OVERRIDE FINAL; UseCounter* useCounter() { return UseCounter::getFrom(contextForParsingSession()); } protected: - virtual void insert(const SegmentedString&) OVERRIDE; + virtual void insert(const SegmentedString&) OVERRIDE FINAL; virtual void append(PassRefPtr<StringImpl>) OVERRIDE; - virtual void finish() OVERRIDE; + virtual void finish() OVERRIDE FINAL; - HTMLDocumentParser(HTMLDocument*, bool reportErrors); + HTMLDocumentParser(HTMLDocument&, bool reportErrors); HTMLDocumentParser(DocumentFragment*, Element* contextElement, ParserContentPolicy); HTMLTreeBuilder* treeBuilder() const { return m_treeBuilder.get(); } @@ -112,31 +120,27 @@ protected: void forcePlaintextForTextDocument(); private: - static PassRefPtr<HTMLDocumentParser> create(DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) + static PassRefPtrWillBeRawPtr<HTMLDocumentParser> create(DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) { - return adoptRef(new HTMLDocumentParser(fragment, contextElement, parserContentPolicy)); + return adoptRefWillBeNoop(new HTMLDocumentParser(fragment, contextElement, parserContentPolicy)); } // DocumentParser - virtual void pinToMainThread() OVERRIDE; - virtual void detach() OVERRIDE; - virtual bool hasInsertionPoint() OVERRIDE; - virtual bool processingData() const OVERRIDE; - virtual void prepareToStopParsing() OVERRIDE; - virtual void stopParsing() OVERRIDE; - virtual bool isWaitingForScripts() const OVERRIDE; - virtual bool isExecutingScript() const OVERRIDE; - virtual void executeScriptsWaitingForResources() OVERRIDE; + virtual void pinToMainThread() OVERRIDE FINAL; + virtual void detach() OVERRIDE FINAL; + virtual bool hasInsertionPoint() OVERRIDE FINAL; + virtual bool processingData() const OVERRIDE FINAL; + virtual void prepareToStopParsing() OVERRIDE FINAL; + virtual void stopParsing() OVERRIDE FINAL; + virtual bool isWaitingForScripts() const OVERRIDE FINAL; + virtual bool isExecutingScript() const OVERRIDE FINAL; + virtual void executeScriptsWaitingForResources() OVERRIDE FINAL; // HTMLScriptRunnerHost - virtual void watchForLoad(Resource*) OVERRIDE; - virtual void stopWatchingForLoad(Resource*) OVERRIDE; - virtual HTMLInputStream& inputStream() { return m_input; } - virtual bool hasPreloadScanner() const { return m_preloadScanner.get() && !shouldUseThreading(); } - virtual void appendCurrentInputStreamToPreloadScannerAndScan() OVERRIDE; - - // ResourceClient - virtual void notifyFinished(Resource*); + virtual void notifyScriptLoaded(Resource*) OVERRIDE FINAL; + virtual HTMLInputStream& inputStream() OVERRIDE FINAL { return m_input; } + virtual bool hasPreloadScanner() const OVERRIDE FINAL { return m_preloadScanner.get() && !shouldUseThreading(); } + virtual void appendCurrentInputStreamToPreloadScannerAndScan() OVERRIDE FINAL; void startBackgroundParser(); void stopBackgroundParser(); @@ -179,8 +183,8 @@ private: OwnPtr<HTMLToken> m_token; OwnPtr<HTMLTokenizer> m_tokenizer; - OwnPtr<HTMLScriptRunner> m_scriptRunner; - OwnPtr<HTMLTreeBuilder> m_treeBuilder; + OwnPtrWillBeMember<HTMLScriptRunner> m_scriptRunner; + OwnPtrWillBeMember<HTMLTreeBuilder> m_treeBuilder; OwnPtr<HTMLPreloadScanner> m_preloadScanner; OwnPtr<HTMLPreloadScanner> m_insertionPreloadScanner; OwnPtr<HTMLParserScheduler> m_parserScheduler; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp index 9adfdf1612c..5ea0549dbae 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp @@ -27,13 +27,11 @@ #include "config.h" #include "core/html/parser/HTMLElementStack.h" -#include "HTMLNames.h" -#include "MathMLNames.h" -#include "SVGNames.h" +#include "core/HTMLNames.h" +#include "core/MathMLNames.h" +#include "core/SVGNames.h" #include "core/dom/Element.h" -#include "core/html/HTMLHtmlElement.h" -#include "core/html/HTMLOptGroupElement.h" -#include "core/html/HTMLTableElement.h" +#include "core/html/HTMLElement.h" namespace WebCore { @@ -45,7 +43,7 @@ namespace { inline bool isRootNode(HTMLStackItem* item) { return item->isDocumentFragmentNode() - || isHTMLHtmlElement(item->node()); + || item->hasTagName(htmlTag); } inline bool isScopeMarker(HTMLStackItem* item) @@ -54,7 +52,7 @@ inline bool isScopeMarker(HTMLStackItem* item) || item->hasTagName(captionTag) || item->hasTagName(marqueeTag) || item->hasTagName(objectTag) - || isHTMLTableElement(item->node()) + || item->hasTagName(tableTag) || item->hasTagName(tdTag) || item->hasTagName(thTag) || item->hasTagName(MathMLNames::miTag) @@ -79,7 +77,7 @@ inline bool isListItemScopeMarker(HTMLStackItem* item) inline bool isTableScopeMarker(HTMLStackItem* item) { - return isHTMLTableElement(item->node()) + return item->hasTagName(tableTag) || item->hasTagName(templateTag) || isRootNode(item); } @@ -115,24 +113,26 @@ inline bool isButtonScopeMarker(HTMLStackItem* item) inline bool isSelectScopeMarker(HTMLStackItem* item) { - return !isHTMLOptGroupElement(item->node()) + return !item->hasTagName(optgroupTag) && !item->hasTagName(optionTag); } } -HTMLElementStack::ElementRecord::ElementRecord(PassRefPtr<HTMLStackItem> item, PassOwnPtr<ElementRecord> next) +HTMLElementStack::ElementRecord::ElementRecord(PassRefPtrWillBeRawPtr<HTMLStackItem> item, PassOwnPtrWillBeRawPtr<ElementRecord> next) : m_item(item) , m_next(next) { ASSERT(m_item); } +#if !ENABLE(OILPAN) HTMLElementStack::ElementRecord::~ElementRecord() { } +#endif -void HTMLElementStack::ElementRecord::replaceElement(PassRefPtr<HTMLStackItem> item) +void HTMLElementStack::ElementRecord::replaceElement(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { ASSERT(item); ASSERT(!m_item || m_item->isElementNode()); @@ -149,10 +149,18 @@ bool HTMLElementStack::ElementRecord::isAbove(ElementRecord* other) const return false; } +void HTMLElementStack::ElementRecord::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_item); + visitor->trace(m_next); +#endif +} + HTMLElementStack::HTMLElementStack() - : m_rootNode(0) - , m_headElement(0) - , m_bodyElement(0) + : m_rootNode(nullptr) + , m_headElement(nullptr) + , m_bodyElement(nullptr) , m_stackDepth(0) { } @@ -181,25 +189,27 @@ bool HTMLElementStack::secondElementIsHTMLBodyElement() const void HTMLElementStack::popHTMLHeadElement() { ASSERT(top() == m_headElement); - m_headElement = 0; + m_headElement = nullptr; popCommon(); } void HTMLElementStack::popHTMLBodyElement() { ASSERT(top() == m_bodyElement); - m_bodyElement = 0; + m_bodyElement = nullptr; popCommon(); } void HTMLElementStack::popAll() { - m_rootNode = 0; - m_headElement = 0; - m_bodyElement = 0; + m_rootNode = nullptr; + m_headElement = nullptr; + m_bodyElement = nullptr; m_stackDepth = 0; while (m_top) { - topNode()->finishParsingChildren(); + Node& node = *topNode(); + if (node.isElementNode()) + toElement(node).finishParsingChildren(); m_top = m_top->releaseNext(); } } @@ -301,19 +311,19 @@ void HTMLElementStack::popUntilForeignContentScopeMarker() pop(); } -void HTMLElementStack::pushRootNode(PassRefPtr<HTMLStackItem> rootItem) +void HTMLElementStack::pushRootNode(PassRefPtrWillBeRawPtr<HTMLStackItem> rootItem) { ASSERT(rootItem->isDocumentFragmentNode()); pushRootNodeCommon(rootItem); } -void HTMLElementStack::pushHTMLHtmlElement(PassRefPtr<HTMLStackItem> item) +void HTMLElementStack::pushHTMLHtmlElement(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { - ASSERT(isHTMLHtmlElement(item->node())); + ASSERT(item->hasTagName(htmlTag)); pushRootNodeCommon(item); } -void HTMLElementStack::pushRootNodeCommon(PassRefPtr<HTMLStackItem> rootItem) +void HTMLElementStack::pushRootNodeCommon(PassRefPtrWillBeRawPtr<HTMLStackItem> rootItem) { ASSERT(!m_top); ASSERT(!m_rootNode); @@ -321,7 +331,7 @@ void HTMLElementStack::pushRootNodeCommon(PassRefPtr<HTMLStackItem> rootItem) pushCommon(rootItem); } -void HTMLElementStack::pushHTMLHeadElement(PassRefPtr<HTMLStackItem> item) +void HTMLElementStack::pushHTMLHeadElement(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { ASSERT(item->hasTagName(HTMLNames::headTag)); ASSERT(!m_headElement); @@ -329,7 +339,7 @@ void HTMLElementStack::pushHTMLHeadElement(PassRefPtr<HTMLStackItem> item) pushCommon(item); } -void HTMLElementStack::pushHTMLBodyElement(PassRefPtr<HTMLStackItem> item) +void HTMLElementStack::pushHTMLBodyElement(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { ASSERT(item->hasTagName(HTMLNames::bodyTag)); ASSERT(!m_bodyElement); @@ -337,23 +347,23 @@ void HTMLElementStack::pushHTMLBodyElement(PassRefPtr<HTMLStackItem> item) pushCommon(item); } -void HTMLElementStack::push(PassRefPtr<HTMLStackItem> item) +void HTMLElementStack::push(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { - ASSERT(!isHTMLHtmlElement(item->node())); - ASSERT(!item->hasTagName(HTMLNames::headTag)); - ASSERT(!item->hasTagName(HTMLNames::bodyTag)); + ASSERT(!item->hasTagName(htmlTag)); + ASSERT(!item->hasTagName(headTag)); + ASSERT(!item->hasTagName(bodyTag)); ASSERT(m_rootNode); pushCommon(item); } -void HTMLElementStack::insertAbove(PassRefPtr<HTMLStackItem> item, ElementRecord* recordBelow) +void HTMLElementStack::insertAbove(PassRefPtrWillBeRawPtr<HTMLStackItem> item, ElementRecord* recordBelow) { ASSERT(item); ASSERT(recordBelow); ASSERT(m_top); - ASSERT(!isHTMLHtmlElement(item->node())); - ASSERT(!item->hasTagName(HTMLNames::headTag)); - ASSERT(!item->hasTagName(HTMLNames::bodyTag)); + ASSERT(!item->hasTagName(htmlTag)); + ASSERT(!item->hasTagName(headTag)); + ASSERT(!item->hasTagName(bodyTag)); ASSERT(m_rootNode); if (recordBelow == m_top) { push(item); @@ -365,7 +375,7 @@ void HTMLElementStack::insertAbove(PassRefPtr<HTMLStackItem> item, ElementRecord continue; m_stackDepth++; - recordAbove->setNext(adoptPtr(new ElementRecord(item, recordAbove->releaseNext()))); + recordAbove->setNext(adoptPtrWillBeNoop(new ElementRecord(item, recordAbove->releaseNext()))); recordAbove->next()->element()->beginParsingChildren(); return; } @@ -395,13 +405,13 @@ void HTMLElementStack::removeHTMLHeadElement(Element* element) popHTMLHeadElement(); return; } - m_headElement = 0; + m_headElement = nullptr; removeNonTopCommon(element); } void HTMLElementStack::remove(Element* element) { - ASSERT(!element->hasTagName(HTMLNames::headTag)); + ASSERT(!isHTMLHeadElement(element)); if (m_top->element() == element) { pop(); return; @@ -556,19 +566,19 @@ ContainerNode* HTMLElementStack::rootNode() const return m_rootNode; } -void HTMLElementStack::pushCommon(PassRefPtr<HTMLStackItem> item) +void HTMLElementStack::pushCommon(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { ASSERT(m_rootNode); m_stackDepth++; - m_top = adoptPtr(new ElementRecord(item, m_top.release())); + m_top = adoptPtrWillBeNoop(new ElementRecord(item, m_top.release())); } void HTMLElementStack::popCommon() { - ASSERT(!isHTMLHtmlElement(topStackItem()->node())); - ASSERT(!topStackItem()->hasTagName(HTMLNames::headTag) || !m_headElement); - ASSERT(!topStackItem()->hasTagName(HTMLNames::bodyTag) || !m_bodyElement); + ASSERT(!topStackItem()->hasTagName(htmlTag)); + ASSERT(!topStackItem()->hasTagName(headTag) || !m_headElement); + ASSERT(!topStackItem()->hasTagName(bodyTag) || !m_bodyElement); top()->finishParsingChildren(); m_top = m_top->releaseNext(); @@ -578,7 +588,7 @@ void HTMLElementStack::popCommon() void HTMLElementStack::removeNonTopCommon(Element* element) { ASSERT(!isHTMLHtmlElement(element)); - ASSERT(!element->hasTagName(HTMLNames::bodyTag)); + ASSERT(!isHTMLBodyElement(element)); ASSERT(top() != element); for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { if (pos->next()->element() == element) { @@ -606,6 +616,14 @@ HTMLElementStack::ElementRecord* HTMLElementStack::furthestBlockForFormattingEle return 0; } +void HTMLElementStack::trace(Visitor* visitor) +{ + visitor->trace(m_top); + visitor->trace(m_rootNode); + visitor->trace(m_headElement); + visitor->trace(m_bodyElement); +} + #ifndef NDEBUG void HTMLElementStack::show() diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.h index e63bbbc3e72..2afead5f97e 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLElementStack.h @@ -44,35 +44,40 @@ class QualifiedName; // NOTE: The HTML5 spec uses a backwards (grows downward) stack. We're using // more standard (grows upwards) stack terminology here. class HTMLElementStack { - WTF_MAKE_NONCOPYABLE(HTMLElementStack); WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(HTMLElementStack); + DISALLOW_ALLOCATION(); public: HTMLElementStack(); ~HTMLElementStack(); - class ElementRecord { - WTF_MAKE_NONCOPYABLE(ElementRecord); WTF_MAKE_FAST_ALLOCATED; + class ElementRecord FINAL : public NoBaseWillBeGarbageCollected<ElementRecord> { + WTF_MAKE_NONCOPYABLE(ElementRecord); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: +#if !ENABLE(OILPAN) ~ElementRecord(); // Public for ~PassOwnPtr() +#endif Element* element() const { return m_item->element(); } ContainerNode* node() const { return m_item->node(); } const AtomicString& namespaceURI() const { return m_item->namespaceURI(); } - PassRefPtr<HTMLStackItem> stackItem() const { return m_item; } - void replaceElement(PassRefPtr<HTMLStackItem>); + PassRefPtrWillBeRawPtr<HTMLStackItem> stackItem() const { return m_item; } + void replaceElement(PassRefPtrWillBeRawPtr<HTMLStackItem>); bool isAbove(ElementRecord*) const; ElementRecord* next() const { return m_next.get(); } + + void trace(Visitor*); private: friend class HTMLElementStack; - ElementRecord(PassRefPtr<HTMLStackItem>, PassOwnPtr<ElementRecord>); + ElementRecord(PassRefPtrWillBeRawPtr<HTMLStackItem>, PassOwnPtrWillBeRawPtr<ElementRecord>); - PassOwnPtr<ElementRecord> releaseNext() { return m_next.release(); } - void setNext(PassOwnPtr<ElementRecord> next) { m_next = next; } + PassOwnPtrWillBeRawPtr<ElementRecord> releaseNext() { return m_next.release(); } + void setNext(PassOwnPtrWillBeRawPtr<ElementRecord> next) { m_next = next; } - RefPtr<HTMLStackItem> m_item; - OwnPtr<ElementRecord> m_next; + RefPtrWillBeMember<HTMLStackItem> m_item; + OwnPtrWillBeMember<ElementRecord> m_next; }; unsigned stackDepth() const { return m_stackDepth; } @@ -103,13 +108,13 @@ public: ElementRecord* furthestBlockForFormattingElement(Element*) const; ElementRecord* topmost(const AtomicString& tagName) const; - void insertAbove(PassRefPtr<HTMLStackItem>, ElementRecord*); + void insertAbove(PassRefPtrWillBeRawPtr<HTMLStackItem>, ElementRecord*); - void push(PassRefPtr<HTMLStackItem>); - void pushRootNode(PassRefPtr<HTMLStackItem>); - void pushHTMLHtmlElement(PassRefPtr<HTMLStackItem>); - void pushHTMLHeadElement(PassRefPtr<HTMLStackItem>); - void pushHTMLBodyElement(PassRefPtr<HTMLStackItem>); + void push(PassRefPtrWillBeRawPtr<HTMLStackItem>); + void pushRootNode(PassRefPtrWillBeRawPtr<HTMLStackItem>); + void pushHTMLHtmlElement(PassRefPtrWillBeRawPtr<HTMLStackItem>); + void pushHTMLHeadElement(PassRefPtrWillBeRawPtr<HTMLStackItem>); + void pushHTMLBodyElement(PassRefPtrWillBeRawPtr<HTMLStackItem>); void pop(); void popUntil(const AtomicString& tagName); @@ -159,26 +164,28 @@ public: ContainerNode* rootNode() const; + void trace(Visitor*); + #ifndef NDEBUG void show(); #endif private: - void pushCommon(PassRefPtr<HTMLStackItem>); - void pushRootNodeCommon(PassRefPtr<HTMLStackItem>); + void pushCommon(PassRefPtrWillBeRawPtr<HTMLStackItem>); + void pushRootNodeCommon(PassRefPtrWillBeRawPtr<HTMLStackItem>); void popCommon(); void removeNonTopCommon(Element*); - OwnPtr<ElementRecord> m_top; + OwnPtrWillBeMember<ElementRecord> m_top; // We remember the root node, <head> and <body> as they are pushed. Their // ElementRecords keep them alive. The root node is never popped. // FIXME: We don't currently require type-specific information about // these elements so we haven't yet bothered to plumb the types all the // way down through createElement, etc. - ContainerNode* m_rootNode; - Element* m_headElement; - Element* m_bodyElement; + RawPtrWillBeMember<ContainerNode> m_rootNode; + RawPtrWillBeMember<Element> m_headElement; + RawPtrWillBeMember<Element> m_bodyElement; unsigned m_stackDepth; }; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp index 97cebee4383..9866313277d 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp @@ -115,7 +115,7 @@ static bool consumeNamedEntity(SegmentedString& source, DecodedHTMLEntity& decod } notEnoughCharacters = source.isEmpty(); if (notEnoughCharacters) { - // We can't an entity because there might be a longer entity + // We can't decide on an entity because there might be a longer entity // that we could match if we had more data. unconsumeCharacters(source, consumedCharacters); return false; @@ -130,11 +130,12 @@ static bool consumeNamedEntity(SegmentedString& source, DecodedHTMLEntity& decod // actual entity. unconsumeCharacters(source, consumedCharacters); consumedCharacters.clear(); - const int length = entitySearch.mostRecentMatch()->length; - const UChar* reference = entitySearch.mostRecentMatch()->entity; + const HTMLEntityTableEntry* mostRecent = entitySearch.mostRecentMatch(); + const int length = mostRecent->length; + const LChar* reference = HTMLEntityTable::entityString(*mostRecent); for (int i = 0; i < length; ++i) { cc = source.currentChar(); - ASSERT_UNUSED(reference, cc == *reference++); + ASSERT_UNUSED(reference, cc == static_cast<UChar>(*reference++)); consumedCharacters.append(cc); source.advanceAndASSERT(cc); ASSERT(!source.isEmpty()); diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntitySearch.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntitySearch.cpp index c4ef2b0c92f..fe847e48038 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntitySearch.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntitySearch.cpp @@ -47,7 +47,8 @@ HTMLEntitySearch::CompareResult HTMLEntitySearch::compare(const HTMLEntityTableE { if (entry->length < m_currentLength + 1) return Before; - UChar entryNextCharacter = entry->entity[m_currentLength]; + const LChar* entityString = HTMLEntityTable::entityString(*entry); + UChar entryNextCharacter = entityString[m_currentLength]; if (entryNextCharacter == nextCharacter) return Prefix; return entryNextCharacter < nextCharacter ? Before : After; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityTable.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityTable.h index f0d775efee7..1e465049b57 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityTable.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLEntityTable.h @@ -30,13 +30,14 @@ namespace WebCore { +// Member order to optimize packing. There will be thousands of these objects. struct HTMLEntityTableEntry { - UChar lastCharacter() const { return entity[length - 1]; } + LChar lastCharacter() const; - const UChar* entity; - int length; UChar32 firstValue; - UChar32 secondValue; + UChar secondValue; // UChar since double char sequences only use BMP chars. + short entityOffset; + short length; }; class HTMLEntityTable { @@ -46,6 +47,8 @@ public: static const HTMLEntityTableEntry* firstEntryStartingWith(UChar); static const HTMLEntityTableEntry* lastEntryStartingWith(UChar); + + static const LChar* entityString(const HTMLEntityTableEntry&); }; } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.cpp index 34215d75e26..26418debc1c 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.cpp @@ -79,7 +79,7 @@ HTMLFormattingElementList::Bookmark HTMLFormattingElementList::bookmarkFor(Eleme return Bookmark(&at(index)); } -void HTMLFormattingElementList::swapTo(Element* oldElement, PassRefPtr<HTMLStackItem> newItem, const Bookmark& bookmark) +void HTMLFormattingElementList::swapTo(Element* oldElement, PassRefPtrWillBeRawPtr<HTMLStackItem> newItem, const Bookmark& bookmark) { ASSERT(contains(oldElement)); ASSERT(!contains(newItem->element())); @@ -94,7 +94,7 @@ void HTMLFormattingElementList::swapTo(Element* oldElement, PassRefPtr<HTMLStack remove(oldElement); } -void HTMLFormattingElementList::append(PassRefPtr<HTMLStackItem> item) +void HTMLFormattingElementList::append(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { ensureNoahsArkCondition(item.get()); m_entries.append(item); @@ -123,7 +123,7 @@ void HTMLFormattingElementList::clearToLastMarker() } } -void HTMLFormattingElementList::tryToEnsureNoahsArkConditionQuickly(HTMLStackItem* newItem, Vector<HTMLStackItem*>& remainingCandidates) +void HTMLFormattingElementList::tryToEnsureNoahsArkConditionQuickly(HTMLStackItem* newItem, WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem> >& remainingCandidates) { ASSERT(remainingCandidates.isEmpty()); @@ -132,7 +132,7 @@ void HTMLFormattingElementList::tryToEnsureNoahsArkConditionQuickly(HTMLStackIte // Use a vector with inline capacity to avoid a malloc in the common case // of a quickly ensuring the condition. - Vector<HTMLStackItem*, 10> candidates; + WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem>, 10> candidates; size_t newItemAttributeCount = newItem->attributes().size(); @@ -155,19 +155,19 @@ void HTMLFormattingElementList::tryToEnsureNoahsArkConditionQuickly(HTMLStackIte if (candidates.size() < kNoahsArkCapacity) return; // There's room for the new element in the ark. There's no need to copy out the remainingCandidates. - remainingCandidates.append(candidates); + remainingCandidates.appendVector(candidates); } void HTMLFormattingElementList::ensureNoahsArkCondition(HTMLStackItem* newItem) { - Vector<HTMLStackItem*> candidates; + WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem> > candidates; tryToEnsureNoahsArkConditionQuickly(newItem, candidates); if (candidates.isEmpty()) return; // We pre-allocate and re-use this second vector to save one malloc per // attribute that we verify. - Vector<HTMLStackItem*> remainingCandidates; + WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem> > remainingCandidates; remainingCandidates.reserveInitialCapacity(candidates.size()); const Vector<Attribute>& attributes = newItem->attributes(); diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.h index 745dba1c771..cb7c0ce34fb 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLFormattingElementList.h @@ -38,6 +38,7 @@ class Element; // This may end up merged into HTMLElementStack. class HTMLFormattingElementList { WTF_MAKE_NONCOPYABLE(HTMLFormattingElementList); + DISALLOW_ALLOCATION(); public: HTMLFormattingElementList(); ~HTMLFormattingElementList(); @@ -46,22 +47,23 @@ public: // between the HTMLFormattingElementList and HTMLElementStack and needs // access to Entry::isMarker() and Entry::replaceElement() to do so. class Entry { + ALLOW_ONLY_INLINE_ALLOCATION(); public: // Inline because they're hot and Vector<T> uses them. - explicit Entry(PassRefPtr<HTMLStackItem> item) + explicit Entry(PassRefPtrWillBeRawPtr<HTMLStackItem> item) : m_item(item) { } enum MarkerEntryType { MarkerEntry }; explicit Entry(MarkerEntryType) - : m_item(0) + : m_item(nullptr) { } ~Entry() {} bool isMarker() const { return !m_item; } - PassRefPtr<HTMLStackItem> stackItem() const { return m_item; } + PassRefPtrWillBeRawPtr<HTMLStackItem> stackItem() const { return m_item; } Element* element() const { // The fact that !m_item == isMarker() is an implementation detail @@ -69,14 +71,16 @@ public: ASSERT(m_item); return m_item->element(); } - void replaceElement(PassRefPtr<HTMLStackItem> item) { m_item = item; } + void replaceElement(PassRefPtrWillBeRawPtr<HTMLStackItem> item) { m_item = item; } // Needed for use with Vector. These are super-hot and must be inline. bool operator==(Element* element) const { return !m_item ? !element : m_item->element() == element; } bool operator!=(Element* element) const { return !m_item ? !!element : m_item->element() != element; } + void trace(Visitor* visitor) { visitor->trace(m_item); } + private: - RefPtr<HTMLStackItem> m_item; + RefPtrWillBeMember<HTMLStackItem> m_item; }; class Bookmark { @@ -108,11 +112,11 @@ public: Entry* find(Element*); bool contains(Element*); - void append(PassRefPtr<HTMLStackItem>); + void append(PassRefPtrWillBeRawPtr<HTMLStackItem>); void remove(Element*); Bookmark bookmarkFor(Element*); - void swapTo(Element* oldElement, PassRefPtr<HTMLStackItem> newItem, const Bookmark&); + void swapTo(Element* oldElement, PassRefPtrWillBeRawPtr<HTMLStackItem> newItem, const Bookmark&); void appendMarker(); // clearToLastMarker also clears the marker (per the HTML5 spec). @@ -121,6 +125,8 @@ public: const Entry& at(size_t i) const { return m_entries[i]; } Entry& at(size_t i) { return m_entries[i]; } + void trace(Visitor* visitor) { visitor->trace(m_entries); } + #ifndef NDEBUG void show(); #endif @@ -130,12 +136,14 @@ private: // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#list-of-active-formatting-elements // These functions enforce the "Noah's Ark" condition, which removes redundant mis-nested elements. - void tryToEnsureNoahsArkConditionQuickly(HTMLStackItem*, Vector<HTMLStackItem*>& remainingCandiates); + void tryToEnsureNoahsArkConditionQuickly(HTMLStackItem*, WillBeHeapVector<RawPtrWillBeMember<HTMLStackItem> >& remainingCandiates); void ensureNoahsArkCondition(HTMLStackItem*); - Vector<Entry> m_entries; + WillBeHeapVector<Entry> m_entries; }; -} +} // namespace WebCore + +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::HTMLFormattingElementList::Entry); #endif // HTMLFormattingElementList_h diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.cpp index 038c8a1e5fb..5fa6d32e73d 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/html/parser/HTMLMetaCharsetParser.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/parser/HTMLParserOptions.h" #include "core/html/parser/HTMLTokenizer.h" @@ -51,61 +51,12 @@ HTMLMetaCharsetParser::~HTMLMetaCharsetParser() { } -static const char charsetString[] = "charset"; -static const size_t charsetLength = sizeof("charset") - 1; - -String HTMLMetaCharsetParser::extractCharset(const String& value) -{ - size_t pos = 0; - unsigned length = value.length(); - - while (pos < length) { - pos = value.find(charsetString, pos, false); - if (pos == kNotFound) - break; - - pos += charsetLength; - - // Skip whitespace. - while (pos < length && value[pos] <= ' ') - ++pos; - - if (value[pos] != '=') - continue; - - ++pos; - - while (pos < length && value[pos] <= ' ') - ++pos; - - char quoteMark = 0; - if (pos < length && (value[pos] == '"' || value[pos] == '\'')) { - quoteMark = static_cast<char>(value[pos++]); - ASSERT(!(quoteMark & 0x80)); - } - - if (pos == length) - break; - - unsigned end = pos; - while (end < length && ((quoteMark && value[end] != quoteMark) || (!quoteMark && value[end] > ' ' && value[end] != '"' && value[end] != '\'' && value[end] != ';'))) - ++end; - - if (quoteMark && (end == length)) - break; // Close quote not found. - - return value.substring(pos, end - pos); - } - - return ""; -} - bool HTMLMetaCharsetParser::processMeta() { const HTMLToken::AttributeList& tokenAttributes = m_token.attributes(); - AttributeList attributes; + HTMLAttributeList attributes; for (HTMLToken::AttributeList::const_iterator iter = tokenAttributes.begin(); iter != tokenAttributes.end(); ++iter) { - String attributeName = StringImpl::create8BitIfPossible(iter->name); + String attributeName = attemptStaticStringCreation(iter->name, Likely8Bit); String attributeValue = StringImpl::create8BitIfPossible(iter->value); attributes.append(std::make_pair(attributeName, attributeValue)); } @@ -114,37 +65,6 @@ bool HTMLMetaCharsetParser::processMeta() return m_encoding.isValid(); } -WTF::TextEncoding HTMLMetaCharsetParser::encodingFromMetaAttributes(const AttributeList& attributes) -{ - bool gotPragma = false; - Mode mode = None; - String charset; - - for (AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { - const AtomicString& attributeName = iter->first; - const String& attributeValue = iter->second; - - if (attributeName == http_equivAttr) { - if (equalIgnoringCase(attributeValue, "content-type")) - gotPragma = true; - } else if (charset.isEmpty()) { - if (attributeName == charsetAttr) { - charset = attributeValue; - mode = Charset; - } else if (attributeName == contentAttr) { - charset = extractCharset(attributeValue); - if (charset.length()) - mode = Pragma; - } - } - } - - if (mode == Charset || (mode == Pragma && gotPragma)) - return WTF::TextEncoding(stripLeadingAndTrailingHTMLSpaces(charset)); - - return WTF::TextEncoding(); -} - static const int bytesToCheckUnconditionally = 1024; // That many input bytes will be checked for meta charset even if <head> section is over. bool HTMLMetaCharsetParser::checkForMetaCharset(const char* data, size_t length) @@ -177,20 +97,20 @@ bool HTMLMetaCharsetParser::checkForMetaCharset(const char* data, size_t length) while (m_tokenizer->nextToken(m_input, m_token)) { bool end = m_token.type() == HTMLToken::EndTag; if (end || m_token.type() == HTMLToken::StartTag) { - AtomicString tagName(m_token.name()); + String tagName = attemptStaticStringCreation(m_token.name(), Likely8Bit); if (!end) { m_tokenizer->updateStateFor(tagName); - if (tagName == metaTag && processMeta()) { + if (threadSafeMatch(tagName, metaTag) && processMeta()) { m_doneChecking = true; return true; } } - if (tagName != scriptTag && tagName != noscriptTag - && tagName != styleTag && tagName != linkTag - && tagName != metaTag && tagName != objectTag - && tagName != titleTag && tagName != baseTag - && (end || tagName != htmlTag) && (end || tagName != headTag)) { + if (!threadSafeMatch(tagName, scriptTag) && !threadSafeMatch(tagName, noscriptTag) + && !threadSafeMatch(tagName, styleTag) && !threadSafeMatch(tagName, linkTag) + && !threadSafeMatch(tagName, metaTag) && !threadSafeMatch(tagName, objectTag) + && !threadSafeMatch(tagName, titleTag) && !threadSafeMatch(tagName, baseTag) + && (end || !threadSafeMatch(tagName, htmlTag)) && (end || !threadSafeMatch(tagName, headTag))) { m_inHeadSection = false; } } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.h index 3393fca40d2..65d9517a2e0 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLMetaCharsetParser.h @@ -48,22 +48,10 @@ public: const WTF::TextEncoding& encoding() { return m_encoding; } - typedef Vector<pair<String, String> > AttributeList; - // The returned encoding might not be valid. - static WTF::TextEncoding encodingFromMetaAttributes(const AttributeList& -); - private: HTMLMetaCharsetParser(); bool processMeta(); - static String extractCharset(const String&); - - enum Mode { - None, - Charset, - Pragma, - }; OwnPtr<HTMLTokenizer> m_tokenizer; OwnPtr<TextCodec> m_assumedCodec; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp index f538c54cc5b..c0557a82281 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp @@ -25,14 +25,18 @@ #include "config.h" #include "core/html/parser/HTMLParserIdioms.h" +#include "core/HTMLNames.h" #include <limits> #include "wtf/MathExtras.h" #include "wtf/text/AtomicString.h" #include "wtf/text/StringBuilder.h" #include "wtf/text/StringHash.h" +#include "wtf/text/TextEncoding.h" namespace WebCore { +using namespace HTMLNames; + template <typename CharType> static String stripLeadingAndTrailingHTMLSpaces(String string, const CharType* characters, unsigned length) { @@ -91,8 +95,7 @@ String serializeForNumberType(double number) Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbackValue) { - // See HTML5 2.5.4.3 `Real numbers.' and parseToDoubleForNumberType - + // http://www.whatwg.org/specs/web-apps/current-work/#floating-point-numbers and parseToDoubleForNumberType // String::toDouble() accepts leading + and whitespace characters, which are not valid here. const UChar firstCharacter = string[0]; if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter)) @@ -102,11 +105,9 @@ Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbac if (!value.isFinite()) return fallbackValue; - // Numbers are considered finite IEEE 754 single-precision floating point values. - // See HTML5 2.5.4.3 `Real numbers.' - // FIXME: We should use numeric_limits<double>::max for number input type. - const Decimal floatMax = Decimal::fromDouble(std::numeric_limits<float>::max()); - if (value < -floatMax || value > floatMax) + // Numbers are considered finite IEEE 754 Double-precision floating point values. + const Decimal doubleMax = Decimal::fromDouble(std::numeric_limits<double>::max()); + if (value < -doubleMax || value > doubleMax) return fallbackValue; // We return +0 for -0 case. @@ -115,8 +116,7 @@ Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbac double parseToDoubleForNumberType(const String& string, double fallbackValue) { - // See HTML5 2.5.4.3 `Real numbers.' - + // http://www.whatwg.org/specs/web-apps/current-work/#floating-point-numbers // String::toDouble() accepts leading + and whitespace characters, which are not valid here. UChar firstCharacter = string[0]; if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter)) @@ -131,9 +131,8 @@ double parseToDoubleForNumberType(const String& string, double fallbackValue) if (!std::isfinite(value)) return fallbackValue; - // Numbers are considered finite IEEE 754 single-precision floating point values. - // See HTML5 2.5.4.3 `Real numbers.' - if (-std::numeric_limits<float>::max() > value || value > std::numeric_limits<float>::max()) + // Numbers are considered finite IEEE 754 Double-precision floating point values. + if (-std::numeric_limits<double>::max() > value || value > std::numeric_limits<double>::max()) return fallbackValue; // The following expression converts -0 to +0. @@ -265,6 +264,92 @@ bool parseHTMLNonNegativeInteger(const String& input, unsigned& value) return parseHTMLNonNegativeIntegerInternal(start, start + length, value); } +static const char charsetString[] = "charset"; +static const size_t charsetLength = sizeof("charset") - 1; + +String extractCharset(const String& value) +{ + size_t pos = 0; + unsigned length = value.length(); + + while (pos < length) { + pos = value.find(charsetString, pos, false); + if (pos == kNotFound) + break; + + pos += charsetLength; + + // Skip whitespace. + while (pos < length && value[pos] <= ' ') + ++pos; + + if (value[pos] != '=') + continue; + + ++pos; + + while (pos < length && value[pos] <= ' ') + ++pos; + + char quoteMark = 0; + if (pos < length && (value[pos] == '"' || value[pos] == '\'')) { + quoteMark = static_cast<char>(value[pos++]); + ASSERT(!(quoteMark & 0x80)); + } + + if (pos == length) + break; + + unsigned end = pos; + while (end < length && ((quoteMark && value[end] != quoteMark) || (!quoteMark && value[end] > ' ' && value[end] != '"' && value[end] != '\'' && value[end] != ';'))) + ++end; + + if (quoteMark && (end == length)) + break; // Close quote not found. + + return value.substring(pos, end - pos); + } + + return ""; +} + +enum Mode { + None, + Charset, + Pragma, +}; + +WTF::TextEncoding encodingFromMetaAttributes(const HTMLAttributeList& attributes) +{ + bool gotPragma = false; + Mode mode = None; + String charset; + + for (HTMLAttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { + const String& attributeName = iter->first; + const String& attributeValue = AtomicString(iter->second); + + if (threadSafeMatch(attributeName, http_equivAttr)) { + if (equalIgnoringCase(attributeValue, "content-type")) + gotPragma = true; + } else if (charset.isEmpty()) { + if (threadSafeMatch(attributeName, charsetAttr)) { + charset = attributeValue; + mode = Charset; + } else if (threadSafeMatch(attributeName, contentAttr)) { + charset = extractCharset(attributeValue); + if (charset.length()) + mode = Pragma; + } + } + } + + if (mode == Charset || (mode == Pragma && gotPragma)) + return WTF::TextEncoding(stripLeadingAndTrailingHTMLSpaces(charset)); + + return WTF::TextEncoding(); +} + static bool threadSafeEqual(const StringImpl* a, const StringImpl* b) { if (a == b) @@ -284,7 +369,8 @@ bool threadSafeMatch(const String& localName, const QualifiedName& qName) return threadSafeEqual(localName.impl(), qName.localName().impl()); } -StringImpl* findStringIfStatic(const UChar* characters, unsigned length) +template<typename CharType> +inline StringImpl* findStringIfStatic(const CharType* characters, unsigned length) { // We don't need to try hashing if we know the string is too long. if (length > StringImpl::highestStaticStringLength()) @@ -306,4 +392,27 @@ StringImpl* findStringIfStatic(const UChar* characters, unsigned length) return it->value; } +String attemptStaticStringCreation(const LChar* characters, size_t size) +{ + String string(findStringIfStatic(characters, size)); + if (string.impl()) + return string; + return String(characters, size); +} + +String attemptStaticStringCreation(const UChar* characters, size_t size, CharacterWidth width) +{ + String string(findStringIfStatic(characters, size)); + if (string.impl()) + return string; + if (width == Likely8Bit) + string = StringImpl::create8BitIfPossible(characters, size); + else if (width == Force8Bit) + string = String::make8BitFrom16BitSource(characters, size); + else + string = String(characters, size); + + return string; +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h index 16fd3eebe3c..d5ab2899638 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h @@ -30,12 +30,11 @@ #include "wtf/Forward.h" #include "wtf/text/WTFString.h" -namespace WebCore { +namespace WTF { +class TextEncoding; +} -// Space characters as defined by the HTML specification. -bool isHTMLSpace(UChar); -bool isHTMLLineBreak(UChar); -bool isNotHTMLSpace(UChar); +namespace WebCore { // Strip leading and trailing whitespace as defined by the HTML specification. String stripLeadingAndTrailingHTMLSpaces(const String&); @@ -59,10 +58,13 @@ double parseToDoubleForNumberType(const String&, double fallbackValue = std::num bool parseHTMLInteger(const String&, int&); // http://www.whatwg.org/specs/web-apps/current-work/#rules-for-parsing-non-negative-integers -bool parseHTMLNonNegativeInteger(const String&, unsigned int&); +bool parseHTMLNonNegativeInteger(const String&, unsigned&); -// Inline implementations of some of the functions declared above. +typedef Vector<pair<String, String> > HTMLAttributeList; +// The returned encoding might not be valid. +WTF::TextEncoding encodingFromMetaAttributes(const HTMLAttributeList&); +// Space characters as defined by the HTML specification. template<typename CharType> inline bool isHTMLSpace(CharType character) { @@ -80,9 +82,15 @@ inline bool isHTMLSpace(CharType character) } template<typename CharType> +inline bool isComma(CharType character) +{ + return character == ','; +} + +template<typename CharType> inline bool isHTMLSpaceOrComma(CharType character) { - return isHTMLSpace<CharType>(character) || character == ','; + return isComma(character) || isHTMLSpace(character); } inline bool isHTMLLineBreak(UChar character) @@ -99,29 +107,29 @@ inline bool isNotHTMLSpace(CharType character) bool threadSafeMatch(const QualifiedName&, const QualifiedName&); bool threadSafeMatch(const String&, const QualifiedName&); -StringImpl* findStringIfStatic(const UChar* characters, unsigned length); - enum CharacterWidth { Likely8Bit, Force8Bit, Force16Bit }; +String attemptStaticStringCreation(const LChar*, size_t); + +String attemptStaticStringCreation(const UChar*, size_t, CharacterWidth); + template<size_t inlineCapacity> -static String attemptStaticStringCreation(const Vector<UChar, inlineCapacity>& vector, CharacterWidth width) +inline static String attemptStaticStringCreation(const Vector<UChar, inlineCapacity>& vector, CharacterWidth width) { - String string(findStringIfStatic(vector.data(), vector.size())); - if (string.impl()) - return string; - if (width == Likely8Bit) - string = StringImpl::create8BitIfPossible(vector); - else if (width == Force8Bit) - string = String::make8BitFrom16BitSource(vector); - else - string = String(vector); - - return string; + return attemptStaticStringCreation(vector.data(), vector.size(), width); } +inline static String attemptStaticStringCreation(const String str) +{ + if (!str.is8Bit()) + return attemptStaticStringCreation(str.characters16(), str.length(), Force16Bit); + return attemptStaticStringCreation(str.characters8(), str.length()); +} + + } #endif diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserOptions.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserOptions.cpp index 98ceb68461d..b08cf92994e 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserOptions.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserOptions.cpp @@ -28,23 +28,28 @@ #include "bindings/v8/ScriptController.h" #include "core/dom/Document.h" -#include "core/loader/FrameLoader.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/loader/FrameLoader.h" namespace WebCore { HTMLParserOptions::HTMLParserOptions(Document* document) { - Frame* frame = document ? document->frame() : 0; + LocalFrame* frame = document ? document->frame() : 0; scriptEnabled = frame && frame->script().canExecuteScripts(NotAboutToExecuteScript); pluginsEnabled = frame && frame->loader().allowPlugins(NotAboutToInstantiatePlugin); - Settings* settings = document ? document->settings() : 0; - // We force the main-thread parser for about:blank, javascript: and data: urls for compatibility - // with historical synchronous loading/parsing behavior of those schemes. - useThreading = settings && settings->threadedHTMLParser() && !document->url().isBlankURL() - && (settings->useThreadedHTMLParserForDataURLs() || !document->url().protocolIsData()); + // We force the main-thread parser for two cases: + // - about:blank and javascript (which uses about:blank) for compatibility + // with historical synchronous loading/parsing behavior. + // - instances where the Document has no Frame (this happens sometimes for + // HTML imports, and possibly other cases). + // FIXME: We want to use the threaded parser for XHRs (where there is no + // frame) so the second case should go away eventually. + // FIXME: Gecko does not load javascript: urls synchronously, why do we? + // See LayoutTests/loader/iframe-sync-loads.html + useThreading = document && document->frame() && !document->url().isAboutBlankURL(); } } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp index c74628479df..61cb172ccae 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp @@ -88,34 +88,14 @@ HTMLParserScheduler::~HTMLParserScheduler() void HTMLParserScheduler::continueNextChunkTimerFired(Timer<HTMLParserScheduler>* timer) { ASSERT_UNUSED(timer, timer == &m_continueNextChunkTimer); - // FIXME: The timer class should handle timer priorities instead of this code. - // If a layout is scheduled, wait again to let the layout timer run first. - // FIXME: We should fix this by reducing the max-parse-time instead of - // artificially forcing the parser to yield agressively before first layout. - if (m_parser->document()->shouldParserYieldAgressivelyBeforeScriptExecution()) { - m_continueNextChunkTimer.startOneShot(0); - return; - } m_parser->resumeParsingAfterYield(); } -void HTMLParserScheduler::checkForYieldBeforeScript(PumpSession& session) -{ - // If we've never painted before and a layout is pending, yield prior to running - // scripts to give the page a chance to paint earlier. - Document* document = m_parser->document(); - bool needsFirstPaint = document->view() && !document->view()->hasEverPainted(); - if (needsFirstPaint && document->shouldParserYieldAgressivelyBeforeScriptExecution()) - session.needsYield = true; - session.didSeeScript = true; -} - void HTMLParserScheduler::scheduleForResume() { - m_continueNextChunkTimer.startOneShot(0); + m_continueNextChunkTimer.startOneShot(0, FROM_HERE); } - void HTMLParserScheduler::suspend() { ASSERT(!m_isSuspendedWithActiveTimer); @@ -131,7 +111,7 @@ void HTMLParserScheduler::resume() if (!m_isSuspendedWithActiveTimer) return; m_isSuspendedWithActiveTimer = false; - m_continueNextChunkTimer.startOneShot(0); + m_continueNextChunkTimer.startOneShot(0, FROM_HERE); } } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h index e8bfe493085..4e3364edfbf 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h @@ -38,15 +38,17 @@ class Document; class HTMLDocumentParser; class ActiveParserSession { + STACK_ALLOCATED(); public: explicit ActiveParserSession(Document*); ~ActiveParserSession(); private: - RefPtr<Document> m_document; + RefPtrWillBeMember<Document> m_document; }; class PumpSession : public NestingLevelIncrementer, public ActiveParserSession { + STACK_ALLOCATED(); public: PumpSession(unsigned& nestingLevel, Document*); ~PumpSession(); @@ -84,7 +86,6 @@ public: } ++session.processedTokens; } - void checkForYieldBeforeScript(PumpSession&); void scheduleForResume(); bool isScheduledForResume() const { return m_isSuspendedWithActiveTimer || m_continueNextChunkTimer.isActive(); } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp index 5a0e30c3e67..5b5c6939714 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp @@ -32,13 +32,15 @@ #include "core/html/parser/HTMLParserThread.h" #include "platform/Task.h" +#include "platform/TaskSynchronizer.h" #include "public/platform/Platform.h" #include "wtf/PassOwnPtr.h" namespace WebCore { +static HTMLParserThread* s_sharedThread = 0; + HTMLParserThread::HTMLParserThread() - : m_thread(adoptPtr(blink::Platform::current()->createThread("HTMLParserThread"))) { } @@ -46,17 +48,66 @@ HTMLParserThread::~HTMLParserThread() { } +void HTMLParserThread::init() +{ + ASSERT(!s_sharedThread); + s_sharedThread = new HTMLParserThread; +} + +void HTMLParserThread::setupHTMLParserThread() +{ + m_pendingGCRunner = adoptPtr(new PendingGCRunner); + m_messageLoopInterruptor = adoptPtr(new MessageLoopInterruptor(&platformThread())); + platformThread().addTaskObserver(m_pendingGCRunner.get()); + ThreadState::attach(); + ThreadState::current()->addInterruptor(m_messageLoopInterruptor.get()); +} + +void HTMLParserThread::shutdown() +{ + ASSERT(s_sharedThread); + // currentThread will always be non-null in production, but can be null in Chromium unit tests. + if (blink::Platform::current()->currentThread() && s_sharedThread->isRunning()) { + TaskSynchronizer taskSynchronizer; + s_sharedThread->postTask(WTF::bind(&HTMLParserThread::cleanupHTMLParserThread, s_sharedThread, &taskSynchronizer)); + taskSynchronizer.waitForTaskCompletion(); + } + delete s_sharedThread; + s_sharedThread = 0; +} + +void HTMLParserThread::cleanupHTMLParserThread(TaskSynchronizer* taskSynchronizer) +{ + ThreadState::current()->removeInterruptor(m_messageLoopInterruptor.get()); + ThreadState::detach(); + platformThread().removeTaskObserver(m_pendingGCRunner.get()); + m_pendingGCRunner = nullptr; + m_messageLoopInterruptor = nullptr; + taskSynchronizer->taskCompleted(); +} + HTMLParserThread* HTMLParserThread::shared() { - static HTMLParserThread* thread; - if (!thread) - thread = new HTMLParserThread; - return thread; + return s_sharedThread; +} + +blink::WebThread& HTMLParserThread::platformThread() +{ + if (!isRunning()) { + m_thread = adoptPtr(blink::Platform::current()->createThread("HTMLParserThread")); + postTask(WTF::bind(&HTMLParserThread::setupHTMLParserThread, this)); + } + return *m_thread; +} + +bool HTMLParserThread::isRunning() +{ + return !!m_thread; } void HTMLParserThread::postTask(const Closure& closure) { - m_thread->postTask(new Task(closure)); + platformThread().postTask(new Task(closure)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.h index e0b85f9399c..42630f39cfa 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThread.h @@ -31,22 +31,37 @@ #ifndef HTMLParserThread_h #define HTMLParserThread_h +#include "platform/heap/glue/MessageLoopInterruptor.h" +#include "platform/heap/glue/PendingGCRunner.h" +#include "public/platform/WebThread.h" #include "wtf/Functional.h" #include "wtf/OwnPtr.h" -#include "public/platform/WebThread.h" namespace WebCore { +class TaskSynchronizer; + class HTMLParserThread { public: + static void init(); + static void shutdown(); + + // It is an error to call shared() before init() or after shutdown(); static HTMLParserThread* shared(); + void postTask(const Closure&); + blink::WebThread& platformThread(); + bool isRunning(); private: HTMLParserThread(); ~HTMLParserThread(); + void setupHTMLParserThread(); + void cleanupHTMLParserThread(TaskSynchronizer*); OwnPtr<blink::WebThread> m_thread; + OwnPtr<PendingGCRunner> m_pendingGCRunner; + OwnPtr<MessageLoopInterruptor> m_messageLoopInterruptor; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThreadTest.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThreadTest.cpp new file mode 100644 index 00000000000..8b742b86dc1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLParserThreadTest.cpp @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/parser/HTMLParserThread.h" + +#include <gtest/gtest.h> + +namespace { + +using namespace WebCore; + +TEST(HTMLParserThread, Init) +{ + // The harness has already run init() for us, so tear down the parser first. + ASSERT_TRUE(HTMLParserThread::shared()); + HTMLParserThread::shutdown(); + + // Make sure starting the parser thread brings it back to life. + ASSERT_FALSE(HTMLParserThread::shared()); + HTMLParserThread::init(); + ASSERT_TRUE(HTMLParserThread::shared()); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp index 0d1e0645ad7..6bea3f676a1 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp @@ -28,13 +28,17 @@ #include "config.h" #include "core/html/parser/HTMLPreloadScanner.h" -#include "HTMLNames.h" -#include "InputTypeNames.h" -#include "RuntimeEnabledFeatures.h" +#include "core/HTMLNames.h" +#include "core/InputTypeNames.h" +#include "core/css/MediaList.h" +#include "core/css/MediaQueryEvaluator.h" +#include "core/css/MediaValues.h" +#include "core/css/parser/SizesAttributeParser.h" #include "core/html/LinkRelAttribute.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/parser/HTMLSrcsetParser.h" #include "core/html/parser/HTMLTokenizer.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" #include "wtf/MainThread.h" @@ -90,19 +94,33 @@ static String initiatorFor(const StringImpl* tagImpl) return emptyString(); } +static bool mediaAttributeMatches(const MediaValues& mediaValues, const String& attributeValue) +{ + RefPtrWillBeRawPtr<MediaQuerySet> mediaQueries = MediaQuerySet::createOffMainThread(attributeValue); + MediaQueryEvaluator mediaQueryEvaluator("screen", mediaValues); + return mediaQueryEvaluator.eval(mediaQueries.get()); +} + class TokenPreloadScanner::StartTagScanner { public: - StartTagScanner(const StringImpl* tagImpl, float deviceScaleFactor) + StartTagScanner(const StringImpl* tagImpl, PassRefPtr<MediaValues> mediaValues) : m_tagImpl(tagImpl) , m_linkIsStyleSheet(false) + , m_matchedMediaAttribute(true) , m_inputIsImage(false) - , m_deviceScaleFactor(deviceScaleFactor) - , m_encounteredImgSrc(false) + , m_sourceSize(0) + , m_sourceSizeSet(false) , m_isCORSEnabled(false) , m_allowCredentials(DoNotAllowStoredCredentials) + , m_mediaValues(mediaValues) { - if (!match(m_tagImpl, imgTag) - && !match(m_tagImpl, inputTag) + if (match(m_tagImpl, imgTag) + || match(m_tagImpl, sourceTag)) { + if (RuntimeEnabledFeatures::pictureSizesEnabled()) + m_sourceSize = SizesAttributeParser::findEffectiveSize(String(), m_mediaValues); + return; + } + if ( !match(m_tagImpl, inputTag) && !match(m_tagImpl, linkTag) && !match(m_tagImpl, scriptTag)) m_tagImpl = 0; @@ -133,57 +151,122 @@ public: processAttribute(iter->name, iter->value); } + void handlePictureSourceURL(String& sourceURL) + { + if (match(m_tagImpl, sourceTag) && m_matchedMediaAttribute && sourceURL.isEmpty()) + sourceURL = m_srcsetImageCandidate.toString(); + else if (match(m_tagImpl, imgTag) && !sourceURL.isEmpty()) + setUrlToLoad(sourceURL, AllowURLReplacement); + } + PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL, const SegmentedString& source) { - if (!shouldPreload()) + if (!shouldPreload() || !m_matchedMediaAttribute) return nullptr; TRACE_EVENT_INSTANT1("net", "PreloadRequest", "url", m_urlToLoad.ascii()); TextPosition position = TextPosition(source.currentLine(), source.currentColumn()); - OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_tagImpl), position, m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribute); + OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_tagImpl), position, m_urlToLoad, predictedBaseURL, resourceType()); if (isCORSEnabled()) - request->setCrossOriginEnabled(allowCredentials()); + request->setCrossOriginEnabled(allowStoredCredentials()); request->setCharset(charset()); return request.release(); } private: template<typename NameType> + void processScriptAttribute(const NameType& attributeName, const String& attributeValue) + { + // FIXME - Don't set crossorigin multiple times. + if (match(attributeName, srcAttr)) + setUrlToLoad(attributeValue, DisallowURLReplacement); + else if (match(attributeName, crossoriginAttr)) + setCrossOriginAllowed(attributeValue); + } + + template<typename NameType> + void processImgAttribute(const NameType& attributeName, const String& attributeValue) + { + if (match(attributeName, srcAttr) && m_imgSrcUrl.isNull()) { + m_imgSrcUrl = attributeValue; + setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_sourceSize, attributeValue, m_srcsetImageCandidate), AllowURLReplacement); + } else if (match(attributeName, crossoriginAttr)) { + setCrossOriginAllowed(attributeValue); + } else if (match(attributeName, srcsetAttr) && m_srcsetImageCandidate.isEmpty()) { + m_srcsetAttributeValue = attributeValue; + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, attributeValue); + setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_sourceSize, m_imgSrcUrl, m_srcsetImageCandidate), AllowURLReplacement); + } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && match(attributeName, sizesAttr) && !m_sourceSizeSet) { + m_sourceSize = SizesAttributeParser::findEffectiveSize(attributeValue, m_mediaValues); + m_sourceSizeSet = true; + if (!m_srcsetImageCandidate.isEmpty()) { + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, m_srcsetAttributeValue); + setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_sourceSize, m_imgSrcUrl, m_srcsetImageCandidate), AllowURLReplacement); + } + } + } + + template<typename NameType> + void processLinkAttribute(const NameType& attributeName, const String& attributeValue) + { + // FIXME - Don't set rel/media/crossorigin multiple times. + if (match(attributeName, hrefAttr)) + setUrlToLoad(attributeValue, DisallowURLReplacement); + else if (match(attributeName, relAttr)) + m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); + else if (match(attributeName, mediaAttr)) + m_matchedMediaAttribute = mediaAttributeMatches(*m_mediaValues, attributeValue); + else if (match(attributeName, crossoriginAttr)) + setCrossOriginAllowed(attributeValue); + } + + template<typename NameType> + void processInputAttribute(const NameType& attributeName, const String& attributeValue) + { + // FIXME - Don't set type multiple times. + if (match(attributeName, srcAttr)) + setUrlToLoad(attributeValue, DisallowURLReplacement); + else if (match(attributeName, typeAttr)) + m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image); + } + + template<typename NameType> + void processSourceAttribute(const NameType& attributeName, const String& attributeValue) + { + if (!RuntimeEnabledFeatures::pictureEnabled()) + return; + if (match(attributeName, srcsetAttr) && m_srcsetImageCandidate.isEmpty()) { + m_srcsetAttributeValue = attributeValue; + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, attributeValue); + } else if (match(attributeName, sizesAttr) && !m_sourceSizeSet) { + m_sourceSize = SizesAttributeParser::findEffectiveSize(attributeValue, m_mediaValues); + m_sourceSizeSet = true; + if (!m_srcsetImageCandidate.isEmpty()) { + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, m_srcsetAttributeValue); + } + } else if (match(attributeName, mediaAttr)) { + // FIXME - Don't match media multiple times. + m_matchedMediaAttribute = mediaAttributeMatches(*m_mediaValues, attributeValue); + } + + } + + template<typename NameType> void processAttribute(const NameType& attributeName, const String& attributeValue) { if (match(attributeName, charsetAttr)) m_charset = attributeValue; - if (match(m_tagImpl, scriptTag)) { - if (match(attributeName, srcAttr)) - setUrlToLoad(attributeValue, DisallowURLReplacement); - else if (match(attributeName, crossoriginAttr)) - setCrossOriginAllowed(attributeValue); - } else if (match(m_tagImpl, imgTag)) { - if (match(attributeName, srcAttr) && !m_encounteredImgSrc) { - m_encounteredImgSrc = true; - setUrlToLoad(bestFitSourceForImageAttributes(m_deviceScaleFactor, attributeValue, m_srcsetImageCandidate), AllowURLReplacement); - } else if (match(attributeName, crossoriginAttr)) { - setCrossOriginAllowed(attributeValue); - } else if (RuntimeEnabledFeatures::srcsetEnabled() - && match(attributeName, srcsetAttr) - && m_srcsetImageCandidate.isEmpty()) { - m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_deviceScaleFactor, attributeValue); - setUrlToLoad(bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcsetImageCandidate), AllowURLReplacement); - } - } else if (match(m_tagImpl, linkTag)) { - if (match(attributeName, hrefAttr)) - setUrlToLoad(attributeValue, DisallowURLReplacement); - else if (match(attributeName, relAttr)) - m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); - else if (match(attributeName, mediaAttr)) - m_mediaAttribute = attributeValue; - } else if (match(m_tagImpl, inputTag)) { - if (match(attributeName, srcAttr)) - setUrlToLoad(attributeValue, DisallowURLReplacement); - else if (match(attributeName, typeAttr)) - m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image); - } + if (match(m_tagImpl, scriptTag)) + processScriptAttribute(attributeName, attributeValue); + else if (match(m_tagImpl, imgTag)) + processImgAttribute(attributeName, attributeValue); + else if (match(m_tagImpl, linkTag)) + processLinkAttribute(attributeName, attributeValue); + else if (match(m_tagImpl, inputTag)) + processInputAttribute(attributeName, attributeValue); + else if (match(m_tagImpl, sourceTag)) + processSourceAttribute(attributeName, attributeValue); } static bool relAttributeIsStyleSheet(const String& attributeValue) @@ -240,7 +323,7 @@ private: return m_isCORSEnabled; } - StoredCredentials allowCredentials() const + StoredCredentials allowStoredCredentials() const { return m_allowCredentials; } @@ -259,19 +342,23 @@ private: ImageCandidate m_srcsetImageCandidate; String m_charset; bool m_linkIsStyleSheet; - String m_mediaAttribute; + bool m_matchedMediaAttribute; bool m_inputIsImage; - float m_deviceScaleFactor; - bool m_encounteredImgSrc; + String m_imgSrcUrl; + String m_srcsetAttributeValue; + unsigned m_sourceSize; + bool m_sourceSizeSet; bool m_isCORSEnabled; StoredCredentials m_allowCredentials; + RefPtr<MediaValues> m_mediaValues; }; -TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL, float deviceScaleFactor) +TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL, PassRefPtr<MediaValues> mediaValues) : m_documentURL(documentURL) , m_inStyle(false) - , m_deviceScaleFactor(deviceScaleFactor) + , m_inPicture(false) , m_templateCount(0) + , m_mediaValues(mediaValues) { } @@ -328,7 +415,10 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString& if (m_inStyle) m_cssScanner.reset(); m_inStyle = false; + return; } + if (match(tagImpl, pictureTag)) + m_inPicture = false; return; } case HTMLToken::StartTag: { @@ -350,9 +440,16 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString& updatePredictedBaseURL(token); return; } + if (RuntimeEnabledFeatures::pictureEnabled() && (match(tagImpl, pictureTag))) { + m_inPicture = true; + m_pictureSourceURL = String(); + return; + } - StartTagScanner scanner(tagImpl, m_deviceScaleFactor); + StartTagScanner scanner(tagImpl, m_mediaValues); scanner.processAttributes(token.attributes()); + if (m_inPicture) + scanner.handlePictureSourceURL(m_pictureSourceURL); OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predictedBaseElementURL, source); if (request) requests.append(request.release()); @@ -372,8 +469,8 @@ void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefAttribute->value)).copy(); } -HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const KURL& documentURL, float deviceScaleFactor) - : m_scanner(documentURL, deviceScaleFactor) +HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const KURL& documentURL, PassRefPtr<MediaValues> mediaValues) + : m_scanner(documentURL, mediaValues) , m_tokenizer(HTMLTokenizer::create(options)) { } @@ -391,6 +488,8 @@ void HTMLPreloadScanner::scan(HTMLResourcePreloader* preloader, const KURL& star { ASSERT(isMainThread()); // HTMLTokenizer::updateStateFor only works on the main thread. + TRACE_EVENT1("webkit", "HTMLPreloadScanner::scan", "source_length", m_source.length()); + // When we start scanning, our best prediction of the baseElementURL is the real one! if (!startingBaseElementURL.isEmpty()) m_scanner.setPredictedBaseElementURL(startingBaseElementURL); @@ -399,7 +498,7 @@ void HTMLPreloadScanner::scan(HTMLResourcePreloader* preloader, const KURL& star while (m_tokenizer->nextToken(m_source, m_token)) { if (m_token.type() == HTMLToken::StartTag) - m_tokenizer->updateStateFor(AtomicString(m_token.name())); + m_tokenizer->updateStateFor(attemptStaticStringCreation(m_token.name(), Likely8Bit)); m_scanner.scan(m_token, m_source, requests); m_token.clear(); } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h index 956d30b3d28..96046e1259d 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h @@ -40,11 +40,12 @@ typedef size_t TokenPreloadScannerCheckpoint; class HTMLParserOptions; class HTMLTokenizer; class SegmentedString; +class MediaValues; class TokenPreloadScanner { WTF_MAKE_NONCOPYABLE(TokenPreloadScanner); WTF_MAKE_FAST_ALLOCATED; public: - TokenPreloadScanner(const KURL& documentURL, float deviceScaleFactor); + TokenPreloadScanner(const KURL& documentURL, PassRefPtr<MediaValues>); ~TokenPreloadScanner(); void scan(const HTMLToken&, const SegmentedString&, PreloadRequestStream& requests); @@ -89,8 +90,10 @@ private: const KURL m_documentURL; KURL m_predictedBaseElementURL; bool m_inStyle; - float m_deviceScaleFactor; + bool m_inPicture; + String m_pictureSourceURL; size_t m_templateCount; + RefPtr<MediaValues> m_mediaValues; Vector<Checkpoint> m_checkpoints; }; @@ -98,7 +101,7 @@ private: class HTMLPreloadScanner { WTF_MAKE_NONCOPYABLE(HTMLPreloadScanner); WTF_MAKE_FAST_ALLOCATED; public: - HTMLPreloadScanner(const HTMLParserOptions&, const KURL& documentURL, float deviceScaleFactor); + HTMLPreloadScanner(const HTMLParserOptions&, const KURL& documentURL, PassRefPtr<MediaValues>); ~HTMLPreloadScanner(); void appendToEnd(const SegmentedString&); diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp index 08e70a6a278..76857627141 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp @@ -29,9 +29,7 @@ #include "core/dom/Document.h" #include "core/fetch/FetchInitiatorInfo.h" #include "core/fetch/ResourceFetcher.h" -#include "core/html/HTMLImport.h" -#include "core/css/MediaList.h" -#include "core/css/MediaQueryEvaluator.h" +#include "core/html/imports/HTMLImport.h" #include "core/rendering/RenderObject.h" #include "public/platform/Platform.h" @@ -42,20 +40,19 @@ bool PreloadRequest::isSafeToSendToAnotherThread() const return m_initiatorName.isSafeToSendToAnotherThread() && m_charset.isSafeToSendToAnotherThread() && m_resourceURL.isSafeToSendToAnotherThread() - && m_mediaAttribute.isSafeToSendToAnotherThread() && m_baseURL.isSafeToSendToAnotherThread(); } KURL PreloadRequest::completeURL(Document* document) { - return document->completeURL(m_resourceURL, m_baseURL.isEmpty() ? document->url() : m_baseURL); + return document->completeURLWithOverride(m_resourceURL, m_baseURL.isEmpty() ? document->url() : m_baseURL); } FetchRequest PreloadRequest::resourceRequest(Document* document) { ASSERT(isMainThread()); FetchInitiatorInfo initiatorInfo; - initiatorInfo.name = m_initiatorName; + initiatorInfo.name = AtomicString(m_initiatorName); initiatorInfo.position = m_initiatorPosition; FetchRequest request(ResourceRequest(completeURL(document)), initiatorInfo); @@ -73,28 +70,11 @@ void HTMLResourcePreloader::takeAndPreload(PreloadRequestStream& r) preload(it->release()); } -static bool mediaAttributeMatches(Frame* frame, RenderStyle* renderStyle, const String& attributeValue) -{ - RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(attributeValue); - MediaQueryEvaluator mediaQueryEvaluator("screen", frame, renderStyle); - return mediaQueryEvaluator.eval(mediaQueries.get()); -} - void HTMLResourcePreloader::preload(PassOwnPtr<PreloadRequest> preload) { - Document* executingDocument = m_document->import() ? m_document->import()->master() : m_document; - Document* loadingDocument = m_document; - - ASSERT(executingDocument->frame()); - ASSERT(executingDocument->renderer()); - ASSERT(executingDocument->renderer()->style()); - if (!preload->media().isEmpty() && !mediaAttributeMatches(executingDocument->frame(), executingDocument->renderer()->style(), preload->media())) - return; - FetchRequest request = preload->resourceRequest(m_document); blink::Platform::current()->histogramCustomCounts("WebCore.PreloadDelayMs", static_cast<int>(1000 * (monotonicallyIncreasingTime() - preload->discoveryTime())), 0, 2000, 20); - loadingDocument->fetcher()->preload(preload->resourceType(), request, preload->charset()); + m_document->fetcher()->preload(preload->resourceType(), request, preload->charset()); } - } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.h index 48686b6ca73..ee6868c143c 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.h @@ -35,14 +35,9 @@ namespace WebCore { class PreloadRequest { public: - static PassOwnPtr<PreloadRequest> create(const String& initiatorName, const TextPosition& initiatorPosition, const String& resourceURL, const KURL& baseURL, Resource::Type resourceType, const String& mediaAttribute) - { - return adoptPtr(new PreloadRequest(initiatorName, initiatorPosition, resourceURL, baseURL, resourceType, mediaAttribute)); - } - static PassOwnPtr<PreloadRequest> create(const String& initiatorName, const TextPosition& initiatorPosition, const String& resourceURL, const KURL& baseURL, Resource::Type resourceType) { - return adoptPtr(new PreloadRequest(initiatorName, initiatorPosition, resourceURL, baseURL, resourceType, "")); + return adoptPtr(new PreloadRequest(initiatorName, initiatorPosition, resourceURL, baseURL, resourceType)); } bool isSafeToSendToAnotherThread() const; @@ -50,7 +45,6 @@ public: FetchRequest resourceRequest(Document*); const String& charset() const { return m_charset; } - const String& media() const { return m_mediaAttribute; } double discoveryTime() const { return m_discoveryTime; } void setCharset(const String& charset) { m_charset = charset.isolatedCopy(); } void setCrossOriginEnabled(StoredCredentials allowCredentials) @@ -62,13 +56,12 @@ public: Resource::Type resourceType() const { return m_resourceType; } private: - PreloadRequest(const String& initiatorName, const TextPosition& initiatorPosition, const String& resourceURL, const KURL& baseURL, Resource::Type resourceType, const String& mediaAttribute) + PreloadRequest(const String& initiatorName, const TextPosition& initiatorPosition, const String& resourceURL, const KURL& baseURL, Resource::Type resourceType) : m_initiatorName(initiatorName) , m_initiatorPosition(initiatorPosition) , m_resourceURL(resourceURL.isolatedCopy()) , m_baseURL(baseURL.copy()) , m_resourceType(resourceType) - , m_mediaAttribute(mediaAttribute.isolatedCopy()) , m_isCORSEnabled(false) , m_allowCredentials(DoNotAllowStoredCredentials) , m_discoveryTime(monotonicallyIncreasingTime()) @@ -83,7 +76,6 @@ private: KURL m_baseURL; String m_charset; Resource::Type m_resourceType; - String m_mediaAttribute; bool m_isCORSEnabled; StoredCredentials m_allowCredentials; double m_discoveryTime; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp index 1cb6555c243..70c4c25f3b5 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp @@ -33,10 +33,10 @@ #include "core/dom/Microtask.h" #include "core/dom/ScriptLoader.h" #include "core/fetch/ScriptResource.h" +#include "core/frame/LocalFrame.h" #include "core/html/parser/HTMLInputStream.h" #include "core/html/parser/HTMLScriptRunnerHost.h" #include "core/html/parser/NestingLevelIncrementer.h" -#include "core/frame/Frame.h" #include "platform/NotImplemented.h" namespace WebCore { @@ -54,7 +54,23 @@ HTMLScriptRunner::HTMLScriptRunner(Document* document, HTMLScriptRunnerHost* hos HTMLScriptRunner::~HTMLScriptRunner() { - // FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction? +#if ENABLE(OILPAN) + // If the document is destructed without having explicitly + // detached the parser (and this script runner object), perform + // detach steps now. This will happen if the Document, the parser + // and this script runner object are swept out in the same GC. + detach(); +#else + // Verify that detach() has been called. + ASSERT(!m_document); +#endif +} + +void HTMLScriptRunner::detach() +{ + if (!m_document) + return; + if (m_parserBlockingScript.resource() && m_parserBlockingScript.watchingForLoad()) stopWatchingForLoad(m_parserBlockingScript); @@ -63,23 +79,25 @@ HTMLScriptRunner::~HTMLScriptRunner() if (pendingScript.resource() && pendingScript.watchingForLoad()) stopWatchingForLoad(pendingScript); } -} - -void HTMLScriptRunner::detach() -{ - m_document = 0; + m_document = nullptr; } static KURL documentURLForScriptExecution(Document* document) { - if (!document || !document->frame()) + if (!document) + return KURL(); + + if (!document->frame()) { + if (document->importsController()) + return document->url(); return KURL(); + } // Use the URL of the currently active document for this frame. return document->frame()->document()->url(); } -inline PassRefPtr<Event> createScriptLoadEvent() +inline PassRefPtrWillBeRawPtr<Event> createScriptLoadEvent() { return Event::create(EventTypeNames::load); } @@ -97,7 +115,7 @@ ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript& bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script) { - m_hasScriptsWaitingForResources = !m_document->haveStylesheetsAndImportsLoaded(); + m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); if (m_hasScriptsWaitingForResources) return false; if (script.resource() && !script.resource()->isLoaded()) @@ -109,14 +127,14 @@ void HTMLScriptRunner::executeParsingBlockingScript() { ASSERT(m_document); ASSERT(!isExecutingScript()); - ASSERT(m_document->haveStylesheetsAndImportsLoaded()); + ASSERT(m_document->isScriptExecutionReady()); ASSERT(isPendingScriptReady(m_parserBlockingScript)); InsertionPointRecord insertionPointRecord(m_host->inputStream()); - executePendingScriptAndDispatchEvent(m_parserBlockingScript); + executePendingScriptAndDispatchEvent(m_parserBlockingScript, PendingScriptBlockingParser); } -void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript) +void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript, PendingScriptType pendingScriptType) { bool errorOccurred = false; ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred); @@ -125,11 +143,18 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi if (pendingScript.resource() && pendingScript.watchingForLoad()) stopWatchingForLoad(pendingScript); - if (!isExecutingScript()) + if (!isExecutingScript()) { Microtask::performCheckpoint(); + if (pendingScriptType == PendingScriptBlockingParser) { + m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); + // The parser cannot be unblocked as a microtask requested another resource + if (m_hasScriptsWaitingForResources) + return; + } + } // Clear the pending script before possible rentrancy from executeScript() - RefPtr<Element> element = pendingScript.releaseElementAndClear(); + RefPtrWillBeRawPtr<Element> element = pendingScript.releaseElementAndClear(); if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element.get())) { NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document); @@ -137,8 +162,8 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi scriptLoader->dispatchErrorEvent(); else { ASSERT(isExecutingScript()); - if (scriptLoader->executePotentiallyCrossOriginScript(sourceCode)) - element->dispatchEvent(createScriptLoadEvent()); + scriptLoader->executeScript(sourceCode); + element->dispatchEvent(createScriptLoadEvent()); } } ASSERT(!isExecutingScript()); @@ -147,20 +172,30 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi void HTMLScriptRunner::watchForLoad(PendingScript& pendingScript) { ASSERT(!pendingScript.watchingForLoad()); - m_host->watchForLoad(pendingScript.resource()); + ASSERT(!pendingScript.resource()->isLoaded()); + // addClient() will call notifyFinished() if the load is complete. + // Callers do not expect to be re-entered from this call, so they + // should not become a client of an already-loaded Resource. + pendingScript.resource()->addClient(this); pendingScript.setWatchingForLoad(true); } void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript) { ASSERT(pendingScript.watchingForLoad()); - m_host->stopWatchingForLoad(pendingScript.resource()); + pendingScript.resource()->removeClient(this); pendingScript.setWatchingForLoad(false); } -// This function should match 10.2.5.11 "An end tag whose tag name is 'script'" -// Script handling lives outside the tree builder to keep the each class simple. -void HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosition& scriptStartPosition) +void HTMLScriptRunner::notifyFinished(Resource* cachedResource) +{ + m_host->notifyScriptLoaded(cachedResource); +} + +// Implements the steps for 'An end tag whose tag name is "script"' +// http://whatwg.org/html#scriptEndTag +// Script handling lives outside the tree builder to keep each class simple. +void HTMLScriptRunner::execute(PassRefPtrWillBeRawPtr<Element> scriptElement, const TextPosition& scriptStartPosition) { ASSERT(scriptElement); // FIXME: If scripting is disabled, always just return. @@ -207,7 +242,7 @@ void HTMLScriptRunner::executeScriptsWaitingForResources() // to prevent parser or script re-entry during </style> parsing. ASSERT(hasScriptsWaitingForResources()); ASSERT(!isExecutingScript()); - ASSERT(m_document->haveStylesheetsAndImportsLoaded()); + ASSERT(m_document->isScriptExecutionReady()); executeParsingBlockingScripts(); } @@ -222,7 +257,7 @@ bool HTMLScriptRunner::executeScriptsWaitingForParsing() return false; } PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); - executePendingScriptAndDispatchEvent(first); + executePendingScriptAndDispatchEvent(first, PendingScriptDeferred); // FIXME: What is this m_document check for? if (!m_document) return false; @@ -268,8 +303,8 @@ bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Elemen return true; } -// This method is meant to match the HTML5 definition of "running a script" -// http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script +// Implements the initial steps for 'An end tag whose tag name is "script"' +// http://whatwg.org/html#scriptEndTag void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStartPosition) { ASSERT(m_document); @@ -285,10 +320,8 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStar if (!scriptLoader) return; - // FIXME: This may be too agressive as we always deliver mutations at - // every script element, even if it's not ready to execute yet. There's - // unfortuantely no obvious way to tell if prepareScript is going to - // execute the script from out here. + ASSERT(scriptLoader->isParserInserted()); + if (!isExecutingScript()) Microtask::performCheckpoint(); @@ -316,4 +349,12 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStar } } +void HTMLScriptRunner::trace(Visitor* visitor) +{ + visitor->trace(m_document); + visitor->trace(m_host); + visitor->trace(m_parserBlockingScript); + visitor->trace(m_scriptsToExecuteAfterParsing); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h index 82d8bc2568a..46f2979bca1 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.h @@ -27,6 +27,8 @@ #define HTMLScriptRunner_h #include "core/dom/PendingScript.h" +#include "core/fetch/ResourceClient.h" +#include "platform/heap/Handle.h" #include "wtf/Deque.h" #include "wtf/PassRefPtr.h" #include "wtf/text/TextPosition.h" @@ -37,23 +39,23 @@ class Resource; class ScriptResource; class Document; class Element; -class Frame; +class LocalFrame; class HTMLScriptRunnerHost; class ScriptSourceCode; -class HTMLScriptRunner { - WTF_MAKE_NONCOPYABLE(HTMLScriptRunner); WTF_MAKE_FAST_ALLOCATED; +class HTMLScriptRunner FINAL : public NoBaseWillBeGarbageCollectedFinalized<HTMLScriptRunner>, private ResourceClient { + WTF_MAKE_NONCOPYABLE(HTMLScriptRunner); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<HTMLScriptRunner> create(Document* document, HTMLScriptRunnerHost* host) + static PassOwnPtrWillBeRawPtr<HTMLScriptRunner> create(Document* document, HTMLScriptRunnerHost* host) { - return adoptPtr(new HTMLScriptRunner(document, host)); + return adoptPtrWillBeNoop(new HTMLScriptRunner(document, host)); } ~HTMLScriptRunner(); void detach(); // Processes the passed in script and any pending scripts if possible. - void execute(PassRefPtr<Element> scriptToProcess, const TextPosition& scriptStartPosition); + void execute(PassRefPtrWillBeRawPtr<Element> scriptToProcess, const TextPosition& scriptStartPosition); void executeScriptsWaitingForLoad(Resource*); bool hasScriptsWaitingForResources() const { return m_hasScriptsWaitingForResources; } @@ -63,13 +65,23 @@ public: bool hasParserBlockingScript() const; bool isExecutingScript() const { return !!m_scriptNestingLevel; } + // ResourceClient + virtual void notifyFinished(Resource*) OVERRIDE; + + void trace(Visitor*); + private: HTMLScriptRunner(Document*, HTMLScriptRunnerHost*); - Frame* frame() const; + LocalFrame* frame() const; + + enum PendingScriptType { + PendingScriptBlockingParser, + PendingScriptDeferred + }; void executeParsingBlockingScript(); - void executePendingScriptAndDispatchEvent(PendingScript&); + void executePendingScriptAndDispatchEvent(PendingScript&, PendingScriptType); void executeParsingBlockingScripts(); void requestParsingBlockingScript(Element*); @@ -84,8 +96,8 @@ private: bool isPendingScriptReady(const PendingScript&); ScriptSourceCode sourceFromPendingScript(const PendingScript&, bool& errorOccurred) const; - Document* m_document; - HTMLScriptRunnerHost* m_host; + RawPtrWillBeMember<Document> m_document; + RawPtrWillBeMember<HTMLScriptRunnerHost> m_host; PendingScript m_parserBlockingScript; Deque<PendingScript> m_scriptsToExecuteAfterParsing; // http://www.whatwg.org/specs/web-apps/current-work/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing unsigned m_scriptNestingLevel; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunnerHost.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunnerHost.h index e5323a2c3ae..ec3a8b68925 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunnerHost.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunnerHost.h @@ -30,20 +30,16 @@ namespace WebCore { -class Resource; -class Element; class HTMLInputStream; -class ScriptSourceCode; +class Resource; +class Visitor; -class HTMLScriptRunnerHost { +class HTMLScriptRunnerHost : public WillBeGarbageCollectedMixin { public: virtual ~HTMLScriptRunnerHost() { } + virtual void trace(Visitor*) { } - // Implementors should call cachedResource->addClient() here or soon after. - virtual void watchForLoad(Resource*) = 0; - // Implementors must call cachedResource->removeClient() immediately. - virtual void stopWatchingForLoad(Resource*) = 0; - + virtual void notifyScriptLoaded(Resource*) = 0; virtual HTMLInputStream& inputStream() = 0; virtual bool hasPreloadScanner() const = 0; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp index 7002dffab3b..f1af160e354 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Apple Inc. All rights reserved. * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,50 +34,176 @@ #include "core/html/parser/HTMLParserIdioms.h" #include "platform/ParsingUtilities.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { -static bool compareByScaleFactor(const ImageCandidate& first, const ImageCandidate& second) +static bool compareByDensity(const ImageCandidate& first, const ImageCandidate& second) { - return first.scaleFactor() < second.scaleFactor(); + return first.density() < second.density(); } +enum DescriptorTokenizerState { + Start, + InParenthesis, + AfterToken, +}; + +struct DescriptorToken { + unsigned start; + unsigned length; + + DescriptorToken(unsigned start, unsigned length) + : start(start) + , length(length) + { + } + + unsigned lastIndex() + { + return start + length - 1; + } + + template<typename CharType> + int toInt(const CharType* attribute, bool& isValid) + { + return charactersToInt(attribute + start, length - 1, &isValid); + } + + template<typename CharType> + float toFloat(const CharType* attribute, bool& isValid) + { + return charactersToFloat(attribute + start, length - 1, &isValid); + } +}; + template<typename CharType> -inline bool isComma(CharType character) +static void appendDescriptorAndReset(const CharType* attributeStart, const CharType*& descriptorStart, const CharType* position, Vector<DescriptorToken>& descriptors) { - return character == ','; + if (position > descriptorStart) + descriptors.append(DescriptorToken(descriptorStart - attributeStart, position - descriptorStart)); + descriptorStart = 0; } +// The following is called appendCharacter to match the spec's terminology. template<typename CharType> -static bool parseDescriptors(const CharType* descriptorsStart, const CharType* descriptorsEnd, float& imgScaleFactor) +static void appendCharacter(const CharType* descriptorStart, const CharType* position) { - const CharType* position = descriptorsStart; - bool isValid = true; - bool isScaleFactorFound = false; - while (position < descriptorsEnd) { - // 13.1. Let descriptor list be the result of splitting unparsed descriptors on spaces. - skipWhile<CharType, isHTMLSpace<CharType> >(position, descriptorsEnd); - const CharType* currentDescriptorStart = position; - skipWhile<CharType, isNotHTMLSpace<CharType> >(position, descriptorsEnd); - const CharType* currentDescriptorEnd = position; + // Since we don't copy the tokens, this just set the point where the descriptor tokens start. + if (!descriptorStart) + descriptorStart = position; +} +template<typename CharType> +static bool isEOF(const CharType* position, const CharType* end) +{ + return position >= end; +} + +template<typename CharType> +static void tokenizeDescriptors(const CharType* attributeStart, + const CharType*& position, + const CharType* attributeEnd, + Vector<DescriptorToken>& descriptors) +{ + DescriptorTokenizerState state = Start; + const CharType* descriptorsStart = position; + const CharType* currentDescriptorStart = descriptorsStart; + while (true) { + switch (state) { + case Start: + if (isEOF(position, attributeEnd)) { + appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); + return; + } + if (isComma(*position)) { + appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); + ++position; + return; + } + if (isHTMLSpace(*position)) { + appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); + currentDescriptorStart = position + 1; + state = AfterToken; + } else if (*position == '(') { + appendCharacter(currentDescriptorStart, position); + state = InParenthesis; + } else { + appendCharacter(currentDescriptorStart, position); + } + break; + case InParenthesis: + if (isEOF(position, attributeEnd)) { + appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); + return; + } + if (*position == ')') { + appendCharacter(currentDescriptorStart, position); + state = Start; + } else { + appendCharacter(currentDescriptorStart, position); + } + break; + case AfterToken: + if (isEOF(position, attributeEnd)) + return; + if (!isHTMLSpace(*position)) { + state = Start; + currentDescriptorStart = position; + --position; + } + break; + } ++position; - ASSERT(currentDescriptorEnd > currentDescriptorStart); - --currentDescriptorEnd; - unsigned descriptorLength = currentDescriptorEnd - currentDescriptorStart; - if (*currentDescriptorEnd == 'x') { - if (isScaleFactorFound) - return false; - imgScaleFactor = charactersToFloat(currentDescriptorStart, descriptorLength, &isValid); - isScaleFactorFound = true; - } else { + } +} + +template<typename CharType> +static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>& descriptors, DescriptorParsingResult& result) +{ + for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descriptors.end(); ++it) { + if (it->length == 0) continue; + CharType c = attribute[it->lastIndex()]; + bool isValid = false; + if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') { + if (result.hasDensity() || result.hasWidth()) + return false; + int resourceWidth = it->toInt(attribute, isValid); + if (!isValid || resourceWidth <= 0) + return false; + result.setResourceWidth(resourceWidth); + } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') { + // This is here only for future compat purposes. + // The value of the 'h' descriptor is not used. + if (result.hasDensity() || result.hasHeight()) + return false; + int resourceHeight = it->toInt(attribute, isValid); + if (!isValid || resourceHeight <= 0) + return false; + result.setResourceHeight(resourceHeight); + } else if (c == 'x') { + if (result.hasDensity() || result.hasHeight() || result.hasWidth()) + return false; + float density = it->toFloat(attribute, isValid); + if (!isValid || density < 0) + return false; + result.setDensity(density); } } - return isValid; + return true; } -// http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#processing-the-image-candidates +static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& descriptors, DescriptorParsingResult& result) +{ + // FIXME: See if StringView can't be extended to replace DescriptorToken here. + if (attribute.is8Bit()) { + return parseDescriptors(attribute.characters8(), descriptors, result); + } + return parseDescriptors(attribute.characters16(), descriptors, result); +} + +// http://picture.responsiveimages.org/#parse-srcset-attr template<typename CharType> static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, const CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandidates) { @@ -84,37 +211,46 @@ static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con const CharType* attributeEnd = position + length; while (position < attributeEnd) { - float imgScaleFactor = 1.0; - - // 4. Splitting loop: Skip whitespace. - skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); - if (position == attributeEnd) + // 4. Splitting loop: Collect a sequence of characters that are space characters or U+002C COMMA characters. + skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEnd); + if (position == attributeEnd) { + // Contrary to spec language - descriptor parsing happens on each candidate, so when we reach the attributeEnd, we can exit. break; - const CharType* imageURLStart = position; - - // If The current candidate is either totally empty or only contains space, skipping. - if (*position == ',') { - ++position; - continue; } + const CharType* imageURLStart = position; + // 6. Collect a sequence of characters that are not space characters, and let that be url. - // 5. Collect a sequence of characters that are not space characters, and let that be url. skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd); const CharType* imageURLEnd = position; - if (position != attributeEnd && *(position - 1) == ',') { - --imageURLEnd; + DescriptorParsingResult result; + + // 8. If url ends with a U+002C COMMA character (,) + if (isComma(*(position - 1))) { + // Remove all trailing U+002C COMMA characters from url. + imageURLEnd = position - 1; + reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart); + ++imageURLEnd; + // If url is empty, then jump to the step labeled splitting loop. + if (imageURLStart == imageURLEnd) + continue; } else { - // 7. Collect a sequence of characters that are not "," (U+002C) characters, and let that be descriptors. - skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd); - const CharType* descriptorsStart = position; - skipUntil<CharType, isComma<CharType> >(position, attributeEnd); - const CharType* descriptorsEnd = position; - if (!parseDescriptors(descriptorsStart, descriptorsEnd, imgScaleFactor)) + // Advancing position here (contrary to spec) to avoid an useless extra state machine step. + // Filed a spec bug: https://github.com/ResponsiveImagesCG/picture-element/issues/189 + ++position; + Vector<DescriptorToken> descriptorTokens; + tokenizeDescriptors(attributeStart, position, attributeEnd, descriptorTokens); + // Contrary to spec language - descriptor parsing happens on each candidate. + // This is a black-box equivalent, to avoid storing descriptor lists for each candidate. + if (!parseDescriptors(attribute, descriptorTokens, result)) continue; } - imageCandidates.append(ImageCandidate(attribute, imageURLStart - attributeStart, imageURLEnd - imageURLStart, imgScaleFactor)); + ASSERT(imageURLEnd > attributeStart); + unsigned imageURLStartingPosition = imageURLStart - attributeStart; + ASSERT(imageURLEnd > imageURLStart); + unsigned imageURLLength = imageURLEnd - imageURLStart; + imageCandidates.append(ImageCandidate(attribute, imageURLStartingPosition, imageURLLength, result, ImageCandidate::SrcsetOrigin)); // 11. Return to the step labeled splitting loop. } } @@ -130,36 +266,61 @@ static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.characters16(), attribute.length(), imageCandidates); } -static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector<ImageCandidate>& imageCandidates) +static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, unsigned sourceSize, Vector<ImageCandidate>& imageCandidates) { + const float defaultDensityValue = 1.0; + bool ignoreSrc = false; if (imageCandidates.isEmpty()) return ImageCandidate(); - std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByScaleFactor); + // http://picture.responsiveimages.org/#normalize-source-densities + for (Vector<ImageCandidate>::iterator it = imageCandidates.begin(); it != imageCandidates.end(); ++it) { + if (it->resourceWidth() > 0) { + it->setDensity((float)it->resourceWidth() / (float)sourceSize); + ignoreSrc = true; + } else if (it->density() < 0) { + it->setDensity(defaultDensityValue); + } + } + + std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByDensity); unsigned i; for (i = 0; i < imageCandidates.size() - 1; ++i) { - if (imageCandidates[i].scaleFactor() >= deviceScaleFactor) + if ((imageCandidates[i].density() >= deviceScaleFactor) && (!ignoreSrc || !imageCandidates[i].srcOrigin())) break; } - return imageCandidates[i]; + + if (imageCandidates[i].srcOrigin() && ignoreSrc) { + ASSERT(i > 0); + --i; + } + float winningDensity = imageCandidates[i].density(); + + unsigned winner = i; + // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates, + // then remove entry b + while ((i > 0) && (imageCandidates[--i].density() == winningDensity)) + winner = i; + + return imageCandidates[winner]; } -ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, const String& srcsetAttribute) +ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, unsigned sourceSize, const String& srcsetAttribute) { Vector<ImageCandidate> imageCandidates; parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); - return pickBestImageCandidate(deviceScaleFactor, imageCandidates); + return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates); } -ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcsetAttribute) +ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, unsigned sourceSize, const String& srcAttribute, const String& srcsetAttribute) { if (srcsetAttribute.isNull()) { if (srcAttribute.isNull()) return ImageCandidate(); - return ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1); + return ImageCandidate(srcAttribute, 0, srcAttribute.length(), DescriptorParsingResult(), ImageCandidate::SrcOrigin); } Vector<ImageCandidate> imageCandidates; @@ -167,12 +328,12 @@ ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const St parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); if (!srcAttribute.isEmpty()) - imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1.0)); + imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); - return pickBestImageCandidate(deviceScaleFactor, imageCandidates); + return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates); } -String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, ImageCandidate& srcsetImageCandidate) +String bestFitSourceForImageAttributes(float deviceScaleFactor, unsigned sourceSize, const String& srcAttribute, ImageCandidate& srcsetImageCandidate) { if (srcsetImageCandidate.isEmpty()) return srcAttribute; @@ -181,9 +342,9 @@ String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& sr imageCandidates.append(srcsetImageCandidate); if (!srcAttribute.isEmpty()) - imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), 1.0)); + imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.length(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); - return pickBestImageCandidate(deviceScaleFactor, imageCandidates).toString(); + return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates).toString(); } } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.h index 8964ffbcd5f..5ba5bff7f4f 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParser.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Apple Inc. All rights reserved. * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,27 +36,85 @@ namespace WebCore { +enum { UninitializedDescriptor = -1 }; + +class DescriptorParsingResult { +public: + DescriptorParsingResult() + : m_density(UninitializedDescriptor) + , m_resourceWidth(UninitializedDescriptor) + , m_resourceHeight(UninitializedDescriptor) + { + } + + bool hasDensity() const { return m_density >= 0; } + bool hasWidth() const { return m_resourceWidth >= 0; } + bool hasHeight() const { return m_resourceHeight >= 0; } + + float density() const { ASSERT(hasDensity()); return m_density; } + unsigned resourceWidth() const { ASSERT(hasWidth()); return m_resourceWidth; } + unsigned resourceHeight() const { ASSERT(hasHeight()); return m_resourceHeight; } + + void setResourceWidth(int width) { ASSERT(width >= 0); m_resourceWidth = (unsigned)width; } + void setResourceHeight(int height) { ASSERT(height >= 0); m_resourceHeight = (unsigned)height; } + void setDensity(float densityToSet) { ASSERT(densityToSet >= 0); m_density = densityToSet; } + +private: + float m_density; + int m_resourceWidth; + int m_resourceHeight; +}; + class ImageCandidate { public: + enum OriginAttribute { + SrcsetOrigin, + SrcOrigin + }; + ImageCandidate() - : m_scaleFactor(1.0) + : m_density(1.0) + , m_resourceWidth(UninitializedDescriptor) + , m_originAttribute(SrcsetOrigin) { } - ImageCandidate(const String& source, unsigned start, unsigned length, float scaleFactor) + ImageCandidate(const String& source, unsigned start, unsigned length, const DescriptorParsingResult& result, OriginAttribute originAttribute) : m_string(source.createView(start, length)) - , m_scaleFactor(scaleFactor) + , m_density(result.hasDensity()?result.density():UninitializedDescriptor) + , m_resourceWidth(result.hasWidth()?result.resourceWidth():UninitializedDescriptor) + , m_originAttribute(originAttribute) { } String toString() const { - return m_string.toString(); + return String(m_string.toString()); + } + + AtomicString url() const + { + return AtomicString(m_string.toString()); + } + + void setDensity(float factor) + { + m_density = factor; + } + + float density() const + { + return m_density; + } + + int resourceWidth() const + { + return m_resourceWidth; } - inline float scaleFactor() const + bool srcOrigin() const { - return m_scaleFactor; + return (m_originAttribute == SrcOrigin); } inline bool isEmpty() const @@ -65,14 +124,16 @@ public: private: StringView m_string; - float m_scaleFactor; + float m_density; + int m_resourceWidth; + OriginAttribute m_originAttribute; }; -ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, const String& srcsetAttribute); +ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, unsigned sourceSize, const String& srcsetAttribute); -ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcsetAttribute); +ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, unsigned sourceSize, const String& srcAttribute, const String& srcsetAttribute); -String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, ImageCandidate& srcsetImageCandidate); +String bestFitSourceForImageAttributes(float deviceScaleFactor, unsigned sourceSize, const String& srcAttribute, ImageCandidate& srcsetImageCandidate); } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParserTest.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParserTest.cpp new file mode 100644 index 00000000000..76236102f90 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLSrcsetParserTest.cpp @@ -0,0 +1,102 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/parser/HTMLSrcsetParser.h" + +#include <gtest/gtest.h> +#include <limits.h> + +namespace WebCore { + +typedef struct { + float deviceScaleFactor; + int effectiveSize; + const char* srcInput; + const char* srcsetInput; + const char* outputURL; + float outputDensity; + int outputResourceWidth; +} TestCase; + +TEST(ImageCandidateTest, Basic) +{ + ImageCandidate candidate; + ASSERT_EQ(candidate.density(), 1); + ASSERT_EQ(candidate.resourceWidth(), -1); + ASSERT_EQ(candidate.srcOrigin(), false); + +} + +TEST(HTMLSrcsetParserTest, Basic) +{ + TestCase testCases[] = { + {2.0, -1, "", "1x.gif 1x, 2x.gif 2x", "2x.gif", 2.0, -1}, + {2.0, -1, "", "1x.gif 1q, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, -1, "", "1x.gif 1q, 2x.gif 2x", "1x.gif", 1.0, -1}, + {1.0, -1, "", "1x.gif 1x 100h, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, -1, "", "1x.gif 1x 100w, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, -1, "", "1x.gif 1x 100h 100w, 2x.gif 2x", "2x.gif", 2.0, -1}, + {2.0, -1, "", "1x.gif 1x, 2x.gif -2x", "1x.gif", 1.0, -1}, + {2.0, -1, "", "0x.gif 0x", "0x.gif", 0.0, -1}, + {2.0, -1, "", "0x.gif -0x", "0x.gif", 0.0, -1}, + {2.0, -1, "", "neg.gif -2x", "", 1.0, -1}, + {2.0, -1, "", "1x.gif 1x, 2x.gif 2q", "1x.gif", 1.0, -1}, + {2.0, -1, "", "1x.gif, 2x.gif 2q", "1x.gif", 1.0, -1}, + {2.0, -1, "", "1x.gif , 2x.gif 2q", "1x.gif", 1.0, -1}, + {2.0, -1, "1x.gif 1x, 2x.gif 2x", "1x.gif 1x, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, -1, "1x.gif 1x, 2x.gif 2x", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1}, + {1.0, -1, "1x.gif 1x, 2x.gif 2x", "", "1x.gif 1x, 2x.gif 2x", 1.0, -1}, + {2.0, -1, "src.gif", "1x.gif 1x, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, -1, "src.gif", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1}, + {1.0, -1, "src.gif", "2x.gif 2x", "src.gif", 1.0, -1}, + {2.0, -1, "src.gif", "2x.gif 2x", "2x.gif", 2.0, -1}, + {1.5, -1, "src.gif", "2x.gif 2x", "2x.gif", 2.0, -1}, + {2.5, -1, "src.gif", "2x.gif 2x", "2x.gif", 2.0, -1}, + {2.5, -1, "src.gif", "2x.gif 2x, 3x.gif 3x", "3x.gif", 3.0, -1}, + {2.0, -1, "", "1x,, , x ,2x ", "1x", 1.0, -1}, + {2.0, -1, "", "1x,, , x ,2x ", "1x", 1.0, -1}, + {2.0, -1, "", ",,1x,, , x ,2x ", "1x", 1.0, -1}, + {2.0, -1, "", ",,1x,,", "1x", 1.0, -1}, + {2.0, -1, "", ",1x,", "1x", 1.0, -1}, + {2.0, -1, "", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg 1x, 2x.gif 2x", "2x.gif", 2.0, -1}, + {2.0, -1, "", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg 2x, 1x.gif 1x", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg", 2.0, -1}, + {2.0, -1, "", "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, 2x.gif 2x ,", "2x.gif", 2.0, -1}, + {4.0, -1, "", "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100h, 5x.gif 5, dx.gif dx, 2x.gif 2x ,", "2x.gif", 2.0, -1}, + {4.0, -1, "", "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, 2x.gif 2x ,", "4x.gif", 4.0, -1}, + {1.0, -1, "", "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, 2x.gif 2x ,", "1x", 1.0, -1}, + {5.0, -1, "", "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, 2x.gif 2x ,", "4x.gif", 4.0, -1}, + {2.0, -1, "", "1x.gif 1x, data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj4KCTxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4K 2x", "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj4KCTxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4K", 2.0, -1 }, + {2.0, -1, "1x.gif", "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj4KCTxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4K 2x", "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj4KCTxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4K", 2.0, -1 }, + {2.0, -1, "1x.svg#red", "1x.svg#green 2x", "1x.svg#green", 2.0, -1 }, + {2.0, -1, "", "1x.svg#red 1x, 1x.svg#green 2x", "1x.svg#green", 2.0, -1 }, + {1.0, 400, "", "400.gif 400w, 6000.gif 6000w", "400.gif", 1.0, 400}, + {1.0, 400, "", "400.gif 400w 400h, 6000.gif 6000w", "400.gif", 1.0, 400}, + {2.0, 400, "", "400.gif 400w, 6000.gif 6000w", "6000.gif", 15.0, 6000}, + {1.0, 400, "src.gif", "800.gif 800w", "800.gif", 2.0, 800}, + {1.0, 400, "src.gif", "0.gif 0w, 800.gif 800w", "800.gif", 2.0, 800}, + {1.0, 400, "src.gif", "0.gif 0w, 2x.gif 2x", "src.gif", 1.0, -1}, + {1.0, 400, "src.gif", "800.gif 2x, 1600.gif 1600w", "800.gif", 2.0, -1}, + {1.0, 400, "", "400.gif 400w, 2x.gif 2x", "400.gif", 1.0, 400}, + {2.0, 400, "", "400.gif 400w, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, 0, "", "400.gif 400w, 6000.gif 6000w", "400.gif", std::numeric_limits<float>::infinity(), 400}, + {2.0, -1, "", ", 1x.gif 1x, 2x.gif 2x", "2x.gif", 2.0, -1}, + {1.0, -1, "", ",1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1}, + {1.2, -1, "", ",1x.gif 1x, 1.4x.gif 1.4x, 2x.gif 2x", "1.4x.gif", 1.4, -1}, + {1.0, -1, "", "inf.gif 0.00000000001x", "inf.gif", 1e-11, -1}, + {1.0, -1, "", ",1x.gif 1x future-descriptor(3x, 4h, whatever), 2x.gif 2x", "1x.gif", 1.0, -1}, + {2.0, -1, "", ",1x.gif 1x future-descriptor(3x, 4h, whatever), 2x.gif 2x", "2x.gif", 2.0, -1}, + {0, 0, 0, 0, 0, 0} // Do not remove the terminator line. + }; + + for (unsigned i = 0; testCases[i].srcInput; ++i) { + TestCase test = testCases[i]; + ImageCandidate candidate = bestFitSourceForImageAttributes(test.deviceScaleFactor, test.effectiveSize, test.srcInput, test.srcsetInput); + ASSERT_EQ(test.outputDensity, candidate.density()); + ASSERT_EQ(test.outputResourceWidth, candidate.resourceWidth()); + ASSERT_STREQ(test.outputURL, candidate.toString().ascii().data()); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h index d3dd15ca269..e15c2c119cc 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h @@ -26,9 +26,9 @@ #ifndef HTMLStackItem_h #define HTMLStackItem_h -#include "HTMLNames.h" -#include "MathMLNames.h" -#include "SVGNames.h" +#include "core/HTMLNames.h" +#include "core/MathMLNames.h" +#include "core/SVGNames.h" #include "core/dom/Element.h" #include "core/html/parser/AtomicHTMLToken.h" #include "wtf/RefCounted.h" @@ -39,7 +39,7 @@ namespace WebCore { class ContainerNode; -class HTMLStackItem : public RefCounted<HTMLStackItem> { +class HTMLStackItem : public RefCountedWillBeGarbageCollectedFinalized<HTMLStackItem> { public: enum ItemType { ItemForContextElement, @@ -47,15 +47,15 @@ public: }; // Used by document fragment node and context element. - static PassRefPtr<HTMLStackItem> create(PassRefPtr<ContainerNode> node, ItemType type) + static PassRefPtrWillBeRawPtr<HTMLStackItem> create(PassRefPtrWillBeRawPtr<ContainerNode> node, ItemType type) { - return adoptRef(new HTMLStackItem(node, type)); + return adoptRefWillBeNoop(new HTMLStackItem(node, type)); } // Used by HTMLElementStack and HTMLFormattingElementList. - static PassRefPtr<HTMLStackItem> create(PassRefPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) + static PassRefPtrWillBeRawPtr<HTMLStackItem> create(PassRefPtrWillBeRawPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) { - return adoptRef(new HTMLStackItem(node, token, namespaceURI)); + return adoptRefWillBeNoop(new HTMLStackItem(node, token, namespaceURI)); } Element* element() const { return toElement(m_node.get()); } @@ -172,7 +172,6 @@ public: || tagName == HTMLNames::iframeTag || tagName == HTMLNames::imgTag || tagName == HTMLNames::inputTag - || tagName == HTMLNames::isindexTag || tagName == HTMLNames::liTag || tagName == HTMLNames::linkTag || tagName == HTMLNames::listingTag @@ -208,8 +207,10 @@ public: || tagName == HTMLNames::xmpTag; } + void trace(Visitor* visitor) { visitor->trace(m_node); } + private: - HTMLStackItem(PassRefPtr<ContainerNode> node, ItemType type) + HTMLStackItem(PassRefPtrWillBeRawPtr<ContainerNode> node, ItemType type) : m_node(node) { switch (type) { @@ -224,7 +225,7 @@ private: } } - HTMLStackItem(PassRefPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) + HTMLStackItem(PassRefPtrWillBeRawPtr<ContainerNode> node, AtomicHTMLToken* token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI) : m_node(node) , m_tokenLocalName(token->name()) , m_tokenAttributes(token->attributes()) @@ -233,7 +234,7 @@ private: { } - RefPtr<ContainerNode> m_node; + RefPtrWillBeMember<ContainerNode> m_node; AtomicString m_tokenLocalName; Vector<Attribute> m_tokenAttributes; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLToken.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLToken.h index 64f3044631b..e2b67fc33aa 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLToken.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLToken.h @@ -27,7 +27,6 @@ #define HTMLToken_h #include "core/dom/Attribute.h" -#include "core/html/parser/HTMLToken.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -104,7 +103,12 @@ public: m_range.start = 0; m_range.end = 0; m_baseOffset = 0; - m_data.clear(); + // Don't call Vector::clear() as that would destroy the + // alloced VectorBuffer. If the innerHTML'd content has + // two 257 character text nodes in a row, we'll needlessly + // thrash malloc. When we finally finish the parse the + // HTMLToken will be destroyed and the VectorBuffer released. + m_data.shrink(0); m_orAllData = 0; } @@ -326,9 +330,7 @@ public: { ASSERT(character); ASSERT(m_type == StartTag || m_type == EndTag); - // FIXME: We should be able to add the following ASSERT once we fix - // https://bugs.webkit.org/show_bug.cgi?id=62971 - // ASSERT(m_currentAttribute->nameRange.start); + ASSERT(m_currentAttribute->nameRange.start); m_currentAttribute->name.append(character); } @@ -426,6 +428,7 @@ public: m_orAllData |= character; } + // Only for XSSAuditor void eraseCharacters() { ASSERT(m_type == Character); diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp index ed8c954a64b..8b03782d45e 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp @@ -28,8 +28,10 @@ #include "config.h" #include "core/html/parser/HTMLTokenizer.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/HTMLTokenizerNames.h" #include "core/html/parser/HTMLEntityParser.h" +#include "core/html/parser/HTMLParserIdioms.h" #include "core/html/parser/HTMLTreeBuilder.h" #include "platform/NotImplemented.h" #include "core/xml/parser/MarkupTokenizerInlines.h" @@ -37,7 +39,9 @@ #include "wtf/text/AtomicString.h" #include "wtf/unicode/Unicode.h" -using namespace WTF; +// Please don't use DEFINE_STATIC_LOCAL in this file. The HTMLTokenizer is used +// from multiple threads and DEFINE_STATIC_LOCAL isn't threadsafe. +#undef DEFINE_STATIC_LOCAL namespace WebCore { @@ -1071,11 +1075,8 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token) END_STATE() HTML_BEGIN_STATE(MarkupDeclarationOpenState) { - DEFINE_STATIC_LOCAL(String, dashDashString, ("--")); - DEFINE_STATIC_LOCAL(String, doctypeString, ("doctype")); - DEFINE_STATIC_LOCAL(String, cdataString, ("[CDATA[")); if (cc == '-') { - SegmentedString::LookAheadResult result = source.lookAhead(dashDashString); + SegmentedString::LookAheadResult result = source.lookAhead(HTMLTokenizerNames::dashDash); if (result == SegmentedString::DidMatch) { source.advanceAndASSERT('-'); source.advanceAndASSERT('-'); @@ -1084,14 +1085,14 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token) } else if (result == SegmentedString::NotEnoughCharacters) return haveBufferedCharacterToken(); } else if (cc == 'D' || cc == 'd') { - SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(doctypeString); + SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(HTMLTokenizerNames::doctype); if (result == SegmentedString::DidMatch) { advanceStringAndASSERTIgnoringCase(source, "doctype"); HTML_SWITCH_TO(DOCTYPEState); } else if (result == SegmentedString::NotEnoughCharacters) return haveBufferedCharacterToken(); } else if (cc == '[' && shouldAllowCDATA()) { - SegmentedString::LookAheadResult result = source.lookAhead(cdataString); + SegmentedString::LookAheadResult result = source.lookAhead(HTMLTokenizerNames::cdata); if (result == SegmentedString::DidMatch) { advanceStringAndASSERT(source, "[CDATA["); HTML_SWITCH_TO(CDATASectionState); @@ -1274,17 +1275,15 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token) m_token->setForceQuirks(); return emitAndReconsumeIn(source, HTMLTokenizer::DataState); } else { - DEFINE_STATIC_LOCAL(String, publicString, ("public")); - DEFINE_STATIC_LOCAL(String, systemString, ("system")); if (cc == 'P' || cc == 'p') { - SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(publicString); + SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(HTMLTokenizerNames::publicString); if (result == SegmentedString::DidMatch) { advanceStringAndASSERTIgnoringCase(source, "public"); HTML_SWITCH_TO(AfterDOCTYPEPublicKeywordState); } else if (result == SegmentedString::NotEnoughCharacters) return haveBufferedCharacterToken(); } else if (cc == 'S' || cc == 's') { - SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(systemString); + SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(HTMLTokenizerNames::system); if (result == SegmentedString::DidMatch) { advanceStringAndASSERTIgnoringCase(source, "system"); HTML_SWITCH_TO(AfterDOCTYPESystemKeywordState); @@ -1596,20 +1595,20 @@ String HTMLTokenizer::bufferedCharacters() const return characters.toString(); } -void HTMLTokenizer::updateStateFor(const AtomicString& tagName) +void HTMLTokenizer::updateStateFor(const String& tagName) { - if (tagName == textareaTag || tagName == titleTag) + if (threadSafeMatch(tagName, textareaTag) || threadSafeMatch(tagName, titleTag)) setState(HTMLTokenizer::RCDATAState); - else if (tagName == plaintextTag) + else if (threadSafeMatch(tagName, plaintextTag)) setState(HTMLTokenizer::PLAINTEXTState); - else if (tagName == scriptTag) + else if (threadSafeMatch(tagName, scriptTag)) setState(HTMLTokenizer::ScriptDataState); - else if (tagName == styleTag - || tagName == iframeTag - || tagName == xmpTag - || (tagName == noembedTag && m_options.pluginsEnabled) - || tagName == noframesTag - || (tagName == noscriptTag && m_options.scriptEnabled)) + else if (threadSafeMatch(tagName, styleTag) + || threadSafeMatch(tagName, iframeTag) + || threadSafeMatch(tagName, xmpTag) + || (threadSafeMatch(tagName, noembedTag) && m_options.pluginsEnabled) + || threadSafeMatch(tagName, noframesTag) + || (threadSafeMatch(tagName, noscriptTag) && m_options.scriptEnabled)) setState(HTMLTokenizer::RAWTEXTState); } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h index aa7c059bf78..3a4ca7f96a1 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h @@ -126,7 +126,6 @@ public: State state; UChar additionalAllowedCharacter; bool skipNextNewLine; - bool forceNullCharacterReplacement; bool shouldAllowCDATA; Checkpoint() @@ -134,7 +133,6 @@ public: , state() , additionalAllowedCharacter('\0') , skipNextNewLine(false) - , forceNullCharacterReplacement(false) , shouldAllowCDATA(false) { } @@ -176,7 +174,7 @@ public: // * CDATA sections in foreign content will be tokenized as bogus comments // instead of as character tokens. // - void updateStateFor(const AtomicString& tagName); + void updateStateFor(const String& tagName); bool forceNullCharacterReplacement() const { return m_forceNullCharacterReplacement; } void setForceNullCharacterReplacement(bool value) { m_forceNullCharacterReplacement = value; } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizerNames.in b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizerNames.in new file mode 100644 index 00000000000..0eab51f4ea0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTokenizerNames.in @@ -0,0 +1,8 @@ +namespace="HTMLTokenizer" + +-- Symbol=dashDash +doctype +[CDATA[ Symbol=cdata +# The symbol "public" conflicts with the C++ keyword. +public Symbol=publicString +system diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp index 4196cde09f0..092240a2c3b 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp @@ -27,19 +27,17 @@ #include "config.h" #include "core/html/parser/HTMLTreeBuilder.h" -#include "HTMLNames.h" -#include "MathMLNames.h" -#include "SVGNames.h" -#include "XLinkNames.h" -#include "XMLNSNames.h" -#include "XMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" +#include "core/MathMLNames.h" +#include "core/SVGNames.h" +#include "core/XLinkNames.h" +#include "core/XMLNSNames.h" +#include "core/XMLNames.h" #include "core/dom/DocumentFragment.h" +#include "core/dom/ElementTraversal.h" #include "core/html/HTMLDocument.h" #include "core/html/HTMLFormElement.h" -#include "core/html/HTMLHtmlElement.h" -#include "core/html/HTMLOptGroupElement.h" -#include "core/html/HTMLTableElement.h" #include "core/html/parser/AtomicHTMLToken.h" #include "core/html/parser/HTMLDocumentParser.h" #include "core/html/parser/HTMLParserIdioms.h" @@ -136,18 +134,10 @@ static bool isFormattingTag(const AtomicString& tagName) return tagName == aTag || isNonAnchorFormattingTag(tagName); } -static HTMLFormElement* closestFormAncestor(Element* element) +static HTMLFormElement* closestFormAncestor(Element& element) { ASSERT(isMainThread()); - while (element) { - if (element->hasTagName(formTag)) - return toHTMLFormElement(element); - ContainerNode* parent = element->parentNode(); - if (!parent || !parent->isElementNode()) - return 0; - element = toElement(parent); - } - return 0; + return Traversal<HTMLFormElement>::firstAncestorOrSelf(element); } class HTMLTreeBuilder::CharacterTokenBuffer { @@ -305,27 +295,33 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* f , m_options(options) { ASSERT(isMainThread()); - // FIXME: This assertion will become invalid if <http://webkit.org/b/60316> is fixed. ASSERT(contextElement); - if (contextElement) { - // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm: - // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case - // For efficiency, we skip step 4.2 ("Let root be a new html element with no attributes") - // and instead use the DocumentFragment as a root node. - m_tree.openElements()->pushRootNode(HTMLStackItem::create(fragment, HTMLStackItem::ItemForDocumentFragmentNode)); - if (contextElement->hasTagName(templateTag)) - m_templateInsertionModes.append(TemplateContentsMode); + // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm: + // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case + // For efficiency, we skip step 4.2 ("Let root be a new html element with no attributes") + // and instead use the DocumentFragment as a root node. + m_tree.openElements()->pushRootNode(HTMLStackItem::create(fragment, HTMLStackItem::ItemForDocumentFragmentNode)); - resetInsertionModeAppropriately(); - m_tree.setForm(closestFormAncestor(contextElement)); - } + if (isHTMLTemplateElement(*contextElement)) + m_templateInsertionModes.append(TemplateContentsMode); + + resetInsertionModeAppropriately(); + m_tree.setForm(closestFormAncestor(*contextElement)); } HTMLTreeBuilder::~HTMLTreeBuilder() { } +void HTMLTreeBuilder::trace(Visitor* visitor) +{ + visitor->trace(m_fragmentContext); + visitor->trace(m_tree); + visitor->trace(m_parser); + visitor->trace(m_scriptToProcess); +} + void HTMLTreeBuilder::detach() { #ifndef NDEBUG @@ -339,14 +335,14 @@ void HTMLTreeBuilder::detach() } HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext() - : m_fragment(0) + : m_fragment(nullptr) { } HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement) : m_fragment(fragment) { - ASSERT(!fragment->hasChildNodes()); + ASSERT(!fragment->hasChildren()); m_contextElementStackItem = HTMLStackItem::create(contextElement, HTMLStackItem::ItemForContextElement); } @@ -354,7 +350,13 @@ HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext() { } -PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition) +void HTMLTreeBuilder::FragmentParsingContext::trace(Visitor* visitor) +{ + visitor->trace(m_fragment); + visitor->trace(m_contextElementStackItem); +} + +PassRefPtrWillBeRawPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition) { ASSERT(m_scriptToProcess); ASSERT(!m_tree.hasPendingTasks()); @@ -461,13 +463,6 @@ void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName) processFakeEndTag(tagName.localName()); } -void HTMLTreeBuilder::processFakeCharacters(const String& characters) -{ - ASSERT(!characters.isEmpty()); - CharacterTokenBuffer buffer(characters); - processCharacterBuffer(buffer); -} - void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope() { if (!m_tree.openElements()->inButtonScope(pTag.localName())) @@ -476,49 +471,6 @@ void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope() processEndTag(&endP); } -Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken* token) -{ - Vector<Attribute> attributes = token->attributes(); - for (int i = attributes.size() - 1; i >= 0; --i) { - const QualifiedName& name = attributes.at(i).name(); - if (name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr)) - attributes.remove(i); - } - - attributes.append(Attribute(nameAttr, isindexTag.localName())); - return attributes; -} - -void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token) -{ - ASSERT(token->type() == HTMLToken::StartTag); - ASSERT(token->name() == isindexTag); - - if (m_parser->useCounter()) - m_parser->useCounter()->count(UseCounter::IsIndexElement); - - parseError(token); - if (m_tree.form()) - return; - notImplemented(); // Acknowledge self-closing flag - processFakeStartTag(formTag); - Attribute* actionAttribute = token->getAttributeItem(actionAttr); - if (actionAttribute) - m_tree.form()->setAttribute(actionAttr, actionAttribute->value()); - processFakeStartTag(hrTag); - processFakeStartTag(labelTag); - Attribute* promptAttribute = token->getAttributeItem(promptAttr); - if (promptAttribute) - processFakeCharacters(promptAttribute->value()); - else - processFakeCharacters(Locale::defaultLocale().queryString(blink::WebLocalizedString::SearchableIndexIntroduction)); - processFakeStartTag(inputTag, attributesForIsindexInput(token)); - notImplemented(); // This second set of characters may be needed by non-english locales. - processFakeEndTag(labelTag); - processFakeStartTag(hrTag); - processFakeEndTag(formTag); -} - namespace { bool isLi(const HTMLStackItem* item) @@ -540,7 +492,7 @@ void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken* token) m_framesetOk = false; HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord(); while (1) { - RefPtr<HTMLStackItem> item = nodeRecord->stackItem(); + RefPtrWillBeRawPtr<HTMLStackItem> item = nodeRecord->stackItem(); if (shouldClose(item.get())) { ASSERT(item->isElementNode()); processFakeEndTag(item->localName()); @@ -572,8 +524,8 @@ static void adjustSVGTagNameCase(AtomicHTMLToken* token) static PrefixedNameToQualifiedNameMap* caseMap = 0; if (!caseMap) { caseMap = new PrefixedNameToQualifiedNameMap; - const QualifiedName* const* svgTags = SVGNames::getSVGTags(); - mapLoweredLocalNameToName(caseMap, svgTags, SVGNames::SVGTagsCount); + OwnPtr<const QualifiedName*[]> svgTags = SVGNames::getSVGTags(); + mapLoweredLocalNameToName(caseMap, svgTags.get(), SVGNames::SVGTagsCount); } const QualifiedName& casedName = caseMap->get(token->name()); @@ -582,14 +534,14 @@ static void adjustSVGTagNameCase(AtomicHTMLToken* token) token->setName(casedName.localName()); } -template<const QualifiedName* const* getAttrs(), unsigned length> +template<PassOwnPtr<const QualifiedName*[]> getAttrs(), unsigned length> static void adjustAttributes(AtomicHTMLToken* token) { static PrefixedNameToQualifiedNameMap* caseMap = 0; if (!caseMap) { caseMap = new PrefixedNameToQualifiedNameMap; - const QualifiedName* const* attrs = getAttrs(); - mapLoweredLocalNameToName(caseMap, attrs, length); + OwnPtr<const QualifiedName*[]> attrs = getAttrs(); + mapLoweredLocalNameToName(caseMap, attrs.get(), length); } for (unsigned i = 0; i < token->attributes().size(); ++i) { @@ -627,11 +579,11 @@ static void adjustForeignAttributes(AtomicHTMLToken* token) if (!map) { map = new PrefixedNameToQualifiedNameMap; - const QualifiedName* const* attrs = XLinkNames::getXLinkAttrs(); - addNamesWithPrefix(map, xlinkAtom, attrs, XLinkNames::XLinkAttrsCount); + OwnPtr<const QualifiedName*[]> attrs = XLinkNames::getXLinkAttrs(); + addNamesWithPrefix(map, xlinkAtom, attrs.get(), XLinkNames::XLinkAttrsCount); - attrs = XMLNames::getXMLAttrs(); - addNamesWithPrefix(map, xmlAtom, attrs, XMLNames::XMLAttrsCount); + OwnPtr<const QualifiedName*[]> xmlAttrs = XMLNames::getXMLAttrs(); + addNamesWithPrefix(map, xmlAtom, xmlAttrs.get(), XMLNames::XMLAttrsCount); map->add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr); map->add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom, XMLNSNames::xmlnsNamespaceURI)); @@ -859,10 +811,6 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token) m_framesetOk = false; return; } - if (token->name() == isindexTag) { - processIsindexStartTagForInBody(token); - return; - } if (token->name() == textareaTag) { m_tree.insertHTMLElement(token); m_shouldSkipLeadingNewline = true; @@ -969,7 +917,7 @@ bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken* token) { ASSERT(token->name() == templateTag.localName()); if (!m_tree.openElements()->hasTemplateInHTMLScope()) { - ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement()->hasTagName(templateTag))); + ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && isHTMLTemplateElement(m_fragmentContext.contextElement()))); parseError(token); return false; } @@ -995,7 +943,7 @@ bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken* tok bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup() { - if (m_tree.currentIsRootNode() || m_tree.currentNode()->hasTagName(templateTag)) { + if (m_tree.currentIsRootNode() || isHTMLTemplateElement(*m_tree.currentNode())) { ASSERT(isParsingFragmentOrTemplateContents()); // FIXME: parse error return false; @@ -1396,7 +1344,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token) AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName()); processEndTag(&endOption); } - if (isHTMLOptGroupElement(m_tree.currentStackItem()->node())) { + if (m_tree.currentStackItem()->hasTagName(optgroupTag)) { AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName()); processEndTag(&endOptgroup); } @@ -1505,7 +1453,7 @@ void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token) ASSERT(token->type() == HTMLToken::EndTag); HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord(); while (1) { - RefPtr<HTMLStackItem> item = record->stackItem(); + RefPtrWillBeRawPtr<HTMLStackItem> item = record->stackItem(); if (item->matchesHTMLTag(token->name())) { m_tree.generateImpliedEndTagsWithExclusion(token->name()); if (!m_tree.currentStackItem()->matchesHTMLTag(token->name())) @@ -1564,7 +1512,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token) } // 7. ASSERT(furthestBlock->isAbove(formattingElementRecord)); - RefPtr<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem(); + RefPtrWillBeRawPtr<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem(); // 8. HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement); // 9. @@ -1587,7 +1535,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token) if (node == formattingElementRecord) break; // 9.7 - RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(node->stackItem().get()); + RefPtrWillBeRawPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(node->stackItem().get()); HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements()->find(node->element()); nodeEntry->replaceElement(newItem); @@ -1604,7 +1552,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token) // 10. m_tree.insertAlreadyParsedChild(commonAncestor.get(), lastNode); // 11. - RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem().get()); + RefPtrWillBeRawPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem().get()); // 12. m_tree.takeAllChildren(newItem.get(), furthestBlock); // 13. @@ -1623,7 +1571,7 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately() bool last = false; HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord(); while (1) { - RefPtr<HTMLStackItem> item = nodeRecord->stackItem(); + RefPtrWillBeRawPtr<HTMLStackItem> item = nodeRecord->stackItem(); if (item->node() == m_tree.openElements()->rootNode()) { last = true; if (isParsingFragment()) @@ -1636,7 +1584,7 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately() while (item->node() != m_tree.openElements()->rootNode() && !item->hasTagName(templateTag)) { nodeRecord = nodeRecord->next(); item = nodeRecord->stackItem(); - if (isHTMLTableElement(item->node())) + if (item->hasTagName(tableTag)) return setInsertionMode(InSelectInTableMode); } } @@ -1653,7 +1601,7 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately() if (item->hasTagName(colgroupTag)) { return setInsertionMode(InColumnGroupMode); } - if (isHTMLTableElement(item->node())) + if (item->hasTagName(tableTag)) return setInsertionMode(InTableMode); if (item->hasTagName(headTag)) { if (!m_fragmentContext.fragment() || m_fragmentContext.contextElement() != item->node()) @@ -1665,7 +1613,7 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately() if (item->hasTagName(framesetTag)) { return setInsertionMode(InFramesetMode); } - if (isHTMLHtmlElement(item->node())) { + if (item->hasTagName(htmlTag)) { if (m_tree.headStackItem()) return setInsertionMode(AfterHeadMode); @@ -1839,7 +1787,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token) return; } if (token->name() == formTag) { - RefPtr<Element> node = m_tree.takeForm(); + RefPtrWillBeRawPtr<Element> node = m_tree.takeForm(); if (!node || !m_tree.openElements()->inScope(node.get())) { parseError(token); return; @@ -2212,9 +2160,9 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token) case InSelectMode: ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode); if (token->name() == optgroupTag) { - if (m_tree.currentStackItem()->hasTagName(optionTag) && m_tree.oneBelowTop() && isHTMLOptGroupElement(m_tree.oneBelowTop()->node())) + if (m_tree.currentStackItem()->hasTagName(optionTag) && m_tree.oneBelowTop() && m_tree.oneBelowTop()->hasTagName(optgroupTag)) processFakeEndTag(optionTag); - if (isHTMLOptGroupElement(m_tree.currentStackItem()->node())) { + if (m_tree.currentStackItem()->hasTagName(optgroupTag)) { m_tree.openElements()->pop(); return; } @@ -2366,11 +2314,11 @@ ReprocessBuffer: ASSERT(insertionMode() == InTableMode || insertionMode() == InTableBodyMode || insertionMode() == InRowMode); ASSERT(m_pendingTableCharacters.isEmpty()); if (m_tree.currentStackItem()->isElementNode() - && (isHTMLTableElement(m_tree.currentStackItem()->node()) - || m_tree.currentStackItem()->hasTagName(HTMLNames::tbodyTag) - || m_tree.currentStackItem()->hasTagName(HTMLNames::tfootTag) - || m_tree.currentStackItem()->hasTagName(HTMLNames::theadTag) - || m_tree.currentStackItem()->hasTagName(HTMLNames::trTag))) { + && (m_tree.currentStackItem()->hasTagName(tableTag) + || m_tree.currentStackItem()->hasTagName(tbodyTag) + || m_tree.currentStackItem()->hasTagName(tfootTag) + || m_tree.currentStackItem()->hasTagName(theadTag) + || m_tree.currentStackItem()->hasTagName(trTag))) { m_originalInsertionMode = m_insertionMode; setInsertionMode(InTableTextMode); // Note that we fall through to the InTableTextMode case below. @@ -2407,7 +2355,6 @@ ReprocessBuffer: // FIXME: parse error setInsertionMode(InBodyMode); goto ReprocessBuffer; - break; } case TextMode: { ASSERT(insertionMode() == TextMode); @@ -2423,7 +2370,6 @@ ReprocessBuffer: return; defaultForInHeadNoscript(); goto ReprocessBuffer; - break; } case InFramesetMode: case AfterFramesetMode: { @@ -2514,7 +2460,7 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token) ASSERT(isParsingFragment()); return; // FIXME: Should we break here instead of returning? } - ASSERT(m_tree.currentNode()->hasTagName(colgroupTag) || m_tree.currentNode()->hasTagName(templateTag)); + ASSERT(m_tree.currentNode()->hasTagName(colgroupTag) || isHTMLTemplateElement(m_tree.currentNode())); processColgroupEndTagForInColumnGroup(); // Fall through case InFramesetMode: diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.h index 60ead95f286..9c9dcdfae8d 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.h @@ -30,6 +30,7 @@ #include "core/html/parser/HTMLConstructionSite.h" #include "core/html/parser/HTMLElementStack.h" #include "core/html/parser/HTMLParserOptions.h" +#include "platform/heap/Handle.h" #include "wtf/Noncopyable.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" @@ -44,24 +45,25 @@ class AtomicHTMLToken; class Document; class DocumentFragment; class Element; -class Frame; +class LocalFrame; class HTMLToken; class HTMLDocument; class Node; class HTMLDocumentParser; -class HTMLTreeBuilder { - WTF_MAKE_NONCOPYABLE(HTMLTreeBuilder); WTF_MAKE_FAST_ALLOCATED; +class HTMLTreeBuilder FINAL : public NoBaseWillBeGarbageCollectedFinalized<HTMLTreeBuilder> { + WTF_MAKE_NONCOPYABLE(HTMLTreeBuilder); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, HTMLDocument* document, ParserContentPolicy parserContentPolicy, bool reportErrors, const HTMLParserOptions& options) + static PassOwnPtrWillBeRawPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, HTMLDocument* document, ParserContentPolicy parserContentPolicy, bool reportErrors, const HTMLParserOptions& options) { - return adoptPtr(new HTMLTreeBuilder(parser, document, parserContentPolicy, reportErrors, options)); + return adoptPtrWillBeNoop(new HTMLTreeBuilder(parser, document, parserContentPolicy, reportErrors, options)); } - static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options) + static PassOwnPtrWillBeRawPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options) { - return adoptPtr(new HTMLTreeBuilder(parser, fragment, contextElement, parserContentPolicy, options)); + return adoptPtrWillBeNoop(new HTMLTreeBuilder(parser, fragment, contextElement, parserContentPolicy, options)); } ~HTMLTreeBuilder(); + void trace(Visitor*); const HTMLElementStack* openElements() const { return m_tree.openElements(); } @@ -75,7 +77,7 @@ public: bool hasParserBlockingScript() const { return !!m_scriptToProcess; } // Must be called to take the parser-blocking script before calling the parser again. - PassRefPtr<Element> takeScriptToProcess(TextPosition& scriptStartPosition); + PassRefPtrWillBeRawPtr<Element> takeScriptToProcess(TextPosition& scriptStartPosition); // Done, close any open tags, etc. void finished(); @@ -153,7 +155,6 @@ private: void processFakeStartTag(const QualifiedName&, const Vector<Attribute>& attributes = Vector<Attribute>()); void processFakeEndTag(const QualifiedName&); void processFakeEndTag(const AtomicString&); - void processFakeCharacters(const String&); void processFakePEndTagIfPInButtonScope(); void processGenericRCDATAStartTag(AtomicHTMLToken*); @@ -195,6 +196,7 @@ private: class FragmentParsingContext { WTF_MAKE_NONCOPYABLE(FragmentParsingContext); + DISALLOW_ALLOCATION(); public: FragmentParsingContext(); FragmentParsingContext(DocumentFragment*, Element* contextElement); @@ -204,9 +206,11 @@ private: Element* contextElement() const { ASSERT(m_fragment); return m_contextElementStackItem->element(); } HTMLStackItem* contextElementStackItem() const { ASSERT(m_fragment); return m_contextElementStackItem.get(); } + void trace(Visitor*); + private: - DocumentFragment* m_fragment; - RefPtr<HTMLStackItem> m_contextElementStackItem; + RawPtrWillBeMember<DocumentFragment> m_fragment; + RefPtrWillBeMember<HTMLStackItem> m_contextElementStackItem; }; bool m_framesetOk; @@ -231,9 +235,9 @@ private: // We access parser because HTML5 spec requires that we be able to change the state of the tokenizer // from within parser actions. We also need it to track the current position. - HTMLDocumentParser* m_parser; + RawPtrWillBeMember<HTMLDocumentParser> m_parser; - RefPtr<Element> m_scriptToProcess; // <script> tag which needs processing before resuming the parser. + RefPtrWillBeMember<Element> m_scriptToProcess; // <script> tag which needs processing before resuming the parser. TextPosition m_scriptToProcessStartPosition; // Starting line number of the script tag needing processing. HTMLParserOptions m_options; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp index 37273cbaea0..2f369953c05 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp @@ -26,9 +26,9 @@ #include "config.h" #include "core/html/parser/HTMLTreeBuilderSimulator.h" -#include "HTMLNames.h" -#include "MathMLNames.h" -#include "SVGNames.h" +#include "core/HTMLNames.h" +#include "core/MathMLNames.h" +#include "core/SVGNames.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/parser/HTMLTokenizer.h" #include "core/html/parser/HTMLTreeBuilder.h" diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp index b46ff5ad2e9..d504a4c5703 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp @@ -27,14 +27,16 @@ #include "core/html/parser/HTMLViewSourceParser.h" #include "core/dom/DOMImplementation.h" +#include "core/html/parser/HTMLParserIdioms.h" #include "core/html/parser/HTMLParserOptions.h" #include "core/html/parser/HTMLToken.h" +#include "core/html/parser/XSSAuditorDelegate.h" namespace WebCore { -HTMLViewSourceParser::HTMLViewSourceParser(HTMLViewSourceDocument* document, const String& mimeType) +HTMLViewSourceParser::HTMLViewSourceParser(HTMLViewSourceDocument& document, const String& mimeType) : DecodedDataDocumentParser(document) - , m_tokenizer(HTMLTokenizer::create(HTMLParserOptions(document))) + , m_tokenizer(HTMLTokenizer::create(HTMLParserOptions(&document))) { if (mimeType != "text/html" && !DOMImplementation::isXMLMIMEType(mimeType)) m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); @@ -42,17 +44,21 @@ HTMLViewSourceParser::HTMLViewSourceParser(HTMLViewSourceDocument* document, con void HTMLViewSourceParser::pumpTokenizer() { + m_xssAuditor.init(document(), 0); + while (true) { m_sourceTracker.start(m_input.current(), m_tokenizer.get(), m_token); if (!m_tokenizer->nextToken(m_input.current(), m_token)) return; m_sourceTracker.end(m_input.current(), m_tokenizer.get(), m_token); - document()->addSource(m_sourceTracker.sourceForToken(m_token), m_token); + OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRequest(m_token, m_sourceTracker, m_tokenizer->shouldAllowCDATA())); + HTMLViewSourceDocument::SourceAnnotation annotation = xssInfo ? HTMLViewSourceDocument::AnnotateSourceAsXSS : HTMLViewSourceDocument::AnnotateSourceAsSafe; + document()->addSource(m_sourceTracker.sourceForToken(m_token), m_token, annotation); // FIXME: The tokenizer should do this work for us. if (m_token.type() == HTMLToken::StartTag) - m_tokenizer->updateStateFor(AtomicString(m_token.name())); + m_tokenizer->updateStateFor(attemptStaticStringCreation(m_token.name(), Likely8Bit)); m_token.clear(); } } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.h b/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.h index d1f0bec23c8..853387be4ab 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.h @@ -31,19 +31,20 @@ #include "core/html/parser/HTMLInputStream.h" #include "core/html/parser/HTMLSourceTracker.h" #include "core/html/parser/HTMLTokenizer.h" +#include "core/html/parser/XSSAuditor.h" namespace WebCore { class HTMLViewSourceParser FINAL : public DecodedDataDocumentParser { public: - static PassRefPtr<HTMLViewSourceParser> create(HTMLViewSourceDocument* document, const String& mimeType) + static PassRefPtrWillBeRawPtr<HTMLViewSourceParser> create(HTMLViewSourceDocument& document, const String& mimeType) { - return adoptRef(new HTMLViewSourceParser(document, mimeType)); + return adoptRefWillBeNoop(new HTMLViewSourceParser(document, mimeType)); } virtual ~HTMLViewSourceParser() { } private: - HTMLViewSourceParser(HTMLViewSourceDocument*, const String& mimeType); + HTMLViewSourceParser(HTMLViewSourceDocument&, const String& mimeType); // DocumentParser virtual void insert(const SegmentedString&) OVERRIDE { ASSERT_NOT_REACHED(); } @@ -59,6 +60,7 @@ private: HTMLToken m_token; HTMLSourceTracker m_sourceTracker; OwnPtr<HTMLTokenizer> m_tokenizer; + XSSAuditor m_xssAuditor; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/parser/NestingLevelIncrementer.h b/chromium/third_party/WebKit/Source/core/html/parser/NestingLevelIncrementer.h index fa1d110bdf3..478210e394e 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/NestingLevelIncrementer.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/NestingLevelIncrementer.h @@ -26,11 +26,13 @@ #ifndef NestingLevelIncrementer_h #define NestingLevelIncrementer_h +#include "platform/heap/Handle.h" #include "wtf/Noncopyable.h" namespace WebCore { class NestingLevelIncrementer { + STACK_ALLOCATED(); WTF_MAKE_NONCOPYABLE(NestingLevelIncrementer); public: explicit NestingLevelIncrementer(unsigned& nestingLevel) diff --git a/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.cpp b/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.cpp index 38175a0f6bf..b7fc5151e67 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.cpp @@ -25,14 +25,14 @@ #include "config.h" #include "core/html/parser/TextDocumentParser.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/parser/HTMLTreeBuilder.h" namespace WebCore { using namespace HTMLNames; -TextDocumentParser::TextDocumentParser(HTMLDocument* document) +TextDocumentParser::TextDocumentParser(HTMLDocument& document) : HTMLDocumentParser(document, false) , m_haveInsertedFakePreElement(false) { @@ -42,11 +42,11 @@ TextDocumentParser::~TextDocumentParser() { } -void TextDocumentParser::append(PassRefPtr<StringImpl> text) +void TextDocumentParser::appendBytes(const char* data, size_t length) { if (!m_haveInsertedFakePreElement) insertFakePreElement(); - HTMLDocumentParser::append(text); + HTMLDocumentParser::appendBytes(data, length); } void TextDocumentParser::insertFakePreElement() diff --git a/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.h b/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.h index 6b5bb9e6a4c..d1de29543dc 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/TextDocumentParser.h @@ -30,18 +30,18 @@ namespace WebCore { -class TextDocumentParser : public HTMLDocumentParser { +class TextDocumentParser FINAL : public HTMLDocumentParser { public: - static PassRefPtr<TextDocumentParser> create(HTMLDocument* document) + static PassRefPtrWillBeRawPtr<TextDocumentParser> create(HTMLDocument& document) { - return adoptRef(new TextDocumentParser(document)); + return adoptRefWillBeNoop(new TextDocumentParser(document)); } virtual ~TextDocumentParser(); private: - explicit TextDocumentParser(HTMLDocument*); + explicit TextDocumentParser(HTMLDocument&); - virtual void append(PassRefPtr<StringImpl>); + virtual void appendBytes(const char*, size_t) OVERRIDE; void insertFakePreElement(); bool m_haveInsertedFakePreElement; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp b/chromium/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp new file mode 100644 index 00000000000..1f21e244f2a --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp @@ -0,0 +1,439 @@ +/* + Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. + Copyright (C) 2005, 2006, 2007 Alexey Proskuryakov (ap@nypop.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 "core/html/parser/TextResourceDecoder.h" + +#include "core/HTMLNames.h" +#include "core/dom/DOMImplementation.h" +#include "core/html/parser/HTMLMetaCharsetParser.h" +#include "platform/text/TextEncodingDetector.h" +#include "wtf/StringExtras.h" +#include "wtf/text/TextCodec.h" +#include "wtf/text/TextEncodingRegistry.h" + +using namespace WTF; + +namespace WebCore { + +using namespace HTMLNames; + +static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4) +{ + return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4; +} + +static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4, char b5) +{ + return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4 && p[5] == b5; +} + +static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7) +{ + return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4 && p[5] == b5 && p[6] == b6 && p[7] == b7; +} + +static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9) +{ + return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4 && p[5] == b5 && p[6] == b6 && p[7] == b7 && p[8] == b8 && p[9] == b9; +} + +// You might think we should put these find functions elsewhere, perhaps with the +// similar functions that operate on UChar, but arguably only the decoder has +// a reason to process strings of char rather than UChar. + +static int find(const char* subject, size_t subjectLength, const char* target) +{ + size_t targetLength = strlen(target); + if (targetLength > subjectLength) + return -1; + for (size_t i = 0; i <= subjectLength - targetLength; ++i) { + bool match = true; + for (size_t j = 0; j < targetLength; ++j) { + if (subject[i + j] != target[j]) { + match = false; + break; + } + } + if (match) + return i; + } + return -1; +} + +static WTF::TextEncoding findTextEncoding(const char* encodingName, int length) +{ + Vector<char, 64> buffer(length + 1); + memcpy(buffer.data(), encodingName, length); + buffer[length] = '\0'; + return buffer.data(); +} + +TextResourceDecoder::ContentType TextResourceDecoder::determineContentType(const String& mimeType) +{ + if (equalIgnoringCase(mimeType, "text/css")) + return CSSContent; + if (equalIgnoringCase(mimeType, "text/html")) + return HTMLContent; + if (DOMImplementation::isXMLMIMEType(mimeType)) + return XMLContent; + return PlainTextContent; +} + +const WTF::TextEncoding& TextResourceDecoder::defaultEncoding(ContentType contentType, const WTF::TextEncoding& specifiedDefaultEncoding) +{ + // Despite 8.5 "Text/xml with Omitted Charset" of RFC 3023, we assume UTF-8 instead of US-ASCII + // for text/xml. This matches Firefox. + if (contentType == XMLContent) + return UTF8Encoding(); + if (!specifiedDefaultEncoding.isValid()) + return Latin1Encoding(); + return specifiedDefaultEncoding; +} + +TextResourceDecoder::TextResourceDecoder(const String& mimeType, const WTF::TextEncoding& specifiedDefaultEncoding, bool usesEncodingDetector) + : m_contentType(determineContentType(mimeType)) + , m_encoding(defaultEncoding(m_contentType, specifiedDefaultEncoding)) + , m_source(DefaultEncoding) + , m_hintEncoding(0) + , m_checkedForBOM(false) + , m_checkedForCSSCharset(false) + , m_checkedForXMLCharset(false) + , m_checkedForMetaCharset(false) + , m_useLenientXMLDecoding(false) + , m_sawError(false) + , m_usesEncodingDetector(usesEncodingDetector) +{ +} + +TextResourceDecoder::~TextResourceDecoder() +{ +} + +void TextResourceDecoder::setEncoding(const WTF::TextEncoding& encoding, EncodingSource source) +{ + // In case the encoding didn't exist, we keep the old one (helps some sites specifying invalid encodings). + if (!encoding.isValid()) + return; + + // When encoding comes from meta tag (i.e. it cannot be XML files sent via XHR), + // treat x-user-defined as windows-1252 (bug 18270) + if (source == EncodingFromMetaTag && !strcasecmp(encoding.name(), "x-user-defined")) + m_encoding = "windows-1252"; + else if (source == EncodingFromMetaTag || source == EncodingFromXMLHeader || source == EncodingFromCSSCharset) + m_encoding = encoding.closestByteBasedEquivalent(); + else + m_encoding = encoding; + + m_codec.clear(); + m_source = source; +} + +// Returns the position of the encoding string. +static int findXMLEncoding(const char* str, int len, int& encodingLength) +{ + int pos = find(str, len, "encoding"); + if (pos == -1) + return -1; + pos += 8; + + // Skip spaces and stray control characters. + while (pos < len && str[pos] <= ' ') + ++pos; + + // Skip equals sign. + if (pos >= len || str[pos] != '=') + return -1; + ++pos; + + // Skip spaces and stray control characters. + while (pos < len && str[pos] <= ' ') + ++pos; + + // Skip quotation mark. + if (pos >= len) + return - 1; + char quoteMark = str[pos]; + if (quoteMark != '"' && quoteMark != '\'') + return -1; + ++pos; + + // Find the trailing quotation mark. + int end = pos; + while (end < len && str[end] != quoteMark) + ++end; + if (end >= len) + return -1; + + encodingLength = end - pos; + return pos; +} + +size_t TextResourceDecoder::checkForBOM(const char* data, size_t len) +{ + // Check for UTF-16/32 or UTF-8 BOM mark at the beginning, which is a sure sign of a Unicode encoding. + // We let it override even a user-chosen encoding. + ASSERT(!m_checkedForBOM); + + size_t lengthOfBOM = 0; + + size_t bufferLength = m_buffer.size(); + + size_t buf1Len = bufferLength; + size_t buf2Len = len; + const unsigned char* buf1 = reinterpret_cast<const unsigned char*>(m_buffer.data()); + const unsigned char* buf2 = reinterpret_cast<const unsigned char*>(data); + unsigned char c1 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0; + unsigned char c2 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0; + unsigned char c3 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0; + unsigned char c4 = buf2Len ? (--buf2Len, *buf2++) : 0; + + // Check for the BOM. + if (c1 == 0xFF && c2 == 0xFE) { + if (c3 || c4) { + setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding); + lengthOfBOM = 2; + } else { + setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding); + lengthOfBOM = 4; + } + } else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) { + setEncoding(UTF8Encoding(), AutoDetectedEncoding); + lengthOfBOM = 3; + } else if (c1 == 0xFE && c2 == 0xFF) { + setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding); + lengthOfBOM = 2; + } else if (!c1 && !c2 && c3 == 0xFE && c4 == 0xFF) { + setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding); + lengthOfBOM = 4; + } + + if (lengthOfBOM || bufferLength + len >= 4) + m_checkedForBOM = true; + + return lengthOfBOM; +} + +bool TextResourceDecoder::checkForCSSCharset(const char* data, size_t len, bool& movedDataToBuffer) +{ + if (m_source != DefaultEncoding && m_source != EncodingFromParentFrame) { + m_checkedForCSSCharset = true; + return true; + } + + size_t oldSize = m_buffer.size(); + m_buffer.grow(oldSize + len); + memcpy(m_buffer.data() + oldSize, data, len); + + movedDataToBuffer = true; + + if (m_buffer.size() <= 13) // strlen('@charset "x";') == 13 + return false; + + const char* dataStart = m_buffer.data(); + const char* dataEnd = dataStart + m_buffer.size(); + + if (bytesEqual(dataStart, '@', 'c', 'h', 'a', 'r', 's', 'e', 't', ' ', '"')) { + dataStart += 10; + const char* pos = dataStart; + + while (pos < dataEnd && *pos != '"') + ++pos; + if (pos == dataEnd) + return false; + + int encodingNameLength = pos - dataStart; + + ++pos; + if (pos == dataEnd) + return false; + + if (*pos == ';') + setEncoding(findTextEncoding(dataStart, encodingNameLength), EncodingFromCSSCharset); + } + + m_checkedForCSSCharset = true; + return true; +} + +bool TextResourceDecoder::checkForXMLCharset(const char* data, size_t len, bool& movedDataToBuffer) +{ + if (m_source != DefaultEncoding && m_source != EncodingFromParentFrame) { + m_checkedForXMLCharset = true; + return true; + } + + // This is not completely efficient, since the function might go + // through the HTML head several times. + + size_t oldSize = m_buffer.size(); + m_buffer.grow(oldSize + len); + memcpy(m_buffer.data() + oldSize, data, len); + + movedDataToBuffer = true; + + const char* ptr = m_buffer.data(); + const char* pEnd = ptr + m_buffer.size(); + + // Is there enough data available to check for XML declaration? + if (m_buffer.size() < 8) + return false; + + // Handle XML declaration, which can have encoding in it. This encoding is honored even for HTML documents. + // It is an error for an XML declaration not to be at the start of an XML document, and it is ignored in HTML documents in such case. + if (bytesEqual(ptr, '<', '?', 'x', 'm', 'l')) { + const char* xmlDeclarationEnd = ptr; + while (xmlDeclarationEnd != pEnd && *xmlDeclarationEnd != '>') + ++xmlDeclarationEnd; + if (xmlDeclarationEnd == pEnd) + return false; + // No need for +1, because we have an extra "?" to lose at the end of XML declaration. + int len = 0; + int pos = findXMLEncoding(ptr, xmlDeclarationEnd - ptr, len); + if (pos != -1) + setEncoding(findTextEncoding(ptr + pos, len), EncodingFromXMLHeader); + // continue looking for a charset - it may be specified in an HTTP-Equiv meta + } else if (bytesEqual(ptr, '<', 0, '?', 0, 'x', 0)) { + setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding); + } else if (bytesEqual(ptr, 0, '<', 0, '?', 0, 'x')) { + setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding); + } else if (bytesEqual(ptr, '<', 0, 0, 0, '?', 0, 0, 0)) { + setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding); + } else if (bytesEqual(ptr, 0, 0, 0, '<', 0, 0, 0, '?')) { + setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding); + } + + m_checkedForXMLCharset = true; + return true; +} + +void TextResourceDecoder::checkForMetaCharset(const char* data, size_t length) +{ + if (m_source == UserChosenEncoding || m_source == EncodingFromHTTPHeader || m_source == AutoDetectedEncoding) { + m_checkedForMetaCharset = true; + return; + } + + if (!m_charsetParser) + m_charsetParser = HTMLMetaCharsetParser::create(); + + if (!m_charsetParser->checkForMetaCharset(data, length)) + return; + + setEncoding(m_charsetParser->encoding(), EncodingFromMetaTag); + m_charsetParser.clear(); + m_checkedForMetaCharset = true; + return; +} + +// We use the encoding detector in two cases: +// 1. Encoding detector is turned ON and no other encoding source is +// available (that is, it's DefaultEncoding). +// 2. Encoding detector is turned ON and the encoding is set to +// the encoding of the parent frame, which is also auto-detected. +// Note that condition #2 is NOT satisfied unless parent-child frame +// relationship is compliant to the same-origin policy. If they're from +// different domains, |m_source| would not be set to EncodingFromParentFrame +// in the first place. +bool TextResourceDecoder::shouldAutoDetect() const +{ + // Just checking m_hintEncoding suffices here because it's only set + // in setHintEncoding when the source is AutoDetectedEncoding. + return m_usesEncodingDetector + && (m_source == DefaultEncoding || (m_source == EncodingFromParentFrame && m_hintEncoding)); +} + +String TextResourceDecoder::decode(const char* data, size_t len) +{ + size_t lengthOfBOM = 0; + if (!m_checkedForBOM) + lengthOfBOM = checkForBOM(data, len); + + bool movedDataToBuffer = false; + + if (m_contentType == CSSContent && !m_checkedForCSSCharset) { + if (!checkForCSSCharset(data, len, movedDataToBuffer)) + return emptyString(); + } + + if ((m_contentType == HTMLContent || m_contentType == XMLContent) && !m_checkedForXMLCharset) { + if (!checkForXMLCharset(data, len, movedDataToBuffer)) + return emptyString(); + } + + const char* dataForDecode = data + lengthOfBOM; + size_t lengthForDecode = len - lengthOfBOM; + + if (!m_buffer.isEmpty()) { + if (!movedDataToBuffer) { + size_t oldSize = m_buffer.size(); + m_buffer.grow(oldSize + len); + memcpy(m_buffer.data() + oldSize, data, len); + } + + dataForDecode = m_buffer.data() + lengthOfBOM; + lengthForDecode = m_buffer.size() - lengthOfBOM; + } + + if (m_contentType == HTMLContent && !m_checkedForMetaCharset) + checkForMetaCharset(dataForDecode, lengthForDecode); + + if (shouldAutoDetect()) { + WTF::TextEncoding detectedEncoding; + if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding)) + setEncoding(detectedEncoding, EncodingFromContentSniffing); + } + + ASSERT(m_encoding.isValid()); + + if (!m_codec) + m_codec = newTextCodec(m_encoding); + + String result = m_codec->decode(dataForDecode, lengthForDecode, DoNotFlush, m_contentType == XMLContent && !m_useLenientXMLDecoding, m_sawError); + + m_buffer.clear(); + return result; +} + +String TextResourceDecoder::flush() +{ + // If we can not identify the encoding even after a document is completely + // loaded, we need to detect the encoding if other conditions for + // autodetection is satisfied. + if (m_buffer.size() && shouldAutoDetect() + && ((!m_checkedForXMLCharset && (m_contentType == HTMLContent || m_contentType == XMLContent)) || (!m_checkedForCSSCharset && (m_contentType == CSSContent)))) { + WTF::TextEncoding detectedEncoding; + if (detectTextEncoding(m_buffer.data(), m_buffer.size(), m_hintEncoding, &detectedEncoding)) + setEncoding(detectedEncoding, EncodingFromContentSniffing); + } + + if (!m_codec) + m_codec = newTextCodec(m_encoding); + + String result = m_codec->decode(m_buffer.data(), m_buffer.size(), FetchEOF, m_contentType == XMLContent && !m_useLenientXMLDecoding, m_sawError); + m_buffer.clear(); + m_codec.clear(); + m_checkedForBOM = false; // Skip BOM again when re-decoding. + return result; +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h b/chromium/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h new file mode 100644 index 00000000000..5ad2ad561f8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h @@ -0,0 +1,106 @@ +/* + Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) + Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + 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 TextResourceDecoder_h +#define TextResourceDecoder_h + +#include "wtf/RefCounted.h" +#include "wtf/text/TextEncoding.h" + +namespace WebCore { + +class DocumentEncodingData; +class HTMLMetaCharsetParser; + +class TextResourceDecoder { +public: + enum EncodingSource { + DefaultEncoding, + AutoDetectedEncoding, + EncodingFromContentSniffing, + EncodingFromXMLHeader, + EncodingFromMetaTag, + EncodingFromCSSCharset, + EncodingFromHTTPHeader, + UserChosenEncoding, + EncodingFromParentFrame + }; + + static PassOwnPtr<TextResourceDecoder> create(const String& mimeType, const WTF::TextEncoding& defaultEncoding = WTF::TextEncoding(), bool usesEncodingDetector = false) + { + return adoptPtr(new TextResourceDecoder(mimeType, defaultEncoding, usesEncodingDetector)); + } + ~TextResourceDecoder(); + + void setEncoding(const WTF::TextEncoding&, EncodingSource); + const WTF::TextEncoding& encoding() const { return m_encoding; } + bool encodingWasDetectedHeuristically() const + { + return m_source == AutoDetectedEncoding + || m_source == EncodingFromContentSniffing; + } + + String decode(const char* data, size_t length); + String flush(); + + void setHintEncoding(const WTF::TextEncoding& encoding) + { + m_hintEncoding = encoding.name(); + } + + void useLenientXMLDecoding() { m_useLenientXMLDecoding = true; } + bool sawError() const { return m_sawError; } + +private: + TextResourceDecoder(const String& mimeType, const WTF::TextEncoding& defaultEncoding, bool usesEncodingDetector); + + enum ContentType { PlainTextContent, HTMLContent, XMLContent, CSSContent }; // PlainText only checks for BOM. + static ContentType determineContentType(const String& mimeType); + static const WTF::TextEncoding& defaultEncoding(ContentType, const WTF::TextEncoding& defaultEncoding); + + size_t checkForBOM(const char*, size_t); + bool checkForCSSCharset(const char*, size_t, bool& movedDataToBuffer); + bool checkForXMLCharset(const char*, size_t, bool& movedDataToBuffer); + void checkForMetaCharset(const char*, size_t); + void detectJapaneseEncoding(const char*, size_t); + bool shouldAutoDetect() const; + + ContentType m_contentType; + WTF::TextEncoding m_encoding; + OwnPtr<TextCodec> m_codec; + EncodingSource m_source; + const char* m_hintEncoding; + Vector<char> m_buffer; + bool m_checkedForBOM; + bool m_checkedForCSSCharset; + bool m_checkedForXMLCharset; + bool m_checkedForMetaCharset; + bool m_useLenientXMLDecoding; // Don't stop on XML decoding errors. + bool m_sawError; + bool m_usesEncodingDetector; + + OwnPtr<HTMLMetaCharsetParser> m_charsetParser; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp b/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp index a43fca982b5..5189447af88 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp @@ -27,22 +27,23 @@ #include "config.h" #include "core/html/parser/XSSAuditor.h" -#include "HTMLNames.h" -#include "SVGNames.h" -#include "XLinkNames.h" +#include "core/HTMLNames.h" +#include "core/SVGNames.h" +#include "core/XLinkNames.h" #include "core/dom/Document.h" -#include "core/fetch/TextResourceDecoder.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLParamElement.h" #include "core/html/parser/HTMLDocumentParser.h" #include "core/html/parser/HTMLParserIdioms.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/html/parser/XSSAuditorDelegate.h" #include "core/loader/DocumentLoader.h" #include "core/frame/Settings.h" #include "platform/JSONValues.h" #include "platform/network/FormData.h" #include "platform/text/DecodeEscapeSequences.h" +#include "wtf/ASCIICType.h" #include "wtf/MainThread.h" namespace { @@ -63,14 +64,11 @@ static bool isNonCanonicalCharacter(UChar c) // Note, we don't remove backslashes like PHP stripslashes(), which among other things converts "\\0" to the \0 character. // Instead, we remove backslashes and zeros (since the string "\\0" =(remove backslashes)=> "0"). However, this has the // adverse effect that we remove any legitimate zeros from a string. + // We also remove forward-slash, because it is common for some servers to collapse successive path components, eg, + // a//b becomes a/b. // - // For instance: new String("http://localhost:8000") => new String("http://localhost:8"). - return (c == '\\' || c == '0' || c == '\0' || c >= 127); -} - -static String canonicalize(const String& string) -{ - return string.removeCharacters(&isNonCanonicalCharacter); + // For instance: new String("http://localhost:8000") => new String("http:localhost:8"). + return (c == '\\' || c == '0' || c == '\0' || c == '/' || c >= 127); } static bool isRequiredForInjection(UChar c) @@ -96,17 +94,28 @@ static bool isJSNewline(UChar c) static bool startsHTMLCommentAt(const String& string, size_t start) { - return (start + 3 < string.length() && string[start] == '<' && string[start+1] == '!' && string[start+2] == '-' && string[start+3] == '-'); + return (start + 3 < string.length() && string[start] == '<' && string[start + 1] == '!' && string[start + 2] == '-' && string[start + 3] == '-'); } static bool startsSingleLineCommentAt(const String& string, size_t start) { - return (start + 1 < string.length() && string[start] == '/' && string[start+1] == '/'); + return (start + 1 < string.length() && string[start] == '/' && string[start + 1] == '/'); } static bool startsMultiLineCommentAt(const String& string, size_t start) { - return (start + 1 < string.length() && string[start] == '/' && string[start+1] == '*'); + return (start + 1 < string.length() && string[start] == '/' && string[start + 1] == '*'); +} + +static bool startsOpeningScriptTagAt(const String& string, size_t start) +{ + return start + 6 < string.length() && string[start] == '<' + && WTF::toASCIILowerUnchecked(string[start + 1]) == 's' + && WTF::toASCIILowerUnchecked(string[start + 2]) == 'c' + && WTF::toASCIILowerUnchecked(string[start + 3]) == 'r' + && WTF::toASCIILowerUnchecked(string[start + 4]) == 'i' + && WTF::toASCIILowerUnchecked(string[start + 5]) == 'p' + && WTF::toASCIILowerUnchecked(string[start + 6]) == 't'; } // If other files need this, we should move this to core/html/parser/HTMLParserIdioms.h @@ -171,10 +180,60 @@ static String fullyDecodeString(const String& string, const WTF::TextEncoding& e workingString = decode16BitUnicodeEscapeSequences(decodeStandardURLEscapeSequences(workingString, encoding)); } while (workingString.length() < oldWorkingStringLength); workingString.replace('+', ' '); - workingString = canonicalize(workingString); return workingString; } +static void truncateForSrcLikeAttribute(String& decodedSnippet) +{ + // In HTTP URLs, characters following the first ?, #, or third slash may come from + // the page itself and can be merely ignored by an attacker's server when a remote + // script or script-like resource is requested. In DATA URLS, the payload starts at + // the first comma, and the the first /*, //, or <!-- may introduce a comment. Characters + // following this may come from the page itself and may be ignored when the script is + // executed. For simplicity, we don't differentiate based on URL scheme, and stop at + // the first # or ?, the third slash, or the first slash or < once a comma is seen. + int slashCount = 0; + bool commaSeen = false; + for (size_t currentLength = 0; currentLength < decodedSnippet.length(); ++currentLength) { + UChar currentChar = decodedSnippet[currentLength]; + if (currentChar == '?' + || currentChar == '#' + || ((currentChar == '/' || currentChar == '\\') && (commaSeen || ++slashCount > 2)) + || (currentChar == '<' && commaSeen)) { + decodedSnippet.truncate(currentLength); + return; + } + if (currentChar == ',') + commaSeen = true; + } +} + +static void truncateForScriptLikeAttribute(String& decodedSnippet) +{ + // Beware of trailing characters which came from the page itself, not the + // injected vector. Excluding the terminating character covers common cases + // where the page immediately ends the attribute, but doesn't cover more + // complex cases where there is other page data following the injection. + // Generally, these won't parse as javascript, so the injected vector + // typically excludes them from consideration via a single-line comment or + // by enclosing them in a string literal terminated later by the page's own + // closing punctuation. Since the snippet has not been parsed, the vector + // may also try to introduce these via entities. As a result, we'd like to + // stop before the first "//", the first <!--, the first entity, or the first + // quote not immediately following the first equals sign (taking whitespace + // into consideration). To keep things simpler, we don't try to distinguish + // between entity-introducing amperands vs. other uses, nor do we bother to + // check for a second slash for a comment, nor do we bother to check for + // !-- following a less-than sign. We stop instead on any ampersand + // slash, or less-than sign. + size_t position = 0; + if ((position = decodedSnippet.find("=")) != kNotFound + && (position = decodedSnippet.find(isNotHTMLSpace<UChar>, position + 1)) != kNotFound + && (position = decodedSnippet.find(isTerminatingCharacter, isHTMLQuote(decodedSnippet[position]) ? position + 1 : position)) != kNotFound) { + decodedSnippet.truncate(position); + } +} + static ReflectedXSSDisposition combineXSSProtectionHeaderAndCSP(ReflectedXSSDisposition xssProtection, ReflectedXSSDisposition reflectedXSS) { ReflectedXSSDisposition result = std::max(xssProtection, reflectedXSS); @@ -190,15 +249,16 @@ static bool isSemicolonSeparatedAttribute(const HTMLToken::Attribute& attribute) return threadSafeMatch(attribute.name, SVGNames::valuesAttr); } -static bool semicolonSeparatedValueContainsJavaScriptURL(const String& value) +static String semicolonSeparatedValueContainingJavaScriptURL(const String& value) { Vector<String> valueList; value.split(';', valueList); for (size_t i = 0; i < valueList.size(); ++i) { - if (protocolIsJavaScript(valueList[i])) - return true; + String stripped = stripLeadingAndTrailingHTMLSpaces(valueList[i]); + if (protocolIsJavaScript(stripped)) + return stripped; } - return false; + return emptyString(); } XSSAuditor::XSSAuditor() @@ -227,9 +287,6 @@ void XSSAuditor::initForFragment() void XSSAuditor::init(Document* document, XSSAuditorDelegate* auditorDelegate) { - const size_t miniumLengthForSuffixTree = 512; // FIXME: Tune this parameter. - const int suffixTreeDepth = 5; - ASSERT(isMainThread()); if (m_state != Uninitialized) return; @@ -243,7 +300,7 @@ void XSSAuditor::init(Document* document, XSSAuditorDelegate* auditorDelegate) m_documentURL = document->url().copy(); - // In theory, the Document could have detached from the Frame after the + // In theory, the Document could have detached from the LocalFrame after the // XSSAuditor was constructed. if (!document->frame()) { m_isEnabled = false; @@ -264,11 +321,6 @@ void XSSAuditor::init(Document* document, XSSAuditorDelegate* auditorDelegate) if (document->encoding().isValid()) m_encoding = document->encoding(); - m_decodedURL = fullyDecodeString(m_documentURL.string(), m_encoding); - if (m_decodedURL.find(isRequiredForInjection) == kNotFound) - m_decodedURL = String(); - - String httpBodyAsString; if (DocumentLoader* documentLoader = document->frame()->loader().documentLoader()) { DEFINE_STATIC_LOCAL(const AtomicString, XSSProtectionHeader, ("X-XSS-Protection", AtomicString::ConstructFromLiteral)); const AtomicString& headerValue = documentLoader->response().httpHeaderField(XSSProtectionHeader); @@ -298,23 +350,40 @@ void XSSAuditor::init(Document* document, XSSAuditorDelegate* auditorDelegate) // FIXME: Combine the two report URLs in some reasonable way. if (auditorDelegate) auditorDelegate->setReportURL(xssProtectionReportURL.copy()); + FormData* httpBody = documentLoader->request().httpBody(); - if (httpBody && !httpBody->isEmpty()) { - httpBodyAsString = httpBody->flattenToString(); - if (!httpBodyAsString.isEmpty()) { - m_decodedHTTPBody = fullyDecodeString(httpBodyAsString, m_encoding); - if (m_decodedHTTPBody.find(isRequiredForInjection) == kNotFound) - m_decodedHTTPBody = String(); - if (m_decodedHTTPBody.length() >= miniumLengthForSuffixTree) - m_decodedHTTPBodySuffixTree = adoptPtr(new SuffixTree<ASCIICodebook>(m_decodedHTTPBody, suffixTreeDepth)); - } - } + if (httpBody && !httpBody->isEmpty()) + m_httpBodyAsString = httpBody->flattenToString(); } - if (m_decodedURL.isEmpty() && m_decodedHTTPBody.isEmpty()) { - m_isEnabled = false; + setEncoding(m_encoding); +} + +void XSSAuditor::setEncoding(const WTF::TextEncoding& encoding) +{ + const size_t miniumLengthForSuffixTree = 512; // FIXME: Tune this parameter. + const int suffixTreeDepth = 5; + + if (!encoding.isValid()) return; + + m_encoding = encoding; + + m_decodedURL = canonicalize(m_documentURL.string(), NoTruncation); + if (m_decodedURL.find(isRequiredForInjection) == kNotFound) + m_decodedURL = String(); + + if (!m_httpBodyAsString.isEmpty()) { + m_decodedHTTPBody = canonicalize(m_httpBodyAsString, NoTruncation); + m_httpBodyAsString = String(); + if (m_decodedHTTPBody.find(isRequiredForInjection) == kNotFound) + m_decodedHTTPBody = String(); + if (m_decodedHTTPBody.length() >= miniumLengthForSuffixTree) + m_decodedHTTPBodySuffixTree = adoptPtr(new SuffixTree<ASCIICodebook>(m_decodedHTTPBody, suffixTreeDepth)); } + + if (m_decodedURL.isEmpty() && m_decodedHTTPBody.isEmpty()) + m_isEnabled = false; } PassOwnPtr<XSSInfo> XSSAuditor::filterToken(const FilterTokenRequest& request) @@ -392,7 +461,7 @@ bool XSSAuditor::filterCharacterToken(const FilterTokenRequest& request) return false; if ((m_state == SuppressingAdjacentCharacterTokens) - || (m_scriptTagFoundInRequest && isContainedInRequest(decodedSnippetForJavaScript(request)))) { + || (m_scriptTagFoundInRequest && isContainedInRequest(canonicalizedSnippetForJavaScript(request)))) { request.token.eraseCharacters(); request.token.appendToCharacter(' '); // Technically, character tokens can't be empty. m_state = SuppressingAdjacentCharacterTokens; @@ -409,10 +478,10 @@ bool XSSAuditor::filterScriptToken(const FilterTokenRequest& request) ASSERT(hasName(request.token, scriptTag)); bool didBlockScript = false; - m_scriptTagFoundInRequest = isContainedInRequest(decodedSnippetForName(request)); + m_scriptTagFoundInRequest = isContainedInRequest(canonicalizedSnippetForTagName(request)); if (m_scriptTagFoundInRequest) { - didBlockScript |= eraseAttributeIfInjected(request, srcAttr, blankURL().string(), SrcLikeAttribute); - didBlockScript |= eraseAttributeIfInjected(request, XLinkNames::hrefAttr, blankURL().string(), SrcLikeAttribute); + didBlockScript |= eraseAttributeIfInjected(request, srcAttr, blankURL().string(), SrcLikeAttributeTruncation); + didBlockScript |= eraseAttributeIfInjected(request, XLinkNames::hrefAttr, blankURL().string(), SrcLikeAttributeTruncation); } return didBlockScript; } @@ -423,8 +492,8 @@ bool XSSAuditor::filterObjectToken(const FilterTokenRequest& request) ASSERT(hasName(request.token, objectTag)); bool didBlockScript = false; - if (isContainedInRequest(decodedSnippetForName(request))) { - didBlockScript |= eraseAttributeIfInjected(request, dataAttr, blankURL().string(), SrcLikeAttribute); + if (isContainedInRequest(canonicalizedSnippetForTagName(request))) { + didBlockScript |= eraseAttributeIfInjected(request, dataAttr, blankURL().string(), SrcLikeAttributeTruncation); didBlockScript |= eraseAttributeIfInjected(request, typeAttr); didBlockScript |= eraseAttributeIfInjected(request, classidAttr); } @@ -444,7 +513,7 @@ bool XSSAuditor::filterParamToken(const FilterTokenRequest& request) if (!HTMLParamElement::isURLParameter(String(nameAttribute.value))) return false; - return eraseAttributeIfInjected(request, valueAttr, blankURL().string(), SrcLikeAttribute); + return eraseAttributeIfInjected(request, valueAttr, blankURL().string(), SrcLikeAttributeTruncation); } bool XSSAuditor::filterEmbedToken(const FilterTokenRequest& request) @@ -453,9 +522,9 @@ bool XSSAuditor::filterEmbedToken(const FilterTokenRequest& request) ASSERT(hasName(request.token, embedTag)); bool didBlockScript = false; - if (isContainedInRequest(decodedSnippetForName(request))) { - didBlockScript |= eraseAttributeIfInjected(request, codeAttr, String(), SrcLikeAttribute); - didBlockScript |= eraseAttributeIfInjected(request, srcAttr, blankURL().string(), SrcLikeAttribute); + if (isContainedInRequest(canonicalizedSnippetForTagName(request))) { + didBlockScript |= eraseAttributeIfInjected(request, codeAttr, String(), SrcLikeAttributeTruncation); + didBlockScript |= eraseAttributeIfInjected(request, srcAttr, blankURL().string(), SrcLikeAttributeTruncation); didBlockScript |= eraseAttributeIfInjected(request, typeAttr); } return didBlockScript; @@ -467,8 +536,8 @@ bool XSSAuditor::filterAppletToken(const FilterTokenRequest& request) ASSERT(hasName(request.token, appletTag)); bool didBlockScript = false; - if (isContainedInRequest(decodedSnippetForName(request))) { - didBlockScript |= eraseAttributeIfInjected(request, codeAttr, String(), SrcLikeAttribute); + if (isContainedInRequest(canonicalizedSnippetForTagName(request))) { + didBlockScript |= eraseAttributeIfInjected(request, codeAttr, String(), SrcLikeAttributeTruncation); didBlockScript |= eraseAttributeIfInjected(request, objectAttr); } return didBlockScript; @@ -479,9 +548,9 @@ bool XSSAuditor::filterFrameToken(const FilterTokenRequest& request) ASSERT(request.token.type() == HTMLToken::StartTag); ASSERT(hasName(request.token, iframeTag) || hasName(request.token, frameTag)); - bool didBlockScript = eraseAttributeIfInjected(request, srcdocAttr, String(), ScriptLikeAttribute); - if (isContainedInRequest(decodedSnippetForName(request))) - didBlockScript |= eraseAttributeIfInjected(request, srcAttr, String(), SrcLikeAttribute); + bool didBlockScript = eraseAttributeIfInjected(request, srcdocAttr, String(), ScriptLikeAttributeTruncation); + if (isContainedInRequest(canonicalizedSnippetForTagName(request))) + didBlockScript |= eraseAttributeIfInjected(request, srcAttr, String(), SrcLikeAttributeTruncation); return didBlockScript; } @@ -515,7 +584,7 @@ bool XSSAuditor::filterInputToken(const FilterTokenRequest& request) ASSERT(request.token.type() == HTMLToken::StartTag); ASSERT(hasName(request.token, inputTag)); - return eraseAttributeIfInjected(request, formactionAttr, kURLWithUniqueOrigin, SrcLikeAttribute); + return eraseAttributeIfInjected(request, formactionAttr, kURLWithUniqueOrigin, SrcLikeAttributeTruncation); } bool XSSAuditor::filterButtonToken(const FilterTokenRequest& request) @@ -523,7 +592,7 @@ bool XSSAuditor::filterButtonToken(const FilterTokenRequest& request) ASSERT(request.token.type() == HTMLToken::StartTag); ASSERT(hasName(request.token, buttonTag)); - return eraseAttributeIfInjected(request, formactionAttr, kURLWithUniqueOrigin, SrcLikeAttribute); + return eraseAttributeIfInjected(request, formactionAttr, kURLWithUniqueOrigin, SrcLikeAttributeTruncation); } bool XSSAuditor::eraseDangerousAttributesIfInjected(const FilterTokenRequest& request) @@ -532,14 +601,24 @@ bool XSSAuditor::eraseDangerousAttributesIfInjected(const FilterTokenRequest& re bool didBlockScript = false; for (size_t i = 0; i < request.token.attributes().size(); ++i) { + bool eraseAttribute = false; + bool valueContainsJavaScriptURL = false; const HTMLToken::Attribute& attribute = request.token.attributes().at(i); - bool isInlineEventHandler = isNameOfInlineEventHandler(attribute.name); - // FIXME: It would be better if we didn't create a new String for every attribute in the document. - String strippedValue = stripLeadingAndTrailingHTMLSpaces(String(attribute.value)); - bool valueContainsJavaScriptURL = (!isInlineEventHandler && protocolIsJavaScript(strippedValue)) || (isSemicolonSeparatedAttribute(attribute) && semicolonSeparatedValueContainsJavaScriptURL(strippedValue)); - if (!isInlineEventHandler && !valueContainsJavaScriptURL) - continue; - if (!isContainedInRequest(decodedSnippetForAttribute(request, attribute, ScriptLikeAttribute))) + // FIXME: Don't create a new String for every attribute.value in the document. + if (isNameOfInlineEventHandler(attribute.name)) { + eraseAttribute = isContainedInRequest(canonicalize(snippetFromAttribute(request, attribute), ScriptLikeAttributeTruncation)); + } else if (isSemicolonSeparatedAttribute(attribute)) { + String subValue = semicolonSeparatedValueContainingJavaScriptURL(String(attribute.value)); + if (!subValue.isEmpty()) { + valueContainsJavaScriptURL = true; + eraseAttribute = isContainedInRequest(canonicalize(nameFromAttribute(request, attribute), NoTruncation)) + && isContainedInRequest(canonicalize(subValue, ScriptLikeAttributeTruncation)); + } + } else if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(String(attribute.value)))) { + valueContainsJavaScriptURL = true; + eraseAttribute = isContainedInRequest(canonicalize(snippetFromAttribute(request, attribute), ScriptLikeAttributeTruncation)); + } + if (!eraseAttribute) continue; request.token.eraseValueOfAttribute(i); if (valueContainsJavaScriptURL) @@ -549,96 +628,79 @@ bool XSSAuditor::eraseDangerousAttributesIfInjected(const FilterTokenRequest& re return didBlockScript; } -bool XSSAuditor::eraseAttributeIfInjected(const FilterTokenRequest& request, const QualifiedName& attributeName, const String& replacementValue, AttributeKind treatment) +bool XSSAuditor::eraseAttributeIfInjected(const FilterTokenRequest& request, const QualifiedName& attributeName, const String& replacementValue, TruncationKind treatment) { size_t indexOfAttribute = 0; - if (findAttributeWithName(request.token, attributeName, indexOfAttribute)) { - const HTMLToken::Attribute& attribute = request.token.attributes().at(indexOfAttribute); - if (isContainedInRequest(decodedSnippetForAttribute(request, attribute, treatment))) { - if (threadSafeMatch(attributeName, srcAttr) && isLikelySafeResource(String(attribute.value))) - return false; - if (threadSafeMatch(attributeName, http_equivAttr) && !isDangerousHTTPEquiv(String(attribute.value))) - return false; - request.token.eraseValueOfAttribute(indexOfAttribute); - if (!replacementValue.isEmpty()) - request.token.appendToAttributeValue(indexOfAttribute, replacementValue); - return true; - } + if (!findAttributeWithName(request.token, attributeName, indexOfAttribute)) + return false; + + const HTMLToken::Attribute& attribute = request.token.attributes().at(indexOfAttribute); + if (!isContainedInRequest(canonicalize(snippetFromAttribute(request, attribute), treatment))) + return false; + + if (threadSafeMatch(attributeName, srcAttr)) { + if (isLikelySafeResource(String(attribute.value))) + return false; + } else if (threadSafeMatch(attributeName, http_equivAttr)) { + if (!isDangerousHTTPEquiv(String(attribute.value))) + return false; } - return false; + + request.token.eraseValueOfAttribute(indexOfAttribute); + if (!replacementValue.isEmpty()) + request.token.appendToAttributeValue(indexOfAttribute, replacementValue); + + return true; } -String XSSAuditor::decodedSnippetForName(const FilterTokenRequest& request) +String XSSAuditor::canonicalizedSnippetForTagName(const FilterTokenRequest& request) { // Grab a fixed number of characters equal to the length of the token's name plus one (to account for the "<"). - return fullyDecodeString(request.sourceTracker.sourceForToken(request.token), m_encoding).substring(0, request.token.name().size() + 1); + return canonicalize(request.sourceTracker.sourceForToken(request.token).substring(0, request.token.name().size() + 1), NoTruncation); +} + +String XSSAuditor::nameFromAttribute(const FilterTokenRequest& request, const HTMLToken::Attribute& attribute) +{ + // The range inlcudes the character which terminates the name. So, + // for an input of |name="value"|, the snippet is |name=|. + int start = attribute.nameRange.start - request.token.startIndex(); + int end = attribute.valueRange.start - request.token.startIndex(); + return request.sourceTracker.sourceForToken(request.token).substring(start, end - start); } -String XSSAuditor::decodedSnippetForAttribute(const FilterTokenRequest& request, const HTMLToken::Attribute& attribute, AttributeKind treatment) +String XSSAuditor::snippetFromAttribute(const FilterTokenRequest& request, const HTMLToken::Attribute& attribute) { - // The range doesn't inlcude the character which terminates the value. So, + // The range doesn't include the character which terminates the value. So, // for an input of |name="value"|, the snippet is |name="value|. For an // unquoted input of |name=value |, the snippet is |name=value|. // FIXME: We should grab one character before the name also. int start = attribute.nameRange.start - request.token.startIndex(); int end = attribute.valueRange.end - request.token.startIndex(); - String decodedSnippet = fullyDecodeString(request.sourceTracker.sourceForToken(request.token).substring(start, end - start), m_encoding); - decodedSnippet.truncate(kMaximumFragmentLengthTarget); - if (treatment == SrcLikeAttribute) { - int slashCount = 0; - bool commaSeen = false; - // In HTTP URLs, characters following the first ?, #, or third slash may come from - // the page itself and can be merely ignored by an attacker's server when a remote - // script or script-like resource is requested. In DATA URLS, the payload starts at - // the first comma, and the the first /*, //, or <!-- may introduce a comment. Characters - // following this may come from the page itself and may be ignored when the script is - // executed. For simplicity, we don't differentiate based on URL scheme, and stop at - // the first # or ?, the third slash, or the first slash or < once a comma is seen. - for (size_t currentLength = 0; currentLength < decodedSnippet.length(); ++currentLength) { - UChar currentChar = decodedSnippet[currentLength]; - if (currentChar == '?' - || currentChar == '#' - || ((currentChar == '/' || currentChar == '\\') && (commaSeen || ++slashCount > 2)) - || (currentChar == '<' && commaSeen)) { - decodedSnippet.truncate(currentLength); - break; - } - if (currentChar == ',') - commaSeen = true; - } - } else if (treatment == ScriptLikeAttribute) { - // Beware of trailing characters which came from the page itself, not the - // injected vector. Excluding the terminating character covers common cases - // where the page immediately ends the attribute, but doesn't cover more - // complex cases where there is other page data following the injection. - // Generally, these won't parse as javascript, so the injected vector - // typically excludes them from consideration via a single-line comment or - // by enclosing them in a string literal terminated later by the page's own - // closing punctuation. Since the snippet has not been parsed, the vector - // may also try to introduce these via entities. As a result, we'd like to - // stop before the first "//", the first <!--, the first entity, or the first - // quote not immediately following the first equals sign (taking whitespace - // into consideration). To keep things simpler, we don't try to distinguish - // between entity-introducing amperands vs. other uses, nor do we bother to - // check for a second slash for a comment, nor do we bother to check for - // !-- following a less-than sign. We stop instead on any ampersand - // slash, or less-than sign. - size_t position = 0; - if ((position = decodedSnippet.find("=")) != kNotFound - && (position = decodedSnippet.find(isNotHTMLSpace<UChar>, position + 1)) != kNotFound - && (position = decodedSnippet.find(isTerminatingCharacter, isHTMLQuote(decodedSnippet[position]) ? position + 1 : position)) != kNotFound) { - decodedSnippet.truncate(position); - } + return request.sourceTracker.sourceForToken(request.token).substring(start, end - start); +} + +String XSSAuditor::canonicalize(String snippet, TruncationKind treatment) +{ + String decodedSnippet = fullyDecodeString(snippet, m_encoding); + + if (treatment != NoTruncation) { + decodedSnippet.truncate(kMaximumFragmentLengthTarget); + if (treatment == SrcLikeAttributeTruncation) + truncateForSrcLikeAttribute(decodedSnippet); + else if (treatment == ScriptLikeAttributeTruncation) + truncateForScriptLikeAttribute(decodedSnippet); } - return decodedSnippet; + + return decodedSnippet.removeCharacters(&isNonCanonicalCharacter); } -String XSSAuditor::decodedSnippetForJavaScript(const FilterTokenRequest& request) +String XSSAuditor::canonicalizedSnippetForJavaScript(const FilterTokenRequest& request) { String string = request.sourceTracker.sourceForToken(request.token); size_t startPosition = 0; size_t endPosition = string.length(); size_t foundPosition = kNotFound; + size_t lastNonSpacePosition = kNotFound; // Skip over initial comments to find start of code. while (startPosition < endPosition) { @@ -667,32 +729,40 @@ String XSSAuditor::decodedSnippetForJavaScript(const FilterTokenRequest& request String result; while (startPosition < endPosition && !result.length()) { - // Stop at next comment (using the same rules as above for SVG/XML vs HTML), when we - // encounter a comma, or when we exceed the maximum length target. The comma rule - // covers a common parameter concatenation case performed by some webservers. - // After hitting the length target, we can only stop at a point where we know we are - // not in the middle of a %-escape sequence. For the sake of simplicity, approximate - // not stopping inside a (possibly multiply encoded) %-esacpe sequence by breaking on - // whitespace only. We should have enough text in these cases to avoid false positives. + // Stop at next comment (using the same rules as above for SVG/XML vs HTML), when we encounter a comma, + // when we hit an opening <script> tag, or when we exceed the maximum length target. The comma rule + // covers a common parameter concatenation case performed by some web servers. + lastNonSpacePosition = kNotFound; for (foundPosition = startPosition; foundPosition < endPosition; foundPosition++) { if (!request.shouldAllowCDATA) { - if (startsSingleLineCommentAt(string, foundPosition) || startsMultiLineCommentAt(string, foundPosition)) { - foundPosition += 2; - break; - } - if (startsHTMLCommentAt(string, foundPosition)) { - foundPosition += 4; + if (startsSingleLineCommentAt(string, foundPosition) + || startsMultiLineCommentAt(string, foundPosition) + || startsHTMLCommentAt(string, foundPosition)) { break; } } - if (string[foundPosition] == ',' || (foundPosition > startPosition + kMaximumFragmentLengthTarget && isHTMLSpace<UChar>(string[foundPosition]))) { + if (string[foundPosition] == ',') + break; + + if (lastNonSpacePosition != kNotFound && startsOpeningScriptTagAt(string, foundPosition)) { + foundPosition = lastNonSpacePosition; break; } + if (foundPosition > startPosition + kMaximumFragmentLengthTarget) { + // After hitting the length target, we can only stop at a point where we know we are + // not in the middle of a %-escape sequence. For the sake of simplicity, approximate + // not stopping inside a (possibly multiply encoded) %-escape sequence by breaking on + // whitespace only. We should have enough text in these cases to avoid false positives. + if (isHTMLSpace<UChar>(string[foundPosition])) + break; + } + if (!isHTMLSpace<UChar>(string[foundPosition])) + lastNonSpacePosition = foundPosition; } - - result = fullyDecodeString(string.substring(startPosition, foundPosition - startPosition), m_encoding); + result = canonicalize(string.substring(startPosition, foundPosition - startPosition), NoTruncation); startPosition = foundPosition + 1; } + return result; } @@ -732,7 +802,8 @@ bool XSSAuditor::isSafeToSendToAnotherThread() const { return m_documentURL.isSafeToSendToAnotherThread() && m_decodedURL.isSafeToSendToAnotherThread() - && m_decodedHTTPBody.isSafeToSendToAnotherThread(); + && m_decodedHTTPBody.isSafeToSendToAnotherThread() + && m_httpBodyAsString.isSafeToSendToAnotherThread(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.h b/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.h index db2655f4a8a..53a38ac606d 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.h +++ b/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditor.h @@ -64,6 +64,8 @@ public: PassOwnPtr<XSSInfo> filterToken(const FilterTokenRequest&); bool isSafeToSendToAnotherThread() const; + void setEncoding(const WTF::TextEncoding&); + private: static const size_t kMaximumFragmentLengthTarget = 100; @@ -74,10 +76,11 @@ private: SuppressingAdjacentCharacterTokens }; - enum AttributeKind { - NormalAttribute, - SrcLikeAttribute, - ScriptLikeAttribute + enum TruncationKind { + NoTruncation, + NormalAttributeTruncation, + SrcLikeAttributeTruncation, + ScriptLikeAttributeTruncation }; bool filterStartToken(const FilterTokenRequest&); @@ -96,12 +99,13 @@ private: bool filterButtonToken(const FilterTokenRequest&); bool eraseDangerousAttributesIfInjected(const FilterTokenRequest&); - bool eraseAttributeIfInjected(const FilterTokenRequest&, const QualifiedName&, const String& replacementValue = String(), AttributeKind treatment = NormalAttribute); + bool eraseAttributeIfInjected(const FilterTokenRequest&, const QualifiedName&, const String& replacementValue = String(), TruncationKind treatment = NormalAttributeTruncation); - String decodedSnippetForToken(const HTMLToken&); - String decodedSnippetForName(const FilterTokenRequest&); - String decodedSnippetForAttribute(const FilterTokenRequest&, const HTMLToken::Attribute&, AttributeKind treatment = NormalAttribute); - String decodedSnippetForJavaScript(const FilterTokenRequest&); + String canonicalizedSnippetForTagName(const FilterTokenRequest&); + String canonicalizedSnippetForJavaScript(const FilterTokenRequest&); + String nameFromAttribute(const FilterTokenRequest&, const HTMLToken::Attribute&); + String snippetFromAttribute(const FilterTokenRequest&, const HTMLToken::Attribute&); + String canonicalize(String, TruncationKind); bool isContainedInRequest(const String&); bool isLikelySafeResource(const String& url); @@ -115,6 +119,7 @@ private: String m_decodedURL; String m_decodedHTTPBody; + String m_httpBodyAsString; OwnPtr<SuffixTree<ASCIICodebook> > m_decodedHTTPBodySuffixTree; State m_state; diff --git a/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditorDelegate.cpp b/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditorDelegate.cpp index 5ea9b66ccf7..9b329e85ccd 100644 --- a/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditorDelegate.cpp +++ b/chromium/third_party/WebKit/Source/core/html/parser/XSSAuditorDelegate.cpp @@ -27,7 +27,7 @@ #include "core/html/parser/XSSAuditorDelegate.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" @@ -100,8 +100,8 @@ void XSSAuditorDelegate::didBlockScript(const XSSInfo& xssInfo) m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, xssInfo.buildConsoleError()); - // stopAllLoaders can detach the Frame, so protect it. - RefPtr<Frame> protect(m_document->frame()); + // stopAllLoaders can detach the LocalFrame, so protect it. + RefPtr<LocalFrame> protect(m_document->frame()); FrameLoader& frameLoader = m_document->frame()->loader(); if (xssInfo.m_didBlockEntirePage) frameLoader.stopAllLoaders(); @@ -116,7 +116,7 @@ void XSSAuditorDelegate::didBlockScript(const XSSInfo& xssInfo) } if (xssInfo.m_didBlockEntirePage) - m_document->frame()->navigationScheduler().scheduleLocationChange(m_document, SecurityOrigin::urlWithUniqueSecurityOrigin(), String()); + m_document->frame()->navigationScheduler().scheduleLocationChange(m_document, SecurityOrigin::urlWithUniqueSecurityOrigin(), Referrer()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/parser/create-html-entity-table b/chromium/third_party/WebKit/Source/core/html/parser/create-html-entity-table index 8c408fead9a..587e8a8f5d1 100755 --- a/chromium/third_party/WebKit/Source/core/html/parser/create-html-entity-table +++ b/chromium/third_party/WebKit/Source/core/html/parser/create-html-entity-table @@ -27,6 +27,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +"""This python script creates the raw data that is our entity +database. The representation is one string database containing all +strings we could need, and then a mapping from offset+length -> entity +data. That is compact, easy to use and efficient.""" + import csv import os.path import string @@ -35,17 +40,6 @@ import sys ENTITY = 0 VALUE = 1 -def convert_entity_to_cpp_name(entity): - postfix = "EntityName" - if entity[-1] == ";": - return "%sSemicolon%s" % (entity[:-1], postfix) - return "%s%s" % (entity, postfix) - - -def convert_entity_to_uchar_array(entity): - return "{'%s'}" % "', '".join(entity) - - def convert_value_to_int(value): if not value: return "0"; @@ -67,9 +61,8 @@ if len(sys.argv) < 4 or sys.argv[1] != "-o": output_path = sys.argv[2] input_path = sys.argv[3] -html_entity_names_file = open(input_path) -entries = list(csv.reader(html_entity_names_file)) -html_entity_names_file.close() +with open(input_path) as html_entity_names_file: + entries = list(csv.reader(html_entity_names_file)) entries.sort(key = lambda entry: entry[ENTITY]) entity_count = len(entries) @@ -101,7 +94,7 @@ output_file.write("""/* * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// THIS FILE IS GENERATED BY WebCore/html/parser/create-html-entity-table +// THIS FILE IS GENERATED BY core/html/parser/create-html-entity-table // DO NOT EDIT (unless you are a ninja)! #include "config.h" @@ -112,62 +105,126 @@ namespace WebCore { namespace { """) +assert len(entries) > 0, "Code assumes a non-empty entity array." +def check_ascii(entity_string): + for c in entity_string: + code = ord(c) + assert 0 <= code <= 127, (c + " is not ASCII. Need to change type " + + "of storage from LChar to UChar to support " + + "this entity.") + +output_file.write("static const LChar staticEntityStringStorage[] = {\n") +output_file.write("'") +all_data = "" +entity_offset = 0 +first_output = True +saved_by_reusing = 0 for entry in entries: - output_file.write("static const UChar %s[] = %s;\n" % ( - convert_entity_to_cpp_name(entry[ENTITY]), - convert_entity_to_uchar_array(entry[ENTITY]))) + check_ascii(entry[ENTITY]) + # Reuse substrings from earlier entries. This saves 1-2000 + # characters, but it's O(n^2) and not very smart. The optimal + # solution has to solve the "Shortest Common Superstring" problem + # and that is NP-Complete or worse. + # + # This would be even more efficient if we didn't store the + # semi-colon in the array but as a bit in the entry. + entity = entry[ENTITY] + already_existing_offset = all_data.find(entity) + if already_existing_offset != -1: + # Reusing space. + this_offset = already_existing_offset + saved_by_reusing += len(entity) + else: + if not first_output: + output_file.write(",\n'") + first_output = False + + # Try the end of the string and see if we can reuse that to + # fit the start of the new entity. + data_to_add = entity + this_offset = entity_offset + for truncated_len in range(len(entity) - 1, 0, -1): + if all_data.endswith(entity[:truncated_len]): + data_to_add = entity[truncated_len:] + this_offset = entity_offset - truncated_len + saved_by_reusing += truncated_len + break + + output_file.write("', '".join(data_to_add)) + all_data += data_to_add + output_file.write("'") + entity_offset += len(data_to_add) + assert len(entry) == 2, "We will use slot [2] in the list for the offset." + assert this_offset < 32768 # Stored in a 16 bit short. + entry.append(this_offset) + +output_file.write("};\n") + +index = {} +for offset, entry in enumerate(entries): + starting_letter = entry[ENTITY][0] + if starting_letter not in index: + index[starting_letter] = offset output_file.write(""" static const HTMLEntityTableEntry staticEntityTable[%s] = {\n""" % entity_count) -index = {} -offset = 0 for entry in entries: - letter = entry[ENTITY][0] - if letter not in index: - index[letter] = offset values = entry[VALUE].split(' ') assert len(values) <= 2, values - output_file.write(' { %s, %s, %s, %s },\n' % ( - convert_entity_to_cpp_name(entry[ENTITY]), - len(entry[ENTITY]), + output_file.write(' { %s, %s, %s, %s }, // &%s\n' % ( convert_value_to_int(values[0]), - convert_value_to_int(values[1] if len(values) >= 2 else ""))) - offset += 1 + convert_value_to_int(values[1] if len(values) >= 2 else ""), + entry[2], + len(entry[ENTITY]), + entry[ENTITY], + )) output_file.write("""}; """) -output_file.write("static const HTMLEntityTableEntry* uppercaseOffset[] = {\n") +output_file.write(""" +} +""") + +output_file.write("static const short uppercaseOffset[] = {\n") for letter in string.ascii_uppercase: - output_file.write("%s\n" % offset_table_entry(index[letter])) -output_file.write("%s\n" % offset_table_entry(index['a'])) + output_file.write("%d,\n" % index[letter]) +output_file.write("%d\n" % index['a']) output_file.write("""}; -static const HTMLEntityTableEntry* lowercaseOffset[] = {\n""") +static const short lowercaseOffset[] = {\n""") for letter in string.ascii_lowercase: - output_file.write("%s\n" % offset_table_entry(index[letter])) -output_file.write("%s\n" % offset_table_entry(entity_count)) + output_file.write("%d,\n" % index[letter]) +output_file.write("%d\n" % entity_count) output_file.write("""}; +const LChar* HTMLEntityTable::entityString(const HTMLEntityTableEntry& entry) +{ + return staticEntityStringStorage + entry.entityOffset; +} + +LChar HTMLEntityTableEntry::lastCharacter() const +{ + return HTMLEntityTable::entityString(*this)[length - 1]; } const HTMLEntityTableEntry* HTMLEntityTable::firstEntryStartingWith(UChar c) { if (c >= 'A' && c <= 'Z') - return uppercaseOffset[c - 'A']; + return &staticEntityTable[uppercaseOffset[c - 'A']]; if (c >= 'a' && c <= 'z') - return lowercaseOffset[c - 'a']; + return &staticEntityTable[lowercaseOffset[c - 'a']]; return 0; } const HTMLEntityTableEntry* HTMLEntityTable::lastEntryStartingWith(UChar c) { if (c >= 'A' && c <= 'Z') - return uppercaseOffset[c - 'A' + 1] - 1; + return &staticEntityTable[uppercaseOffset[c - 'A' + 1]] - 1; if (c >= 'a' && c <= 'z') - return lowercaseOffset[c - 'a' + 1] - 1; + return &staticEntityTable[lowercaseOffset[c - 'a' + 1]] - 1; return 0; } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.cpp index cb928e81dce..adbd8f8adde 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.cpp @@ -27,9 +27,9 @@ #include "core/html/shadow/ClearButtonElement.h" #include "core/events/MouseEvent.h" +#include "core/frame/LocalFrame.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/page/EventHandler.h" -#include "core/frame/Frame.h" #include "core/rendering/RenderView.h" namespace WebCore { @@ -43,10 +43,10 @@ inline ClearButtonElement::ClearButtonElement(Document& document, ClearButtonOwn { } -PassRefPtr<ClearButtonElement> ClearButtonElement::create(Document& document, ClearButtonOwner& clearButtonOwner) +PassRefPtrWillBeRawPtr<ClearButtonElement> ClearButtonElement::create(Document& document, ClearButtonOwner& clearButtonOwner) { - RefPtr<ClearButtonElement> element = adoptRef(new ClearButtonElement(document, clearButtonOwner)); - element->setPseudo(AtomicString("-webkit-clear-button", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<ClearButtonElement> element = adoptRefWillBeNoop(new ClearButtonElement(document, clearButtonOwner)); + element->setShadowPseudoId(AtomicString("-webkit-clear-button", AtomicString::ConstructFromLiteral)); element->setAttribute(idAttr, ShadowElementNames::clearButton()); return element.release(); } @@ -54,8 +54,8 @@ PassRefPtr<ClearButtonElement> ClearButtonElement::create(Document& document, Cl void ClearButtonElement::detach(const AttachContext& context) { if (m_capturing) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) + frame->eventHandler().setCapturingMouseEventsNode(nullptr); } HTMLDivElement::detach(context); } @@ -65,8 +65,8 @@ void ClearButtonElement::releaseCapture() if (!m_capturing) return; - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) { + frame->eventHandler().setCapturingMouseEventsNode(nullptr); m_capturing = false; } } @@ -87,7 +87,7 @@ void ClearButtonElement::defaultEventHandler(Event* event) if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { if (renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { + if (LocalFrame* frame = document().frame()) { frame->eventHandler().setCapturingMouseEventsNode(this); m_capturing = true; } @@ -97,8 +97,8 @@ void ClearButtonElement::defaultEventHandler(Event* event) } if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { if (m_capturing) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) { + frame->eventHandler().setCapturingMouseEventsNode(nullptr); m_capturing = false; } if (hovered()) { @@ -117,4 +117,10 @@ bool ClearButtonElement::isClearButtonElement() const return true; } +void ClearButtonElement::trace(Visitor* visitor) +{ + visitor->trace(m_clearButtonOwner); + HTMLDivElement::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.h index 47c91115e31..eba5309fa30 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/ClearButtonElement.h @@ -33,7 +33,7 @@ namespace WebCore { class ClearButtonElement FINAL : public HTMLDivElement { public: - class ClearButtonOwner { + class ClearButtonOwner : public WillBeGarbageCollectedMixin { public: virtual ~ClearButtonOwner() { } virtual void focusAndSelectClearButtonOwner() = 0; @@ -41,18 +41,20 @@ public: virtual void clearValue() = 0; }; - static PassRefPtr<ClearButtonElement> create(Document&, ClearButtonOwner&); + static PassRefPtrWillBeRawPtr<ClearButtonElement> create(Document&, ClearButtonOwner&); void releaseCapture(); - void removeClearButtonOwner() { m_clearButtonOwner = 0; } + void removeClearButtonOwner() { m_clearButtonOwner = nullptr; } + + virtual void trace(Visitor*) OVERRIDE; private: ClearButtonElement(Document&, ClearButtonOwner&); virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - virtual bool isMouseFocusable() const { return false; } - virtual void defaultEventHandler(Event*); + virtual bool isMouseFocusable() const OVERRIDE { return false; } + virtual void defaultEventHandler(Event*) OVERRIDE; virtual bool isClearButtonElement() const OVERRIDE; - ClearButtonOwner* m_clearButtonOwner; + RawPtrWillBeMember<ClearButtonOwner> m_clearButtonOwner; bool m_capturing; }; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp index eb3508e9dc8..3b337ddf0f1 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp @@ -27,8 +27,9 @@ #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include "core/html/shadow/DateTimeEditElement.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/HTMLNames.h" +#include "core/dom/Document.h" #include "core/dom/Text.h" #include "core/events/MouseEvent.h" #include "core/html/forms/DateTimeFieldsState.h" @@ -147,7 +148,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co switch (fieldType) { case DateTimeFormat::FieldTypeDayOfMonth: { - RefPtr<DateTimeFieldElement> field = DateTimeDayFieldElement::create(document, m_editElement, m_parameters.placeholderForDay, m_dayRange); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeDayFieldElement::create(document, m_editElement, m_parameters.placeholderForDay, m_dayRange); m_editElement.addField(field); if (shouldDayOfMonthFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -158,7 +159,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeHour11: { DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerHour * 12); - RefPtr<DateTimeFieldElement> field = DateTimeHour11FieldElement::create(document, m_editElement, m_hour23Range, step); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeHour11FieldElement::create(document, m_editElement, m_hour23Range, step); m_editElement.addField(field); if (shouldHourFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -169,7 +170,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeHour12: { DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerHour * 12); - RefPtr<DateTimeFieldElement> field = DateTimeHour12FieldElement::create(document, m_editElement, m_hour23Range, step); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeHour12FieldElement::create(document, m_editElement, m_hour23Range, step); m_editElement.addField(field); if (shouldHourFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -180,7 +181,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeHour23: { DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerDay); - RefPtr<DateTimeFieldElement> field = DateTimeHour23FieldElement::create(document, m_editElement, m_hour23Range, step); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeHour23FieldElement::create(document, m_editElement, m_hour23Range, step); m_editElement.addField(field); if (shouldHourFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -191,7 +192,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeHour24: { DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerDay); - RefPtr<DateTimeFieldElement> field = DateTimeHour24FieldElement::create(document, m_editElement, m_hour23Range, step); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeHour24FieldElement::create(document, m_editElement, m_hour23Range, step); m_editElement.addField(field); if (shouldHourFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -202,7 +203,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeMinute: { DateTimeNumericFieldElement::Step step = createStep(msPerMinute, msPerHour); - RefPtr<DateTimeNumericFieldElement> field = DateTimeMinuteFieldElement::create(document, m_editElement, m_minuteRange, step); + RefPtrWillBeRawPtr<DateTimeNumericFieldElement> field = DateTimeMinuteFieldElement::create(document, m_editElement, m_minuteRange, step); m_editElement.addField(field); if (shouldMinuteFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -221,7 +222,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co minMonth = m_parameters.minimum.month(); maxMonth = m_parameters.maximum.month(); } - RefPtr<DateTimeFieldElement> field; + RefPtrWillBeRawPtr<DateTimeFieldElement> field; switch (count) { case countForNarrowMonth: // Fallthrough. case countForAbbreviatedMonth: @@ -243,7 +244,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co } case DateTimeFormat::FieldTypePeriod: { - RefPtr<DateTimeFieldElement> field = DateTimeAMPMFieldElement::create(document, m_editElement, m_parameters.locale.timeAMPMLabels()); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeAMPMFieldElement::create(document, m_editElement, m_parameters.locale.timeAMPMLabels()); m_editElement.addField(field); if (shouldAMPMFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -254,7 +255,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeSecond: { DateTimeNumericFieldElement::Step step = createStep(msPerSecond, msPerMinute); - RefPtr<DateTimeNumericFieldElement> field = DateTimeSecondFieldElement::create(document, m_editElement, m_secondRange, step); + RefPtrWillBeRawPtr<DateTimeNumericFieldElement> field = DateTimeSecondFieldElement::create(document, m_editElement, m_secondRange, step); m_editElement.addField(field); if (shouldSecondFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -270,7 +271,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co case DateTimeFormat::FieldTypeFractionalSecond: { DateTimeNumericFieldElement::Step step = createStep(1, msPerSecond); - RefPtr<DateTimeNumericFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement, m_millisecondRange, step); + RefPtrWillBeRawPtr<DateTimeNumericFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement, m_millisecondRange, step); m_editElement.addField(field); if (shouldMillisecondFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -313,7 +314,7 @@ void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int co std::swap(yearParams.minIsSpecified, yearParams.maxIsSpecified); } yearParams.placeholder = m_parameters.placeholderForYear; - RefPtr<DateTimeFieldElement> field = DateTimeYearFieldElement::create(document, m_editElement, yearParams); + RefPtrWillBeRawPtr<DateTimeFieldElement> field = DateTimeYearFieldElement::create(document, m_editElement, yearParams); m_editElement.addField(field); if (shouldYearFieldDisabled()) { field->setValueAsDate(m_dateValue); @@ -401,8 +402,8 @@ void DateTimeEditBuilder::visitLiteral(const String& text) { DEFINE_STATIC_LOCAL(AtomicString, textPseudoId, ("-webkit-datetime-edit-text", AtomicString::ConstructFromLiteral)); ASSERT(text.length()); - RefPtr<HTMLDivElement> element = HTMLDivElement::create(m_editElement.document()); - element->setPseudo(textPseudoId); + RefPtrWillBeRawPtr<HTMLDivElement> element = HTMLDivElement::create(m_editElement.document()); + element->setShadowPseudoId(textPseudoId); if (m_parameters.locale.isRTL() && text.length()) { Direction dir = direction(text[0]); if (dir == SegmentSeparator || dir == WhiteSpaceNeutral || dir == OtherNeutral) @@ -448,8 +449,19 @@ DateTimeEditElement::DateTimeEditElement(Document& document, EditControlOwner& e DateTimeEditElement::~DateTimeEditElement() { +#if !ENABLE(OILPAN) for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) m_fields[fieldIndex]->removeEventHandler(); +#endif +} + +void DateTimeEditElement::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_fields); +#endif + visitor->trace(m_editControlOwner); + HTMLDivElement::trace(visitor); } inline Element* DateTimeEditElement::fieldsWrapperElement() const @@ -458,7 +470,7 @@ inline Element* DateTimeEditElement::fieldsWrapperElement() const return toElement(firstChild()); } -void DateTimeEditElement::addField(PassRefPtr<DateTimeFieldElement> field) +void DateTimeEditElement::addField(PassRefPtrWillBeRawPtr<DateTimeFieldElement> field) { if (m_fields.size() == m_fields.capacity()) return; @@ -481,10 +493,10 @@ void DateTimeEditElement::blurByOwner() field->blur(); } -PassRefPtr<DateTimeEditElement> DateTimeEditElement::create(Document& document, EditControlOwner& editControlOwner) +PassRefPtrWillBeRawPtr<DateTimeEditElement> DateTimeEditElement::create(Document& document, EditControlOwner& editControlOwner) { - RefPtr<DateTimeEditElement> container = adoptRef(new DateTimeEditElement(document, editControlOwner)); - container->setPseudo(AtomicString("-webkit-datetime-edit", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<DateTimeEditElement> container = adoptRefWillBeNoop(new DateTimeEditElement(document, editControlOwner)); + container->setShadowPseudoId(AtomicString("-webkit-datetime-edit", AtomicString::ConstructFromLiteral)); container->setAttribute(idAttr, ShadowElementNames::dateTimeEdit()); return container.release(); } @@ -534,7 +546,7 @@ void DateTimeEditElement::disabledStateChanged() DateTimeFieldElement* DateTimeEditElement::fieldAt(size_t fieldIndex) const { - return fieldIndex < m_fields.size() ? m_fields[fieldIndex] : 0; + return fieldIndex < m_fields.size() ? m_fields[fieldIndex].get() : 0; } size_t DateTimeEditElement::fieldIndexOf(const DateTimeFieldElement& field) const @@ -651,8 +663,8 @@ void DateTimeEditElement::layout(const LayoutParameters& layoutParameters, const { DEFINE_STATIC_LOCAL(AtomicString, fieldsWrapperPseudoId, ("-webkit-datetime-edit-fields-wrapper", AtomicString::ConstructFromLiteral)); if (!firstChild()) { - RefPtr<HTMLDivElement> element = HTMLDivElement::create(document()); - element->setPseudo(fieldsWrapperPseudoId); + RefPtrWillBeRawPtr<HTMLDivElement> element = HTMLDivElement::create(document()); + element->setShadowPseudoId(fieldsWrapperPseudoId); appendChild(element.get()); } Element* fieldsWrapper = fieldsWrapperElement(); @@ -685,7 +697,7 @@ void DateTimeEditElement::layout(const LayoutParameters& layoutParameters, const if (childNode == lastChildToBeRemoved) break; } - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } } @@ -694,6 +706,12 @@ AtomicString DateTimeEditElement::localeIdentifier() const return m_editControlOwner ? m_editControlOwner->localeIdentifier() : nullAtom; } +void DateTimeEditElement::fieldDidChangeValueByKeyboard() +{ + if (m_editControlOwner) + m_editControlOwner->editControlDidChangeValueByKeyboard(); +} + void DateTimeEditElement::readOnlyStateChanged() { updateUIState(); diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h index 87226cb136b..8621afdad8e 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.h @@ -45,11 +45,12 @@ class StepRange; // - Hour, Minute, Second, Millisecond, AM/PM class DateTimeEditElement FINAL : public HTMLDivElement, public DateTimeFieldElement::FieldOwner { WTF_MAKE_NONCOPYABLE(DateTimeEditElement); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DateTimeEditElement); public: // EditControlOwner implementer must call removeEditControlOwner when // it doesn't handle event, e.g. at destruction. - class EditControlOwner { + class EditControlOwner : public WillBeGarbageCollectedMixin { public: virtual ~EditControlOwner(); virtual void didBlurFromControl() = 0; @@ -59,6 +60,7 @@ public: virtual bool isEditControlOwnerDisabled() const = 0; virtual bool isEditControlOwnerReadOnly() const = 0; virtual AtomicString localeIdentifier() const = 0; + virtual void editControlDidChangeValueByKeyboard() = 0; }; struct LayoutParameters { @@ -79,10 +81,12 @@ public: } }; - static PassRefPtr<DateTimeEditElement> create(Document&, EditControlOwner&); + static PassRefPtrWillBeRawPtr<DateTimeEditElement> create(Document&, EditControlOwner&); virtual ~DateTimeEditElement(); - void addField(PassRefPtr<DateTimeFieldElement>); + virtual void trace(Visitor*) OVERRIDE; + + void addField(PassRefPtrWillBeRawPtr<DateTimeFieldElement>); bool anyEditableFieldsHaveValues() const; void blurByOwner(); virtual void defaultEventHandler(Event*) OVERRIDE; @@ -94,7 +98,7 @@ public: void focusByOwner(Element* oldFocusedElement = 0); bool hasFocusedField(); void readOnlyStateChanged(); - void removeEditControlOwner() { m_editControlOwner = 0; } + void removeEditControlOwner() { m_editControlOwner = nullptr; } void resetFields(); void setEmptyValue(const LayoutParameters&, const DateComponents& dateForReadOnlyField); void setValueAsDate(const LayoutParameters&, const DateComponents&); @@ -136,17 +140,18 @@ private: virtual bool isDateTimeEditElement() const OVERRIDE; // DateTimeFieldElement::FieldOwner functions. - virtual void didBlurFromField() OVERRIDE FINAL; - virtual void didFocusOnField() OVERRIDE FINAL; - virtual void fieldValueChanged() OVERRIDE FINAL; - virtual bool focusOnNextField(const DateTimeFieldElement&) OVERRIDE FINAL; - virtual bool focusOnPreviousField(const DateTimeFieldElement&) OVERRIDE FINAL; - virtual bool isFieldOwnerDisabled() const OVERRIDE FINAL; - virtual bool isFieldOwnerReadOnly() const OVERRIDE FINAL; - virtual AtomicString localeIdentifier() const OVERRIDE FINAL; - - Vector<DateTimeFieldElement*, maximumNumberOfFields> m_fields; - EditControlOwner* m_editControlOwner; + virtual void didBlurFromField() OVERRIDE; + virtual void didFocusOnField() OVERRIDE; + virtual void fieldValueChanged() OVERRIDE; + virtual bool focusOnNextField(const DateTimeFieldElement&) OVERRIDE; + virtual bool focusOnPreviousField(const DateTimeFieldElement&) OVERRIDE; + virtual bool isFieldOwnerDisabled() const OVERRIDE; + virtual bool isFieldOwnerReadOnly() const OVERRIDE; + virtual AtomicString localeIdentifier() const OVERRIDE; + virtual void fieldDidChangeValueByKeyboard() OVERRIDE; + + WillBeHeapVector<RawPtrWillBeMember<DateTimeFieldElement>, maximumNumberOfFields> m_fields; + RawPtrWillBeMember<EditControlOwner> m_editControlOwner; }; DEFINE_TYPE_CASTS(DateTimeEditElement, Element, element, element->isDateTimeEditElement(), element.isDateTimeEditElement()); diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp index 31cdb06f9c4..e96cc7a4fb5 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.cpp @@ -27,7 +27,8 @@ #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include "core/html/shadow/DateTimeFieldElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" +#include "core/dom/Document.h" #include "core/dom/Text.h" #include "core/events/KeyboardEvent.h" #include "platform/text/PlatformLocale.h" @@ -52,22 +53,27 @@ DateTimeFieldElement::DateTimeFieldElement(Document& document, FieldOwner& field { } -void DateTimeFieldElement::defaultEventHandler(Event* event) +void DateTimeFieldElement::trace(Visitor* visitor) { - if (event->type() == EventTypeNames::blur) - didBlur(); - - if (event->type() == EventTypeNames::focus) - didFocus(); + visitor->trace(m_fieldOwner); + HTMLSpanElement::trace(visitor); +} +void DateTimeFieldElement::defaultEventHandler(Event* event) +{ if (event->isKeyboardEvent()) { KeyboardEvent* keyboardEvent = toKeyboardEvent(event); if (!isDisabled() && !isFieldOwnerDisabled() && !isFieldOwnerReadOnly()) { handleKeyboardEvent(keyboardEvent); - if (keyboardEvent->defaultHandled()) + if (keyboardEvent->defaultHandled()) { + if (m_fieldOwner) + m_fieldOwner->fieldDidChangeValueByKeyboard(); return; + } } defaultKeyboardEventHandler(keyboardEvent); + if (m_fieldOwner) + m_fieldOwner->fieldDidChangeValueByKeyboard(); if (keyboardEvent->defaultHandled()) return; } @@ -129,16 +135,11 @@ void DateTimeFieldElement::defaultKeyboardEventHandler(KeyboardEvent* keyboardEv } } -void DateTimeFieldElement::didBlur() -{ - if (m_fieldOwner) - m_fieldOwner->didBlurFromField(); -} - -void DateTimeFieldElement::didFocus() +void DateTimeFieldElement::setFocus(bool value) { if (m_fieldOwner) - m_fieldOwner->didFocusOnField(); + value ? m_fieldOwner->didFocusOnField() : m_fieldOwner->didBlurFromField(); + ContainerNode::setFocus(value); } void DateTimeFieldElement::focusOnNextField() @@ -152,12 +153,12 @@ void DateTimeFieldElement::initialize(const AtomicString& pseudo, const String& { // On accessibility, DateTimeFieldElement acts like spin button. setAttribute(roleAttr, AtomicString("spinbutton", AtomicString::ConstructFromLiteral)); - setAttribute(aria_valuetextAttr, emptyValueAXText()); - setAttribute(aria_valueminAttr, String::number(axMinimum)); - setAttribute(aria_valuemaxAttr, String::number(axMaximum)); + setAttribute(aria_valuetextAttr, AtomicString(emptyValueAXText())); + setAttribute(aria_valueminAttr, AtomicString::number(axMinimum)); + setAttribute(aria_valuemaxAttr, AtomicString::number(axMaximum)); - setAttribute(aria_helpAttr, axHelpText); - setPseudo(pseudo); + setAttribute(aria_helpAttr, AtomicString(axHelpText)); + setShadowPseudoId(pseudo); appendChild(Text::create(document(), visibleValue())); } @@ -201,7 +202,7 @@ void DateTimeFieldElement::setDisabled() { // Set HTML attribute disabled to change apperance. setBooleanAttribute(disabledAttr, true); - setNeedsStyleRecalc(); + setNeedsStyleRecalc(SubtreeStyleChange); } bool DateTimeFieldElement::supportsFocus() const @@ -220,10 +221,10 @@ void DateTimeFieldElement::updateVisibleValue(EventBehavior eventBehavior) textNode->replaceWholeText(newVisibleValue); if (hasValue()) { - setAttribute(aria_valuetextAttr, newVisibleValue); - setAttribute(aria_valuenowAttr, String::number(valueForARIAValueNow())); + setAttribute(aria_valuetextAttr, AtomicString(newVisibleValue)); + setAttribute(aria_valuenowAttr, AtomicString::number(valueForARIAValueNow())); } else { - setAttribute(aria_valuetextAttr, emptyValueAXText()); + setAttribute(aria_valuetextAttr, AtomicString(emptyValueAXText())); removeAttribute(aria_valuenowAttr); } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h index a2e42a9599b..1fe32594769 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElement.h @@ -48,7 +48,7 @@ public: // FieldOwner implementer must call removeEventHandler when // it doesn't handle event, e.g. at destruction. - class FieldOwner { + class FieldOwner : public WillBeGarbageCollectedMixin { public: virtual ~FieldOwner(); virtual void didBlurFromField() = 0; @@ -59,6 +59,7 @@ public: virtual bool isFieldOwnerDisabled() const = 0; virtual bool isFieldOwnerReadOnly() const = 0; virtual AtomicString localeIdentifier() const = 0; + virtual void fieldDidChangeValueByKeyboard() = 0; }; virtual void defaultEventHandler(Event*) OVERRIDE; @@ -66,7 +67,7 @@ public: bool isDisabled() const; virtual float maximumWidth(const Font&); virtual void populateDateTimeFieldsState(DateTimeFieldsState&) = 0; - void removeEventHandler() { m_fieldOwner = 0; } + void removeEventHandler() { m_fieldOwner = nullptr; } void setDisabled(); virtual void setEmptyValue(EventBehavior = DispatchNoEvent) = 0; virtual void setValueAsDate(const DateComponents&) = 0; @@ -76,11 +77,10 @@ public: virtual void stepUp() = 0; virtual String value() const = 0; virtual String visibleValue() const = 0; + virtual void trace(Visitor*) OVERRIDE; protected: DateTimeFieldElement(Document&, FieldOwner&); - virtual void didBlur(); - virtual void didFocus(); void focusOnNextField(); virtual void handleKeyboardEvent(KeyboardEvent*) = 0; void initialize(const AtomicString& pseudo, const String& axHelpText, int axMinimum, int axMaximum); @@ -90,14 +90,17 @@ protected: virtual int valueAsInteger() const = 0; virtual int valueForARIAValueNow() const; + // Node functions. + virtual void setFocus(bool) OVERRIDE; + private: void defaultKeyboardEventHandler(KeyboardEvent*); - virtual bool isDateTimeFieldElement() const OVERRIDE; + virtual bool isDateTimeFieldElement() const OVERRIDE FINAL; bool isFieldOwnerDisabled() const; bool isFieldOwnerReadOnly() const; virtual bool supportsFocus() const OVERRIDE FINAL; - FieldOwner* m_fieldOwner; + RawPtrWillBeMember<FieldOwner> m_fieldOwner; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp index 5353c04ff2e..9479d9682ba 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.cpp @@ -47,10 +47,10 @@ DateTimeAMPMFieldElement::DateTimeAMPMFieldElement(Document& document, FieldOwne { } -PassRefPtr<DateTimeAMPMFieldElement> DateTimeAMPMFieldElement::create(Document& document, FieldOwner& fieldOwner, const Vector<String>& ampmLabels) +PassRefPtrWillBeRawPtr<DateTimeAMPMFieldElement> DateTimeAMPMFieldElement::create(Document& document, FieldOwner& fieldOwner, const Vector<String>& ampmLabels) { DEFINE_STATIC_LOCAL(AtomicString, ampmPsuedoId, ("-webkit-datetime-edit-ampm-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeAMPMFieldElement> field = adoptRef(new DateTimeAMPMFieldElement(document, fieldOwner, ampmLabels)); + RefPtrWillBeRawPtr<DateTimeAMPMFieldElement> field = adoptRefWillBeNoop(new DateTimeAMPMFieldElement(document, fieldOwner, ampmLabels)); field->initialize(ampmPsuedoId, queryString(WebLocalizedString::AXAMPMFieldText)); return field.release(); } @@ -83,10 +83,10 @@ DateTimeDayFieldElement::DateTimeDayFieldElement(Document& document, FieldOwner& { } -PassRefPtr<DateTimeDayFieldElement> DateTimeDayFieldElement::create(Document& document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) +PassRefPtrWillBeRawPtr<DateTimeDayFieldElement> DateTimeDayFieldElement::create(Document& document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) { DEFINE_STATIC_LOCAL(AtomicString, dayPsuedoId, ("-webkit-datetime-edit-day-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeDayFieldElement> field = adoptRef(new DateTimeDayFieldElement(document, fieldOwner, placeholder.isEmpty() ? "--" : placeholder, range)); + RefPtrWillBeRawPtr<DateTimeDayFieldElement> field = adoptRefWillBeNoop(new DateTimeDayFieldElement(document, fieldOwner, placeholder.isEmpty() ? "--" : placeholder, range)); field->initialize(dayPsuedoId, queryString(WebLocalizedString::AXDayOfMonthFieldText)); return field.release(); } @@ -159,7 +159,7 @@ DateTimeHour11FieldElement::DateTimeHour11FieldElement(Document& document, Field { } -PassRefPtr<DateTimeHour11FieldElement> DateTimeHour11FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeHour11FieldElement> DateTimeHour11FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) { ASSERT(hour23Range.minimum >= 0); ASSERT(hour23Range.maximum <= 23); @@ -172,7 +172,7 @@ PassRefPtr<DateTimeHour11FieldElement> DateTimeHour11FieldElement::create(Docume range.maximum = hour23Range.maximum - 12; } - RefPtr<DateTimeHour11FieldElement> field = adoptRef(new DateTimeHour11FieldElement(document, fieldOwner, range, step)); + RefPtrWillBeRawPtr<DateTimeHour11FieldElement> field = adoptRefWillBeNoop(new DateTimeHour11FieldElement(document, fieldOwner, range, step)); field->initialize(); return field.release(); } @@ -200,7 +200,7 @@ DateTimeHour12FieldElement::DateTimeHour12FieldElement(Document& document, Field { } -PassRefPtr<DateTimeHour12FieldElement> DateTimeHour12FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeHour12FieldElement> DateTimeHour12FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) { ASSERT(hour23Range.minimum >= 0); ASSERT(hour23Range.maximum <= 23); @@ -220,7 +220,7 @@ PassRefPtr<DateTimeHour12FieldElement> DateTimeHour12FieldElement::create(Docume range.minimum = 1; range.maximum = 12; } - RefPtr<DateTimeHour12FieldElement> field = adoptRef(new DateTimeHour12FieldElement(document, fieldOwner, range, step)); + RefPtrWillBeRawPtr<DateTimeHour12FieldElement> field = adoptRefWillBeNoop(new DateTimeHour12FieldElement(document, fieldOwner, range, step)); field->initialize(); return field.release(); } @@ -243,12 +243,12 @@ DateTimeHour23FieldElement::DateTimeHour23FieldElement(Document& document, Field { } -PassRefPtr<DateTimeHour23FieldElement> DateTimeHour23FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeHour23FieldElement> DateTimeHour23FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) { ASSERT(hour23Range.minimum >= 0); ASSERT(hour23Range.maximum <= 23); ASSERT(hour23Range.minimum <= hour23Range.maximum); - RefPtr<DateTimeHour23FieldElement> field = adoptRef(new DateTimeHour23FieldElement(document, fieldOwner, hour23Range, step)); + RefPtrWillBeRawPtr<DateTimeHour23FieldElement> field = adoptRefWillBeNoop(new DateTimeHour23FieldElement(document, fieldOwner, hour23Range, step)); field->initialize(); return field.release(); } @@ -279,7 +279,7 @@ DateTimeHour24FieldElement::DateTimeHour24FieldElement(Document& document, Field { } -PassRefPtr<DateTimeHour24FieldElement> DateTimeHour24FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeHour24FieldElement> DateTimeHour24FieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& hour23Range, const Step& step) { ASSERT(hour23Range.minimum >= 0); ASSERT(hour23Range.maximum <= 23); @@ -290,7 +290,7 @@ PassRefPtr<DateTimeHour24FieldElement> DateTimeHour24FieldElement::create(Docume range.maximum = 24; } - RefPtr<DateTimeHour24FieldElement> field = adoptRef(new DateTimeHour24FieldElement(document, fieldOwner, range, step)); + RefPtrWillBeRawPtr<DateTimeHour24FieldElement> field = adoptRefWillBeNoop(new DateTimeHour24FieldElement(document, fieldOwner, range, step)); field->initialize(); return field.release(); } @@ -326,10 +326,10 @@ DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement(Document& docum { } -PassRefPtr<DateTimeMillisecondFieldElement> DateTimeMillisecondFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeMillisecondFieldElement> DateTimeMillisecondFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range, const Step& step) { DEFINE_STATIC_LOCAL(AtomicString, millisecondPsuedoId, ("-webkit-datetime-edit-millisecond-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeMillisecondFieldElement> field = adoptRef(new DateTimeMillisecondFieldElement(document, fieldOwner, range, step)); + RefPtrWillBeRawPtr<DateTimeMillisecondFieldElement> field = adoptRefWillBeNoop(new DateTimeMillisecondFieldElement(document, fieldOwner, range, step)); field->initialize(millisecondPsuedoId, queryString(WebLocalizedString::AXMillisecondFieldText)); return field.release(); } @@ -367,10 +367,10 @@ DateTimeMinuteFieldElement::DateTimeMinuteFieldElement(Document& document, Field { } -PassRefPtr<DateTimeMinuteFieldElement> DateTimeMinuteFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeMinuteFieldElement> DateTimeMinuteFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range, const Step& step) { DEFINE_STATIC_LOCAL(AtomicString, minutePsuedoId, ("-webkit-datetime-edit-minute-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeMinuteFieldElement> field = adoptRef(new DateTimeMinuteFieldElement(document, fieldOwner, range, step)); + RefPtrWillBeRawPtr<DateTimeMinuteFieldElement> field = adoptRefWillBeNoop(new DateTimeMinuteFieldElement(document, fieldOwner, range, step)); field->initialize(minutePsuedoId, queryString(WebLocalizedString::AXMinuteFieldText)); return field.release(); } @@ -408,10 +408,10 @@ DateTimeMonthFieldElement::DateTimeMonthFieldElement(Document& document, FieldOw { } -PassRefPtr<DateTimeMonthFieldElement> DateTimeMonthFieldElement::create(Document& document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) +PassRefPtrWillBeRawPtr<DateTimeMonthFieldElement> DateTimeMonthFieldElement::create(Document& document, FieldOwner& fieldOwner, const String& placeholder, const Range& range) { DEFINE_STATIC_LOCAL(AtomicString, monthPsuedoId, ("-webkit-datetime-edit-month-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeMonthFieldElement> field = adoptRef(new DateTimeMonthFieldElement(document, fieldOwner, placeholder.isEmpty() ? "--" : placeholder, range)); + RefPtrWillBeRawPtr<DateTimeMonthFieldElement> field = adoptRefWillBeNoop(new DateTimeMonthFieldElement(document, fieldOwner, placeholder.isEmpty() ? "--" : placeholder, range)); field->initialize(monthPsuedoId, queryString(WebLocalizedString::AXMonthFieldText)); return field.release(); } @@ -449,10 +449,10 @@ DateTimeSecondFieldElement::DateTimeSecondFieldElement(Document& document, Field { } -PassRefPtr<DateTimeSecondFieldElement> DateTimeSecondFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range, const Step& step) +PassRefPtrWillBeRawPtr<DateTimeSecondFieldElement> DateTimeSecondFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range, const Step& step) { DEFINE_STATIC_LOCAL(AtomicString, secondPsuedoId, ("-webkit-datetime-edit-second-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeSecondFieldElement> field = adoptRef(new DateTimeSecondFieldElement(document, fieldOwner, range, step)); + RefPtrWillBeRawPtr<DateTimeSecondFieldElement> field = adoptRefWillBeNoop(new DateTimeSecondFieldElement(document, fieldOwner, range, step)); field->initialize(secondPsuedoId, queryString(WebLocalizedString::AXSecondFieldText)); return field.release(); } @@ -490,10 +490,10 @@ DateTimeSymbolicMonthFieldElement::DateTimeSymbolicMonthFieldElement(Document& d { } -PassRefPtr<DateTimeSymbolicMonthFieldElement> DateTimeSymbolicMonthFieldElement::create(Document& document, FieldOwner& fieldOwner, const Vector<String>& labels, int minimum, int maximum) +PassRefPtrWillBeRawPtr<DateTimeSymbolicMonthFieldElement> DateTimeSymbolicMonthFieldElement::create(Document& document, FieldOwner& fieldOwner, const Vector<String>& labels, int minimum, int maximum) { DEFINE_STATIC_LOCAL(AtomicString, monthPsuedoId, ("-webkit-datetime-edit-month-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeSymbolicMonthFieldElement> field = adoptRef(new DateTimeSymbolicMonthFieldElement(document, fieldOwner, labels, minimum, maximum)); + RefPtrWillBeRawPtr<DateTimeSymbolicMonthFieldElement> field = adoptRefWillBeNoop(new DateTimeSymbolicMonthFieldElement(document, fieldOwner, labels, minimum, maximum)); field->initialize(monthPsuedoId, queryString(WebLocalizedString::AXMonthFieldText)); return field.release(); } @@ -534,10 +534,10 @@ DateTimeWeekFieldElement::DateTimeWeekFieldElement(Document& document, FieldOwne { } -PassRefPtr<DateTimeWeekFieldElement> DateTimeWeekFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range) +PassRefPtrWillBeRawPtr<DateTimeWeekFieldElement> DateTimeWeekFieldElement::create(Document& document, FieldOwner& fieldOwner, const Range& range) { DEFINE_STATIC_LOCAL(AtomicString, weekPsuedoId, ("-webkit-datetime-edit-week-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeWeekFieldElement> field = adoptRef(new DateTimeWeekFieldElement(document, fieldOwner, range)); + RefPtrWillBeRawPtr<DateTimeWeekFieldElement> field = adoptRefWillBeNoop(new DateTimeWeekFieldElement(document, fieldOwner, range)); field->initialize(weekPsuedoId, queryString(WebLocalizedString::AXWeekOfYearFieldText)); return field.release(); } @@ -579,10 +579,10 @@ DateTimeYearFieldElement::DateTimeYearFieldElement(Document& document, FieldOwne ASSERT(parameters.maximumYear <= DateComponents::maximumYear()); } -PassRefPtr<DateTimeYearFieldElement> DateTimeYearFieldElement::create(Document& document, FieldOwner& fieldOwner, const DateTimeYearFieldElement::Parameters& parameters) +PassRefPtrWillBeRawPtr<DateTimeYearFieldElement> DateTimeYearFieldElement::create(Document& document, FieldOwner& fieldOwner, const DateTimeYearFieldElement::Parameters& parameters) { DEFINE_STATIC_LOCAL(AtomicString, yearPsuedoId, ("-webkit-datetime-edit-year-field", AtomicString::ConstructFromLiteral)); - RefPtr<DateTimeYearFieldElement> field = adoptRef(new DateTimeYearFieldElement(document, fieldOwner, parameters)); + RefPtrWillBeRawPtr<DateTimeYearFieldElement> field = adoptRefWillBeNoop(new DateTimeYearFieldElement(document, fieldOwner, parameters)); field->initialize(yearPsuedoId, queryString(WebLocalizedString::AXYearFieldText)); return field.release(); } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h index fb8ef52b22e..19050dbf6dc 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeFieldElements.h @@ -36,30 +36,30 @@ class DateTimeAMPMFieldElement FINAL : public DateTimeSymbolicFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeAMPMFieldElement); public: - static PassRefPtr<DateTimeAMPMFieldElement> create(Document&, FieldOwner&, const Vector<String>&); + static PassRefPtrWillBeRawPtr<DateTimeAMPMFieldElement> create(Document&, FieldOwner&, const Vector<String>&); private: DateTimeAMPMFieldElement(Document&, FieldOwner&, const Vector<String>&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeDayFieldElement FINAL : public DateTimeNumericFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeDayFieldElement); public: - static PassRefPtr<DateTimeDayFieldElement> create(Document&, FieldOwner&, const String& placeholder, const Range&); + static PassRefPtrWillBeRawPtr<DateTimeDayFieldElement> create(Document&, FieldOwner&, const String& placeholder, const Range&); private: DateTimeDayFieldElement(Document&, FieldOwner&, const String& placeholder, const Range&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeHourFieldElementBase : public DateTimeNumericFieldElement { @@ -71,154 +71,154 @@ protected: private: // DateTimeFieldElement functions. - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeHour11FieldElement FINAL : public DateTimeHourFieldElementBase { WTF_MAKE_NONCOPYABLE(DateTimeHour11FieldElement); public: - static PassRefPtr<DateTimeHour11FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeHour11FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeHour11FieldElement(Document&, FieldOwner&, const Range& hour23Range, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE; }; class DateTimeHour12FieldElement FINAL : public DateTimeHourFieldElementBase { WTF_MAKE_NONCOPYABLE(DateTimeHour12FieldElement); public: - static PassRefPtr<DateTimeHour12FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeHour12FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeHour12FieldElement(Document&, FieldOwner&, const Range& hour23Range, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE; }; class DateTimeHour23FieldElement FINAL : public DateTimeHourFieldElementBase { WTF_MAKE_NONCOPYABLE(DateTimeHour23FieldElement); public: - static PassRefPtr<DateTimeHour23FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeHour23FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeHour23FieldElement(Document&, FieldOwner&, const Range& hour23Range, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE; }; class DateTimeHour24FieldElement FINAL : public DateTimeHourFieldElementBase { WTF_MAKE_NONCOPYABLE(DateTimeHour24FieldElement); public: - static PassRefPtr<DateTimeHour24FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeHour24FieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeHour24FieldElement(Document&, FieldOwner&, const Range& hour23Range, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE; }; class DateTimeMillisecondFieldElement FINAL : public DateTimeNumericFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeMillisecondFieldElement); public: - static PassRefPtr<DateTimeMillisecondFieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeMillisecondFieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeMillisecondFieldElement(Document&, FieldOwner&, const Range&, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeMinuteFieldElement FINAL : public DateTimeNumericFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeMinuteFieldElement); public: - static PassRefPtr<DateTimeMinuteFieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeMinuteFieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeMinuteFieldElement(Document&, FieldOwner&, const Range&, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeMonthFieldElement FINAL : public DateTimeNumericFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeMonthFieldElement); public: - static PassRefPtr<DateTimeMonthFieldElement> create(Document&, FieldOwner&, const String& placeholder, const Range&); + static PassRefPtrWillBeRawPtr<DateTimeMonthFieldElement> create(Document&, FieldOwner&, const String& placeholder, const Range&); private: DateTimeMonthFieldElement(Document&, FieldOwner&, const String& placeholder, const Range&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeSecondFieldElement FINAL : public DateTimeNumericFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeSecondFieldElement); public: - static PassRefPtr<DateTimeSecondFieldElement> create(Document&, FieldOwner&, const Range&, const Step&); + static PassRefPtrWillBeRawPtr<DateTimeSecondFieldElement> create(Document&, FieldOwner&, const Range&, const Step&); private: DateTimeSecondFieldElement(Document&, FieldOwner&, const Range&, const Step&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeSymbolicMonthFieldElement FINAL : public DateTimeSymbolicFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeSymbolicMonthFieldElement); public: - static PassRefPtr<DateTimeSymbolicMonthFieldElement> create(Document&, FieldOwner&, const Vector<String>&, int minimum, int maximum); + static PassRefPtrWillBeRawPtr<DateTimeSymbolicMonthFieldElement> create(Document&, FieldOwner&, const Vector<String>&, int minimum, int maximum); private: DateTimeSymbolicMonthFieldElement(Document&, FieldOwner&, const Vector<String>&, int minimum, int maximum); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeWeekFieldElement FINAL : public DateTimeNumericFieldElement { WTF_MAKE_NONCOPYABLE(DateTimeWeekFieldElement); public: - static PassRefPtr<DateTimeWeekFieldElement> create(Document&, FieldOwner&, const Range&); + static PassRefPtrWillBeRawPtr<DateTimeWeekFieldElement> create(Document&, FieldOwner&, const Range&); private: DateTimeWeekFieldElement(Document&, FieldOwner&, const Range&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; }; class DateTimeYearFieldElement FINAL : public DateTimeNumericFieldElement { @@ -241,19 +241,19 @@ public: } }; - static PassRefPtr<DateTimeYearFieldElement> create(Document&, FieldOwner&, const Parameters&); + static PassRefPtrWillBeRawPtr<DateTimeYearFieldElement> create(Document&, FieldOwner&, const Parameters&); private: DateTimeYearFieldElement(Document&, FieldOwner&, const Parameters&); // DateTimeFieldElement functions. - virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; - virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; - virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE FINAL; + virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE; + virtual void setValueAsDate(const DateComponents&) OVERRIDE; + virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&) OVERRIDE; // DateTimeNumericFieldElement functions. - virtual int defaultValueForStepDown() const OVERRIDE FINAL; - virtual int defaultValueForStepUp() const OVERRIDE FINAL; + virtual int defaultValueForStepDown() const OVERRIDE; + virtual int defaultValueForStepUp() const OVERRIDE; bool m_minIsSpecified; bool m_maxIsSpecified; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp index 537416f7402..64b3e46b90c 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.cpp @@ -27,8 +27,8 @@ #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include "core/html/shadow/DateTimeNumericFieldElement.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" #include "core/events/KeyboardEvent.h" #include "platform/fonts/Font.h" #include "platform/text/PlatformLocale.h" @@ -91,13 +91,15 @@ int DateTimeNumericFieldElement::defaultValueForStepUp() const return m_range.minimum; } -void DateTimeNumericFieldElement::didBlur() +void DateTimeNumericFieldElement::setFocus(bool value) { - int value = typeAheadValue(); - m_typeAheadBuffer.clear(); - if (value >= 0) - setValueAsInteger(value, DispatchEvent); - DateTimeFieldElement::didBlur(); + if (!value) { + int value = typeAheadValue(); + m_typeAheadBuffer.clear(); + if (value >= 0) + setValueAsInteger(value, DispatchEvent); + } + DateTimeFieldElement::setFocus(value); } String DateTimeNumericFieldElement::formatValue(int value) const @@ -122,6 +124,13 @@ void DateTimeNumericFieldElement::handleKeyboardEvent(KeyboardEvent* keyboardEve if (digit < 0 || digit > 9) return; + unsigned maximumLength = DateTimeNumericFieldElement::formatValue(m_range.maximum).length(); + if (m_typeAheadBuffer.length() >= maximumLength) { + String current = m_typeAheadBuffer.toString(); + m_typeAheadBuffer.clear(); + unsigned desiredLength = maximumLength - 1; + m_typeAheadBuffer.append(current, current.length() - desiredLength, desiredLength); + } m_typeAheadBuffer.append(number); int newValue = typeAheadValue(); if (newValue >= m_hardLimits.minimum) @@ -131,7 +140,7 @@ void DateTimeNumericFieldElement::handleKeyboardEvent(KeyboardEvent* keyboardEve updateVisibleValue(DispatchEvent); } - if (m_typeAheadBuffer.length() >= DateTimeNumericFieldElement::formatValue(m_range.maximum).length() || newValue * 10 > m_range.maximum) + if (m_typeAheadBuffer.length() >= maximumLength || newValue * 10 > m_range.maximum) focusOnNextField(); keyboardEvent->setDefaultHandled(); diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h index 9b96fb54e3b..9a6272f8f01 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DateTimeNumericFieldElement.h @@ -80,13 +80,15 @@ protected: private: // DateTimeFieldElement functions. - virtual void didBlur() OVERRIDE FINAL; virtual void handleKeyboardEvent(KeyboardEvent*) OVERRIDE FINAL; virtual float maximumWidth(const Font&) OVERRIDE; virtual void stepDown() OVERRIDE FINAL; virtual void stepUp() OVERRIDE FINAL; virtual String value() const OVERRIDE FINAL; + // Node functions. + virtual void setFocus(bool) OVERRIDE FINAL; + String formatValue(int) const; int roundUp(int) const; int roundDown(int) const; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.cpp index f3f2adb3b8e..3da57cd08ea 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "core/html/shadow/DetailsMarkerControl.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLSummaryElement.h" #include "core/rendering/RenderDetailsMarker.h" diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.h b/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.h index 118063ef090..62fe336a698 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/DetailsMarkerControl.h @@ -40,20 +40,20 @@ class HTMLSummaryElement; class DetailsMarkerControl FINAL : public HTMLDivElement { public: - DetailsMarkerControl(Document&); - static PassRefPtr<DetailsMarkerControl> create(Document&); + explicit DetailsMarkerControl(Document&); + static PassRefPtrWillBeRawPtr<DetailsMarkerControl> create(Document&); private: - virtual RenderObject* createRenderer(RenderStyle*); - virtual bool rendererIsNeeded(const RenderStyle&); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; HTMLSummaryElement* summaryElement(); }; -inline PassRefPtr<DetailsMarkerControl> DetailsMarkerControl::create(Document& document) +inline PassRefPtrWillBeRawPtr<DetailsMarkerControl> DetailsMarkerControl::create(Document& document) { - RefPtr<DetailsMarkerControl> element = adoptRef(new DetailsMarkerControl(document)); - element->setPseudo(AtomicString("-webkit-details-marker", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<DetailsMarkerControl> element = adoptRefWillBeNoop(new DetailsMarkerControl(document)); + element->setShadowPseudoId(AtomicString("-webkit-details-marker", AtomicString::ConstructFromLiteral)); return element.release(); } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.h deleted file mode 100644 index b8f0f4fdd58..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/HTMLContentElement.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HTMLContentElement_h -#define HTMLContentElement_h - -#include "core/css/CSSSelectorList.h" -#include "core/dom/shadow/InsertionPoint.h" - -namespace WebCore { - -class HTMLContentElement FINAL : public InsertionPoint { -public: - static PassRefPtr<HTMLContentElement> create(Document&); - - virtual ~HTMLContentElement(); - - virtual bool canAffectSelector() const OVERRIDE { return true; } - - bool canSelectNode(const Vector<Node*, 32>& siblings, int nth) const; - - const CSSSelectorList& selectorList() const; - bool isSelectValid() const; - -private: - explicit HTMLContentElement(Document&); - - virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; - - bool validateSelect() const; - void parseSelect(); - - bool matchSelector(const Vector<Node*, 32>& siblings, int nth) const; - - bool m_shouldParseSelect; - bool m_isValidSelector; - AtomicString m_select; - CSSSelectorList m_selectorList; -}; - -inline const CSSSelectorList& HTMLContentElement::selectorList() const -{ - if (m_shouldParseSelect) - const_cast<HTMLContentElement*>(this)->parseSelect(); - return m_selectorList; -} - -inline bool HTMLContentElement::isSelectValid() const -{ - if (m_shouldParseSelect) - const_cast<HTMLContentElement*>(this)->parseSelect(); - return m_isValidSelector; -} - -inline bool HTMLContentElement::canSelectNode(const Vector<Node*, 32>& siblings, int nth) const -{ - if (m_select.isNull() || m_select.isEmpty()) - return true; - if (!isSelectValid()) - return false; - if (!siblings[nth]->isElementNode()) - return false; - return matchSelector(siblings, nth); -} - -inline bool isHTMLContentElement(const Node* node) -{ - return node->hasTagName(HTMLNames::contentTag); -} - -inline bool isHTMLContentElement(const Element* element) -{ - return element->hasTagName(HTMLNames::contentTag); -} - -DEFINE_NODE_TYPE_CASTS(HTMLContentElement, hasTagName(HTMLNames::contentTag)); - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.cpp index dc7f986e04e..989244d1bf8 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.cpp @@ -31,11 +31,13 @@ #include "core/html/shadow/MediaControlElementTypes.h" -#include "CSSValueKeywords.h" -#include "HTMLNames.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSValueKeywords.h" +#include "core/HTMLNames.h" #include "core/css/StylePropertySet.h" #include "core/events/MouseEvent.h" +#include "core/html/HTMLMediaElement.h" +#include "core/html/shadow/MediaControls.h" namespace WebCore { @@ -50,7 +52,7 @@ HTMLMediaElement* toParentMediaElement(Node* node) Node* mediaNode = node->shadowHost(); if (!mediaNode) mediaNode = node; - if (!mediaNode || !mediaNode->isElementNode() || !toElement(mediaNode)->isMediaElement()) + if (!isHTMLMediaElement(mediaNode)) return 0; return toHTMLMediaElement(mediaNode); @@ -60,18 +62,23 @@ MediaControlElementType mediaControlElementType(Node* node) { ASSERT_WITH_SECURITY_IMPLICATION(node->isMediaControlElement()); HTMLElement* element = toHTMLElement(node); - if (element->hasTagName(inputTag)) + if (isHTMLInputElement(*element)) return static_cast<MediaControlInputElement*>(element)->displayType(); return static_cast<MediaControlDivElement*>(element)->displayType(); } -MediaControlElement::MediaControlElement(MediaControlElementType displayType, HTMLElement* element) - : m_mediaController(0) +MediaControlElement::MediaControlElement(MediaControls& mediaControls, MediaControlElementType displayType, HTMLElement* element) + : m_mediaControls(mediaControls) , m_displayType(displayType) , m_element(element) { } +HTMLMediaElement& MediaControlElement::mediaElement() const +{ + return mediaControls().mediaElement(); +} + void MediaControlElement::hide() { m_element->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); @@ -82,14 +89,6 @@ void MediaControlElement::show() m_element->removeInlineStyleProperty(CSSPropertyDisplay); } -bool MediaControlElement::isShowing() const -{ - const StylePropertySet* propertySet = m_element->inlineStyle(); - // Following the code from show() and hide() above, we only have - // to check for the presense of inline display. - return (!propertySet || !propertySet->getPropertyCSSValue(CSSPropertyDisplay)); -} - void MediaControlElement::setDisplayType(MediaControlElementType displayType) { if (displayType == m_displayType) @@ -97,22 +96,22 @@ void MediaControlElement::setDisplayType(MediaControlElementType displayType) m_displayType = displayType; if (RenderObject* object = m_element->renderer()) - object->repaint(); + object->paintInvalidationForWholeRenderer(); } // ---------------------------- -MediaControlDivElement::MediaControlDivElement(Document& document, MediaControlElementType displayType) - : HTMLDivElement(document) - , MediaControlElement(displayType, this) +MediaControlDivElement::MediaControlDivElement(MediaControls& mediaControls, MediaControlElementType displayType) + : HTMLDivElement(mediaControls.document()) + , MediaControlElement(mediaControls, displayType, this) { } // ---------------------------- -MediaControlInputElement::MediaControlInputElement(Document& document, MediaControlElementType displayType) - : HTMLInputElement(document, 0, false) - , MediaControlElement(displayType, this) +MediaControlInputElement::MediaControlInputElement(MediaControls& mediaControls, MediaControlElementType displayType) + : HTMLInputElement(mediaControls.document(), 0, false) + , MediaControlElement(mediaControls, displayType, this) { } @@ -123,8 +122,8 @@ bool MediaControlInputElement::isMouseFocusable() const // ---------------------------- -MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document& document, MediaControlElementType displayType) - : MediaControlDivElement(document, displayType) +MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(MediaControls& mediaControls, MediaControlElementType displayType) + : MediaControlDivElement(mediaControls, displayType) , m_currentValue(0) { } @@ -134,87 +133,4 @@ void MediaControlTimeDisplayElement::setCurrentValue(double time) m_currentValue = time; } -// ---------------------------- - -MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document& document, MediaControlElementType displayType) - : MediaControlInputElement(document, displayType) -{ -} - -void MediaControlMuteButtonElement::defaultEventHandler(Event* event) -{ - if (event->type() == EventTypeNames::click) { - mediaController()->setMuted(!mediaController()->muted()); - event->setDefaultHandled(); - } - - HTMLInputElement::defaultEventHandler(event); -} - -void MediaControlMuteButtonElement::changedMute() -{ - updateDisplayType(); -} - -void MediaControlMuteButtonElement::updateDisplayType() -{ - setDisplayType(mediaController()->muted() ? MediaUnMuteButton : MediaMuteButton); -} - -// ---------------------------- - -MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document& document) - : MediaControlInputElement(document, MediaVolumeSlider) - , m_clearMutedOnUserInteraction(false) -{ -} - -void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) -{ - // Left button is 0. Rejects mouse events not from left button. - if (event->isMouseEvent() && toMouseEvent(event)->button()) - return; - - if (!inDocument() || !document().isActive()) - return; - - MediaControlInputElement::defaultEventHandler(event); - - if (event->type() == EventTypeNames::mouseover || event->type() == EventTypeNames::mouseout || event->type() == EventTypeNames::mousemove) - return; - - double volume = value().toDouble(); - if (volume != mediaController()->volume()) - mediaController()->setVolume(volume, ASSERT_NO_EXCEPTION); - if (m_clearMutedOnUserInteraction) - mediaController()->setMuted(false); -} - -bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents() -{ - if (!inDocument() || !document().isActive()) - return false; - - return MediaControlInputElement::willRespondToMouseMoveEvents(); -} - -bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents() -{ - if (!inDocument() || !document().isActive()) - return false; - - return MediaControlInputElement::willRespondToMouseClickEvents(); -} - -void MediaControlVolumeSliderElement::setVolume(double volume) -{ - if (value().toDouble() != volume) - setValue(String::number(volume)); -} - -void MediaControlVolumeSliderElement::setClearMutedOnUserInteraction(bool clearMute) -{ - m_clearMutedOnUserInteraction = clearMute; -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h index 6293e6dac09..6213debb7b3 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h @@ -32,23 +32,19 @@ #include "core/html/HTMLDivElement.h" #include "core/html/HTMLInputElement.h" -#include "core/html/HTMLMediaElement.h" -#include "core/html/MediaControllerInterface.h" #include "core/rendering/RenderBlock.h" namespace WebCore { -// Must match WebKitSystemInterface.h +class HTMLMediaElement; +class MediaControls; + enum MediaControlElementType { MediaEnterFullscreenButton = 0, MediaMuteButton, MediaPlayButton, - MediaSeekBackButton, - MediaSeekForwardButton, MediaSlider, MediaSliderThumb, - MediaRewindButton, - MediaReturnToRealtimeButton, MediaShowClosedCaptionsButton, MediaHideClosedCaptionsButton, MediaUnMuteButton, @@ -63,7 +59,6 @@ enum MediaControlElementType { MediaVolumeSliderThumb, MediaFullScreenVolumeSlider, MediaFullScreenVolumeSliderThumb, - MediaVolumeSliderMuteButton, MediaTextTrackDisplayContainer, MediaTextTrackDisplay, MediaExitFullscreenButton, @@ -77,27 +72,23 @@ MediaControlElementType mediaControlElementType(Node*); // ---------------------------- -class MediaControlElement { +class MediaControlElement : public WillBeGarbageCollectedMixin { public: - virtual void hide(); - virtual void show(); - virtual bool isShowing() const; - - virtual MediaControlElementType displayType() { return m_displayType; } - virtual const AtomicString& pseudo() const = 0; + void hide(); + void show(); - virtual void setMediaController(MediaControllerInterface* controller) { m_mediaController = controller; } - virtual MediaControllerInterface* mediaController() const { return m_mediaController; } + MediaControlElementType displayType() { return m_displayType; } protected: - explicit MediaControlElement(MediaControlElementType, HTMLElement*); - ~MediaControlElement() { } + MediaControlElement(MediaControls&, MediaControlElementType, HTMLElement*); - virtual void setDisplayType(MediaControlElementType); - virtual bool isMediaControlElement() const { return true; } + MediaControls& mediaControls() const { return m_mediaControls; } + HTMLMediaElement& mediaElement() const; + + void setDisplayType(MediaControlElementType); private: - MediaControllerInterface* m_mediaController; + MediaControls& m_mediaControls; MediaControlElementType m_displayType; HTMLElement* m_element; }; @@ -105,17 +96,21 @@ private: // ---------------------------- class MediaControlDivElement : public HTMLDivElement, public MediaControlElement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaControlDivElement); + protected: - virtual bool isMediaControlElement() const OVERRIDE { return MediaControlElement::isMediaControlElement(); } - explicit MediaControlDivElement(Document&, MediaControlElementType); + virtual bool isMediaControlElement() const OVERRIDE FINAL { return true; } + MediaControlDivElement(MediaControls&, MediaControlElementType); }; // ---------------------------- class MediaControlInputElement : public HTMLInputElement, public MediaControlElement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaControlInputElement); + protected: - virtual bool isMediaControlElement() const OVERRIDE { return MediaControlElement::isMediaControlElement(); } - explicit MediaControlInputElement(Document&, MediaControlElementType); + virtual bool isMediaControlElement() const OVERRIDE FINAL { return true; } + MediaControlInputElement(MediaControls&, MediaControlElementType); private: virtual void updateDisplayType() { } @@ -130,47 +125,12 @@ public: double currentValue() const { return m_currentValue; } protected: - explicit MediaControlTimeDisplayElement(Document&, MediaControlElementType); + MediaControlTimeDisplayElement(MediaControls&, MediaControlElementType); private: double m_currentValue; }; -// ---------------------------- - -class MediaControlMuteButtonElement : public MediaControlInputElement { -public: - void changedMute(); - - virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; } - -protected: - explicit MediaControlMuteButtonElement(Document&, MediaControlElementType); - - virtual void defaultEventHandler(Event*) OVERRIDE; - -private: - virtual void updateDisplayType() OVERRIDE; -}; - -// ---------------------------- - -class MediaControlVolumeSliderElement : public MediaControlInputElement { -public: - virtual bool willRespondToMouseMoveEvents() OVERRIDE; - virtual bool willRespondToMouseClickEvents() OVERRIDE; - void setVolume(double); - void setClearMutedOnUserInteraction(bool); - -protected: - explicit MediaControlVolumeSliderElement(Document&); - - virtual void defaultEventHandler(Event*) OVERRIDE; - -private: - bool m_clearMutedOnUserInteraction; -}; - } // namespace WebCore #endif // MediaControlElementTypes_h diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp index 9c3aee249b1..674675fbff9 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp @@ -30,24 +30,23 @@ #include "config.h" #include "core/html/shadow/MediaControlElements.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/dom/DOMTokenList.h" #include "core/dom/FullscreenElementStack.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/events/MouseEvent.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLVideoElement.h" +#include "core/html/MediaController.h" #include "core/html/shadow/MediaControls.h" #include "core/html/track/TextTrack.h" #include "core/html/track/vtt/VTTRegionList.h" #include "core/page/EventHandler.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/rendering/RenderMediaControlElements.h" #include "core/rendering/RenderSlider.h" #include "core/rendering/RenderTheme.h" #include "core/rendering/RenderVideo.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { @@ -56,76 +55,39 @@ using namespace HTMLNames; static const AtomicString& getMediaControlCurrentTimeDisplayElementShadowPseudoId(); static const AtomicString& getMediaControlTimeRemainingDisplayElementShadowPseudoId(); +// If you change any of the following fade durations, then also update the +// corresponding values in LayoutTests/media/media-controls.js. static const double fadeInDuration = 0.1; static const double fadeOutDuration = 0.3; -MediaControlPanelElement::MediaControlPanelElement(Document& document) - : MediaControlDivElement(document, MediaControlsPanel) - , m_canBeDragged(false) - , m_isBeingDragged(false) +MediaControlPanelElement::MediaControlPanelElement(MediaControls& mediaControls) + : MediaControlDivElement(mediaControls, MediaControlsPanel) , m_isDisplayed(false) , m_opaque(true) , m_transitionTimer(this, &MediaControlPanelElement::transitionTimerFired) { } -PassRefPtr<MediaControlPanelElement> MediaControlPanelElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlPanelElement> MediaControlPanelElement::create(MediaControls& mediaControls) { - return adoptRef(new MediaControlPanelElement(document)); + return adoptRefWillBeNoop(new MediaControlPanelElement(mediaControls)); } -const AtomicString& MediaControlPanelElement::pseudo() const +const AtomicString& MediaControlPanelElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-panel", AtomicString::ConstructFromLiteral)); return id; } -void MediaControlPanelElement::startDrag(const LayoutPoint& eventLocation) -{ - if (!m_canBeDragged) - return; - - if (m_isBeingDragged) - return; - - RenderObject* renderer = this->renderer(); - if (!renderer || !renderer->isBox()) - return; - - Frame* frame = document().frame(); - if (!frame) - return; - - m_lastDragEventLocation = eventLocation; - - frame->eventHandler().setCapturingMouseEventsNode(this); - - m_isBeingDragged = true; -} - -void MediaControlPanelElement::continueDrag(const LayoutPoint& eventLocation) -{ - if (!m_isBeingDragged) - return; - - LayoutSize distanceDragged = eventLocation - m_lastDragEventLocation; - m_cumulativeDragOffset.move(distanceDragged); - m_lastDragEventLocation = eventLocation; - setPosition(m_cumulativeDragOffset); -} - -void MediaControlPanelElement::endDrag() +void MediaControlPanelElement::defaultEventHandler(Event* event) { - if (!m_isBeingDragged) - return; - - m_isBeingDragged = false; - - Frame* frame = document().frame(); - if (!frame) + // Suppress the media element activation behavior (toggle play/pause) when + // any part of the control panel is clicked. + if (event->type() == EventTypeNames::click) { + event->setDefaultHandled(); return; - - frame->eventHandler().setCapturingMouseEventsNode(0); + } + HTMLDivElement::defaultEventHandler(event); } void MediaControlPanelElement::startTimer() @@ -136,7 +98,7 @@ void MediaControlPanelElement::startTimer() // such that captions are correctly displayed at the bottom of the video // at the end of the fadeout transition. // FIXME: Racing a transition with a setTimeout like this is wrong. - m_transitionTimer.startOneShot(fadeOutDuration); + m_transitionTimer.startOneShot(fadeOutDuration, FROM_HERE); } void MediaControlPanelElement::stopTimer() @@ -153,34 +115,6 @@ void MediaControlPanelElement::transitionTimerFired(Timer<MediaControlPanelEleme stopTimer(); } -void MediaControlPanelElement::setPosition(const LayoutPoint& position) -{ - double left = position.x(); - double top = position.y(); - - // Set the left and top to control the panel's position; this depends on it being absolute positioned. - // Set the margin to zero since the position passed in will already include the effect of the margin. - setInlineStyleProperty(CSSPropertyLeft, left, CSSPrimitiveValue::CSS_PX); - setInlineStyleProperty(CSSPropertyTop, top, CSSPrimitiveValue::CSS_PX); - setInlineStyleProperty(CSSPropertyMarginLeft, 0.0, CSSPrimitiveValue::CSS_PX); - setInlineStyleProperty(CSSPropertyMarginTop, 0.0, CSSPrimitiveValue::CSS_PX); - - classList()->add("dragged", IGNORE_EXCEPTION); -} - -void MediaControlPanelElement::resetPosition() -{ - removeInlineStyleProperty(CSSPropertyLeft); - removeInlineStyleProperty(CSSPropertyTop); - removeInlineStyleProperty(CSSPropertyMarginLeft); - removeInlineStyleProperty(CSSPropertyMarginTop); - - classList()->remove("dragged", IGNORE_EXCEPTION); - - m_cumulativeDragOffset.setX(0); - m_cumulativeDragOffset.setY(0); -} - void MediaControlPanelElement::makeOpaque() { if (m_opaque) @@ -209,36 +143,6 @@ void MediaControlPanelElement::makeTransparent() startTimer(); } -void MediaControlPanelElement::defaultEventHandler(Event* event) -{ - MediaControlDivElement::defaultEventHandler(event); - - if (event->isMouseEvent()) { - LayoutPoint location = toMouseEvent(event)->absoluteLocation(); - if (event->type() == EventTypeNames::mousedown && event->target() == this) { - startDrag(location); - event->setDefaultHandled(); - } else if (event->type() == EventTypeNames::mousemove && m_isBeingDragged) - continueDrag(location); - else if (event->type() == EventTypeNames::mouseup && m_isBeingDragged) { - continueDrag(location); - endDrag(); - event->setDefaultHandled(); - } - } -} - -void MediaControlPanelElement::setCanBeDragged(bool canBeDragged) -{ - if (m_canBeDragged == canBeDragged) - return; - - m_canBeDragged = canBeDragged; - - if (!canBeDragged) - endDrag(); -} - void MediaControlPanelElement::setIsDisplayed(bool isDisplayed) { m_isDisplayed = isDisplayed; @@ -246,18 +150,18 @@ void MediaControlPanelElement::setIsDisplayed(bool isDisplayed) // ---------------------------- -MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(Document& document) +MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(MediaControls& mediaControls) // Mapping onto same MediaControlElementType as panel element, since it has similar properties. - : MediaControlDivElement(document, MediaControlsPanel) + : MediaControlDivElement(mediaControls, MediaControlsPanel) { } -PassRefPtr<MediaControlPanelEnclosureElement> MediaControlPanelEnclosureElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> MediaControlPanelEnclosureElement::create(MediaControls& mediaControls) { - return adoptRef(new MediaControlPanelEnclosureElement(document)); + return adoptRefWillBeNoop(new MediaControlPanelEnclosureElement(mediaControls)); } -const AtomicString& MediaControlPanelEnclosureElement::pseudo() const +const AtomicString& MediaControlPanelEnclosureElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-enclosure", AtomicString::ConstructFromLiteral)); return id; @@ -265,18 +169,18 @@ const AtomicString& MediaControlPanelEnclosureElement::pseudo() const // ---------------------------- -MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(Document& document) +MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(MediaControls& mediaControls) // Mapping onto same MediaControlElementType as panel element, since it has similar properties. - : MediaControlDivElement(document, MediaControlsPanel) + : MediaControlDivElement(mediaControls, MediaControlsPanel) { } -PassRefPtr<MediaControlOverlayEnclosureElement> MediaControlOverlayEnclosureElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> MediaControlOverlayEnclosureElement::create(MediaControls& mediaControls) { - return adoptRef(new MediaControlOverlayEnclosureElement(document)); + return adoptRefWillBeNoop(new MediaControlOverlayEnclosureElement(mediaControls)); } -const AtomicString& MediaControlOverlayEnclosureElement::pseudo() const +const AtomicString& MediaControlOverlayEnclosureElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-overlay-enclosure", AtomicString::ConstructFromLiteral)); return id; @@ -284,67 +188,50 @@ const AtomicString& MediaControlOverlayEnclosureElement::pseudo() const // ---------------------------- -MediaControlPanelMuteButtonElement::MediaControlPanelMuteButtonElement(Document& document, MediaControls* controls) - : MediaControlMuteButtonElement(document, MediaMuteButton) - , m_controls(controls) +MediaControlMuteButtonElement::MediaControlMuteButtonElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaMuteButton) { } -PassRefPtr<MediaControlPanelMuteButtonElement> MediaControlPanelMuteButtonElement::create(Document& document, MediaControls* controls) +PassRefPtrWillBeRawPtr<MediaControlMuteButtonElement> MediaControlMuteButtonElement::create(MediaControls& mediaControls) { - ASSERT(controls); - - RefPtr<MediaControlPanelMuteButtonElement> button = adoptRef(new MediaControlPanelMuteButtonElement(document, controls)); + RefPtrWillBeRawPtr<MediaControlMuteButtonElement> button = adoptRefWillBeNoop(new MediaControlMuteButtonElement(mediaControls)); button->ensureUserAgentShadowRoot(); button->setType("button"); return button.release(); } -void MediaControlPanelMuteButtonElement::defaultEventHandler(Event* event) +void MediaControlMuteButtonElement::defaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::mouseover) - m_controls->showVolumeSlider(); - - MediaControlMuteButtonElement::defaultEventHandler(event); -} - -const AtomicString& MediaControlPanelMuteButtonElement::pseudo() const -{ - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-mute-button", AtomicString::ConstructFromLiteral)); - return id; -} - -// ---------------------------- + if (event->type() == EventTypeNames::click) { + mediaElement().setMuted(!mediaElement().muted()); + event->setDefaultHandled(); + } -MediaControlVolumeSliderMuteButtonElement::MediaControlVolumeSliderMuteButtonElement(Document& document) - : MediaControlMuteButtonElement(document, MediaMuteButton) -{ + HTMLInputElement::defaultEventHandler(event); } -PassRefPtr<MediaControlVolumeSliderMuteButtonElement> MediaControlVolumeSliderMuteButtonElement::create(Document& document) +void MediaControlMuteButtonElement::updateDisplayType() { - RefPtr<MediaControlVolumeSliderMuteButtonElement> button = adoptRef(new MediaControlVolumeSliderMuteButtonElement(document)); - button->ensureUserAgentShadowRoot(); - button->setType("button"); - return button.release(); + setDisplayType(mediaElement().muted() ? MediaUnMuteButton : MediaMuteButton); } -const AtomicString& MediaControlVolumeSliderMuteButtonElement::pseudo() const +const AtomicString& MediaControlMuteButtonElement::shadowPseudoId() const { - DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-mute-button", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-mute-button", AtomicString::ConstructFromLiteral)); return id; } // ---------------------------- -MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document& document) - : MediaControlInputElement(document, MediaPlayButton) +MediaControlPlayButtonElement::MediaControlPlayButtonElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaPlayButton) { } -PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(MediaControls& mediaControls) { - RefPtr<MediaControlPlayButtonElement> button = adoptRef(new MediaControlPlayButtonElement(document)); + RefPtrWillBeRawPtr<MediaControlPlayButtonElement> button = adoptRefWillBeNoop(new MediaControlPlayButtonElement(mediaControls)); button->ensureUserAgentShadowRoot(); button->setType("button"); return button.release(); @@ -353,10 +240,7 @@ PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create( void MediaControlPlayButtonElement::defaultEventHandler(Event* event) { if (event->type() == EventTypeNames::click) { - if (mediaController()->canPlay()) - mediaController()->play(); - else - mediaController()->pause(); + mediaElement().togglePlayState(); updateDisplayType(); event->setDefaultHandled(); } @@ -365,10 +249,10 @@ void MediaControlPlayButtonElement::defaultEventHandler(Event* event) void MediaControlPlayButtonElement::updateDisplayType() { - setDisplayType(mediaController()->canPlay() ? MediaPlayButton : MediaPauseButton); + setDisplayType(mediaElement().togglePlayStateWillPlay() ? MediaPlayButton : MediaPauseButton); } -const AtomicString& MediaControlPlayButtonElement::pseudo() const +const AtomicString& MediaControlPlayButtonElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-play-button", AtomicString::ConstructFromLiteral)); return id; @@ -376,14 +260,14 @@ const AtomicString& MediaControlPlayButtonElement::pseudo() const // ---------------------------- -MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(Document& document) - : MediaControlInputElement(document, MediaOverlayPlayButton) +MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaOverlayPlayButton) { } -PassRefPtr<MediaControlOverlayPlayButtonElement> MediaControlOverlayPlayButtonElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> MediaControlOverlayPlayButtonElement::create(MediaControls& mediaControls) { - RefPtr<MediaControlOverlayPlayButtonElement> button = adoptRef(new MediaControlOverlayPlayButtonElement(document)); + RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> button = adoptRefWillBeNoop(new MediaControlOverlayPlayButtonElement(mediaControls)); button->ensureUserAgentShadowRoot(); button->setType("button"); return button.release(); @@ -391,23 +275,22 @@ PassRefPtr<MediaControlOverlayPlayButtonElement> MediaControlOverlayPlayButtonEl void MediaControlOverlayPlayButtonElement::defaultEventHandler(Event* event) { - if (event->type() == EventTypeNames::click && mediaController()->canPlay()) { - mediaController()->play(); + if (event->type() == EventTypeNames::click && mediaElement().togglePlayStateWillPlay()) { + mediaElement().togglePlayState(); updateDisplayType(); event->setDefaultHandled(); } - HTMLInputElement::defaultEventHandler(event); } void MediaControlOverlayPlayButtonElement::updateDisplayType() { - if (mediaController()->canPlay()) { + if (mediaElement().togglePlayStateWillPlay()) { show(); } else hide(); } -const AtomicString& MediaControlOverlayPlayButtonElement::pseudo() const +const AtomicString& MediaControlOverlayPlayButtonElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-overlay-play-button", AtomicString::ConstructFromLiteral)); return id; @@ -416,16 +299,14 @@ const AtomicString& MediaControlOverlayPlayButtonElement::pseudo() const // ---------------------------- -MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document& document, MediaControls*) - : MediaControlInputElement(document, MediaShowClosedCaptionsButton) +MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaShowClosedCaptionsButton) { } -PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(Document& document, MediaControls* controls) +PassRefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(MediaControls& mediaControls) { - ASSERT(controls); - - RefPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(new MediaControlToggleClosedCaptionsButtonElement(document, controls)); + RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRefWillBeNoop(new MediaControlToggleClosedCaptionsButtonElement(mediaControls)); button->ensureUserAgentShadowRoot(); button->setType("button"); button->hide(); @@ -434,7 +315,7 @@ PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClos void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() { - bool captionsVisible = mediaController()->closedCaptionsVisible(); + bool captionsVisible = mediaElement().closedCaptionsVisible(); setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton); setChecked(captionsVisible); } @@ -442,8 +323,8 @@ void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event) { if (event->type() == EventTypeNames::click) { - mediaController()->setClosedCaptionsVisible(!mediaController()->closedCaptionsVisible()); - setChecked(mediaController()->closedCaptionsVisible()); + mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVisible()); + setChecked(mediaElement().closedCaptionsVisible()); updateDisplayType(); event->setDefaultHandled(); } @@ -451,7 +332,7 @@ void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlToggleClosedCaptionsButtonElement::pseudo() const +const AtomicString& MediaControlToggleClosedCaptionsButtonElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-toggle-closed-captions-button", AtomicString::ConstructFromLiteral)); return id; @@ -459,17 +340,14 @@ const AtomicString& MediaControlToggleClosedCaptionsButtonElement::pseudo() cons // ---------------------------- -MediaControlTimelineElement::MediaControlTimelineElement(Document& document, MediaControls* controls) - : MediaControlInputElement(document, MediaSlider) - , m_controls(controls) +MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaSlider) { } -PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(Document& document, MediaControls* controls) +PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(MediaControls& mediaControls) { - ASSERT(controls); - - RefPtr<MediaControlTimelineElement> timeline = adoptRef(new MediaControlTimelineElement(document, controls)); + RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoop(new MediaControlTimelineElement(mediaControls)); timeline->ensureUserAgentShadowRoot(); timeline->setType("range"); timeline->setAttribute(stepAttr, "any"); @@ -478,18 +356,17 @@ PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(Docu void MediaControlTimelineElement::defaultEventHandler(Event* event) { - // Left button is 0. Rejects mouse events not from left button. - if (event->isMouseEvent() && toMouseEvent(event)->button()) + if (event->isMouseEvent() && toMouseEvent(event)->button() != LeftButton) return; if (!inDocument() || !document().isActive()) return; if (event->type() == EventTypeNames::mousedown) - mediaController()->beginScrubbing(); + mediaControls().beginScrubbing(); if (event->type() == EventTypeNames::mouseup) - mediaController()->endScrubbing(); + mediaControls().endScrubbing(); MediaControlInputElement::defaultEventHandler(event); @@ -497,12 +374,18 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event) return; double time = value().toDouble(); - if (event->type() == EventTypeNames::input && time != mediaController()->currentTime()) - mediaController()->setCurrentTime(time, IGNORE_EXCEPTION); + if (event->type() == EventTypeNames::input) { + // FIXME: This will need to take the timeline offset into consideration + // once that concept is supported, see https://crbug.com/312699 + if (mediaElement().controller()) + mediaElement().controller()->setCurrentTime(time, IGNORE_EXCEPTION); + else + mediaElement().setCurrentTime(time, IGNORE_EXCEPTION); + } RenderSlider* slider = toRenderSlider(renderer()); if (slider && slider->inDragMode()) - m_controls->updateCurrentTimeDisplay(); + mediaControls().updateCurrentTimeDisplay(); } bool MediaControlTimelineElement::willRespondToMouseClickEvents() @@ -521,7 +404,7 @@ void MediaControlTimelineElement::setDuration(double duration) } -const AtomicString& MediaControlTimelineElement::pseudo() const +const AtomicString& MediaControlTimelineElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline", AtomicString::ConstructFromLiteral)); return id; @@ -529,14 +412,14 @@ const AtomicString& MediaControlTimelineElement::pseudo() const // ---------------------------- -MediaControlPanelVolumeSliderElement::MediaControlPanelVolumeSliderElement(Document& document) - : MediaControlVolumeSliderElement(document) +MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaVolumeSlider) { } -PassRefPtr<MediaControlPanelVolumeSliderElement> MediaControlPanelVolumeSliderElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlVolumeSliderElement> MediaControlVolumeSliderElement::create(MediaControls& mediaControls) { - RefPtr<MediaControlPanelVolumeSliderElement> slider = adoptRef(new MediaControlPanelVolumeSliderElement(document)); + RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = adoptRefWillBeNoop(new MediaControlVolumeSliderElement(mediaControls)); slider->ensureUserAgentShadowRoot(); slider->setType("range"); slider->setAttribute(stepAttr, "any"); @@ -544,7 +427,47 @@ PassRefPtr<MediaControlPanelVolumeSliderElement> MediaControlPanelVolumeSliderEl return slider.release(); } -const AtomicString& MediaControlPanelVolumeSliderElement::pseudo() const +void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) +{ + if (event->isMouseEvent() && toMouseEvent(event)->button() != LeftButton) + return; + + if (!inDocument() || !document().isActive()) + return; + + MediaControlInputElement::defaultEventHandler(event); + + if (event->type() == EventTypeNames::mouseover || event->type() == EventTypeNames::mouseout || event->type() == EventTypeNames::mousemove) + return; + + double volume = value().toDouble(); + mediaElement().setVolume(volume, ASSERT_NO_EXCEPTION); + mediaElement().setMuted(false); +} + +bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents() +{ + if (!inDocument() || !document().isActive()) + return false; + + return MediaControlInputElement::willRespondToMouseMoveEvents(); +} + +bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents() +{ + if (!inDocument() || !document().isActive()) + return false; + + return MediaControlInputElement::willRespondToMouseClickEvents(); +} + +void MediaControlVolumeSliderElement::setVolume(double volume) +{ + if (value().toDouble() != volume) + setValue(String::number(volume)); +} + +const AtomicString& MediaControlVolumeSliderElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider", AtomicString::ConstructFromLiteral)); return id; @@ -552,14 +475,14 @@ const AtomicString& MediaControlPanelVolumeSliderElement::pseudo() const // ---------------------------- -MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document& document) - : MediaControlInputElement(document, MediaEnterFullscreenButton) +MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(MediaControls& mediaControls) + : MediaControlInputElement(mediaControls, MediaEnterFullscreenButton) { } -PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(MediaControls& mediaControls) { - RefPtr<MediaControlFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenButtonElement(document)); + RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> button = adoptRefWillBeNoop(new MediaControlFullscreenButtonElement(mediaControls)); button->ensureUserAgentShadowRoot(); button->setType("button"); button->hide(); @@ -569,24 +492,16 @@ PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElem void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) { if (event->type() == EventTypeNames::click) { - // Only use the new full screen API if the fullScreenEnabled setting has - // been explicitly enabled. Otherwise, use the old fullscreen API. This - // allows apps which embed a WebView to retain the existing full screen - // video implementation without requiring them to implement their own full - // screen behavior. - if (document().settings() && document().settings()->fullScreenEnabled()) { - if (FullscreenElementStack::isActiveFullScreenElement(toParentMediaElement(this))) - FullscreenElementStack::from(&document())->webkitCancelFullScreen(); - else - FullscreenElementStack::from(&document())->requestFullScreenForElement(toParentMediaElement(this), 0, FullscreenElementStack::ExemptIFrameAllowFullScreenRequirement); - } else - mediaController()->enterFullscreen(); + if (FullscreenElementStack::isActiveFullScreenElement(&mediaElement())) + FullscreenElementStack::from(document()).webkitCancelFullScreen(); + else + FullscreenElementStack::from(document()).requestFullScreenForElement(&mediaElement(), 0, FullscreenElementStack::ExemptIFrameAllowFullScreenRequirement); event->setDefaultHandled(); } HTMLInputElement::defaultEventHandler(event); } -const AtomicString& MediaControlFullscreenButtonElement::pseudo() const +const AtomicString& MediaControlFullscreenButtonElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button", AtomicString::ConstructFromLiteral)); return id; @@ -599,14 +514,14 @@ void MediaControlFullscreenButtonElement::setIsFullscreen(bool isFullscreen) // ---------------------------- -MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(Document& document) - : MediaControlTimeDisplayElement(document, MediaTimeRemainingDisplay) +MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(MediaControls& mediaControls) + : MediaControlTimeDisplayElement(mediaControls, MediaTimeRemainingDisplay) { } -PassRefPtr<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(MediaControls& mediaControls) { - return adoptRef(new MediaControlTimeRemainingDisplayElement(document)); + return adoptRefWillBeNoop(new MediaControlTimeRemainingDisplayElement(mediaControls)); } static const AtomicString& getMediaControlTimeRemainingDisplayElementShadowPseudoId() @@ -615,21 +530,21 @@ static const AtomicString& getMediaControlTimeRemainingDisplayElementShadowPseud return id; } -const AtomicString& MediaControlTimeRemainingDisplayElement::pseudo() const +const AtomicString& MediaControlTimeRemainingDisplayElement::shadowPseudoId() const { return getMediaControlTimeRemainingDisplayElementShadowPseudoId(); } // ---------------------------- -MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(Document& document) - : MediaControlTimeDisplayElement(document, MediaCurrentTimeDisplay) +MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(MediaControls& mediaControls) + : MediaControlTimeDisplayElement(mediaControls, MediaCurrentTimeDisplay) { } -PassRefPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(MediaControls& mediaControls) { - return adoptRef(new MediaControlCurrentTimeDisplayElement(document)); + return adoptRefWillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls)); } static const AtomicString& getMediaControlCurrentTimeDisplayElementShadowPseudoId() @@ -638,22 +553,22 @@ static const AtomicString& getMediaControlCurrentTimeDisplayElementShadowPseudoI return id; } -const AtomicString& MediaControlCurrentTimeDisplayElement::pseudo() const +const AtomicString& MediaControlCurrentTimeDisplayElement::shadowPseudoId() const { return getMediaControlCurrentTimeDisplayElementShadowPseudoId(); } // ---------------------------- -MediaControlTextTrackContainerElement::MediaControlTextTrackContainerElement(Document& document) - : MediaControlDivElement(document, MediaTextTrackDisplayContainer) +MediaControlTextTrackContainerElement::MediaControlTextTrackContainerElement(MediaControls& mediaControls) + : MediaControlDivElement(mediaControls, MediaTextTrackDisplayContainer) , m_fontSize(0) { } -PassRefPtr<MediaControlTextTrackContainerElement> MediaControlTextTrackContainerElement::create(Document& document) +PassRefPtrWillBeRawPtr<MediaControlTextTrackContainerElement> MediaControlTextTrackContainerElement::create(MediaControls& mediaControls) { - RefPtr<MediaControlTextTrackContainerElement> element = adoptRef(new MediaControlTextTrackContainerElement(document)); + RefPtrWillBeRawPtr<MediaControlTextTrackContainerElement> element = adoptRefWillBeNoop(new MediaControlTextTrackContainerElement(mediaControls)); element->hide(); return element.release(); } @@ -669,30 +584,28 @@ const AtomicString& MediaControlTextTrackContainerElement::textTrackContainerEle return id; } -const AtomicString& MediaControlTextTrackContainerElement::pseudo() const +const AtomicString& MediaControlTextTrackContainerElement::shadowPseudoId() const { return textTrackContainerElementShadowPseudoId(); } void MediaControlTextTrackContainerElement::updateDisplay() { - if (!mediaController()->closedCaptionsVisible()) { + if (!mediaElement().closedCaptionsVisible()) { removeChildren(); return; } - HTMLMediaElement* mediaElement = toParentMediaElement(this); // 1. If the media element is an audio element, or is another playback // mechanism with no rendering area, abort these steps. There is nothing to // render. - if (!mediaElement || !mediaElement->isVideo()) + if (isHTMLAudioElement(mediaElement())) return; // 2. Let video be the media element or other playback mechanism. - HTMLVideoElement* video = toHTMLVideoElement(mediaElement); + HTMLVideoElement& video = toHTMLVideoElement(mediaElement()); // 3. Let output be an empty list of absolutely positioned CSS block boxes. - Vector<RefPtr<HTMLDivElement> > output; // 4. If the user agent is exposing a user interface for video, add to // output one or more completely transparent positioned CSS block boxes that @@ -713,7 +626,7 @@ void MediaControlTextTrackContainerElement::updateDisplay() // 7. Let cues be an empty list of text track cues. // 8. For each track track in tracks, append to cues all the cues from // track's list of cues that have their text track cue active flag set. - CueList activeCues = video->currentlyActiveCues(); + CueList activeCues = video.currentlyActiveCues(); // 9. If reset is false, then, for each text track cue cue in cues: if cue's // text track cue display state has a set of CSS boxes, then add those boxes @@ -737,28 +650,24 @@ void MediaControlTextTrackContainerElement::updateDisplay() } // 11. Return output. - if (hasChildNodes()) + if (hasChildren()) show(); else hide(); } -void MediaControlTextTrackContainerElement::updateSizes(bool forceUpdate) +void MediaControlTextTrackContainerElement::updateSizes() { - HTMLMediaElement* mediaElement = toParentMediaElement(this); - if (!mediaElement) - return; - if (!document().isActive()) return; IntRect videoBox; - if (!mediaElement->renderer() || !mediaElement->renderer()->isVideo()) + if (!mediaElement().renderer() || !mediaElement().renderer()->isVideo()) return; - videoBox = toRenderVideo(mediaElement->renderer())->videoBox(); + videoBox = toRenderVideo(mediaElement().renderer())->videoBox(); - if (!forceUpdate && m_videoDisplaySize == videoBox) + if (m_videoDisplaySize == videoBox) return; m_videoDisplaySize = videoBox; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h index 3d631dbb9b9..06c03206b75 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h @@ -38,40 +38,25 @@ namespace WebCore { class MediaControlPanelElement FINAL : public MediaControlDivElement { public: - static PassRefPtr<MediaControlPanelElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlPanelElement> create(MediaControls&); - void setCanBeDragged(bool); void setIsDisplayed(bool); - void resetPosition(); void makeOpaque(); void makeTransparent(); - virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; } - virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; } - private: - explicit MediaControlPanelElement(Document&); + explicit MediaControlPanelElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; - void startDrag(const LayoutPoint& eventLocation); - void continueDrag(const LayoutPoint& eventLocation); - void endDrag(); - void startTimer(); void stopTimer(); void transitionTimerFired(Timer<MediaControlPanelElement>*); - void setPosition(const LayoutPoint&); - - bool m_canBeDragged; - bool m_isBeingDragged; bool m_isDisplayed; bool m_opaque; - LayoutPoint m_lastDragEventLocation; - LayoutPoint m_cumulativeDragOffset; Timer<MediaControlPanelElement> m_transitionTimer; }; @@ -80,66 +65,53 @@ private: class MediaControlPanelEnclosureElement FINAL : public MediaControlDivElement { public: - static PassRefPtr<MediaControlPanelEnclosureElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> create(MediaControls&); private: - explicit MediaControlPanelEnclosureElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit MediaControlPanelEnclosureElement(MediaControls&); + virtual const AtomicString& shadowPseudoId() const OVERRIDE; }; // ---------------------------- class MediaControlOverlayEnclosureElement FINAL : public MediaControlDivElement { public: - static PassRefPtr<MediaControlOverlayEnclosureElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> create(MediaControls&); private: - explicit MediaControlOverlayEnclosureElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit MediaControlOverlayEnclosureElement(MediaControls&); + virtual const AtomicString& shadowPseudoId() const OVERRIDE; }; // ---------------------------- -class MediaControlPanelMuteButtonElement FINAL : public MediaControlMuteButtonElement { +class MediaControlMuteButtonElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlPanelMuteButtonElement> create(Document&, MediaControls*); + static PassRefPtrWillBeRawPtr<MediaControlMuteButtonElement> create(MediaControls&); - virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; } + virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; } + virtual void updateDisplayType() OVERRIDE; private: - explicit MediaControlPanelMuteButtonElement(Document&, MediaControls*); + explicit MediaControlMuteButtonElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; - - MediaControls* m_controls; -}; - -// ---------------------------- - -class MediaControlVolumeSliderMuteButtonElement FINAL : public MediaControlMuteButtonElement { -public: - static PassRefPtr<MediaControlVolumeSliderMuteButtonElement> create(Document&); - -private: - explicit MediaControlVolumeSliderMuteButtonElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; }; - // ---------------------------- class MediaControlPlayButtonElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlPlayButtonElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlPlayButtonElement> create(MediaControls&); virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; } virtual void updateDisplayType() OVERRIDE; private: - explicit MediaControlPlayButtonElement(Document&); + explicit MediaControlPlayButtonElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; }; @@ -147,14 +119,14 @@ private: class MediaControlOverlayPlayButtonElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlOverlayPlayButtonElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> create(MediaControls&); virtual void updateDisplayType() OVERRIDE; private: - explicit MediaControlOverlayPlayButtonElement(Document&); + explicit MediaControlOverlayPlayButtonElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; }; @@ -162,16 +134,16 @@ private: class MediaControlToggleClosedCaptionsButtonElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(Document&, MediaControls*); + static PassRefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> create(MediaControls&); virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; } virtual void updateDisplayType() OVERRIDE; private: - explicit MediaControlToggleClosedCaptionsButtonElement(Document&, MediaControls*); + explicit MediaControlToggleClosedCaptionsButtonElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; }; @@ -179,87 +151,93 @@ private: class MediaControlTimelineElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlTimelineElement> create(Document&, MediaControls*); + static PassRefPtrWillBeRawPtr<MediaControlTimelineElement> create(MediaControls&); virtual bool willRespondToMouseClickEvents() OVERRIDE; + // FIXME: An "earliest possible position" will be needed once that concept + // is supported by HTMLMediaElement, see https://crbug.com/137275 void setPosition(double); void setDuration(double); private: - explicit MediaControlTimelineElement(Document&, MediaControls*); + explicit MediaControlTimelineElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; - - MediaControls* m_controls; }; // ---------------------------- class MediaControlFullscreenButtonElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlFullscreenButtonElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> create(MediaControls&); virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; } - virtual void setIsFullscreen(bool); + void setIsFullscreen(bool); private: - explicit MediaControlFullscreenButtonElement(Document&); + explicit MediaControlFullscreenButtonElement(MediaControls&); - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual void defaultEventHandler(Event*) OVERRIDE; }; // ---------------------------- -class MediaControlPanelVolumeSliderElement FINAL : public MediaControlVolumeSliderElement { +class MediaControlVolumeSliderElement FINAL : public MediaControlInputElement { public: - static PassRefPtr<MediaControlPanelVolumeSliderElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlVolumeSliderElement> create(MediaControls&); + + virtual bool willRespondToMouseMoveEvents() OVERRIDE; + virtual bool willRespondToMouseClickEvents() OVERRIDE; + void setVolume(double); private: - explicit MediaControlPanelVolumeSliderElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit MediaControlVolumeSliderElement(MediaControls&); + + virtual const AtomicString& shadowPseudoId() const OVERRIDE; + virtual void defaultEventHandler(Event*) OVERRIDE; }; // ---------------------------- class MediaControlTimeRemainingDisplayElement FINAL : public MediaControlTimeDisplayElement { public: - static PassRefPtr<MediaControlTimeRemainingDisplayElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> create(MediaControls&); private: - explicit MediaControlTimeRemainingDisplayElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit MediaControlTimeRemainingDisplayElement(MediaControls&); + virtual const AtomicString& shadowPseudoId() const OVERRIDE; }; // ---------------------------- class MediaControlCurrentTimeDisplayElement FINAL : public MediaControlTimeDisplayElement { public: - static PassRefPtr<MediaControlCurrentTimeDisplayElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> create(MediaControls&); private: - explicit MediaControlCurrentTimeDisplayElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit MediaControlCurrentTimeDisplayElement(MediaControls&); + virtual const AtomicString& shadowPseudoId() const OVERRIDE; }; // ---------------------------- class MediaControlTextTrackContainerElement FINAL : public MediaControlDivElement { public: - static PassRefPtr<MediaControlTextTrackContainerElement> create(Document&); + static PassRefPtrWillBeRawPtr<MediaControlTextTrackContainerElement> create(MediaControls&); void updateDisplay(); - void updateSizes(bool forceUpdate = false); + void updateSizes(); static const AtomicString& textTrackContainerElementShadowPseudoId(); private: - explicit MediaControlTextTrackContainerElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit MediaControlTextTrackContainerElement(MediaControls&); + virtual const AtomicString& shadowPseudoId() const OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; IntRect m_videoDisplaySize; float m_fontSize; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp index 0e2fa811fba..a82cf61a972 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp @@ -28,118 +28,162 @@ #include "core/html/shadow/MediaControls.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/events/MouseEvent.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLMediaElement.h" +#include "core/html/MediaController.h" +#include "core/rendering/RenderTheme.h" namespace WebCore { -static const double timeWithoutMouseMovementBeforeHidingFullscreenControls = 3; - -MediaControls::MediaControls(Document& document) - : HTMLDivElement(document) - , m_mediaController(0) - , m_panel(0) - , m_textDisplayContainer(0) - , m_playButton(0) - , m_currentTimeDisplay(0) - , m_timeline(0) - , m_panelMuteButton(0) - , m_volumeSlider(0) - , m_toggleClosedCaptionsButton(0) - , m_fullScreenButton(0) - , m_hideFullscreenControlsTimer(this, &MediaControls::hideFullscreenControlsTimerFired) - , m_isFullscreen(false) +// If you change this value, then also update the corresponding value in +// LayoutTests/media/media-controls.js. +static const double timeWithoutMouseMovementBeforeHidingMediaControls = 3; + +MediaControls::MediaControls(HTMLMediaElement& mediaElement) + : HTMLDivElement(mediaElement.document()) + , m_mediaElement(&mediaElement) + , m_panel(nullptr) + , m_textDisplayContainer(nullptr) + , m_overlayPlayButton(nullptr) + , m_overlayEnclosure(nullptr) + , m_playButton(nullptr) + , m_currentTimeDisplay(nullptr) + , m_timeline(nullptr) + , m_muteButton(nullptr) + , m_volumeSlider(nullptr) + , m_toggleClosedCaptionsButton(nullptr) + , m_fullScreenButton(nullptr) + , m_durationDisplay(nullptr) + , m_enclosure(nullptr) + , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired) , m_isMouseOverControls(false) + , m_isPausedForScrubbing(false) { } -void MediaControls::setMediaController(MediaControllerInterface* controller) +PassRefPtrWillBeRawPtr<MediaControls> MediaControls::create(HTMLMediaElement& mediaElement) { - if (m_mediaController == controller) - return; - m_mediaController = controller; + RefPtrWillBeRawPtr<MediaControls> controls = adoptRefWillBeNoop(new MediaControls(mediaElement)); - if (m_panel) - m_panel->setMediaController(controller); - if (m_textDisplayContainer) - m_textDisplayContainer->setMediaController(controller); - if (m_playButton) - m_playButton->setMediaController(controller); - if (m_currentTimeDisplay) - m_currentTimeDisplay->setMediaController(controller); - if (m_timeline) - m_timeline->setMediaController(controller); - if (m_panelMuteButton) - m_panelMuteButton->setMediaController(controller); - if (m_volumeSlider) - m_volumeSlider->setMediaController(controller); - if (m_toggleClosedCaptionsButton) - m_toggleClosedCaptionsButton->setMediaController(controller); - if (m_fullScreenButton) - m_fullScreenButton->setMediaController(controller); + if (controls->initializeControls()) + return controls.release(); + + return nullptr; } -void MediaControls::reset() +bool MediaControls::initializeControls() { - Page* page = document().page(); - if (!page) - return; + TrackExceptionState exceptionState; - m_playButton->updateDisplayType(); + if (document().settings() && document().settings()->mediaControlsOverlayPlayButtonEnabled()) { + RefPtrWillBeRawPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = MediaControlOverlayEnclosureElement::create(*this); + RefPtrWillBeRawPtr<MediaControlOverlayPlayButtonElement> overlayPlayButton = MediaControlOverlayPlayButtonElement::create(*this); + m_overlayPlayButton = overlayPlayButton.get(); + overlayEnclosure->appendChild(overlayPlayButton.release(), exceptionState); + if (exceptionState.hadException()) + return false; - updateCurrentTimeDisplay(); - - double duration = m_mediaController->duration(); - if (std::isfinite(duration) || RenderTheme::theme().hasOwnDisabledStateHandlingFor(MediaSliderPart)) { - m_timeline->setDuration(duration); - m_timeline->setPosition(m_mediaController->currentTime()); + m_overlayEnclosure = overlayEnclosure.get(); + appendChild(overlayEnclosure.release(), exceptionState); + if (exceptionState.hadException()) + return false; } - if (m_mediaController->hasAudio() || RenderTheme::theme().hasOwnDisabledStateHandlingFor(MediaMuteButtonPart)) - m_panelMuteButton->show(); - else - m_panelMuteButton->hide(); - - if (m_volumeSlider) { - if (!m_mediaController->hasAudio()) - m_volumeSlider->hide(); - else { - m_volumeSlider->show(); - m_volumeSlider->setVolume(m_mediaController->volume()); - } - } + // Create an enclosing element for the panel so we can visually offset the controls correctly. + RefPtrWillBeRawPtr<MediaControlPanelEnclosureElement> enclosure = MediaControlPanelEnclosureElement::create(*this); - refreshClosedCaptionsButtonVisibility(); + RefPtrWillBeRawPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(*this); - if (m_fullScreenButton) { - if (m_mediaController->supportsFullscreen() && m_mediaController->hasVideo()) - m_fullScreenButton->show(); - else - m_fullScreenButton->hide(); - } + RefPtrWillBeRawPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(*this); + m_playButton = playButton.get(); + panel->appendChild(playButton.release(), exceptionState); + if (exceptionState.hadException()) + return false; - makeOpaque(); + RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(*this); + m_timeline = timeline.get(); + panel->appendChild(timeline.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(*this); + m_currentTimeDisplay = currentTimeDisplay.get(); + m_currentTimeDisplay->hide(); + panel->appendChild(currentTimeDisplay.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + RefPtrWillBeRawPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(*this); + m_durationDisplay = durationDisplay.get(); + panel->appendChild(durationDisplay.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + RefPtrWillBeRawPtr<MediaControlMuteButtonElement> muteButton = MediaControlMuteButtonElement::create(*this); + m_muteButton = muteButton.get(); + panel->appendChild(muteButton.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + RefPtrWillBeRawPtr<MediaControlVolumeSliderElement> slider = MediaControlVolumeSliderElement::create(*this); + m_volumeSlider = slider.get(); + panel->appendChild(slider.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + RefPtrWillBeRawPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(*this); + m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); + panel->appendChild(toggleClosedCaptionsButton.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + RefPtrWillBeRawPtr<MediaControlFullscreenButtonElement> fullscreenButton = MediaControlFullscreenButtonElement::create(*this); + m_fullScreenButton = fullscreenButton.get(); + panel->appendChild(fullscreenButton.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + m_panel = panel.get(); + enclosure->appendChild(panel.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + m_enclosure = enclosure.get(); + appendChild(enclosure.release(), exceptionState); + if (exceptionState.hadException()) + return false; + + return true; } -void MediaControls::reportedError() +void MediaControls::reset() { - Page* page = document().page(); - if (!page) - return; + double duration = mediaElement().duration(); + m_durationDisplay->setInnerText(RenderTheme::theme().formatMediaControlsTime(duration), ASSERT_NO_EXCEPTION); + m_durationDisplay->setCurrentValue(duration); + + updatePlayState(); + + updateCurrentTimeDisplay(); - if (!RenderTheme::theme().hasOwnDisabledStateHandlingFor(MediaMuteButtonPart)) { - m_panelMuteButton->hide(); + m_timeline->setDuration(duration); + m_timeline->setPosition(mediaElement().currentTime()); + + if (!mediaElement().hasAudio()) m_volumeSlider->hide(); - } + else + m_volumeSlider->show(); + updateVolume(); - if (m_toggleClosedCaptionsButton && !RenderTheme::theme().hasOwnDisabledStateHandlingFor(MediaToggleClosedCaptionsButtonPart)) - m_toggleClosedCaptionsButton->hide(); + refreshClosedCaptionsButtonVisibility(); - if (m_fullScreenButton && !RenderTheme::theme().hasOwnDisabledStateHandlingFor(MediaEnterFullscreenButtonPart)) + if (mediaElement().hasVideo()) + m_fullScreenButton->show(); + else m_fullScreenButton->hide(); -} -void MediaControls::loadedMetadata() -{ - reset(); + makeOpaque(); } void MediaControls::show() @@ -149,6 +193,12 @@ void MediaControls::show() m_panel->show(); } +void MediaControls::mediaElementFocused() +{ + show(); + stopHideMediaControlsTimer(); +} + void MediaControls::hide() { m_panel->setIsDisplayed(false); @@ -165,81 +215,118 @@ void MediaControls::makeTransparent() m_panel->makeTransparent(); } -bool MediaControls::shouldHideControls() +bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const { - return !m_panel->hovered(); -} - -void MediaControls::bufferingProgressed() -{ - // We only need to update buffering progress when paused, during normal - // playback playbackProgressed() will take care of it. - if (m_mediaController->paused()) - m_timeline->setPosition(m_mediaController->currentTime()); + // Never hide for a media element without visual representation. + if (!mediaElement().hasVideo()) + return false; + // Don't hide if the controls are hovered or the mouse is over the video area. + const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover; + if (m_panel->hovered() || (!ignoreVideoHover && m_isMouseOverControls)) + return false; + // Don't hide if focus is on the HTMLMediaElement or within the + // controls/shadow tree. (Perform the checks separately to avoid going + // through all the potential ancestor hosts for the focused element.) + const bool ignoreFocus = behaviorFlags & IgnoreFocus; + if (!ignoreFocus && (mediaElement().focused() || contains(document().focusedElement()))) + return false; + return true; } void MediaControls::playbackStarted() { - m_playButton->updateDisplayType(); - m_timeline->setPosition(m_mediaController->currentTime()); + m_currentTimeDisplay->show(); + m_durationDisplay->hide(); + + updatePlayState(); + m_timeline->setPosition(mediaElement().currentTime()); updateCurrentTimeDisplay(); - if (m_isFullscreen) - startHideFullscreenControlsTimer(); + startHideMediaControlsTimer(); } void MediaControls::playbackProgressed() { - m_timeline->setPosition(m_mediaController->currentTime()); + m_timeline->setPosition(mediaElement().currentTime()); updateCurrentTimeDisplay(); - if (!m_isMouseOverControls && m_mediaController->hasVideo()) + if (shouldHideMediaControls()) makeTransparent(); } void MediaControls::playbackStopped() { - m_playButton->updateDisplayType(); - m_timeline->setPosition(m_mediaController->currentTime()); + updatePlayState(); + m_timeline->setPosition(mediaElement().currentTime()); updateCurrentTimeDisplay(); makeOpaque(); - stopHideFullscreenControlsTimer(); + stopHideMediaControlsTimer(); } -void MediaControls::showVolumeSlider() +void MediaControls::updatePlayState() { - if (!m_mediaController->hasAudio()) + if (m_isPausedForScrubbing) return; - m_volumeSlider->show(); + if (m_overlayPlayButton) + m_overlayPlayButton->updateDisplayType(); + m_playButton->updateDisplayType(); } -void MediaControls::changedMute() +void MediaControls::beginScrubbing() { - m_panelMuteButton->changedMute(); + if (!mediaElement().togglePlayStateWillPlay()) { + m_isPausedForScrubbing = true; + mediaElement().togglePlayState(); + } } -void MediaControls::changedVolume() +void MediaControls::endScrubbing() { - if (m_volumeSlider) - m_volumeSlider->setVolume(m_mediaController->volume()); - if (m_panelMuteButton && m_panelMuteButton->renderer()) - m_panelMuteButton->renderer()->repaint(); + if (m_isPausedForScrubbing) { + m_isPausedForScrubbing = false; + if (mediaElement().togglePlayStateWillPlay()) + mediaElement().togglePlayState(); + } +} + +void MediaControls::updateCurrentTimeDisplay() +{ + double now = mediaElement().currentTime(); + double duration = mediaElement().duration(); + + // After seek, hide duration display and show current time. + if (now > 0) { + m_currentTimeDisplay->show(); + m_durationDisplay->hide(); + } + + // Allow the theme to format the time. + m_currentTimeDisplay->setInnerText(RenderTheme::theme().formatMediaControlsCurrentTime(now, duration), IGNORE_EXCEPTION); + m_currentTimeDisplay->setCurrentValue(now); +} + +void MediaControls::updateVolume() +{ + m_muteButton->updateDisplayType(); + if (m_muteButton->renderer()) + m_muteButton->renderer()->paintInvalidationForWholeRenderer(); + + if (mediaElement().muted()) + m_volumeSlider->setVolume(0); + else + m_volumeSlider->setVolume(mediaElement().volume()); } void MediaControls::changedClosedCaptionsVisibility() { - if (m_toggleClosedCaptionsButton) - m_toggleClosedCaptionsButton->updateDisplayType(); + m_toggleClosedCaptionsButton->updateDisplayType(); } void MediaControls::refreshClosedCaptionsButtonVisibility() { - if (!m_toggleClosedCaptionsButton) - return; - - if (m_mediaController->hasClosedCaptions()) + if (mediaElement().hasClosedCaptions()) m_toggleClosedCaptionsButton->show(); else m_toggleClosedCaptionsButton->hide(); @@ -252,16 +339,16 @@ void MediaControls::closedCaptionTracksChanged() void MediaControls::enteredFullscreen() { - m_isFullscreen = true; m_fullScreenButton->setIsFullscreen(true); - startHideFullscreenControlsTimer(); + stopHideMediaControlsTimer(); + startHideMediaControlsTimer(); } void MediaControls::exitedFullscreen() { - m_isFullscreen = false; m_fullScreenButton->setIsFullscreen(false); - stopHideFullscreenControlsTimer(); + stopHideMediaControlsTimer(); + startHideMediaControlsTimer(); } void MediaControls::defaultEventHandler(Event* event) @@ -271,10 +358,10 @@ void MediaControls::defaultEventHandler(Event* event) if (event->type() == EventTypeNames::mouseover) { if (!containsRelatedTarget(event)) { m_isMouseOverControls = true; - if (!m_mediaController->canPlay()) { + if (!mediaElement().togglePlayStateWillPlay()) { makeOpaque(); - if (shouldHideControls()) - startHideFullscreenControlsTimer(); + if (shouldHideMediaControls()) + startHideMediaControlsTimer(); } } return; @@ -283,55 +370,43 @@ void MediaControls::defaultEventHandler(Event* event) if (event->type() == EventTypeNames::mouseout) { if (!containsRelatedTarget(event)) { m_isMouseOverControls = false; - stopHideFullscreenControlsTimer(); + stopHideMediaControlsTimer(); } return; } if (event->type() == EventTypeNames::mousemove) { - if (m_isFullscreen) { - // When we get a mouse move in fullscreen mode, show the media controls, and start a timer - // that will hide the media controls after a 3 seconds without a mouse move. - makeOpaque(); - if (shouldHideControls()) - startHideFullscreenControlsTimer(); - } + // When we get a mouse move, show the media controls, and start a timer + // that will hide the media controls after a 3 seconds without a mouse move. + makeOpaque(); + if (shouldHideMediaControls(IgnoreVideoHover)) + startHideMediaControlsTimer(); return; } } -void MediaControls::hideFullscreenControlsTimerFired(Timer<MediaControls>*) +void MediaControls::hideMediaControlsTimerFired(Timer<MediaControls>*) { - if (m_mediaController->paused()) + if (mediaElement().togglePlayStateWillPlay()) return; - if (!m_isFullscreen) - return; - - if (!shouldHideControls()) + if (!shouldHideMediaControls(IgnoreFocus | IgnoreVideoHover)) return; makeTransparent(); } -void MediaControls::startHideFullscreenControlsTimer() +void MediaControls::startHideMediaControlsTimer() { - if (!m_isFullscreen) - return; - - Page* page = document().page(); - if (!page) - return; - - m_hideFullscreenControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingFullscreenControls); + m_hideMediaControlsTimer.startOneShot(timeWithoutMouseMovementBeforeHidingMediaControls, FROM_HERE); } -void MediaControls::stopHideFullscreenControlsTimer() +void MediaControls::stopHideMediaControlsTimer() { - m_hideFullscreenControlsTimer.stop(); + m_hideMediaControlsTimer.stop(); } -const AtomicString& MediaControls::pseudo() const +const AtomicString& MediaControls::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls")); return id; @@ -352,14 +427,14 @@ void MediaControls::createTextTrackDisplay() if (m_textDisplayContainer) return; - RefPtr<MediaControlTextTrackContainerElement> textDisplayContainer = MediaControlTextTrackContainerElement::create(document()); + RefPtrWillBeRawPtr<MediaControlTextTrackContainerElement> textDisplayContainer = MediaControlTextTrackContainerElement::create(*this); m_textDisplayContainer = textDisplayContainer.get(); - if (m_mediaController) - m_textDisplayContainer->setMediaController(m_mediaController); - - // Insert it before the first controller element so it always displays behind the controls. - insertBefore(textDisplayContainer.release(), m_panel, IGNORE_EXCEPTION); + // Insert it before (behind) all other control elements. + if (m_overlayEnclosure && m_overlayPlayButton) + m_overlayEnclosure->insertBefore(textDisplayContainer.release(), m_overlayPlayButton); + else + insertBefore(textDisplayContainer.release(), m_enclosure); } void MediaControls::showTextTrackDisplay() @@ -384,4 +459,23 @@ void MediaControls::updateTextTrackDisplay() m_textDisplayContainer->updateDisplay(); } +void MediaControls::trace(Visitor* visitor) +{ + visitor->trace(m_mediaElement); + visitor->trace(m_panel); + visitor->trace(m_textDisplayContainer); + visitor->trace(m_overlayPlayButton); + visitor->trace(m_overlayEnclosure); + visitor->trace(m_playButton); + visitor->trace(m_currentTimeDisplay); + visitor->trace(m_timeline); + visitor->trace(m_muteButton); + visitor->trace(m_volumeSlider); + visitor->trace(m_toggleClosedCaptionsButton); + visitor->trace(m_fullScreenButton); + visitor->trace(m_durationDisplay); + visitor->trace(m_enclosure); + HTMLDivElement::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.h b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.h index ea87254a8e2..7879662b3cb 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControls.h @@ -27,106 +27,109 @@ #ifndef MediaControls_h #define MediaControls_h -#include "core/events/MouseEvent.h" #include "core/html/HTMLDivElement.h" #include "core/html/shadow/MediaControlElements.h" -#include "core/rendering/RenderTheme.h" namespace WebCore { class Document; class Event; -class MediaPlayer; -class RenderBox; -class RenderMedia; +class MediaControls FINAL : public HTMLDivElement { +public: + static PassRefPtrWillBeRawPtr<MediaControls> create(HTMLMediaElement&); -// An abstract class with the media control elements that all ports support. -class MediaControls : public HTMLDivElement { - public: - virtual ~MediaControls() {} + HTMLMediaElement& mediaElement() const { return *m_mediaElement; } - // This function is to be implemented in your port-specific media - // controls implementation since it will return a child instance. - static PassRefPtr<MediaControls> create(Document&); + void reset(); - virtual void setMediaController(MediaControllerInterface*); + void show(); + void hide(); - virtual void reset(); - virtual void reportedError(); - virtual void loadedMetadata(); + void playbackStarted(); + void playbackProgressed(); + void playbackStopped(); - virtual void show(); - virtual void hide(); - virtual void makeOpaque(); - virtual void makeTransparent(); - virtual bool shouldHideControls(); + void beginScrubbing(); + void endScrubbing(); - virtual void bufferingProgressed(); - virtual void playbackStarted(); - virtual void playbackProgressed(); - virtual void playbackStopped(); + void updateCurrentTimeDisplay(); - virtual void updateStatusDisplay() { }; - virtual void updateCurrentTimeDisplay() = 0; - virtual void showVolumeSlider(); + void updateVolume(); - virtual void changedMute(); - virtual void changedVolume(); + void changedClosedCaptionsVisibility(); + void refreshClosedCaptionsButtonVisibility(); + void closedCaptionTracksChanged(); - virtual void changedClosedCaptionsVisibility(); - virtual void refreshClosedCaptionsButtonVisibility(); - virtual void closedCaptionTracksChanged(); + void enteredFullscreen(); + void exitedFullscreen(); - virtual void enteredFullscreen(); - virtual void exitedFullscreen(); + void updateTextTrackDisplay(); - virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; } + void mediaElementFocused(); + + virtual void trace(Visitor*) OVERRIDE; + +private: + explicit MediaControls(HTMLMediaElement&); + + bool initializeControls(); - virtual void hideFullscreenControlsTimerFired(Timer<MediaControls>*); - virtual void startHideFullscreenControlsTimer(); - virtual void stopHideFullscreenControlsTimer(); + void makeOpaque(); + void makeTransparent(); - virtual void createTextTrackDisplay(); - virtual void showTextTrackDisplay(); - virtual void hideTextTrackDisplay(); - virtual void updateTextTrackDisplay(); + void updatePlayState(); -protected: - explicit MediaControls(Document&); + enum HideBehaviorFlags { + IgnoreVideoHover = 1 << 0, + IgnoreFocus = 1 << 1 + }; - virtual void defaultEventHandler(Event*); + bool shouldHideMediaControls(unsigned behaviorFlags = 0) const; + void hideMediaControlsTimerFired(Timer<MediaControls>*); + void startHideMediaControlsTimer(); + void stopHideMediaControlsTimer(); - virtual bool containsRelatedTarget(Event*); + void createTextTrackDisplay(); + void showTextTrackDisplay(); + void hideTextTrackDisplay(); - MediaControllerInterface* m_mediaController; + // Node + virtual bool isMediaControls() const OVERRIDE { return true; } + virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; } + virtual void defaultEventHandler(Event*) OVERRIDE; + bool containsRelatedTarget(Event*); + + // Element + virtual const AtomicString& shadowPseudoId() const OVERRIDE; + + RawPtrWillBeMember<HTMLMediaElement> m_mediaElement; // Container for the media control elements. - MediaControlPanelElement* m_panel; + RawPtrWillBeMember<MediaControlPanelElement> m_panel; // Container for the text track cues. - MediaControlTextTrackContainerElement* m_textDisplayContainer; + RawPtrWillBeMember<MediaControlTextTrackContainerElement> m_textDisplayContainer; // Media control elements. - MediaControlPlayButtonElement* m_playButton; - MediaControlCurrentTimeDisplayElement* m_currentTimeDisplay; - MediaControlTimelineElement* m_timeline; - MediaControlPanelMuteButtonElement* m_panelMuteButton; - MediaControlPanelVolumeSliderElement* m_volumeSlider; - MediaControlToggleClosedCaptionsButtonElement* m_toggleClosedCaptionsButton; - MediaControlFullscreenButtonElement* m_fullScreenButton; - - Timer<MediaControls> m_hideFullscreenControlsTimer; - bool m_isFullscreen; - bool m_isMouseOverControls; - -private: - virtual bool isMediaControls() const { return true; } - - virtual const AtomicString& pseudo() const; + RawPtrWillBeMember<MediaControlOverlayPlayButtonElement> m_overlayPlayButton; + RawPtrWillBeMember<MediaControlOverlayEnclosureElement> m_overlayEnclosure; + RawPtrWillBeMember<MediaControlPlayButtonElement> m_playButton; + RawPtrWillBeMember<MediaControlCurrentTimeDisplayElement> m_currentTimeDisplay; + RawPtrWillBeMember<MediaControlTimelineElement> m_timeline; + RawPtrWillBeMember<MediaControlMuteButtonElement> m_muteButton; + RawPtrWillBeMember<MediaControlVolumeSliderElement> m_volumeSlider; + RawPtrWillBeMember<MediaControlToggleClosedCaptionsButtonElement> m_toggleClosedCaptionsButton; + RawPtrWillBeMember<MediaControlFullscreenButtonElement> m_fullScreenButton; + RawPtrWillBeMember<MediaControlTimeRemainingDisplayElement> m_durationDisplay; + RawPtrWillBeMember<MediaControlPanelEnclosureElement> m_enclosure; + + Timer<MediaControls> m_hideMediaControlsTimer; + bool m_isMouseOverControls : 1; + bool m_isPausedForScrubbing : 1; }; -DEFINE_NODE_TYPE_CASTS(MediaControls, isMediaControls()); +DEFINE_ELEMENT_TYPE_CASTS(MediaControls, isMediaControls()); } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromium.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromium.cpp deleted file mode 100644 index d1d4ccbfd40..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromium.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2011, 2012 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 "core/html/shadow/MediaControlsChromium.h" - -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ExceptionStatePlaceholder.h" - -using namespace std; - -namespace WebCore { - -MediaControlsChromium::MediaControlsChromium(Document& document) - : MediaControls(document) - , m_durationDisplay(0) - , m_enclosure(0) -{ -} - -// MediaControls::create() for Android is defined in MediaControlsChromiumAndroid.cpp. -#if !OS(ANDROID) -PassRefPtr<MediaControls> MediaControls::create(Document& document) -{ - return MediaControlsChromium::createControls(document); -} -#endif - -PassRefPtr<MediaControlsChromium> MediaControlsChromium::createControls(Document& document) -{ - if (!document.page()) - return 0; - - RefPtr<MediaControlsChromium> controls = adoptRef(new MediaControlsChromium(document)); - - if (controls->initializeControls(document)) - return controls.release(); - - return 0; -} - -bool MediaControlsChromium::initializeControls(Document& document) -{ - // Create an enclosing element for the panel so we can visually offset the controls correctly. - RefPtr<MediaControlPanelEnclosureElement> enclosure = MediaControlPanelEnclosureElement::create(document); - - RefPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(document); - - TrackExceptionState exceptionState; - - RefPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(document); - m_playButton = playButton.get(); - panel->appendChild(playButton.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - RefPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(document, this); - m_timeline = timeline.get(); - panel->appendChild(timeline.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - RefPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(document); - m_currentTimeDisplay = currentTimeDisplay.get(); - m_currentTimeDisplay->hide(); - panel->appendChild(currentTimeDisplay.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - RefPtr<MediaControlTimeRemainingDisplayElement> durationDisplay = MediaControlTimeRemainingDisplayElement::create(document); - m_durationDisplay = durationDisplay.get(); - panel->appendChild(durationDisplay.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - RefPtr<MediaControlPanelMuteButtonElement> panelMuteButton = MediaControlPanelMuteButtonElement::create(document, this); - m_panelMuteButton = panelMuteButton.get(); - panel->appendChild(panelMuteButton.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - RefPtr<MediaControlPanelVolumeSliderElement> slider = MediaControlPanelVolumeSliderElement::create(document); - m_volumeSlider = slider.get(); - m_volumeSlider->setClearMutedOnUserInteraction(true); - panel->appendChild(slider.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - if (RenderTheme::theme().supportsClosedCaptioning()) { - RefPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(document, this); - m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get(); - panel->appendChild(toggleClosedCaptionsButton.release(), exceptionState); - if (exceptionState.hadException()) - return false; - } - - RefPtr<MediaControlFullscreenButtonElement> fullscreenButton = MediaControlFullscreenButtonElement::create(document); - m_fullScreenButton = fullscreenButton.get(); - panel->appendChild(fullscreenButton.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - m_panel = panel.get(); - enclosure->appendChild(panel.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - m_enclosure = enclosure.get(); - appendChild(enclosure.release(), exceptionState); - if (exceptionState.hadException()) - return false; - - return true; -} - -void MediaControlsChromium::setMediaController(MediaControllerInterface* controller) -{ - if (m_mediaController == controller) - return; - - MediaControls::setMediaController(controller); - - if (m_durationDisplay) - m_durationDisplay->setMediaController(controller); - if (m_enclosure) - m_enclosure->setMediaController(controller); -} - -void MediaControlsChromium::reset() -{ - Page* page = document().page(); - if (!page) - return; - - double duration = m_mediaController->duration(); - m_durationDisplay->setInnerText(RenderTheme::theme().formatMediaControlsTime(duration), ASSERT_NO_EXCEPTION); - m_durationDisplay->setCurrentValue(duration); - - MediaControls::reset(); -} - -void MediaControlsChromium::playbackStarted() -{ - m_currentTimeDisplay->show(); - m_durationDisplay->hide(); - - MediaControls::playbackStarted(); -} - -void MediaControlsChromium::updateCurrentTimeDisplay() -{ - double now = m_mediaController->currentTime(); - double duration = m_mediaController->duration(); - - Page* page = document().page(); - if (!page) - return; - - // After seek, hide duration display and show current time. - if (now > 0) { - m_currentTimeDisplay->show(); - m_durationDisplay->hide(); - } - - // Allow the theme to format the time. - m_currentTimeDisplay->setInnerText(RenderTheme::theme().formatMediaControlsCurrentTime(now, duration), IGNORE_EXCEPTION); - m_currentTimeDisplay->setCurrentValue(now); -} - -void MediaControlsChromium::changedMute() -{ - MediaControls::changedMute(); - - if (m_mediaController->muted()) - m_volumeSlider->setVolume(0); - else - m_volumeSlider->setVolume(m_mediaController->volume()); -} - -void MediaControlsChromium::createTextTrackDisplay() -{ - if (m_textDisplayContainer) - return; - - RefPtr<MediaControlTextTrackContainerElement> textDisplayContainer = MediaControlTextTrackContainerElement::create(document()); - m_textDisplayContainer = textDisplayContainer.get(); - - if (m_mediaController) - m_textDisplayContainer->setMediaController(m_mediaController); - - insertTextTrackContainer(textDisplayContainer.release()); -} - -void MediaControlsChromium::insertTextTrackContainer(PassRefPtr<MediaControlTextTrackContainerElement> textTrackContainer) -{ - // Insert it before the first controller element so it always displays behind the controls. - // In the Chromium case, that's the enclosure element. - insertBefore(textTrackContainer, m_enclosure); -} - - -} diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromium.h b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromium.h deleted file mode 100644 index 5e3c55e8512..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromium.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2011, 2012 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 MediaControlsChromium_h -#define MediaControlsChromium_h - -#include "core/html/shadow/MediaControls.h" - -namespace WebCore { - -class MediaControlsChromium : public MediaControls { -public: - // Called from port-specific parent create function to create custom controls. - static PassRefPtr<MediaControlsChromium> createControls(Document&); - - virtual void setMediaController(MediaControllerInterface*) OVERRIDE; - - virtual void reset() OVERRIDE; - - virtual void playbackStarted() OVERRIDE; - - void changedMute() OVERRIDE; - - virtual void updateCurrentTimeDisplay() OVERRIDE; - - void createTextTrackDisplay() OVERRIDE; - - virtual void insertTextTrackContainer(PassRefPtr<MediaControlTextTrackContainerElement>); - -protected: - explicit MediaControlsChromium(Document&); - - bool initializeControls(Document&); - -private: - MediaControlTimeRemainingDisplayElement* m_durationDisplay; - MediaControlPanelEnclosureElement* m_enclosure; -}; - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromiumAndroid.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromiumAndroid.cpp deleted file mode 100644 index f81c9309b37..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromiumAndroid.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2012 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 "core/html/shadow/MediaControlsChromiumAndroid.h" - -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ExceptionStatePlaceholder.h" - -namespace WebCore { - -MediaControlsChromiumAndroid::MediaControlsChromiumAndroid(Document& document) - : MediaControlsChromium(document) - , m_overlayPlayButton(0) - , m_overlayEnclosure(0) -{ -} - -PassRefPtr<MediaControls> MediaControls::create(Document& document) -{ - return MediaControlsChromiumAndroid::createControls(document); -} - -PassRefPtr<MediaControlsChromiumAndroid> MediaControlsChromiumAndroid::createControls(Document& document) -{ - if (!document.page()) - return 0; - - RefPtr<MediaControlsChromiumAndroid> controls = adoptRef(new MediaControlsChromiumAndroid(document)); - - TrackExceptionState exceptionState; - - RefPtr<MediaControlOverlayEnclosureElement> overlayEnclosure = MediaControlOverlayEnclosureElement::create(document); - RefPtr<MediaControlOverlayPlayButtonElement> overlayPlayButton = MediaControlOverlayPlayButtonElement::create(document); - controls->m_overlayPlayButton = overlayPlayButton.get(); - overlayEnclosure->appendChild(overlayPlayButton.release(), exceptionState); - if (exceptionState.hadException()) - return 0; - - controls->m_overlayEnclosure = overlayEnclosure.get(); - controls->appendChild(overlayEnclosure.release(), exceptionState); - if (exceptionState.hadException()) - return 0; - - if (controls->initializeControls(document)) - return controls.release(); - - return 0; -} - -void MediaControlsChromiumAndroid::setMediaController(MediaControllerInterface* controller) -{ - if (m_overlayPlayButton) - m_overlayPlayButton->setMediaController(controller); - if (m_overlayEnclosure) - m_overlayEnclosure->setMediaController(controller); - MediaControlsChromium::setMediaController(controller); -} - -void MediaControlsChromiumAndroid::playbackStarted() -{ - m_overlayPlayButton->updateDisplayType(); - MediaControlsChromium::playbackStarted(); -} - -void MediaControlsChromiumAndroid::playbackStopped() -{ - m_overlayPlayButton->updateDisplayType(); - MediaControlsChromium::playbackStopped(); -} - -void MediaControlsChromiumAndroid::insertTextTrackContainer(PassRefPtr<MediaControlTextTrackContainerElement> textTrackContainer) -{ - // Insert it before the overlay play button so it always displays behind it. - m_overlayEnclosure->insertBefore(textTrackContainer, m_overlayPlayButton); -} -} diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromiumAndroid.h b/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromiumAndroid.h deleted file mode 100644 index 8b8a90069f4..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MediaControlsChromiumAndroid.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 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 MediaControlsChromiumAndroid_h -#define MediaControlsChromiumAndroid_h - -#include "core/html/shadow/MediaControls.h" -#include "core/html/shadow/MediaControlsChromium.h" - -namespace WebCore { - -class MediaControlsChromiumAndroid : public MediaControlsChromium { -public: - static PassRefPtr<MediaControlsChromiumAndroid> createControls(Document&); - - virtual void setMediaController(MediaControllerInterface*) OVERRIDE; - virtual void playbackStarted() OVERRIDE; - virtual void playbackStopped() OVERRIDE; - virtual bool shouldHideControls() OVERRIDE { return true; } - - void insertTextTrackContainer(PassRefPtr<MediaControlTextTrackContainerElement>) OVERRIDE; - -private: - explicit MediaControlsChromiumAndroid(Document&); - - MediaControlOverlayPlayButtonElement* m_overlayPlayButton; - MediaControlOverlayEnclosureElement* m_overlayEnclosure; -}; - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.cpp index a39c29cdb71..8f8f0cc4671 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.cpp @@ -32,8 +32,8 @@ #include "core/html/shadow/MeterShadowElement.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLMeterElement.h" #include "core/rendering/RenderMeter.h" #include "core/rendering/RenderTheme.h" @@ -63,10 +63,10 @@ inline MeterInnerElement::MeterInnerElement(Document& document) { } -PassRefPtr<MeterInnerElement> MeterInnerElement::create(Document& document) +PassRefPtrWillBeRawPtr<MeterInnerElement> MeterInnerElement::create(Document& document) { - RefPtr<MeterInnerElement> element = adoptRef(new MeterInnerElement(document)); - element->setPseudo(AtomicString("-webkit-meter-inner-element", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<MeterInnerElement> element = adoptRefWillBeNoop(new MeterInnerElement(document)); + element->setShadowPseudoId(AtomicString("-webkit-meter-inner-element", AtomicString::ConstructFromLiteral)); return element.release(); } @@ -89,10 +89,10 @@ inline MeterBarElement::MeterBarElement(Document& document) { } -PassRefPtr<MeterBarElement> MeterBarElement::create(Document& document) +PassRefPtrWillBeRawPtr<MeterBarElement> MeterBarElement::create(Document& document) { - RefPtr<MeterBarElement> element = adoptRef(new MeterBarElement(document)); - element->setPseudo(AtomicString("-webkit-meter-bar", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<MeterBarElement> element = adoptRefWillBeNoop(new MeterBarElement(document)); + element->setShadowPseudoId(AtomicString("-webkit-meter-bar", AtomicString::ConstructFromLiteral)); return element.release(); } @@ -101,9 +101,9 @@ inline MeterValueElement::MeterValueElement(Document& document) { } -PassRefPtr<MeterValueElement> MeterValueElement::create(Document& document) +PassRefPtrWillBeRawPtr<MeterValueElement> MeterValueElement::create(Document& document) { - RefPtr<MeterValueElement> element = adoptRef(new MeterValueElement(document)); + RefPtrWillBeRawPtr<MeterValueElement> element = adoptRefWillBeNoop(new MeterValueElement(document)); element->updatePseudo(); return element.release(); } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.h index c15bfdcbcb7..22847f7a8f7 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/MeterShadowElement.h @@ -41,39 +41,39 @@ class RenderMeter; class MeterShadowElement : public HTMLDivElement { protected: - MeterShadowElement(Document&); + explicit MeterShadowElement(Document&); HTMLMeterElement* meterElement() const; private: - virtual bool rendererIsNeeded(const RenderStyle&); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; }; class MeterInnerElement FINAL : public MeterShadowElement { public: - static PassRefPtr<MeterInnerElement> create(Document&); + static PassRefPtrWillBeRawPtr<MeterInnerElement> create(Document&); private: - MeterInnerElement(Document&); + explicit MeterInnerElement(Document&); virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; }; class MeterBarElement FINAL : public MeterShadowElement { private: - MeterBarElement(Document&); + explicit MeterBarElement(Document&); public: - static PassRefPtr<MeterBarElement> create(Document&); + static PassRefPtrWillBeRawPtr<MeterBarElement> create(Document&); }; class MeterValueElement FINAL : public MeterShadowElement { public: - static PassRefPtr<MeterValueElement> create(Document&); + static PassRefPtrWillBeRawPtr<MeterValueElement> create(Document&); void setWidthPercentage(double); - void updatePseudo() { setPseudo(valuePseudoId()); } + void updatePseudo() { setShadowPseudoId(valuePseudoId()); } private: - MeterValueElement(Document&); + explicit MeterValueElement(Document&); const AtomicString& valuePseudoId() const; }; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/PasswordGeneratorButtonElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/PasswordGeneratorButtonElement.cpp deleted file mode 100644 index 238c3f41aee..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/PasswordGeneratorButtonElement.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/html/shadow/PasswordGeneratorButtonElement.h" - -#include "core/events/Event.h" -#include "core/dom/NodeRenderStyle.h" -#include "core/fetch/ImageResource.h" -#include "core/html/HTMLInputElement.h" -#include "core/html/shadow/ShadowElementNames.h" -#include "core/page/Chrome.h" -#include "core/page/ChromeClient.h" -#include "core/page/Page.h" -#include "core/rendering/RenderImage.h" -#include "platform/graphics/Image.h" - -namespace WebCore { - -using namespace HTMLNames; - -PasswordGeneratorButtonElement::PasswordGeneratorButtonElement(Document& document) - : HTMLDivElement(document) - , m_isInHoverState(false) -{ - setHasCustomStyleCallbacks(); -} - -PassRefPtr<PasswordGeneratorButtonElement> PasswordGeneratorButtonElement::create(Document& document) -{ - RefPtr<PasswordGeneratorButtonElement> element = adoptRef(new PasswordGeneratorButtonElement(document)); - element->setAttribute(idAttr, ShadowElementNames::passwordGenerator()); - return element.release(); -} - -inline HTMLInputElement* PasswordGeneratorButtonElement::hostInput() -{ - // PasswordGeneratorButtonElement is created only by C++ code, and it is always - // in <input> shadow. - return toHTMLInputElement(shadowHost()); -} - -void PasswordGeneratorButtonElement::updateImage() -{ - if (!renderer() || !renderer()->isImage()) - return; - RenderImageResource* resource = toRenderImage(renderer())->imageResource(); - ImageResource* image = m_isInHoverState ? imageForHoverState() : imageForNormalState(); - ASSERT(image); - resource->setImageResource(image); -} - -PassRefPtr<RenderStyle> PasswordGeneratorButtonElement::customStyleForRenderer() -{ - RefPtr<RenderStyle> originalStyle = originalStyleForRenderer(); - RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get()); - RenderStyle* inputStyle = hostInput()->renderStyle(); - ASSERT(inputStyle); - style->setWidth(Length(inputStyle->fontSize(), Fixed)); - style->setHeight(Length(inputStyle->fontSize(), Fixed)); - style->setUnique(); - updateImage(); - return style.release(); -} - -RenderObject* PasswordGeneratorButtonElement::createRenderer(RenderStyle*) -{ - RenderImage* image = new RenderImage(this); - image->setImageResource(RenderImageResource::create()); - return image; -} - -void PasswordGeneratorButtonElement::attach(const AttachContext& context) -{ - HTMLDivElement::attach(context); - updateImage(); -} - -ImageResource* PasswordGeneratorButtonElement::imageForNormalState() -{ - if (!m_cachedImageForNormalState) { - RefPtr<Image> image = Image::loadPlatformResource("generatePassword"); - m_cachedImageForNormalState = new ImageResource(image.get()); - } - return m_cachedImageForNormalState.get(); -} - -ImageResource* PasswordGeneratorButtonElement::imageForHoverState() -{ - if (!m_cachedImageForHoverState) { - RefPtr<Image> image = Image::loadPlatformResource("generatePasswordHover"); - m_cachedImageForHoverState = new ImageResource(image.get()); - } - return m_cachedImageForHoverState.get(); -} - -void PasswordGeneratorButtonElement::defaultEventHandler(Event* event) -{ - RefPtr<HTMLInputElement> input = hostInput(); - if (!input || input->isDisabledOrReadOnly() || !event->isMouseEvent()) { - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); - return; - } - - RefPtr<PasswordGeneratorButtonElement> protector(this); - if (event->type() == EventTypeNames::click) { - if (Page* page = document().page()) - page->chrome().client().openPasswordGenerator(input.get()); - event->setDefaultHandled(); - } - - if (event->type() == EventTypeNames::mouseover) { - m_isInHoverState = true; - updateImage(); - } - - if (event->type() == EventTypeNames::mouseout) { - m_isInHoverState = false; - updateImage(); - } - - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); -} - -bool PasswordGeneratorButtonElement::willRespondToMouseMoveEvents() -{ - const HTMLInputElement* input = hostInput(); - if (!input->isDisabledOrReadOnly()) - return true; - - return HTMLDivElement::willRespondToMouseMoveEvents(); -} - -bool PasswordGeneratorButtonElement::willRespondToMouseClickEvents() -{ - const HTMLInputElement* input = hostInput(); - if (!input->isDisabledOrReadOnly()) - return true; - - return HTMLDivElement::willRespondToMouseClickEvents(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/PasswordGeneratorButtonElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/PasswordGeneratorButtonElement.h deleted file mode 100644 index 0d220f9c6b1..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/shadow/PasswordGeneratorButtonElement.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PasswordGeneratorButtonElement_h -#define PasswordGeneratorButtonElement_h - -#include "core/fetch/ResourcePtr.h" -#include "core/html/HTMLDivElement.h" - -namespace WebCore { - -class ImageResource; -class HTMLInputElement; -class ShadowRoot; - -class PasswordGeneratorButtonElement FINAL : public HTMLDivElement { -public: - static PassRefPtr<PasswordGeneratorButtonElement> create(Document&); - - void decorate(HTMLInputElement*); - - virtual bool willRespondToMouseMoveEvents() OVERRIDE; - virtual bool willRespondToMouseClickEvents() OVERRIDE; - -private: - PasswordGeneratorButtonElement(Document&); - virtual bool isPasswordGeneratorButtonElement() const OVERRIDE { return true; } - virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE; - virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; - virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; - virtual bool isMouseFocusable() const OVERRIDE { return false; } - virtual void defaultEventHandler(Event*) OVERRIDE; - - ImageResource* imageForNormalState(); - ImageResource* imageForHoverState(); - - HTMLInputElement* hostInput(); - void updateImage(); - - ResourcePtr<ImageResource> m_cachedImageForNormalState; - ResourcePtr<ImageResource> m_cachedImageForHoverState; - bool m_isInHoverState; -}; - -} -#endif diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp index 40aec28a852..1c838a2683a 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.cpp @@ -37,6 +37,7 @@ #include "core/page/Chrome.h" #include "core/page/Page.h" #include "core/rendering/RenderDetailsMarker.h" +#include "wtf/TemporaryChange.h" using namespace WTF::Unicode; @@ -47,21 +48,20 @@ using namespace HTMLNames; inline PickerIndicatorElement::PickerIndicatorElement(Document& document, PickerIndicatorOwner& pickerIndicatorOwner) : HTMLDivElement(document) , m_pickerIndicatorOwner(&pickerIndicatorOwner) + , m_isInOpenPopup(false) { } -PassRefPtr<PickerIndicatorElement> PickerIndicatorElement::create(Document& document, PickerIndicatorOwner& pickerIndicatorOwner) +PassRefPtrWillBeRawPtr<PickerIndicatorElement> PickerIndicatorElement::create(Document& document, PickerIndicatorOwner& pickerIndicatorOwner) { - RefPtr<PickerIndicatorElement> element = adoptRef(new PickerIndicatorElement(document, pickerIndicatorOwner)); - element->setPseudo(AtomicString("-webkit-calendar-picker-indicator", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<PickerIndicatorElement> element = adoptRefWillBeNoop(new PickerIndicatorElement(document, pickerIndicatorOwner)); + element->setShadowPseudoId(AtomicString("-webkit-calendar-picker-indicator", AtomicString::ConstructFromLiteral)); element->setAttribute(idAttr, ShadowElementNames::pickerIndicator()); return element.release(); } PickerIndicatorElement::~PickerIndicatorElement() { - closePopup(); - ASSERT(!m_chooser); } RenderObject* PickerIndicatorElement::createRenderer(RenderStyle*) @@ -113,6 +113,12 @@ void PickerIndicatorElement::didEndChooser() void PickerIndicatorElement::openPopup() { + // The m_isInOpenPopup flag is unnecessary in production. + // MockPagePopupDriver allows to execute JavaScript code in + // DateTimeChooserImpl constructor. It might create another DateTimeChooser. + if (m_isInOpenPopup) + return; + TemporaryChange<bool> reentrancyProtector(m_isInOpenPopup, true); if (m_chooser) return; if (!document().page()) @@ -143,6 +149,14 @@ bool PickerIndicatorElement::isPickerIndicatorElement() const return true; } +void PickerIndicatorElement::trace(Visitor* visitor) +{ + visitor->trace(m_pickerIndicatorOwner); + visitor->trace(m_chooser); + HTMLDivElement::trace(visitor); + DateTimeChooserClient::trace(visitor); +} + } #endif diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h index 8b7a5e3d740..914fd9887d3 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/PickerIndicatorElement.h @@ -42,10 +42,11 @@ class HTMLInputElement; class PagePopup; class PickerIndicatorElement FINAL : public HTMLDivElement, public DateTimeChooserClient { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(PickerIndicatorElement); public: // PickerIndicatorOwner implementer must call removePickerIndicatorOwner when // it doesn't handle event, e.g. at destruction. - class PickerIndicatorOwner { + class PickerIndicatorOwner : public WillBeGarbageCollectedMixin { public: virtual ~PickerIndicatorOwner() { } virtual bool isPickerIndicatorOwnerDisabledOrReadOnly() const = 0; @@ -55,12 +56,14 @@ public: virtual bool setupDateTimeChooserParameters(DateTimeChooserParameters&) = 0; }; - static PassRefPtr<PickerIndicatorElement> create(Document&, PickerIndicatorOwner&); + static PassRefPtrWillBeRawPtr<PickerIndicatorElement> create(Document&, PickerIndicatorOwner&); virtual ~PickerIndicatorElement(); + virtual void trace(Visitor*) OVERRIDE; + void openPopup(); void closePopup(); virtual bool willRespondToMouseClickEvents() OVERRIDE; - void removePickerIndicatorOwner() { m_pickerIndicatorOwner = 0; } + void removePickerIndicatorOwner() { m_pickerIndicatorOwner = nullptr; } // DateTimeChooserClient implementation. virtual void didChooseValue(const String&) OVERRIDE; @@ -76,8 +79,9 @@ private: HTMLInputElement* hostInput(); - PickerIndicatorOwner* m_pickerIndicatorOwner; - RefPtr<DateTimeChooser> m_chooser; + RawPtrWillBeMember<PickerIndicatorOwner> m_pickerIndicatorOwner; + RefPtrWillBeMember<DateTimeChooser> m_chooser; + bool m_isInOpenPopup; }; DEFINE_TYPE_CASTS(PickerIndicatorElement, Element, element, element->isPickerIndicatorElement(), element.isPickerIndicatorElement()); diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.cpp index 50c8d1dc9a4..0f8b72f069c 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.cpp @@ -32,7 +32,7 @@ #include "core/html/shadow/ProgressShadowElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLProgressElement.h" #include "core/rendering/RenderProgress.h" @@ -56,11 +56,13 @@ bool ProgressShadowElement::rendererIsNeeded(const RenderStyle& style) return progressRenderer && !progressRenderer->style()->hasAppearance() && HTMLDivElement::rendererIsNeeded(style); } -ProgressInnerElement::ProgressInnerElement(Document& document) +inline ProgressInnerElement::ProgressInnerElement(Document& document) : ProgressShadowElement(document) { } +DEFINE_NODE_FACTORY(ProgressInnerElement) + RenderObject* ProgressInnerElement::createRenderer(RenderStyle*) { return new RenderProgress(this); @@ -75,11 +77,13 @@ bool ProgressInnerElement::rendererIsNeeded(const RenderStyle& style) return progressRenderer && !progressRenderer->style()->hasAppearance() && HTMLDivElement::rendererIsNeeded(style); } -ProgressBarElement::ProgressBarElement(Document& document) +inline ProgressBarElement::ProgressBarElement(Document& document) : ProgressShadowElement(document) { } +DEFINE_NODE_FACTORY(ProgressBarElement) + ProgressValueElement::ProgressValueElement(Document& document) : ProgressShadowElement(document) { @@ -90,4 +94,6 @@ void ProgressValueElement::setWidthPercentage(double width) setInlineStyleProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); } +DEFINE_NODE_FACTORY(ProgressValueElement) + } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.h index b375fcc88d7..825b0b68437 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/ProgressShadowElement.h @@ -41,56 +41,41 @@ class HTMLProgressElement; class ProgressShadowElement : public HTMLDivElement { public: - ProgressShadowElement(Document&); + explicit ProgressShadowElement(Document&); HTMLProgressElement* progressElement() const; protected: - virtual bool rendererIsNeeded(const RenderStyle&); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; }; class ProgressInnerElement FINAL : public ProgressShadowElement { public: - static PassRefPtr<ProgressInnerElement> create(Document&); + DECLARE_NODE_FACTORY(ProgressInnerElement); private: - ProgressInnerElement(Document&); + explicit ProgressInnerElement(Document&); virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; - virtual bool rendererIsNeeded(const RenderStyle&); + virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE; }; -inline PassRefPtr<ProgressInnerElement> ProgressInnerElement::create(Document& document) -{ - return adoptRef(new ProgressInnerElement(document)); -} - class ProgressBarElement FINAL : public ProgressShadowElement { public: - static PassRefPtr<ProgressBarElement> create(Document&); + DECLARE_NODE_FACTORY(ProgressBarElement); private: - ProgressBarElement(Document&); + explicit ProgressBarElement(Document&); }; -inline PassRefPtr<ProgressBarElement> ProgressBarElement::create(Document& document) -{ - return adoptRef(new ProgressBarElement(document)); -} - class ProgressValueElement FINAL : public ProgressShadowElement { public: - static PassRefPtr<ProgressValueElement> create(Document&); + DECLARE_NODE_FACTORY(ProgressValueElement); void setWidthPercentage(double); private: - ProgressValueElement(Document&); + explicit ProgressValueElement(Document&); }; -inline PassRefPtr<ProgressValueElement> ProgressValueElement::create(Document& document) -{ - return adoptRef(new ProgressValueElement(document)); -} - } #endif // ProgressShadowElement_h diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.cpp index abe60e1d644..ad2f183effb 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.cpp @@ -35,6 +35,18 @@ namespace WebCore { namespace ShadowElementNames { +const AtomicString& detailsContent() +{ + DEFINE_STATIC_LOCAL(AtomicString, name, ("details-content", AtomicString::ConstructFromLiteral)); + return name; +} + +const AtomicString& detailsSummary() +{ + DEFINE_STATIC_LOCAL(AtomicString, name, ("details-summary", AtomicString::ConstructFromLiteral)); + return name; +} + const AtomicString& dateTimeEdit() { DEFINE_STATIC_LOCAL(AtomicString, name, ("date-time-edit", AtomicString::ConstructFromLiteral)); @@ -65,12 +77,6 @@ const AtomicString& innerEditor() return name; } -const AtomicString& passwordGenerator() -{ - DEFINE_STATIC_LOCAL(AtomicString, name, ("password-generator", AtomicString::ConstructFromLiteral)); - return name; -} - const AtomicString& pickerIndicator() { DEFINE_STATIC_LOCAL(AtomicString, name, ("picker", AtomicString::ConstructFromLiteral)); diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.h b/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.h index 46788a1cdfb..61ee1ca1680 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/ShadowElementNames.h @@ -37,12 +37,13 @@ namespace WebCore { namespace ShadowElementNames { +const AtomicString& detailsContent(); +const AtomicString& detailsSummary(); const AtomicString& dateTimeEdit(); const AtomicString& spinButton(); const AtomicString& clearButton(); const AtomicString& editingViewPort(); const AtomicString& innerEditor(); -const AtomicString& passwordGenerator(); const AtomicString& pickerIndicator(); const AtomicString& placeholder(); const AtomicString& searchDecoration(); diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.cpp index dc7d5080591..3e9ab2fd281 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.cpp @@ -36,18 +36,16 @@ #include "core/events/Event.h" #include "core/events/MouseEvent.h" #include "core/dom/shadow/ShadowRoot.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLInputElement.h" #include "core/html/forms/StepRange.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/page/EventHandler.h" -#include "core/frame/Frame.h" #include "core/rendering/RenderFlexibleBox.h" #include "core/rendering/RenderSlider.h" #include "core/rendering/RenderTheme.h" -using namespace std; - namespace WebCore { using namespace HTMLNames; @@ -64,9 +62,6 @@ inline static bool hasVerticalAppearance(HTMLInputElement* input) ASSERT(input->renderer()); RenderStyle* sliderStyle = input->renderer()->style(); - if (sliderStyle->appearance() == MediaVolumeSliderPart && RenderTheme::theme().usesVerticalVolumeSlider()) - return true; - return sliderStyle->appearance() == SliderVerticalPart; } @@ -131,11 +126,18 @@ void RenderSliderContainer::computeLogicalHeight(LayoutUnit logicalHeight, Layou if (zoomFactor != 1.0) trackHeight *= zoomFactor; + // FIXME: The trackHeight should have been added before updateLogicalHeight was called to avoid this hack. + updateIntrinsicContentLogicalHeight(trackHeight); + RenderBox::computeLogicalHeight(trackHeight, logicalTop, computedValues); return; } if (isVertical) logicalHeight = RenderSlider::defaultTrackLength; + + // FIXME: The trackHeight should have been added before updateLogicalHeight was called to avoid this hack. + updateIntrinsicContentLogicalHeight(logicalHeight); + RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues); } @@ -157,7 +159,7 @@ void RenderSliderContainer::layout() RenderBox* thumb = thumbElement ? thumbElement->renderBox() : 0; RenderBox* track = trackElement ? trackElement->renderBox() : 0; - SubtreeLayoutScope layoutScope(this); + SubtreeLayoutScope layoutScope(*this); // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place. // FIXME: Make a custom Render class for the track and move the thumb positioning code there. if (track) @@ -182,14 +184,14 @@ void RenderSliderContainer::layout() else thumbLocation.setX(thumbLocation.x() - offset); thumb->setLocation(thumbLocation); - if (checkForRepaintDuringLayout() && parent() + if (checkForPaintInvalidationDuringLayout() && parent() && (parent()->style()->appearance() == MediaVolumeSliderPart || parent()->style()->appearance() == MediaSliderPart)) { // This will sometimes repaint too much. However, it is necessary to // correctly repaint media controls (volume and timeline sliders) - // they have special painting code in RenderMediaControls.cpp:paintMediaVolumeSlider // and paintMediaSlider that gets called via -webkit-appearance and RenderTheme, // so nothing else would otherwise invalidate the slider. - repaint(); + paintInvalidationForWholeRenderer(); } } @@ -201,9 +203,9 @@ inline SliderThumbElement::SliderThumbElement(Document& document) { } -PassRefPtr<SliderThumbElement> SliderThumbElement::create(Document& document) +PassRefPtrWillBeRawPtr<SliderThumbElement> SliderThumbElement::create(Document& document) { - RefPtr<SliderThumbElement> element = adoptRef(new SliderThumbElement(document)); + RefPtrWillBeRawPtr<SliderThumbElement> element = adoptRefWillBeNoop(new SliderThumbElement(document)); element->setAttribute(idAttr, ShadowElementNames::sliderThumb()); return element.release(); } @@ -214,7 +216,7 @@ void SliderThumbElement::setPositionFromValue() // path, we don't actually update the value here. Instead, we poke at the // renderer directly to trigger layout. if (renderer()) - renderer()->setNeedsLayout(); + renderer()->setNeedsLayoutAndFullPaintInvalidation(); } RenderObject* SliderThumbElement::createRenderer(RenderStyle*) @@ -229,12 +231,12 @@ bool SliderThumbElement::isDisabledFormControl() const bool SliderThumbElement::matchesReadOnlyPseudoClass() const { - return hostInput()->matchesReadOnlyPseudoClass(); + return hostInput() && hostInput()->matchesReadOnlyPseudoClass(); } bool SliderThumbElement::matchesReadWritePseudoClass() const { - return hostInput()->matchesReadWritePseudoClass(); + return hostInput() && hostInput()->matchesReadWritePseudoClass(); } Node* SliderThumbElement::focusDelegate() @@ -244,14 +246,14 @@ Node* SliderThumbElement::focusDelegate() void SliderThumbElement::dragFrom(const LayoutPoint& point) { - RefPtr<SliderThumbElement> protector(this); + RefPtrWillBeRawPtr<SliderThumbElement> protector(this); startDragging(); setPositionFromPoint(point); } void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point) { - RefPtr<HTMLInputElement> input(hostInput()); + RefPtrWillBeRawPtr<HTMLInputElement> input(hostInput()); Element* trackElement = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderTrack()); if (!input->renderer() || !renderBox() || !trackElement->renderBox()) @@ -281,7 +283,7 @@ void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point) position -= isLeftToRightDirection ? renderBox()->marginLeft() : renderBox()->marginRight(); currentPosition = absoluteThumbOrigin.x() - absoluteSliderContentOrigin.x(); } - position = max<LayoutUnit>(0, min(position, trackSize)); + position = std::max<LayoutUnit>(0, std::min(position, trackSize)); const Decimal ratio = Decimal::fromDouble(static_cast<double>(position) / trackSize); const Decimal fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio; StepRange stepRange(input->createStepRange(RejectAny)); @@ -304,13 +306,12 @@ void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point) // FIXME: This is no longer being set from renderer. Consider updating the method name. input->setValueFromRenderer(valueString); if (renderer()) - renderer()->setNeedsLayout(); - input->dispatchFormControlChangeEvent(); + renderer()->setNeedsLayoutAndFullPaintInvalidation(); } void SliderThumbElement::startDragging() { - if (Frame* frame = document().frame()) { + if (LocalFrame* frame = document().frame()) { frame->eventHandler().setCapturingMouseEventsNode(this); m_inDragMode = true; } @@ -321,11 +322,13 @@ void SliderThumbElement::stopDragging() if (!m_inDragMode) return; - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) + frame->eventHandler().setCapturingMouseEventsNode(nullptr); m_inDragMode = false; if (renderer()) - renderer()->setNeedsLayout(); + renderer()->setNeedsLayoutAndFullPaintInvalidation(); + if (hostInput()) + hostInput()->dispatchFormControlChangeEvent(); } void SliderThumbElement::defaultEventHandler(Event* event) @@ -387,8 +390,8 @@ bool SliderThumbElement::willRespondToMouseClickEvents() void SliderThumbElement::detach(const AttachContext& context) { if (m_inDragMode) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) + frame->eventHandler().setCapturingMouseEventsNode(nullptr); } HTMLDivElement::detach(context); } @@ -412,10 +415,10 @@ static const AtomicString& mediaSliderThumbShadowPartId() return mediaSliderThumb; } -const AtomicString& SliderThumbElement::pseudo() const +const AtomicString& SliderThumbElement::shadowPseudoId() const { HTMLInputElement* input = hostInput(); - if (!input) + if (!input || !input->renderer()) return sliderThumbShadowPartId(); RenderStyle* sliderStyle = input->renderer()->style(); @@ -439,25 +442,22 @@ inline SliderContainerElement::SliderContainerElement(Document& document) { } -PassRefPtr<SliderContainerElement> SliderContainerElement::create(Document& document) -{ - return adoptRef(new SliderContainerElement(document)); -} +DEFINE_NODE_FACTORY(SliderContainerElement) RenderObject* SliderContainerElement::createRenderer(RenderStyle*) { return new RenderSliderContainer(this); } -const AtomicString& SliderContainerElement::pseudo() const +const AtomicString& SliderContainerElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(const AtomicString, mediaSliderContainer, ("-webkit-media-slider-container", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(const AtomicString, sliderContainer, ("-webkit-slider-container", AtomicString::ConstructFromLiteral)); - if (!shadowHost()->hasTagName(inputTag)) + if (!shadowHost() || !shadowHost()->renderer()) return sliderContainer; - RenderStyle* sliderStyle = toHTMLInputElement(shadowHost())->renderer()->style(); + RenderStyle* sliderStyle = shadowHost()->renderer()->style(); switch (sliderStyle->appearance()) { case MediaSliderPart: case MediaSliderThumbPart: diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.h index a7af7771fbd..efb41d65fa0 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/SliderThumbElement.h @@ -32,7 +32,7 @@ #ifndef SliderThumbElement_h #define SliderThumbElement_h -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/html/HTMLDivElement.h" #include "core/rendering/RenderBlockFlow.h" #include "wtf/Forward.h" @@ -46,43 +46,40 @@ class FloatPoint; class SliderThumbElement FINAL : public HTMLDivElement { public: - static PassRefPtr<SliderThumbElement> create(Document&); + static PassRefPtrWillBeRawPtr<SliderThumbElement> create(Document&); void setPositionFromValue(); void dragFrom(const LayoutPoint&); - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; virtual bool willRespondToMouseMoveEvents() OVERRIDE; virtual bool willRespondToMouseClickEvents() OVERRIDE; virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - virtual const AtomicString& pseudo() const OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; HTMLInputElement* hostInput() const; void setPositionFromPoint(const LayoutPoint&); void stopDragging(); private: SliderThumbElement(Document&); - virtual RenderObject* createRenderer(RenderStyle*); - virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren(); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual PassRefPtrWillBeRawPtr<Element> cloneElementWithoutAttributesAndChildren() OVERRIDE; virtual bool isDisabledFormControl() const OVERRIDE; virtual bool matchesReadOnlyPseudoClass() const OVERRIDE; virtual bool matchesReadWritePseudoClass() const OVERRIDE; - virtual Node* focusDelegate(); + virtual Node* focusDelegate() OVERRIDE; void startDragging(); bool m_inDragMode; }; -inline PassRefPtr<Element> SliderThumbElement::cloneElementWithoutAttributesAndChildren() +inline PassRefPtrWillBeRawPtr<Element> SliderThumbElement::cloneElementWithoutAttributesAndChildren() { return create(document()); } -inline SliderThumbElement* toSliderThumbElement(Node* node) -{ - ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isHTMLElement()); - return static_cast<SliderThumbElement*>(node); -} +// FIXME: There are no ways to check if a node is a SliderThumbElement. +DEFINE_ELEMENT_TYPE_CASTS(SliderThumbElement, isHTMLElement()); // -------------------------------- @@ -92,20 +89,19 @@ public: void updateAppearance(RenderStyle* parentStyle); private: - virtual bool isSliderThumb() const; - virtual bool supportsPartialLayout() const OVERRIDE { return false; } + virtual bool isSliderThumb() const OVERRIDE; }; // -------------------------------- class SliderContainerElement FINAL : public HTMLDivElement { public: - static PassRefPtr<SliderContainerElement> create(Document&); + DECLARE_NODE_FACTORY(SliderContainerElement); private: - SliderContainerElement(Document&); - virtual RenderObject* createRenderer(RenderStyle*); - virtual const AtomicString& pseudo() const; + explicit SliderContainerElement(Document&); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; + virtual const AtomicString& shadowPseudoId() const OVERRIDE; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.cpp index 38303b5aca5..0671ee1beef 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.cpp @@ -27,14 +27,13 @@ #include "config.h" #include "core/html/shadow/SpinButtonElement.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/events/MouseEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/events/WheelEvent.h" +#include "core/frame/LocalFrame.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/page/Chrome.h" #include "core/page/EventHandler.h" -#include "core/frame/Frame.h" #include "core/page/Page.h" #include "core/rendering/RenderBox.h" #include "platform/scroll/ScrollbarTheme.h" @@ -53,17 +52,17 @@ inline SpinButtonElement::SpinButtonElement(Document& document, SpinButtonOwner& { } -PassRefPtr<SpinButtonElement> SpinButtonElement::create(Document& document, SpinButtonOwner& spinButtonOwner) +PassRefPtrWillBeRawPtr<SpinButtonElement> SpinButtonElement::create(Document& document, SpinButtonOwner& spinButtonOwner) { - RefPtr<SpinButtonElement> element = adoptRef(new SpinButtonElement(document, spinButtonOwner)); - element->setPseudo(AtomicString("-webkit-inner-spin-button", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<SpinButtonElement> element = adoptRefWillBeNoop(new SpinButtonElement(document, spinButtonOwner)); + element->setShadowPseudoId(AtomicString("-webkit-inner-spin-button", AtomicString::ConstructFromLiteral)); element->setAttribute(idAttr, ShadowElementNames::spinButton()); return element.release(); } void SpinButtonElement::detach(const AttachContext& context) { - releaseCapture(); + releaseCapture(EventDispatchDisallowed); HTMLDivElement::detach(context); } @@ -95,7 +94,7 @@ void SpinButtonElement::defaultEventHandler(Event* event) // The following functions of HTMLInputElement may run JavaScript // code which detaches this shadow node. We need to take a reference // and check renderer() after such function calls. - RefPtr<Node> protector(this); + RefPtrWillBeRawPtr<Node> protector(this); if (m_spinButtonOwner) m_spinButtonOwner->focusAndSelectSpinButtonOwner(); if (renderer()) { @@ -111,12 +110,12 @@ void SpinButtonElement::defaultEventHandler(Event* event) } event->setDefaultHandled(); } - } else if (mouseEvent->type() == EventTypeNames::mouseup && mouseEvent->button() == LeftButton) - stopRepeatingTimer(); - else if (event->type() == EventTypeNames::mousemove) { + } else if (mouseEvent->type() == EventTypeNames::mouseup && mouseEvent->button() == LeftButton) { + releaseCapture(); + } else if (event->type() == EventTypeNames::mousemove) { if (box->pixelSnappedBorderBoxRect().contains(local)) { if (!m_capturing) { - if (Frame* frame = document().frame()) { + if (LocalFrame* frame = document().frame()) { frame->eventHandler().setCapturingMouseEventsNode(this); m_capturing = true; if (Page* page = document().page()) @@ -126,7 +125,7 @@ void SpinButtonElement::defaultEventHandler(Event* event) UpDownState oldUpDownState = m_upDownState; m_upDownState = (local.y() < box->height() / 2) ? Up : Down; if (m_upDownState != oldUpDownState) - renderer()->repaint(); + renderer()->paintInvalidationForWholeRenderer(); } else { releaseCapture(); m_upDownState = Indeterminate; @@ -188,17 +187,20 @@ void SpinButtonElement::doStepAction(int amount) m_spinButtonOwner->spinButtonStepDown(); } -void SpinButtonElement::releaseCapture() +void SpinButtonElement::releaseCapture(EventDispatch eventDispatch) { stopRepeatingTimer(); if (m_capturing) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) { + frame->eventHandler().setCapturingMouseEventsNode(nullptr); m_capturing = false; if (Page* page = document().page()) page->chrome().unregisterPopupOpeningObserver(this); } } + if (m_spinButtonOwner) + m_spinButtonOwner->spinButtonDidReleaseMouseCapture(eventDispatch); + } bool SpinButtonElement::matchesReadOnlyPseudoClass() const @@ -215,7 +217,7 @@ void SpinButtonElement::startRepeatingTimer() { m_pressStartingState = m_upDownState; ScrollbarTheme* theme = ScrollbarTheme::theme(); - m_repeatingTimer.start(theme->initialAutoscrollTimerDelay(), theme->autoscrollTimerDelay()); + m_repeatingTimer.start(theme->initialAutoscrollTimerDelay(), theme->autoscrollTimerDelay(), FROM_HERE); } void SpinButtonElement::stopRepeatingTimer() @@ -255,4 +257,10 @@ bool SpinButtonElement::shouldRespondToMouseEvents() return !m_spinButtonOwner || m_spinButtonOwner->shouldSpinButtonRespondToMouseEvents(); } +void SpinButtonElement::trace(Visitor* visitor) +{ + visitor->trace(m_spinButtonOwner); + HTMLDivElement::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.h b/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.h index 41de8fcdaee..25c0b30d8b3 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/SpinButtonElement.h @@ -40,13 +40,17 @@ public: Down, Up, }; - - class SpinButtonOwner { + enum EventDispatch { + EventDispatchAllowed, + EventDispatchDisallowed, + }; + class SpinButtonOwner : public WillBeGarbageCollectedMixin { public: virtual ~SpinButtonOwner() { } virtual void focusAndSelectSpinButtonOwner() = 0; virtual bool shouldSpinButtonRespondToMouseEvents() = 0; virtual bool shouldSpinButtonRespondToWheelEvents() = 0; + virtual void spinButtonDidReleaseMouseCapture(EventDispatch) = 0; virtual void spinButtonStepDown() = 0; virtual void spinButtonStepUp() = 0; }; @@ -54,10 +58,10 @@ public: // The owner of SpinButtonElement must call removeSpinButtonOwner // because SpinButtonElement can be outlive SpinButtonOwner // implementation, e.g. during event handling. - static PassRefPtr<SpinButtonElement> create(Document&, SpinButtonOwner&); + static PassRefPtrWillBeRawPtr<SpinButtonElement> create(Document&, SpinButtonOwner&); UpDownState upDownState() const { return m_upDownState; } - virtual void releaseCapture(); - void removeSpinButtonOwner() { m_spinButtonOwner = 0; } + void releaseCapture(EventDispatch = EventDispatchAllowed); + void removeSpinButtonOwner() { m_spinButtonOwner = nullptr; } void step(int amount); @@ -66,25 +70,27 @@ public: void forwardEvent(Event*); + virtual void trace(Visitor*) OVERRIDE; + private: SpinButtonElement(Document&, SpinButtonOwner&); - virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - virtual bool isSpinButtonElement() const { return true; } + virtual void detach(const AttachContext&) OVERRIDE; + virtual bool isSpinButtonElement() const OVERRIDE { return true; } virtual bool isDisabledFormControl() const OVERRIDE { return shadowHost() && shadowHost()->isDisabledFormControl(); } virtual bool matchesReadOnlyPseudoClass() const OVERRIDE; virtual bool matchesReadWritePseudoClass() const OVERRIDE; - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; virtual void willOpenPopup() OVERRIDE; void doStepAction(int); void startRepeatingTimer(); void stopRepeatingTimer(); void repeatingTimerFired(Timer<SpinButtonElement>*); - virtual void setHovered(bool = true); + virtual void setHovered(bool = true) OVERRIDE; bool shouldRespondToMouseEvents(); - virtual bool isMouseFocusable() const { return false; } + virtual bool isMouseFocusable() const OVERRIDE { return false; } - SpinButtonOwner* m_spinButtonOwner; + RawPtrWillBeMember<SpinButtonOwner> m_spinButtonOwner; bool m_capturing; UpDownState m_upDownState; UpDownState m_pressStartingState; diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.cpp b/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.cpp index a19fef2c9e9..57c9fc665a6 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.cpp +++ b/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.cpp @@ -27,21 +27,18 @@ #include "config.h" #include "core/html/shadow/TextControlInnerElements.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/NodeRenderStyle.h" #include "core/events/MouseEvent.h" #include "core/events/TextEvent.h" #include "core/events/TextEventInputType.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLInputElement.h" #include "core/html/shadow/ShadowElementNames.h" #include "core/page/EventHandler.h" -#include "core/frame/Frame.h" #include "core/rendering/RenderTextControlSingleLine.h" #include "core/rendering/RenderView.h" -#include "core/speech/SpeechInput.h" -#include "core/speech/SpeechInputEvent.h" #include "platform/UserGestureIndicator.h" namespace WebCore { @@ -53,9 +50,9 @@ TextControlInnerContainer::TextControlInnerContainer(Document& document) { } -PassRefPtr<TextControlInnerContainer> TextControlInnerContainer::create(Document& document) +PassRefPtrWillBeRawPtr<TextControlInnerContainer> TextControlInnerContainer::create(Document& document) { - RefPtr<TextControlInnerContainer> element = adoptRef(new TextControlInnerContainer(document)); + RefPtrWillBeRawPtr<TextControlInnerContainer> element = adoptRefWillBeNoop(new TextControlInnerContainer(document)); element->setAttribute(idAttr, ShadowElementNames::textFieldContainer()); return element.release(); } @@ -73,9 +70,9 @@ EditingViewPortElement::EditingViewPortElement(Document& document) setHasCustomStyleCallbacks(); } -PassRefPtr<EditingViewPortElement> EditingViewPortElement::create(Document& document) +PassRefPtrWillBeRawPtr<EditingViewPortElement> EditingViewPortElement::create(Document& document) { - RefPtr<EditingViewPortElement> element = adoptRef(new EditingViewPortElement(document)); + RefPtrWillBeRawPtr<EditingViewPortElement> element = adoptRefWillBeNoop(new EditingViewPortElement(document)); element->setAttribute(idAttr, ShadowElementNames::editingViewPort()); return element.release(); } @@ -88,9 +85,6 @@ PassRefPtr<RenderStyle> EditingViewPortElement::customStyleForRenderer() style->inheritFrom(shadowHost()->renderStyle()); style->setFlexGrow(1); - // min-width: 0; is needed for correct shrinking. - // FIXME: Remove this line when https://bugs.webkit.org/show_bug.cgi?id=111790 is fixed. - style->setMinWidth(Length(0, Fixed)); style->setDisplay(BLOCK); style->setDirection(LTR); @@ -104,20 +98,20 @@ PassRefPtr<RenderStyle> EditingViewPortElement::customStyleForRenderer() // --------------------------- -inline TextControlInnerTextElement::TextControlInnerTextElement(Document& document) +inline TextControlInnerEditorElement::TextControlInnerEditorElement(Document& document) : HTMLDivElement(document) { setHasCustomStyleCallbacks(); } -PassRefPtr<TextControlInnerTextElement> TextControlInnerTextElement::create(Document& document) +PassRefPtrWillBeRawPtr<TextControlInnerEditorElement> TextControlInnerEditorElement::create(Document& document) { - RefPtr<TextControlInnerTextElement> element = adoptRef(new TextControlInnerTextElement(document)); + RefPtrWillBeRawPtr<TextControlInnerEditorElement> element = adoptRefWillBeNoop(new TextControlInnerEditorElement(document)); element->setAttribute(idAttr, ShadowElementNames::innerEditor()); return element.release(); } -void TextControlInnerTextElement::defaultEventHandler(Event* event) +void TextControlInnerEditorElement::defaultEventHandler(Event* event) { // FIXME: In the future, we should add a way to have default event listeners. // Then we would add one to the text field's inner div, and we wouldn't need this subclass. @@ -136,18 +130,18 @@ void TextControlInnerTextElement::defaultEventHandler(Event* event) HTMLDivElement::defaultEventHandler(event); } -RenderObject* TextControlInnerTextElement::createRenderer(RenderStyle*) +RenderObject* TextControlInnerEditorElement::createRenderer(RenderStyle*) { return new RenderTextControlInnerBlock(this); } -PassRefPtr<RenderStyle> TextControlInnerTextElement::customStyleForRenderer() +PassRefPtr<RenderStyle> TextControlInnerEditorElement::customStyleForRenderer() { RenderObject* parentRenderer = shadowHost()->renderer(); if (!parentRenderer || !parentRenderer->isTextControl()) return originalStyleForRenderer(); RenderTextControl* textControlRenderer = toRenderTextControl(parentRenderer); - return textControlRenderer->createInnerTextStyle(textControlRenderer->style()); + return textControlRenderer->createInnerEditorStyle(textControlRenderer->style()); } // ---------------------------- @@ -157,21 +151,21 @@ inline SearchFieldDecorationElement::SearchFieldDecorationElement(Document& docu { } -PassRefPtr<SearchFieldDecorationElement> SearchFieldDecorationElement::create(Document& document) +PassRefPtrWillBeRawPtr<SearchFieldDecorationElement> SearchFieldDecorationElement::create(Document& document) { - RefPtr<SearchFieldDecorationElement> element = adoptRef(new SearchFieldDecorationElement(document)); + RefPtrWillBeRawPtr<SearchFieldDecorationElement> element = adoptRefWillBeNoop(new SearchFieldDecorationElement(document)); element->setAttribute(idAttr, ShadowElementNames::searchDecoration()); return element.release(); } -const AtomicString& SearchFieldDecorationElement::pseudo() const +const AtomicString& SearchFieldDecorationElement::shadowPseudoId() const { DEFINE_STATIC_LOCAL(AtomicString, resultsDecorationId, ("-webkit-search-results-decoration", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, decorationId, ("-webkit-search-decoration", AtomicString::ConstructFromLiteral)); Element* host = shadowHost(); if (!host) return resultsDecorationId; - if (host->hasTagName(inputTag)) { + if (isHTMLInputElement(*host)) { if (toHTMLInputElement(host)->maxResults() < 0) return decorationId; return resultsDecorationId; @@ -206,10 +200,10 @@ inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& { } -PassRefPtr<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document) +PassRefPtrWillBeRawPtr<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document) { - RefPtr<SearchFieldCancelButtonElement> element = adoptRef(new SearchFieldCancelButtonElement(document)); - element->setPseudo(AtomicString("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral)); + RefPtrWillBeRawPtr<SearchFieldCancelButtonElement> element = adoptRefWillBeNoop(new SearchFieldCancelButtonElement(document)); + element->setShadowPseudoId(AtomicString("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral)); element->setAttribute(idAttr, ShadowElementNames::clearButton()); return element.release(); } @@ -217,8 +211,8 @@ PassRefPtr<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::creat void SearchFieldCancelButtonElement::detach(const AttachContext& context) { if (m_capturing) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsNode(0); + if (LocalFrame* frame = document().frame()) + frame->eventHandler().setCapturingMouseEventsNode(nullptr); } HTMLDivElement::detach(context); } @@ -227,136 +221,17 @@ void SearchFieldCancelButtonElement::detach(const AttachContext& context) void SearchFieldCancelButtonElement::defaultEventHandler(Event* event) { // If the element is visible, on mouseup, clear the value, and set selection - RefPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); + RefPtrWillBeRawPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); if (!input || input->isDisabledOrReadOnly()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } - if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { - if (renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(this); - m_capturing = true; - } - } - input->focus(); - input->select(); - event->setDefaultHandled(); - } - if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { - if (m_capturing) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(0); - m_capturing = false; - } - if (hovered()) { - String oldValue = input->value(); - input->setValueForUser(""); - input->onSearch(); - event->setDefaultHandled(); - } - } - } - - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); -} - -bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents() -{ - const HTMLInputElement* input = toHTMLInputElement(shadowHost()); - if (input && !input->isDisabledOrReadOnly()) - return true; - - return HTMLDivElement::willRespondToMouseClickEvents(); -} - -// ---------------------------- - -#if ENABLE(INPUT_SPEECH) - -inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(Document& document) - : HTMLDivElement(document) - , m_capturing(false) - , m_state(Idle) - , m_listenerId(0) -{ -} - -InputFieldSpeechButtonElement::~InputFieldSpeechButtonElement() -{ - SpeechInput* speech = speechInput(); - if (speech && m_listenerId) { // Could be null when page is unloading. - if (m_state != Idle) - speech->cancelRecognition(m_listenerId); - speech->unregisterListener(m_listenerId); - } -} - -PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(Document& document) -{ - RefPtr<InputFieldSpeechButtonElement> element = adoptRef(new InputFieldSpeechButtonElement(document)); - element->setPseudo(AtomicString("-webkit-input-speech-button", AtomicString::ConstructFromLiteral)); - element->setAttribute(idAttr, ShadowElementNames::speechButton()); - return element.release(); -} - -void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) -{ - // For privacy reasons, only allow clicks directly coming from the user. - if (!UserGestureIndicator::processingUserGesture()) { - HTMLDivElement::defaultEventHandler(event); - return; - } - - // The call to focus() below dispatches a focus event, and an event handler in the page might - // remove the input element from DOM. To make sure it remains valid until we finish our work - // here, we take a temporary reference. - RefPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); - - if (!input || input->isDisabledOrReadOnly()) { - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); - return; - } - // On mouse down, select the text and set focus. - if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { - if (renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(this); - m_capturing = true; - } - } - RefPtr<InputFieldSpeechButtonElement> holdRefButton(this); - input->focus(); - input->select(); - event->setDefaultHandled(); - } - // On mouse up, release capture cleanly. - if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { - if (m_capturing && renderer() && renderer()->visibleToHitTesting()) { - if (Frame* frame = document().frame()) { - frame->eventHandler().setCapturingMouseEventsNode(0); - m_capturing = false; - } - } - } - - if (event->type() == EventTypeNames::click && m_listenerId) { - switch (m_state) { - case Idle: - startSpeechInput(); - break; - case Recording: - stopSpeechInput(); - break; - case Recognizing: - // Nothing to do here, we will continue to wait for results. - break; - } + if (event->type() == EventTypeNames::click && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { + input->setValueForUser(""); + input->onSearch(); event->setDefaultHandled(); } @@ -364,7 +239,7 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) HTMLDivElement::defaultEventHandler(event); } -bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents() +bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents() { const HTMLInputElement* input = toHTMLInputElement(shadowHost()); if (input && !input->isDisabledOrReadOnly()) @@ -373,102 +248,4 @@ bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents() return HTMLDivElement::willRespondToMouseClickEvents(); } -void InputFieldSpeechButtonElement::setState(SpeechInputState state) -{ - if (m_state != state) { - m_state = state; - shadowHost()->renderer()->repaint(); - } -} - -SpeechInput* InputFieldSpeechButtonElement::speechInput() -{ - return SpeechInput::from(document().page()); -} - -void InputFieldSpeechButtonElement::didCompleteRecording(int) -{ - setState(Recognizing); -} - -void InputFieldSpeechButtonElement::didCompleteRecognition(int) -{ - setState(Idle); -} - -void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputResultArray& results) -{ - m_results = results; - - // The call to setValue() below dispatches an event, and an event handler in the page might - // remove the input element from DOM. To make sure it remains valid until we finish our work - // here, we take a temporary reference. - RefPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost())); - if (!input || input->isDisabledOrReadOnly()) - return; - - RefPtr<InputFieldSpeechButtonElement> holdRefButton(this); - if (document().domWindow()) { - // Call selectionChanged, causing the element to cache the selection, - // so that the text event inserts the text in this element even if - // focus has moved away from it. - input->selectionChanged(false); - input->dispatchEvent(TextEvent::create(document().domWindow(), results.isEmpty() ? "" : results[0]->utterance(), TextEventInputOther)); - } - - // This event is sent after the text event so the website can perform actions using the input field content immediately. - // It provides alternative recognition hypotheses and notifies that the results come from speech input. - input->dispatchEvent(SpeechInputEvent::create(EventTypeNames::webkitspeechchange, results)); - - // Check before accessing the renderer as the above event could have potentially turned off - // speech in the input element, hence removing this button and renderer from the hierarchy. - if (renderer()) - renderer()->repaint(); -} - -void InputFieldSpeechButtonElement::attach(const AttachContext& context) -{ - ASSERT(!m_listenerId); - if (SpeechInput* input = SpeechInput::from(document().page())) - m_listenerId = input->registerListener(this); - HTMLDivElement::attach(context); -} - -void InputFieldSpeechButtonElement::detach(const AttachContext& context) -{ - if (m_capturing) { - if (Frame* frame = document().frame()) - frame->eventHandler().setCapturingMouseEventsNode(0); - } - - if (m_listenerId) { - if (m_state != Idle) - speechInput()->cancelRecognition(m_listenerId); - speechInput()->unregisterListener(m_listenerId); - m_listenerId = 0; - } - - HTMLDivElement::detach(context); -} - -void InputFieldSpeechButtonElement::startSpeechInput() -{ - if (m_state != Idle) - return; - - RefPtr<HTMLInputElement> input = toHTMLInputElement(shadowHost()); - AtomicString language = input->computeInheritedLanguage(); - String grammar = input->getAttribute(webkitgrammarAttr); - IntRect rect = document().view()->contentsToRootView(pixelSnappedBoundingBox()); - if (speechInput()->startRecognition(m_listenerId, rect, language, grammar, document().securityOrigin())) - setState(Recording); -} - -void InputFieldSpeechButtonElement::stopSpeechInput() -{ - if (m_state == Recording) - speechInput()->stopRecording(m_listenerId); -} -#endif // ENABLE(INPUT_SPEECH) - } diff --git a/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.h b/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.h index 6b6fb0ff6f4..65c994d7d2e 100644 --- a/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.h +++ b/chromium/third_party/WebKit/Source/core/html/shadow/TextControlInnerElements.h @@ -28,119 +28,72 @@ #define TextControlInnerElements_h #include "core/html/HTMLDivElement.h" -#include "core/speech/SpeechInputListener.h" #include "wtf/Forward.h" namespace WebCore { -class SpeechInput; - class TextControlInnerContainer FINAL : public HTMLDivElement { public: - static PassRefPtr<TextControlInnerContainer> create(Document&); + static PassRefPtrWillBeRawPtr<TextControlInnerContainer> create(Document&); + protected: - TextControlInnerContainer(Document&); - virtual RenderObject* createRenderer(RenderStyle*); + explicit TextControlInnerContainer(Document&); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; }; class EditingViewPortElement FINAL : public HTMLDivElement { public: - static PassRefPtr<EditingViewPortElement> create(Document&); + static PassRefPtrWillBeRawPtr<EditingViewPortElement> create(Document&); protected: - EditingViewPortElement(Document&); + explicit EditingViewPortElement(Document&); virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE; private: virtual bool supportsFocus() const OVERRIDE { return false; } }; -class TextControlInnerTextElement FINAL : public HTMLDivElement { +class TextControlInnerEditorElement FINAL : public HTMLDivElement { public: - static PassRefPtr<TextControlInnerTextElement> create(Document&); + static PassRefPtrWillBeRawPtr<TextControlInnerEditorElement> create(Document&); - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; private: - TextControlInnerTextElement(Document&); - virtual RenderObject* createRenderer(RenderStyle*); + explicit TextControlInnerEditorElement(Document&); + virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE; virtual bool supportsFocus() const OVERRIDE { return false; } }; class SearchFieldDecorationElement FINAL : public HTMLDivElement { public: - static PassRefPtr<SearchFieldDecorationElement> create(Document&); + static PassRefPtrWillBeRawPtr<SearchFieldDecorationElement> create(Document&); - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; virtual bool willRespondToMouseClickEvents() OVERRIDE; private: - SearchFieldDecorationElement(Document&); - virtual const AtomicString& pseudo() const OVERRIDE; + explicit SearchFieldDecorationElement(Document&); + virtual const AtomicString& shadowPseudoId() const OVERRIDE; virtual bool supportsFocus() const OVERRIDE { return false; } }; class SearchFieldCancelButtonElement FINAL : public HTMLDivElement { public: - static PassRefPtr<SearchFieldCancelButtonElement> create(Document&); + static PassRefPtrWillBeRawPtr<SearchFieldCancelButtonElement> create(Document&); - virtual void defaultEventHandler(Event*); + virtual void defaultEventHandler(Event*) OVERRIDE; virtual bool willRespondToMouseClickEvents() OVERRIDE; private: - SearchFieldCancelButtonElement(Document&); + explicit SearchFieldCancelButtonElement(Document&); virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; virtual bool supportsFocus() const OVERRIDE { return false; } bool m_capturing; }; -#if ENABLE(INPUT_SPEECH) - -class InputFieldSpeechButtonElement FINAL - : public HTMLDivElement, - public SpeechInputListener { -public: - enum SpeechInputState { - Idle, - Recording, - Recognizing, - }; - - static PassRefPtr<InputFieldSpeechButtonElement> create(Document&); - virtual ~InputFieldSpeechButtonElement(); - - virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; - virtual void defaultEventHandler(Event*); - virtual bool willRespondToMouseClickEvents(); - virtual bool isInputFieldSpeechButtonElement() const { return true; } - SpeechInputState state() const { return m_state; } - void startSpeechInput(); - void stopSpeechInput(); - - // SpeechInputListener methods. - void didCompleteRecording(int); - void didCompleteRecognition(int); - void setRecognitionResult(int, const SpeechInputResultArray&); - -private: - InputFieldSpeechButtonElement(Document&); - SpeechInput* speechInput(); - void setState(SpeechInputState state); - virtual bool isMouseFocusable() const { return false; } - virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; - - bool m_capturing; - SpeechInputState m_state; - int m_listenerId; - SpeechInputResultArray m_results; -}; - -DEFINE_TYPE_CASTS(InputFieldSpeechButtonElement, Element, element, element->isInputFieldSpeechButtonElement(), element.isInputFieldSpeechButtonElement()); - -#endif // ENABLE(INPUT_SPEECH) - } // namespace #endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.cpp b/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.cpp new file mode 100644 index 00000000000..cfa0de3f3f6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.cpp @@ -0,0 +1,86 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/track/AudioTrack.h" + +#include "core/html/HTMLMediaElement.h" + +namespace WebCore { + +AudioTrack::AudioTrack(const String& id, const AtomicString& kind, const AtomicString& label, const AtomicString& language, bool enabled) + : TrackBase(TrackBase::AudioTrack, label, language, id) + , m_enabled(enabled) +{ + ScriptWrappable::init(this); + setKind(kind); +} + +AudioTrack::~AudioTrack() +{ +} + +void AudioTrack::setEnabled(bool enabled) +{ + if (enabled == m_enabled) + return; + + m_enabled = enabled; + + if (mediaElement()) + mediaElement()->audioTrackChanged(); +} + +const AtomicString& AudioTrack::alternativeKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("alternative", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& AudioTrack::descriptionsKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("descriptions", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& AudioTrack::mainKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("main", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& AudioTrack::mainDescriptionsKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("main-desc", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& AudioTrack::translationKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("translation", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& AudioTrack::commentaryKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("commentary", AtomicString::ConstructFromLiteral)); + return keyword; +} + +bool AudioTrack::isValidKind(const AtomicString& kind) const +{ + return (kind == alternativeKeyword()) + || (kind == descriptionsKeyword()) + || (kind == mainKeyword()) + || (kind == mainDescriptionsKeyword()) + || (kind == translationKeyword()) + || (kind == commentaryKeyword()); +} + +AtomicString AudioTrack::defaultKind() const +{ + return emptyAtom; +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.h b/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.h new file mode 100644 index 00000000000..dc690ca1dc6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.h @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef AudioTrack_h +#define AudioTrack_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/track/TrackBase.h" + +namespace WebCore { + +class AudioTrack FINAL : public TrackBase, public ScriptWrappable { +public: + static PassRefPtrWillBeRawPtr<AudioTrack> create(const String& id, const AtomicString& kind, const AtomicString& label, const AtomicString& language, bool enabled) + { + return adoptRefWillBeRefCountedGarbageCollected(new AudioTrack(id, kind, label, language, enabled)); + } + virtual ~AudioTrack(); + + bool enabled() const { return m_enabled; } + void setEnabled(bool); + + // Valid kind keywords. + static const AtomicString& alternativeKeyword(); + static const AtomicString& descriptionsKeyword(); + static const AtomicString& mainKeyword(); + static const AtomicString& mainDescriptionsKeyword(); + static const AtomicString& translationKeyword(); + static const AtomicString& commentaryKeyword(); + +private: + AudioTrack(const String& id, const AtomicString& kind, const AtomicString& label, const AtomicString& language, bool enabled); + + // TrackBase + virtual bool isValidKind(const AtomicString&) const OVERRIDE; + virtual AtomicString defaultKind() const OVERRIDE; + + bool m_enabled; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.idl b/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.idl new file mode 100644 index 00000000000..d5e0449c02e --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/AudioTrack.idl @@ -0,0 +1,15 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=AudioVideoTracks, + SetWrapperReferenceFrom=owner, + WillBeGarbageCollected, +] interface AudioTrack { + readonly attribute DOMString id; + readonly attribute DOMString kind; + readonly attribute DOMString label; + readonly attribute DOMString language; + attribute boolean enabled; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.cpp b/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.cpp new file mode 100644 index 00000000000..c4653cdf48b --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.cpp @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/track/AudioTrackList.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<AudioTrackList> AudioTrackList::create(HTMLMediaElement& mediaElement) +{ + return adoptRefWillBeRefCountedGarbageCollected(new AudioTrackList(mediaElement)); +} + +AudioTrackList::~AudioTrackList() +{ +} + +AudioTrackList::AudioTrackList(HTMLMediaElement& mediaElement) + : TrackListBase<AudioTrack>(&mediaElement) +{ + ScriptWrappable::init(this); +} + +bool AudioTrackList::hasEnabledTrack() const +{ + for (unsigned i = 0; i < length(); ++i) { + if (anonymousIndexedGetter(i)->enabled()) + return true; + } + + return false; +} + +const AtomicString& AudioTrackList::interfaceName() const +{ + return EventTargetNames::AudioTrackList; +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.h b/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.h new file mode 100644 index 00000000000..504de8be9cd --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef AudioTrackList_h +#define AudioTrackList_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/track/AudioTrack.h" +#include "core/html/track/TrackListBase.h" + +namespace WebCore { + +class AudioTrackList FINAL : public TrackListBase<AudioTrack>, public ScriptWrappable { +public: + static PassRefPtrWillBeRawPtr<AudioTrackList> create(HTMLMediaElement&); + + virtual ~AudioTrackList(); + + bool hasEnabledTrack() const; + + // EventTarget + virtual const AtomicString& interfaceName() const OVERRIDE; + +private: + explicit AudioTrackList(HTMLMediaElement&); +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.idl b/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.idl new file mode 100644 index 00000000000..6bcd4736ce5 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/AudioTrackList.idl @@ -0,0 +1,16 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=AudioVideoTracks, + SetWrapperReferenceFrom=owner, +] interface AudioTrackList : EventTarget { + readonly attribute unsigned long length; + getter AudioTrack (unsigned long index); + AudioTrack? getTrackById(DOMString id); + + attribute EventHandler onchange; + attribute EventHandler onaddtrack; + attribute EventHandler onremovetrack; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.cpp b/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.cpp index 925f84e7c9d..ce05095498b 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.cpp @@ -27,6 +27,7 @@ #include "core/html/track/InbandTextTrack.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/html/HTMLMediaElement.h" #include "core/html/track/vtt/VTTCue.h" #include "platform/Logging.h" #include "public/platform/WebInbandTextTrack.h" @@ -38,13 +39,13 @@ using blink::WebString; namespace WebCore { -PassRefPtr<InbandTextTrack> InbandTextTrack::create(Document& document, TextTrackClient* client, WebInbandTextTrack* webTrack) +PassRefPtrWillBeRawPtr<InbandTextTrack> InbandTextTrack::create(Document& document, WebInbandTextTrack* webTrack) { - return adoptRef(new InbandTextTrack(document, client, webTrack)); + return adoptRefWillBeRefCountedGarbageCollected(new InbandTextTrack(document, webTrack)); } -InbandTextTrack::InbandTextTrack(Document& document, TextTrackClient* client, WebInbandTextTrack* webTrack) - : TextTrack(document, client, emptyAtom, webTrack->label(), webTrack->language(), webTrack->id(), InBand) +InbandTextTrack::InbandTextTrack(Document& document, WebInbandTextTrack* webTrack) + : TextTrack(document, emptyAtom, webTrack->label(), webTrack->language(), webTrack->id(), InBand) , m_webTrack(webTrack) { m_webTrack->setClient(this); @@ -74,8 +75,13 @@ InbandTextTrack::InbandTextTrack(Document& document, TextTrackClient* client, We InbandTextTrack::~InbandTextTrack() { +#if ENABLE(OILPAN) + if (m_webTrack) + m_webTrack->setClient(0); +#else // Make sure m_webTrack was cleared by trackRemoved() before destruction. ASSERT(!m_webTrack); +#endif } size_t InbandTextTrack::inbandTrackIndex() @@ -84,17 +90,22 @@ size_t InbandTextTrack::inbandTrackIndex() return m_webTrack->textTrackIndex(); } -void InbandTextTrack::trackRemoved() +void InbandTextTrack::setTrackList(TextTrackList* trackList) { + TextTrack::setTrackList(trackList); + if (trackList) + return; + ASSERT(m_webTrack); m_webTrack->setClient(0); m_webTrack = 0; - clearClient(); } void InbandTextTrack::addWebVTTCue(double start, double end, const WebString& id, const WebString& content, const WebString& settings) { - RefPtr<VTTCue> cue = VTTCue::create(document(), start, end, content); + HTMLMediaElement* owner = mediaElement(); + ASSERT(owner); + RefPtrWillBeRawPtr<VTTCue> cue = VTTCue::create(owner->document(), start, end, content); cue->setId(id); cue->parseSettings(settings); addCue(cue); diff --git a/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.h b/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.h index 83948f0e77a..47d39f39555 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.h +++ b/chromium/third_party/WebKit/Source/core/html/track/InbandTextTrack.h @@ -27,6 +27,7 @@ #define InbandTextTrack_h #include "core/html/track/TextTrack.h" +#include "platform/heap/Handle.h" #include "public/platform/WebInbandTextTrackClient.h" #include "wtf/RefPtr.h" @@ -41,16 +42,16 @@ class Document; class MediaPlayer; class TextTrackCue; -class InbandTextTrack : public TextTrack, public blink::WebInbandTextTrackClient { +class InbandTextTrack FINAL : public TextTrack, public blink::WebInbandTextTrackClient { public: - static PassRefPtr<InbandTextTrack> create(Document&, TextTrackClient*, blink::WebInbandTextTrack*); + static PassRefPtrWillBeRawPtr<InbandTextTrack> create(Document&, blink::WebInbandTextTrack*); virtual ~InbandTextTrack(); size_t inbandTrackIndex(); - void trackRemoved(); + virtual void setTrackList(TextTrackList*) OVERRIDE FINAL; private: - InbandTextTrack(Document&, TextTrackClient*, blink::WebInbandTextTrack*); + InbandTextTrack(Document&, blink::WebInbandTextTrack*); virtual void addWebVTTCue(double, double, const blink::WebString&, const blink::WebString&, const blink::WebString&) OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.cpp b/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.cpp index 588c06c79ff..288ec204df8 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.cpp @@ -26,14 +26,18 @@ #include "config.h" #include "core/html/track/LoadableTextTrack.h" +#include "core/dom/ElementTraversal.h" +#include "core/html/HTMLMediaElement.h" #include "core/html/HTMLTrackElement.h" #include "core/html/track/TextTrackCueList.h" #include "core/html/track/vtt/VTTRegionList.h" namespace WebCore { +using namespace HTMLNames; + LoadableTextTrack::LoadableTextTrack(HTMLTrackElement* track) - : TextTrack(track->document(), track, emptyAtom, emptyAtom, emptyAtom, emptyAtom, TrackElement) + : TextTrack(track->document(), emptyAtom, emptyAtom, emptyAtom, emptyAtom, TrackElement) , m_trackElement(track) , m_loadTimer(this, &LoadableTextTrack::loadTimerFired) , m_isDefault(false) @@ -42,12 +46,26 @@ LoadableTextTrack::LoadableTextTrack(HTMLTrackElement* track) LoadableTextTrack::~LoadableTextTrack() { +#if !ENABLE(OILPAN) + ASSERT(!m_trackElement); +#endif } -void LoadableTextTrack::clearClient() +#if !ENABLE(OILPAN) +void LoadableTextTrack::clearTrackElement() { - m_trackElement = 0; - TextTrack::clearClient(); + m_trackElement = nullptr; +} +#endif + +void LoadableTextTrack::setMode(const AtomicString& mode) +{ + TextTrack::setMode(mode); + if (!m_trackElement) + return; + + if (m_trackElement->readyState() == HTMLTrackElement::NONE) + m_trackElement->scheduleLoad(); } void LoadableTextTrack::scheduleLoad(const KURL& url) @@ -72,7 +90,7 @@ void LoadableTextTrack::scheduleLoad(const KURL& url) // 3. Asynchronously run the remaining steps, while continuing with whatever task // was responsible for creating the text track or changing the text track mode. if (!m_loadTimer.isActive()) - m_loadTimer.startOneShot(0); + m_loadTimer.startOneShot(0, FROM_HERE); } void LoadableTextTrack::loadTimerFired(Timer<LoadableTextTrack>*) @@ -97,7 +115,7 @@ void LoadableTextTrack::newCuesAvailable(TextTrackLoader* loader) { ASSERT_UNUSED(loader, m_loader == loader); - Vector<RefPtr<VTTCue> > newCues; + WillBeHeapVector<RefPtrWillBeMember<VTTCue> > newCues; m_loader->getNewCues(newCues); if (!m_cues) @@ -105,11 +123,11 @@ void LoadableTextTrack::newCuesAvailable(TextTrackLoader* loader) for (size_t i = 0; i < newCues.size(); ++i) { newCues[i]->setTrack(this); - m_cues->add(newCues[i]); + m_cues->add(newCues[i].release()); } - if (client()) - client()->textTrackAddCues(this, m_cues.get()); + if (mediaElement()) + mediaElement()->textTrackAddCues(this, m_cues.get()); } void LoadableTextTrack::cueLoadingCompleted(TextTrackLoader* loader, bool loadingFailed) @@ -126,7 +144,7 @@ void LoadableTextTrack::newRegionsAvailable(TextTrackLoader* loader) { ASSERT_UNUSED(loader, m_loader == loader); - Vector<RefPtr<VTTRegion> > newRegions; + WillBeHeapVector<RefPtrWillBeMember<VTTRegion> > newRegions; m_loader->getNewRegions(newRegions); for (size_t i = 0; i < newRegions.size(); ++i) { @@ -141,10 +159,10 @@ size_t LoadableTextTrack::trackElementIndex() ASSERT(m_trackElement->parentNode()); size_t index = 0; - for (Node* node = m_trackElement->parentNode()->firstChild(); node; node = node->nextSibling()) { - if (!node->hasTagName(trackTag) || !node->parentNode()) + for (HTMLTrackElement* track = Traversal<HTMLTrackElement>::firstChild(*m_trackElement->parentNode()); track; track = Traversal<HTMLTrackElement>::nextSibling(*track)) { + if (!track->parentNode()) continue; - if (node == m_trackElement) + if (track == m_trackElement) return index; ++index; } @@ -153,5 +171,11 @@ size_t LoadableTextTrack::trackElementIndex() return 0; } -} // namespace WebCore +void LoadableTextTrack::trace(Visitor* visitor) +{ + visitor->trace(m_trackElement); + visitor->trace(m_loader); + TextTrack::trace(visitor); +} +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h b/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h index 487e7caab78..c99f4f1b3c6 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h +++ b/chromium/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h @@ -28,6 +28,7 @@ #include "core/html/track/TextTrack.h" #include "core/loader/TextTrackLoader.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" namespace WebCore { @@ -35,25 +36,30 @@ namespace WebCore { class HTMLTrackElement; class LoadableTextTrack; -class LoadableTextTrack : public TextTrack, private TextTrackLoaderClient { +class LoadableTextTrack FINAL : public TextTrack, private TextTrackLoaderClient { public: - static PassRefPtr<LoadableTextTrack> create(HTMLTrackElement* track) + static PassRefPtrWillBeRawPtr<LoadableTextTrack> create(HTMLTrackElement* track) { - return adoptRef(new LoadableTextTrack(track)); + return adoptRefWillBeRefCountedGarbageCollected(new LoadableTextTrack(track)); } virtual ~LoadableTextTrack(); void scheduleLoad(const KURL&); - // This shadows TextTrack::clearClient, but need not be virtual. - void clearClient(); + // TextTrack method. + virtual void setMode(const AtomicString&) OVERRIDE; size_t trackElementIndex(); HTMLTrackElement* trackElement() { return m_trackElement; } +#if !ENABLE(OILPAN) + void clearTrackElement(); +#endif virtual bool isDefault() const OVERRIDE { return m_isDefault; } virtual void setIsDefault(bool isDefault) OVERRIDE { m_isDefault = isDefault; } + virtual void trace(Visitor*) OVERRIDE; + private: // TextTrackLoaderClient virtual void newCuesAvailable(TextTrackLoader*) OVERRIDE; @@ -64,9 +70,11 @@ private: void loadTimerFired(Timer<LoadableTextTrack>*); - HTMLTrackElement* m_trackElement; + // FIXME: Oilpan: This should be a strong pointer once Member pointers + // into the Node hierarchy can be used. + RawPtrWillBeWeakMember<HTMLTrackElement> m_trackElement; Timer<LoadableTextTrack> m_loadTimer; - OwnPtr<TextTrackLoader> m_loader; + OwnPtrWillBeMember<TextTrackLoader> m_loader; KURL m_url; bool m_isDefault; }; diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrack.cpp b/chromium/third_party/WebKit/Source/core/html/track/TextTrack.cpp index 84dea3e44a3..cf5b51248b9 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrack.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrack.cpp @@ -32,7 +32,6 @@ #include "config.h" #include "core/html/track/TextTrack.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/dom/Document.h" @@ -42,6 +41,7 @@ #include "core/html/track/TextTrackList.h" #include "core/html/track/vtt/VTTRegion.h" #include "core/html/track/vtt/VTTRegionList.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { @@ -95,17 +95,12 @@ const AtomicString& TextTrack::showingKeyword() return ended; } -TextTrack::TextTrack(Document& document, TextTrackClient* client, const AtomicString& kind, const AtomicString& label, const AtomicString& language, const AtomicString& id, TextTrackType type) - : TrackBase(TrackBase::TextTrack) - , m_cues(0) - , m_regions(0) - , m_document(&document) - , m_mediaElement(0) - , m_label(label) - , m_language(language) - , m_id(id) +TextTrack::TextTrack(Document& document, const AtomicString& kind, const AtomicString& label, const AtomicString& language, const AtomicString& id, TextTrackType type) + : TrackBase(TrackBase::TextTrack, label, language, id) + , m_cues(nullptr) + , m_regions(nullptr) + , m_trackList(nullptr) , m_mode(disabledKeyword()) - , m_client(client) , m_trackType(type) , m_readinessState(NotLoaded) , m_trackIndex(invalidTrackIndex) @@ -118,19 +113,18 @@ TextTrack::TextTrack(Document& document, TextTrackClient* client, const AtomicSt TextTrack::~TextTrack() { - if (m_cues) { - if (m_client) - m_client->textTrackRemoveCues(this, m_cues.get()); +#if !ENABLE(OILPAN) + ASSERT(!m_trackList); + if (m_cues) { for (size_t i = 0; i < m_cues->length(); ++i) m_cues->item(i)->setTrack(0); } - if (m_regions) { for (size_t i = 0; i < m_regions->length(); ++i) m_regions->item(i)->setTrack(0); } - clearClient(); +#endif } bool TextTrack::isValidKindKeyword(const AtomicString& value) @@ -149,17 +143,22 @@ bool TextTrack::isValidKindKeyword(const AtomicString& value) return false; } -void TextTrack::setKind(const AtomicString& kind) +void TextTrack::setTrackList(TextTrackList* trackList) { - String oldKind = m_kind; + if (!trackList && mediaElement() && m_cues) + mediaElement()->textTrackRemoveCues(this, m_cues.get()); + + m_trackList = trackList; + invalidateTrackIndex(); +} - if (isValidKindKeyword(kind)) - m_kind = kind; - else - m_kind = subtitlesKeyword(); +void TextTrack::setKind(const AtomicString& newKind) +{ + AtomicString oldKind = kind(); + TrackBase::setKind(newKind); - if (m_client && oldKind != m_kind) - m_client->textTrackKindChanged(this); + if (mediaElement() && oldKind != kind()) + mediaElement()->textTrackKindChanged(this); } void TextTrack::setMode(const AtomicString& mode) @@ -173,8 +172,8 @@ void TextTrack::setMode(const AtomicString& mode) // If mode changes to disabled, remove this track's cues from the client // because they will no longer be accessible from the cues() function. - if (mode == disabledKeyword() && m_client && m_cues) - m_client->textTrackRemoveCues(this, m_cues.get()); + if (mode == disabledKeyword() && mediaElement() && m_cues) + mediaElement()->textTrackRemoveCues(this, m_cues.get()); if (mode != showingKeyword() && m_cues) for (size_t i = 0; i < m_cues->length(); ++i) @@ -182,8 +181,8 @@ void TextTrack::setMode(const AtomicString& mode) m_mode = mode; - if (m_client) - m_client->textTrackModeChanged(this); + if (mediaElement()) + mediaElement()->textTrackModeChanged(this); } TextTrackCueList* TextTrack::cues() @@ -203,13 +202,13 @@ void TextTrack::removeAllCues() if (!m_cues) return; - if (m_client) - m_client->textTrackRemoveCues(this, m_cues.get()); + if (mediaElement()) + mediaElement()->textTrackRemoveCues(this, m_cues.get()); for (size_t i = 0; i < m_cues->length(); ++i) m_cues->item(i)->setTrack(0); - m_cues = 0; + m_cues = nullptr; } TextTrackCueList* TextTrack::activeCues() const @@ -225,12 +224,12 @@ TextTrackCueList* TextTrack::activeCues() const return 0; } -void TextTrack::addCue(PassRefPtr<TextTrackCue> prpCue) +void TextTrack::addCue(PassRefPtrWillBeRawPtr<TextTrackCue> prpCue) { if (!prpCue) return; - RefPtr<TextTrackCue> cue = prpCue; + RefPtrWillBeRawPtr<TextTrackCue> cue = prpCue; // TODO(93143): Add spec-compliant behavior for negative time values. if (std::isnan(cue->startTime()) || std::isnan(cue->endTime()) || cue->startTime() < 0 || cue->endTime() < 0) @@ -250,8 +249,8 @@ void TextTrack::addCue(PassRefPtr<TextTrackCue> prpCue) cue->setTrack(this); ensureTextTrackCueList()->add(cue); - if (m_client) - m_client->textTrackAddCue(this, cue.get()); + if (mediaElement()) + mediaElement()->textTrackAddCue(this, cue.get()); } void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exceptionState) @@ -277,8 +276,8 @@ void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exceptionState) } cue->setTrack(0); - if (m_client) - m_client->textTrackRemoveCue(this, cue); + if (mediaElement()) + mediaElement()->textTrackRemoveCue(this, cue); } VTTRegionList* TextTrack::ensureVTTRegionList() @@ -302,12 +301,12 @@ VTTRegionList* TextTrack::regions() return 0; } -void TextTrack::addRegion(PassRefPtr<VTTRegion> prpRegion) +void TextTrack::addRegion(PassRefPtrWillBeRawPtr<VTTRegion> prpRegion) { if (!prpRegion) return; - RefPtr<VTTRegion> region = prpRegion; + RefPtrWillBeRawPtr<VTTRegion> region = prpRegion; VTTRegionList* regionList = ensureVTTRegionList(); // 1. If the given region is in a text track list of regions, then remove @@ -354,32 +353,32 @@ void TextTrack::removeRegion(VTTRegion* region, ExceptionState &exceptionState) void TextTrack::cueWillChange(TextTrackCue* cue) { - if (!m_client) + if (!mediaElement()) return; // The cue may need to be repositioned in the media element's interval tree, may need to // be re-rendered, etc, so remove it before the modification... - m_client->textTrackRemoveCue(this, cue); + mediaElement()->textTrackRemoveCue(this, cue); } void TextTrack::cueDidChange(TextTrackCue* cue) { - if (!m_client) + if (!mediaElement()) return; // Make sure the TextTrackCueList order is up-to-date. ensureTextTrackCueList()->updateCueIndex(cue); // ... and add it back again. - m_client->textTrackAddCue(this, cue); + mediaElement()->textTrackAddCue(this, cue); } int TextTrack::trackIndex() { - ASSERT(m_mediaElement); + ASSERT(m_trackList); if (m_trackIndex == invalidTrackIndex) - m_trackIndex = m_mediaElement->textTracks()->getTrackIndex(this); + m_trackIndex = m_trackList->getTrackIndex(this); return m_trackIndex; } @@ -392,7 +391,7 @@ void TextTrack::invalidateTrackIndex() bool TextTrack::isRendered() { - if (m_kind != captionsKeyword() && m_kind != subtitlesKeyword()) + if (kind() != captionsKeyword() && kind() != subtitlesKeyword()) return false; if (m_mode != showingKeyword()) @@ -411,10 +410,10 @@ TextTrackCueList* TextTrack::ensureTextTrackCueList() int TextTrack::trackIndexRelativeToRenderedTracks() { - ASSERT(m_mediaElement); + ASSERT(m_trackList); if (m_renderedTrackIndex == invalidTrackIndex) - m_renderedTrackIndex = m_mediaElement->textTracks()->getTrackIndexRelativeToRenderedTracks(this); + m_renderedTrackIndex = m_trackList->getTrackIndexRelativeToRenderedTracks(this); return m_renderedTrackIndex; } @@ -426,8 +425,27 @@ const AtomicString& TextTrack::interfaceName() const ExecutionContext* TextTrack::executionContext() const { - return m_document; + HTMLMediaElement* owner = mediaElement(); + return owner ? owner->executionContext() : 0; } -} // namespace WebCore +HTMLMediaElement* TextTrack::mediaElement() const +{ + return m_trackList ? m_trackList->owner() : 0; +} + +Node* TextTrack::owner() const +{ + return mediaElement(); +} +void TextTrack::trace(Visitor* visitor) +{ + visitor->trace(m_cues); + visitor->trace(m_regions); + visitor->trace(m_trackList); + TrackBase::trace(visitor); + EventTargetWithInlineData::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrack.h b/chromium/third_party/WebKit/Source/core/html/track/TextTrack.h index 721c55566b0..3be6bdf469a 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrack.h +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrack.h @@ -28,7 +28,9 @@ #define TextTrack_h #include "bindings/v8/ScriptWrappable.h" +#include "core/events/EventTarget.h" #include "core/html/track/TrackBase.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -39,33 +41,24 @@ class HTMLMediaElement; class TextTrack; class TextTrackCue; class TextTrackCueList; +class TextTrackList; class VTTRegion; class VTTRegionList; -class TextTrackClient { +class TextTrack : public TrackBase, public ScriptWrappable, public EventTargetWithInlineData { + REFCOUNTED_EVENT_TARGET(TrackBase); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TextTrack); public: - virtual ~TextTrackClient() { } - virtual void textTrackKindChanged(TextTrack*) = 0; - virtual void textTrackModeChanged(TextTrack*) = 0; - virtual void textTrackAddCues(TextTrack*, const TextTrackCueList*) = 0; - virtual void textTrackRemoveCues(TextTrack*, const TextTrackCueList*) = 0; - virtual void textTrackAddCue(TextTrack*, PassRefPtr<TextTrackCue>) = 0; - virtual void textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue>) = 0; -}; - -class TextTrack : public TrackBase, public ScriptWrappable { -public: - static PassRefPtr<TextTrack> create(Document& document, TextTrackClient* client, const AtomicString& kind, const AtomicString& label, const AtomicString& language) + static PassRefPtrWillBeRawPtr<TextTrack> create(Document& document, const AtomicString& kind, const AtomicString& label, const AtomicString& language) { - return adoptRef(new TextTrack(document, client, kind, label, language, emptyAtom, AddTrack)); + return adoptRefWillBeRefCountedGarbageCollected(new TextTrack(document, kind, label, language, emptyAtom, AddTrack)); } virtual ~TextTrack(); - void setMediaElement(HTMLMediaElement* element) { m_mediaElement = element; } - HTMLMediaElement* mediaElement() { return m_mediaElement; } + virtual void setTrackList(TextTrackList*); + TextTrackList* trackList() { return m_trackList; } - const AtomicString& kind() const { return m_kind; } - void setKind(const AtomicString&); + virtual void setKind(const AtomicString&) OVERRIDE; static const AtomicString& subtitlesKeyword(); static const AtomicString& captionsKeyword(); @@ -74,21 +67,12 @@ public: static const AtomicString& metadataKeyword(); static bool isValidKindKeyword(const AtomicString&); - AtomicString label() const { return m_label; } - void setLabel(const AtomicString& label) { m_label = label; } - - AtomicString language() const { return m_language; } - void setLanguage(const AtomicString& language) { m_language = language; } - - AtomicString id() const { return m_id; } - void setId(const AtomicString& id) { m_id = id; } - static const AtomicString& disabledKeyword(); static const AtomicString& hiddenKeyword(); static const AtomicString& showingKeyword(); AtomicString mode() const { return m_mode; } - void setMode(const AtomicString&); + virtual void setMode(const AtomicString&); enum ReadinessState { NotLoaded = 0, Loading = 1, Loaded = 2, FailedToLoad = 3 }; ReadinessState readinessState() const { return m_readinessState; } @@ -97,14 +81,14 @@ public: TextTrackCueList* cues(); TextTrackCueList* activeCues() const; - void clearClient() { m_client = 0; } - TextTrackClient* client() { return m_client; } + HTMLMediaElement* mediaElement() const; + Node* owner() const; - void addCue(PassRefPtr<TextTrackCue>); + void addCue(PassRefPtrWillBeRawPtr<TextTrackCue>); void removeCue(TextTrackCue*, ExceptionState&); VTTRegionList* regions(); - void addRegion(PassRefPtr<VTTRegion>); + void addRegion(PassRefPtrWillBeRawPtr<VTTRegion>); void removeRegion(VTTRegion*, ExceptionState&); void cueWillChange(TextTrackCue*); @@ -129,33 +113,28 @@ public: void removeAllCues(); - Document& document() const { return *m_document; } - // EventTarget methods virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + protected: - TextTrack(Document&, TextTrackClient*, const AtomicString& kind, const AtomicString& label, const AtomicString& language, const AtomicString& id, TextTrackType); + TextTrack(Document&, const AtomicString& kind, const AtomicString& label, const AtomicString& language, const AtomicString& id, TextTrackType); - RefPtr<TextTrackCueList> m_cues; + virtual bool isValidKind(const AtomicString& kind) const OVERRIDE { return isValidKindKeyword(kind); } + virtual AtomicString defaultKind() const OVERRIDE { return subtitlesKeyword(); } + + RefPtrWillBeMember<TextTrackCueList> m_cues; private: VTTRegionList* ensureVTTRegionList(); - RefPtr<VTTRegionList> m_regions; + RefPtrWillBeMember<VTTRegionList> m_regions; TextTrackCueList* ensureTextTrackCueList(); - // FIXME: Remove this pointer and get the Document from m_client - Document* m_document; - - HTMLMediaElement* m_mediaElement; - AtomicString m_kind; - AtomicString m_label; - AtomicString m_language; - AtomicString m_id; + RawPtrWillBeMember<TextTrackList> m_trackList; AtomicString m_mode; - TextTrackClient* m_client; TextTrackType m_trackType; ReadinessState m_readinessState; int m_trackIndex; diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrack.idl b/chromium/third_party/WebKit/Source/core/html/track/TextTrack.idl index a64462d028f..9a75f4b0def 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrack.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrack.idl @@ -27,7 +27,8 @@ enum TextTrackMode { "disabled", "hidden", "showing" }; enum TextTrackKind { "subtitles", "captions", "descriptions", "chapters", "metadata" }; [ - RuntimeEnabled=VideoTrack + SetWrapperReferenceFrom=owner, + WillBeGarbageCollected, ] interface TextTrack : EventTarget { readonly attribute TextTrackKind kind; readonly attribute DOMString label; diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.cpp b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.cpp index cfb2effe24b..bdb32505bb7 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.cpp @@ -42,20 +42,11 @@ namespace WebCore { static const int invalidCueIndex = -1; -bool TextTrackCue::isInfiniteOrNonNumber(double value, ExceptionState& exceptionState) -{ - if (!std::isfinite(value)) { - exceptionState.throwTypeError(ExceptionMessages::notAFiniteNumber(value)); - return true; - } - return false; -} - TextTrackCue::TextTrackCue(double start, double end) : m_startTime(start) , m_endTime(end) , m_cueIndex(invalidCueIndex) - , m_track(0) + , m_track(nullptr) , m_isActive(false) , m_pauseOnExit(false) { @@ -83,7 +74,12 @@ void TextTrackCue::setTrack(TextTrack* track) m_track = track; } -void TextTrackCue::setId(const String& id) +Node* TextTrackCue::owner() const +{ + return m_track ? m_track->owner() : 0; +} + +void TextTrackCue::setId(const AtomicString& id) { if (m_id == id) return; @@ -93,12 +89,8 @@ void TextTrackCue::setId(const String& id) cueDidChange(); } -void TextTrackCue::setStartTime(double value, ExceptionState& exceptionState) +void TextTrackCue::setStartTime(double value) { - // NaN, Infinity and -Infinity values should trigger a TypeError. - if (isInfiniteOrNonNumber(value, exceptionState)) - return; - // TODO(93143): Add spec-compliant behavior for negative time values. if (m_startTime == value || value < 0) return; @@ -108,12 +100,8 @@ void TextTrackCue::setStartTime(double value, ExceptionState& exceptionState) cueDidChange(); } -void TextTrackCue::setEndTime(double value, ExceptionState& exceptionState) +void TextTrackCue::setEndTime(double value) { - // NaN, Infinity and -Infinity values should trigger a TypeError. - if (isInfiniteOrNonNumber(value, exceptionState)) - return; - // TODO(93143): Add spec-compliant behavior for negative time values. if (m_endTime == value || value < 0) return; @@ -146,7 +134,7 @@ void TextTrackCue::invalidateCueIndex() m_cueIndex = invalidCueIndex; } -bool TextTrackCue::dispatchEvent(PassRefPtr<Event> event) +bool TextTrackCue::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { // When a TextTrack's mode is disabled: no cues are active, no events fired. if (!track() || track()->mode() == TextTrack::disabledKeyword()) @@ -174,4 +162,10 @@ const AtomicString& TextTrackCue::interfaceName() const return EventTargetNames::TextTrackCue; } +void TextTrackCue::trace(Visitor* visitor) +{ + visitor->trace(m_track); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.h b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.h index 1779e37a7d1..dd2d235b732 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.h +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.h @@ -34,17 +34,17 @@ #include "core/events/EventTarget.h" #include "core/html/HTMLDivElement.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" namespace WebCore { class ExceptionState; -class TextTrackCue : public RefCounted<TextTrackCue>, public EventTargetWithInlineData { +class TextTrackCue : public RefCountedWillBeRefCountedGarbageCollected<TextTrackCue>, public EventTargetWithInlineData { REFCOUNTED_EVENT_TARGET(TextTrackCue); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TextTrackCue); public: - static bool isInfiniteOrNonNumber(double value, ExceptionState&); - static const AtomicString& cueShadowPseudoId() { DEFINE_STATIC_LOCAL(const AtomicString, cue, ("cue", AtomicString::ConstructFromLiteral)); @@ -56,14 +56,16 @@ public: TextTrack* track() const; void setTrack(TextTrack*); - const String& id() const { return m_id; } - void setId(const String&); + Node* owner() const; + + const AtomicString& id() const { return m_id; } + void setId(const AtomicString&); double startTime() const { return m_startTime; } - void setStartTime(double, ExceptionState&); + void setStartTime(double); double endTime() const { return m_endTime; } - void setEndTime(double, ExceptionState&); + void setEndTime(double); bool pauseOnExit() const { return m_pauseOnExit; } void setPauseOnExit(bool); @@ -72,7 +74,7 @@ public: void invalidateCueIndex(); using EventTarget::dispatchEvent; - virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; + virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE; bool isActive(); void setIsActive(bool); @@ -94,6 +96,8 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(enter); DEFINE_ATTRIBUTE_EVENT_LISTENER(exit); + virtual void trace(Visitor*) OVERRIDE; + protected: TextTrackCue(double start, double end); @@ -101,12 +105,12 @@ protected: virtual void cueDidChange(); private: - String m_id; + AtomicString m_id; double m_startTime; double m_endTime; int m_cueIndex; - TextTrack* m_track; + RawPtrWillBeMember<TextTrack> m_track; bool m_isActive : 1; bool m_pauseOnExit : 1; diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.idl b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.idl index efc18e3e60a..d243c43edec 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCue.idl @@ -23,18 +23,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#texttrackcue + [ Custom=ToV8, - CustomConstructor(double startTime, double endTime, DOMString text), - RuntimeEnabled=VideoTrack, + SetWrapperReferenceFrom=owner, + TypeChecking=Unrestricted, + WillBeGarbageCollected, ] interface TextTrackCue : EventTarget { - readonly attribute TextTrack track; + readonly attribute TextTrack track; // FIXME: should be nullable - attribute DOMString id; - [RaisesException=Setter] attribute double startTime; - [RaisesException=Setter] attribute double endTime; - attribute boolean pauseOnExit; + attribute DOMString id; + attribute double startTime; + attribute double endTime; + attribute boolean pauseOnExit; - attribute EventHandler onenter; - attribute EventHandler onexit; + attribute EventHandler onenter; + attribute EventHandler onexit; }; diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp index 43fa9b55c40..a3dba2dc76b 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp @@ -51,7 +51,7 @@ TextTrackCue* TextTrackCueList::item(unsigned index) const return 0; } -TextTrackCue* TextTrackCueList::getCueById(const String& id) const +TextTrackCue* TextTrackCueList::getCueById(const AtomicString& id) const { for (size_t i = 0; i < m_list.size(); ++i) { if (m_list[i]->id() == id) @@ -67,14 +67,14 @@ TextTrackCueList* TextTrackCueList::activeCues() m_activeCues->clear(); for (size_t i = 0; i < m_list.size(); ++i) { - RefPtr<TextTrackCue> cue = m_list[i]; + RefPtrWillBeRawPtr<TextTrackCue> cue = m_list[i]; if (cue->isActive()) m_activeCues->add(cue); } return m_activeCues.get(); } -bool TextTrackCueList::add(PassRefPtr<TextTrackCue> cue) +bool TextTrackCueList::add(PassRefPtrWillBeRawPtr<TextTrackCue> cue) { ASSERT(cue->startTime() >= 0); ASSERT(cue->endTime() >= 0); @@ -82,14 +82,14 @@ bool TextTrackCueList::add(PassRefPtr<TextTrackCue> cue) return add(cue, 0, m_list.size()); } -bool TextTrackCueList::add(PassRefPtr<TextTrackCue> prpCue, size_t start, size_t end) +bool TextTrackCueList::add(PassRefPtrWillBeRawPtr<TextTrackCue> prpCue, size_t start, size_t end) { ASSERT_WITH_SECURITY_IMPLICATION(start <= m_list.size()); ASSERT_WITH_SECURITY_IMPLICATION(end <= m_list.size()); // Maintain text track cue order: // http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-order - RefPtr<TextTrackCue> cue = prpCue; + RefPtrWillBeRawPtr<TextTrackCue> cue = prpCue; if (start == end) { if (!m_list.isEmpty() && (start > 0) && (m_list[start - 1].get() == cue.get())) return false; @@ -142,5 +142,11 @@ void TextTrackCueList::invalidateCueIndexes(size_t start) m_list[i]->invalidateCueIndex(); } +void TextTrackCueList::trace(Visitor* visitor) +{ + visitor->trace(m_list); + visitor->trace(m_activeCues); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.h b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.h index b209fcf6e26..ace42e12f6b 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.h +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.h @@ -34,11 +34,11 @@ namespace WebCore { -class TextTrackCueList : public RefCounted<TextTrackCueList>, public ScriptWrappable { +class TextTrackCueList FINAL : public RefCountedWillBeGarbageCollectedFinalized<TextTrackCueList>, public ScriptWrappable { public: - static PassRefPtr<TextTrackCueList> create() + static PassRefPtrWillBeRawPtr<TextTrackCueList> create() { - return adoptRef(new TextTrackCueList); + return adoptRefWillBeNoop(new TextTrackCueList); } ~TextTrackCueList() { } @@ -47,23 +47,25 @@ public: unsigned long getCueIndex(TextTrackCue*) const; TextTrackCue* item(unsigned index) const; - TextTrackCue* getCueById(const String&) const; + TextTrackCue* getCueById(const AtomicString&) const; TextTrackCueList* activeCues(); - bool add(PassRefPtr<TextTrackCue>); + bool add(PassRefPtrWillBeRawPtr<TextTrackCue>); bool remove(TextTrackCue*); bool contains(TextTrackCue*) const; bool updateCueIndex(TextTrackCue*); + void trace(Visitor*); + private: TextTrackCueList(); - bool add(PassRefPtr<TextTrackCue>, size_t, size_t); + bool add(PassRefPtrWillBeRawPtr<TextTrackCue>, size_t, size_t); void clear(); void invalidateCueIndexes(size_t); - Vector<RefPtr<TextTrackCue> > m_list; - RefPtr<TextTrackCueList> m_activeCues; + WillBeHeapVector<RefPtrWillBeMember<TextTrackCue> > m_list; + RefPtrWillBeMember<TextTrackCueList> m_activeCues; }; diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.idl b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.idl index a71d6875ddb..6ea59a645cd 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackCueList.idl @@ -24,7 +24,7 @@ */ [ - RuntimeEnabled=VideoTrack + WillBeGarbageCollected, ] interface TextTrackCueList { readonly attribute unsigned long length; getter TextTrackCue item(unsigned long index); diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.cpp b/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.cpp index 0d00ba33fee..0738c95e7ba 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.cpp @@ -28,7 +28,6 @@ #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/events/GenericEventQueue.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/html/HTMLMediaElement.h" #include "core/html/track/InbandTextTrack.h" #include "core/html/track/LoadableTextTrack.h" @@ -46,7 +45,18 @@ TextTrackList::TextTrackList(HTMLMediaElement* owner) TextTrackList::~TextTrackList() { +#if !ENABLE(OILPAN) + ASSERT(!m_owner); + + // TextTrackList and m_asyncEventQueue always become unreachable + // together. So TextTrackList and m_asyncEventQueue are destructed in the + // same GC. We don't need to close it explicitly in Oilpan. m_asyncEventQueue->close(); + + for (unsigned i = 0; i < length(); ++i) { + item(i)->setTrackList(0); + } +#endif } unsigned TextTrackList::length() const @@ -148,7 +158,7 @@ TextTrack* TextTrackList::getTrackById(const AtomicString& id) void TextTrackList::invalidateTrackIndexesAfterTrack(TextTrack* track) { - Vector<RefPtr<TextTrack> >* tracks = 0; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> >* tracks = 0; if (track->trackType() == TextTrack::TrackElement) { tracks = &m_elementTracks; @@ -173,9 +183,9 @@ void TextTrackList::invalidateTrackIndexesAfterTrack(TextTrack* track) tracks->at(index)->invalidateTrackIndex(); } -void TextTrackList::append(PassRefPtr<TextTrack> prpTrack) +void TextTrackList::append(PassRefPtrWillBeRawPtr<TextTrack> prpTrack) { - RefPtr<TextTrack> track = prpTrack; + RefPtrWillBeRawPtr<TextTrack> track = prpTrack; if (track->trackType() == TextTrack::AddTrack) m_addTrackTracks.append(track); @@ -192,16 +202,15 @@ void TextTrackList::append(PassRefPtr<TextTrack> prpTrack) invalidateTrackIndexesAfterTrack(track.get()); - ASSERT(!track->mediaElement() || track->mediaElement() == m_owner); - track->setMediaElement(m_owner); + ASSERT(!track->trackList()); + track->setTrackList(this); scheduleAddTrackEvent(track.release()); } void TextTrackList::remove(TextTrack* track) { - Vector<RefPtr<TextTrack> >* tracks = 0; - RefPtr<InbandTextTrack> inbandTrack; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> >* tracks = 0; if (track->trackType() == TextTrack::TrackElement) { tracks = &m_elementTracks; @@ -209,7 +218,6 @@ void TextTrackList::remove(TextTrack* track) tracks = &m_addTrackTracks; } else if (track->trackType() == TextTrack::InBand) { tracks = &m_inbandTracks; - inbandTrack = static_cast<InbandTextTrack*>(track); } else { ASSERT_NOT_REACHED(); } @@ -220,20 +228,25 @@ void TextTrackList::remove(TextTrack* track) invalidateTrackIndexesAfterTrack(track); - ASSERT(track->mediaElement() == m_owner); - track->setMediaElement(0); + ASSERT(track->trackList() == this); + track->setTrackList(0); tracks->remove(index); - if (inbandTrack) - inbandTrack->trackRemoved(); - scheduleRemoveTrackEvent(track); } +void TextTrackList::removeAllInbandTracks() +{ + for (unsigned i = 0; i < m_inbandTracks.size(); ++i) { + m_inbandTracks[i]->setTrackList(0); + } + m_inbandTracks.clear(); +} + bool TextTrackList::contains(TextTrack* track) const { - const Vector<RefPtr<TextTrack> >* tracks = 0; + const WillBeHeapVector<RefPtrWillBeMember<TextTrack> >* tracks = 0; if (track->trackType() == TextTrack::TrackElement) tracks = &m_elementTracks; @@ -254,11 +267,17 @@ const AtomicString& TextTrackList::interfaceName() const ExecutionContext* TextTrackList::executionContext() const { - ASSERT(m_owner); - return m_owner->executionContext(); + return m_owner ? m_owner->executionContext() : 0; +} + +#if !ENABLE(OILPAN) +void TextTrackList::clearOwner() +{ + m_owner = nullptr; } +#endif -void TextTrackList::scheduleTrackEvent(const AtomicString& eventName, PassRefPtr<TextTrack> track) +void TextTrackList::scheduleTrackEvent(const AtomicString& eventName, PassRefPtrWillBeRawPtr<TextTrack> track) { TrackEventInit initializer; initializer.track = track; @@ -268,7 +287,7 @@ void TextTrackList::scheduleTrackEvent(const AtomicString& eventName, PassRefPtr m_asyncEventQueue->enqueueEvent(TrackEvent::create(eventName, initializer)); } -void TextTrackList::scheduleAddTrackEvent(PassRefPtr<TextTrack> track) +void TextTrackList::scheduleAddTrackEvent(PassRefPtrWillBeRawPtr<TextTrack> track) { // 4.8.10.12.3 Sourcing out-of-band text tracks // 4.8.10.12.4 Text track API @@ -296,7 +315,7 @@ void TextTrackList::scheduleChangeEvent() m_asyncEventQueue->enqueueEvent(Event::create(EventTypeNames::change, initializer)); } -void TextTrackList::scheduleRemoveTrackEvent(PassRefPtr<TextTrack> track) +void TextTrackList::scheduleRemoveTrackEvent(PassRefPtrWillBeRawPtr<TextTrack> track) { // 4.8.10.12.3 Sourcing out-of-band text tracks // When a track element's parent element changes and the old parent was a @@ -310,7 +329,17 @@ void TextTrackList::scheduleRemoveTrackEvent(PassRefPtr<TextTrack> track) scheduleTrackEvent(EventTypeNames::removetrack, track); } -Node* TextTrackList::owner() const +HTMLMediaElement* TextTrackList::owner() const { return m_owner; } + +void TextTrackList::trace(Visitor* visitor) +{ + visitor->trace(m_owner); + visitor->trace(m_asyncEventQueue); + visitor->trace(m_addTrackTracks); + visitor->trace(m_elementTracks); + visitor->trace(m_inbandTracks); + EventTargetWithInlineData::trace(visitor); +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.h b/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.h index 7c150b2c931..a544f24761c 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.h +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.h @@ -29,7 +29,9 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/events/EventListener.h" #include "core/events/EventTarget.h" +#include "core/html/HTMLMediaElement.h" #include "platform/Timer.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" @@ -37,18 +39,17 @@ namespace WebCore { class GenericEventQueue; -class HTMLMediaElement; class TextTrack; -class TextTrackList; -class TextTrackList : public RefCounted<TextTrackList>, public ScriptWrappable, public EventTargetWithInlineData { +class TextTrackList FINAL : public RefCountedWillBeRefCountedGarbageCollected<TextTrackList>, public ScriptWrappable, public EventTargetWithInlineData { REFCOUNTED_EVENT_TARGET(TextTrackList); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TextTrackList); public: - static PassRefPtr<TextTrackList> create(HTMLMediaElement* owner) + static PassRefPtrWillBeRawPtr<TextTrackList> create(HTMLMediaElement* owner) { - return adoptRef(new TextTrackList(owner)); + return adoptRefWillBeRefCountedGarbageCollected(new TextTrackList(owner)); } - ~TextTrackList(); + virtual ~TextTrackList(); unsigned length() const; int getTrackIndex(TextTrack*); @@ -57,7 +58,7 @@ public: TextTrack* item(unsigned index); TextTrack* getTrackById(const AtomicString& id); - void append(PassRefPtr<TextTrack>); + void append(PassRefPtrWillBeRawPtr<TextTrack>); void remove(TextTrack*); // EventTarget @@ -68,28 +69,33 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(change); DEFINE_ATTRIBUTE_EVENT_LISTENER(removetrack); - void clearOwner() { m_owner = 0; } - Node* owner() const; +#if !ENABLE(OILPAN) + void clearOwner(); +#endif + HTMLMediaElement* owner() const; void scheduleChangeEvent(); + void removeAllInbandTracks(); + + virtual void trace(Visitor*) OVERRIDE; private: explicit TextTrackList(HTMLMediaElement*); - void scheduleTrackEvent(const AtomicString& eventName, PassRefPtr<TextTrack>); + void scheduleTrackEvent(const AtomicString& eventName, PassRefPtrWillBeRawPtr<TextTrack>); - void scheduleAddTrackEvent(PassRefPtr<TextTrack>); - void scheduleRemoveTrackEvent(PassRefPtr<TextTrack>); + void scheduleAddTrackEvent(PassRefPtrWillBeRawPtr<TextTrack>); + void scheduleRemoveTrackEvent(PassRefPtrWillBeRawPtr<TextTrack>); void invalidateTrackIndexesAfterTrack(TextTrack*); - HTMLMediaElement* m_owner; + RawPtrWillBeMember<HTMLMediaElement> m_owner; - OwnPtr<GenericEventQueue> m_asyncEventQueue; + OwnPtrWillBeMember<GenericEventQueue> m_asyncEventQueue; - Vector<RefPtr<TextTrack> > m_addTrackTracks; - Vector<RefPtr<TextTrack> > m_elementTracks; - Vector<RefPtr<TextTrack> > m_inbandTracks; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> > m_addTrackTracks; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> > m_elementTracks; + WillBeHeapVector<RefPtrWillBeMember<TextTrack> > m_inbandTracks; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.idl b/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.idl index bbcd2d96499..8fbc775a993 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/TextTrackList.idl @@ -24,15 +24,13 @@ */ [ - GenerateVisitDOMWrapper=owner, - RuntimeEnabled=VideoTrack, + SetWrapperReferenceFrom=owner, ] interface TextTrackList : EventTarget { readonly attribute unsigned long length; getter TextTrack item(unsigned long index); - TextTrack getTrackById(DOMString id); + TextTrack? getTrackById(DOMString id); attribute EventHandler onaddtrack; attribute EventHandler onchange; attribute EventHandler onremovetrack; }; - diff --git a/chromium/third_party/WebKit/Source/core/html/ime/Composition.cpp b/chromium/third_party/WebKit/Source/core/html/track/TrackBase.cpp index 17250b38ba6..a63849b253f 100644 --- a/chromium/third_party/WebKit/Source/core/html/ime/Composition.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/TrackBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013 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 @@ -29,55 +29,52 @@ */ #include "config.h" -#include "core/html/ime/Composition.h" +#include "core/html/track/TrackBase.h" -#include "core/html/ime/InputMethodContext.h" +#include "core/html/HTMLMediaElement.h" namespace WebCore { -Composition::~Composition() +static blink::WebMediaPlayer::TrackId nextTrackId() { + static blink::WebMediaPlayer::TrackId next = 0; + return ++next; } -void Composition::ref() +TrackBase::TrackBase(Type type, const AtomicString& label, const AtomicString& language, const String& id) + : m_trackId(nextTrackId()) + , m_type(type) + , m_label(label) + , m_language(language) + , m_id(id) + , m_mediaElement(nullptr) { - m_inputMethodContext->ref(); } -void Composition::deref() +TrackBase::~TrackBase() { - m_inputMethodContext->deref(); +#if !ENABLE(OILPAN) + ASSERT(!m_mediaElement); +#endif } -PassOwnPtr<Composition> Composition::create(InputMethodContext* context) -{ - return adoptPtr(new Composition(context)); -} - -Composition::Composition(InputMethodContext* context) - : m_inputMethodContext(context) -{ - ScriptWrappable::init(this); -} - -String Composition::text() const -{ - return m_inputMethodContext->compositionText(); -} -int Composition::selectionStart() const +Node* TrackBase::owner() const { - return m_inputMethodContext->selectionStart(); + return m_mediaElement; } -int Composition::selectionEnd() const +void TrackBase::trace(Visitor* visitor) { - return m_inputMethodContext->selectionEnd(); + visitor->trace(m_mediaElement); } -const Vector<unsigned>& Composition::getSegments() const +void TrackBase::setKind(const AtomicString& kind) { - return m_inputMethodContext->segments(); + if (isValidKind(kind)) + m_kind = kind; + else + m_kind = defaultKind(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TrackBase.h b/chromium/third_party/WebKit/Source/core/html/track/TrackBase.h index 38ead6489f0..cff2b8a6562 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TrackBase.h +++ b/chromium/third_party/WebKit/Source/core/html/track/TrackBase.h @@ -26,24 +26,56 @@ #ifndef TrackBase_h #define TrackBase_h -#include "core/events/EventTarget.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebMediaPlayer.h" #include "wtf/RefCounted.h" +#include "wtf/text/AtomicString.h" namespace WebCore { -class TrackBase : public RefCounted<TrackBase>, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(TrackBase); +class HTMLMediaElement; + +class TrackBase : public RefCountedWillBeRefCountedGarbageCollected<TrackBase> { public: - virtual ~TrackBase() { } + virtual ~TrackBase(); + + blink::WebMediaPlayer::TrackId trackId() const { return m_trackId; } enum Type { TextTrack, AudioTrack, VideoTrack }; Type type() const { return m_type; } + const AtomicString& kind() const { return m_kind; } + virtual void setKind(const AtomicString&); + + AtomicString label() const { return m_label; } + void setLabel(const AtomicString& label) { m_label = label; } + + AtomicString language() const { return m_language; } + void setLanguage(const AtomicString& language) { m_language = language; } + + String id() const { return m_id; } + void setId(const String& id) { m_id = id; } + + void setMediaElement(HTMLMediaElement* mediaElement) { m_mediaElement = mediaElement; } + HTMLMediaElement* mediaElement() const { return m_mediaElement; } + Node* owner() const; + + virtual void trace(Visitor*); + protected: - explicit TrackBase(Type type) : m_type(type) { } + TrackBase(Type, const AtomicString& label, const AtomicString& language, const String& id); + + virtual bool isValidKind(const AtomicString&) const = 0; + virtual AtomicString defaultKind() const = 0; private: + blink::WebMediaPlayer::TrackId m_trackId; Type m_type; + AtomicString m_kind; + AtomicString m_label; + AtomicString m_language; + String m_id; + RawPtrWillBeMember<HTMLMediaElement> m_mediaElement; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.cpp b/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.cpp index 39d70bd1961..12d9263eb33 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.cpp @@ -27,8 +27,6 @@ #include "core/html/track/TrackEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { TrackEventInit::TrackEventInit() @@ -57,5 +55,11 @@ const AtomicString& TrackEvent::interfaceName() const return EventNames::TrackEvent; } +void TrackEvent::trace(Visitor* visitor) +{ + visitor->trace(m_track); + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.h b/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.h index 606bc1488cc..b77be6b7998 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.h +++ b/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.h @@ -34,32 +34,34 @@ namespace WebCore { struct TrackEventInit : public EventInit { TrackEventInit(); - RefPtr<TrackBase> track; + RefPtrWillBeMember<TrackBase> track; }; -class TrackEvent : public Event { +class TrackEvent FINAL : public Event { public: virtual ~TrackEvent(); - static PassRefPtr<TrackEvent> create() + static PassRefPtrWillBeRawPtr<TrackEvent> create() { - return adoptRef(new TrackEvent); + return adoptRefWillBeNoop(new TrackEvent); } - static PassRefPtr<TrackEvent> create(const AtomicString& type, const TrackEventInit& initializer) + static PassRefPtrWillBeRawPtr<TrackEvent> create(const AtomicString& type, const TrackEventInit& initializer) { - return adoptRef(new TrackEvent(type, initializer)); + return adoptRefWillBeNoop(new TrackEvent(type, initializer)); } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; TrackBase* track() const { return m_track.get(); } + virtual void trace(Visitor*) OVERRIDE; + private: TrackEvent(); TrackEvent(const AtomicString& type, const TrackEventInit& initializer); - RefPtr<TrackBase> m_track; + RefPtrWillBeMember<TrackBase> m_track; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.idl b/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.idl index eed92389f38..38ad03dcdd8 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/TrackEvent.idl @@ -24,9 +24,7 @@ */ [ - RuntimeEnabled=VideoTrack, EventConstructor, ] interface TrackEvent : Event { [InitializedByEventConstructor, Custom=Getter] readonly attribute object track; -}; - +};
\ No newline at end of file diff --git a/chromium/third_party/WebKit/Source/core/html/track/TrackListBase.h b/chromium/third_party/WebKit/Source/core/html/track/TrackListBase.h new file mode 100644 index 00000000000..24405a482d7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/TrackListBase.h @@ -0,0 +1,139 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TrackListBase_h +#define TrackListBase_h + +#include "core/events/EventTarget.h" + +#include "core/html/HTMLMediaElement.h" +#include "core/html/track/TrackEvent.h" + +namespace WebCore { + +template<class T> +class TrackListBase : public RefCountedWillBeRefCountedGarbageCollected<TrackListBase<T> >, public EventTargetWithInlineData { + REFCOUNTED_EVENT_TARGET(TrackListBase); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TrackListBase); +public: + explicit TrackListBase(HTMLMediaElement* mediaElement) + : m_mediaElement(mediaElement) + { + } + + virtual ~TrackListBase() + { +#if !ENABLE(OILPAN) + ASSERT(m_tracks.isEmpty()); + ASSERT(!m_mediaElement); +#endif + } + + unsigned length() const { return m_tracks.size(); } + T* anonymousIndexedGetter(unsigned index) const + { + if (index >= m_tracks.size()) + return 0; + return m_tracks[index].get(); + } + + T* getTrackById(const String& id) const + { + for (unsigned i = 0; i < m_tracks.size(); ++i) { + if (m_tracks[i]->id() == id) + return m_tracks[i].get(); + } + + return 0; + } + + DEFINE_ATTRIBUTE_EVENT_LISTENER(change); + DEFINE_ATTRIBUTE_EVENT_LISTENER(addtrack); + DEFINE_ATTRIBUTE_EVENT_LISTENER(removetrack); + + // EventTarget interface + virtual ExecutionContext* executionContext() const OVERRIDE + { + if (m_mediaElement) + return m_mediaElement->executionContext(); + return 0; + } + +#if !ENABLE(OILPAN) + void shutdown() + { + removeAll(); + m_mediaElement = nullptr; + } +#endif + + void add(PassRefPtrWillBeRawPtr<T> prpTrack) + { + RefPtrWillBeRawPtr<T> track = prpTrack; + + track->setMediaElement(m_mediaElement); + m_tracks.append(track); + scheduleTrackEvent(EventTypeNames::addtrack, track.release()); + } + + void remove(blink::WebMediaPlayer::TrackId trackId) + { + for (unsigned i = 0; i < m_tracks.size(); ++i) { + if (m_tracks[i]->trackId() != trackId) + continue; + + m_tracks[i]->setMediaElement(0); + scheduleTrackEvent(EventTypeNames::removetrack, m_tracks[i]); + m_tracks.remove(i); + return; + } + ASSERT_NOT_REACHED(); + } + + void removeAll() + { + for (unsigned i = 0; i < m_tracks.size(); ++i) + m_tracks[i]->setMediaElement(0); + + m_tracks.clear(); + } + + void scheduleChangeEvent() + { + EventInit initializer; + initializer.bubbles = false; + initializer.cancelable = false; + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::change, initializer); + event->setTarget(this); + m_mediaElement->scheduleEvent(event); + } + + Node* owner() const { return m_mediaElement; } + + void trace(Visitor* visitor) + { + visitor->trace(m_tracks); + visitor->trace(m_mediaElement); + EventTargetWithInlineData::trace(visitor); + } + +private: + void scheduleTrackEvent(const AtomicString& eventName, PassRefPtrWillBeRawPtr<T> track) + { + TrackEventInit initializer; + initializer.track = track; + initializer.bubbles = false; + initializer.cancelable = false; + RefPtrWillBeRawPtr<Event> event = TrackEvent::create(eventName, initializer); + event->setTarget(this); + m_mediaElement->scheduleEvent(event); + } + + WillBeHeapVector<RefPtrWillBeMember<T> > m_tracks; + RawPtrWillBeMember<HTMLMediaElement> m_mediaElement; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.cpp b/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.cpp new file mode 100644 index 00000000000..5a93e6ed0f7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.cpp @@ -0,0 +1,88 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/track/VideoTrack.h" + +#include "core/html/HTMLMediaElement.h" + +namespace WebCore { + +VideoTrack::VideoTrack(const String& id, const AtomicString& kind, const AtomicString& label, const AtomicString& language, bool selected) + : TrackBase(TrackBase::VideoTrack, label, language, id) + , m_selected(selected) +{ + ScriptWrappable::init(this); + setKind(kind); +} + +VideoTrack::~VideoTrack() +{ +} + +void VideoTrack::setSelected(bool selected) +{ + if (selected == m_selected) + return; + + m_selected = selected; + + if (mediaElement()) { + blink::WebMediaPlayer::TrackId selectedTrackId = trackId(); + mediaElement()->selectedVideoTrackChanged(selected ? &selectedTrackId : 0); + } +} + +const AtomicString& VideoTrack::alternativeKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("alternative", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& VideoTrack::captionsKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("captions", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& VideoTrack::mainKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("main", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& VideoTrack::signKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("sign", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& VideoTrack::subtitlesKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("subtitles", AtomicString::ConstructFromLiteral)); + return keyword; +} + +const AtomicString& VideoTrack::commentaryKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, keyword, ("commentary", AtomicString::ConstructFromLiteral)); + return keyword; +} + +bool VideoTrack::isValidKind(const AtomicString& kind) const +{ + return (kind == alternativeKeyword()) + || (kind == captionsKeyword()) + || (kind == mainKeyword()) + || (kind == signKeyword()) + || (kind == subtitlesKeyword()) + || (kind == commentaryKeyword()); +} + +AtomicString VideoTrack::defaultKind() const +{ + return emptyAtom; +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.h b/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.h new file mode 100644 index 00000000000..8e405e4f2ab --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.h @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VideoTrack_h +#define VideoTrack_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/track/TrackBase.h" + +namespace WebCore { + +class VideoTrack FINAL : public TrackBase, public ScriptWrappable { +public: + static PassRefPtrWillBeRawPtr<VideoTrack> create(const String& id, const AtomicString& kind, const AtomicString& label, const AtomicString& language, bool selected) + { + return adoptRefWillBeRefCountedGarbageCollected(new VideoTrack(id, kind, label, language, selected)); + } + virtual ~VideoTrack(); + + bool selected() const { return m_selected; } + void setSelected(bool); + + // Set selected to false without notifying the owner media element. Used when + // another video track is selected, implicitly deselecting this one. + void clearSelected() { m_selected = false; } + + // Valid kind keywords. + static const AtomicString& alternativeKeyword(); + static const AtomicString& captionsKeyword(); + static const AtomicString& mainKeyword(); + static const AtomicString& signKeyword(); + static const AtomicString& subtitlesKeyword(); + static const AtomicString& commentaryKeyword(); + +private: + VideoTrack(const String& id, const AtomicString& kind, const AtomicString& label, const AtomicString& language, bool selected); + + // TrackBase + virtual bool isValidKind(const AtomicString&) const OVERRIDE; + virtual AtomicString defaultKind() const OVERRIDE; + + bool m_selected; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.idl b/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.idl new file mode 100644 index 00000000000..cc4efee29da --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/VideoTrack.idl @@ -0,0 +1,15 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=AudioVideoTracks, + SetWrapperReferenceFrom=owner, + WillBeGarbageCollected, +] interface VideoTrack { + readonly attribute DOMString id; + readonly attribute DOMString kind; + readonly attribute DOMString label; + readonly attribute DOMString language; + attribute boolean selected; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.cpp b/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.cpp new file mode 100644 index 00000000000..e107717dfa4 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.cpp @@ -0,0 +1,60 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/html/track/VideoTrackList.h" + +#include "core/html/HTMLMediaElement.h" +#include "core/html/track/VideoTrack.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<VideoTrackList> VideoTrackList::create(HTMLMediaElement& mediaElement) +{ + return adoptRefWillBeRefCountedGarbageCollected(new VideoTrackList(mediaElement)); +} + +VideoTrackList::~VideoTrackList() +{ +} + +VideoTrackList::VideoTrackList(HTMLMediaElement& mediaElement) + : TrackListBase<VideoTrack>(&mediaElement) +{ + ScriptWrappable::init(this); +} + +const AtomicString& VideoTrackList::interfaceName() const +{ + return EventTargetNames::VideoTrackList; +} + +int VideoTrackList::selectedIndex() const +{ + for (unsigned i = 0; i < length(); ++i) { + VideoTrack* track = anonymousIndexedGetter(i); + + if (track->selected()) + return i; + } + + return -1; +} + +void VideoTrackList::trackSelected(blink::WebMediaPlayer::TrackId selectedTrackId) +{ + // Clear the selected flag on the previously selected track, if any. + for (unsigned i = 0; i < length(); ++i) { + VideoTrack* track = anonymousIndexedGetter(i); + + if (track->trackId() != selectedTrackId) + track->clearSelected(); + else + ASSERT(track->selected()); + } + + scheduleChangeEvent(); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.h b/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.h new file mode 100644 index 00000000000..5e60b3171cb --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.h @@ -0,0 +1,33 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VideoTrackList_h +#define VideoTrackList_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/track/TrackListBase.h" +#include "core/html/track/VideoTrack.h" + +namespace WebCore { + +class VideoTrackList FINAL : public TrackListBase<VideoTrack>, public ScriptWrappable { +public: + static PassRefPtrWillBeRawPtr<VideoTrackList> create(HTMLMediaElement&); + + virtual ~VideoTrackList(); + + int selectedIndex() const; + + // EventTarget + virtual const AtomicString& interfaceName() const OVERRIDE; + + void trackSelected(blink::WebMediaPlayer::TrackId selectedTrackId); + +private: + explicit VideoTrackList(HTMLMediaElement&); +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.idl b/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.idl new file mode 100644 index 00000000000..f7663350649 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/VideoTrackList.idl @@ -0,0 +1,17 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=AudioVideoTracks, + SetWrapperReferenceFrom=owner, +] interface VideoTrackList : EventTarget { + readonly attribute unsigned long length; + getter VideoTrack (unsigned long index); + VideoTrack? getTrackById(DOMString id); + readonly attribute long selectedIndex; + + attribute EventHandler onchange; + attribute EventHandler onaddtrack; + attribute EventHandler onremovetrack; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/BufferedLineReader.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/BufferedLineReader.cpp index 3a4aab74416..2c024bb3d9c 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/BufferedLineReader.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/BufferedLineReader.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "BufferedLineReader.h" +#include "core/html/track/vtt/BufferedLineReader.h" #include "wtf/unicode/CharacterNames.h" diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp index ab185dc3d67..8069c26ad2f 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp @@ -30,21 +30,23 @@ #include "config.h" #include "core/html/track/vtt/VTTCue.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" #include "core/dom/DocumentFragment.h" #include "core/dom/NodeTraversal.h" #include "core/events/Event.h" +#include "core/frame/UseCounter.h" #include "core/html/HTMLDivElement.h" #include "core/html/track/TextTrack.h" #include "core/html/track/TextTrackCueList.h" #include "core/html/track/vtt/VTTElement.h" #include "core/html/track/vtt/VTTParser.h" #include "core/html/track/vtt/VTTRegionList.h" +#include "core/html/track/vtt/VTTScanner.h" #include "core/rendering/RenderVTTCue.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/text/BidiResolver.h" #include "platform/text/TextRunIterator.h" #include "wtf/MathExtras.h" @@ -53,6 +55,7 @@ namespace WebCore { static const int undefinedPosition = -1; +static const int undefinedSize = -1; static const CSSValueID displayWritingModeMap[] = { CSSValueHorizontalTb, CSSValueVerticalRl, CSSValueVerticalLr @@ -113,12 +116,10 @@ static const String& verticalGrowingRightKeyword() return verticallr; } -static bool isInvalidPercentage(double value, ExceptionState& exceptionState) +static bool isInvalidPercentage(int value, ExceptionState& exceptionState) { - if (TextTrackCue::isInfiniteOrNonNumber(value, exceptionState)) - return true; if (value < 0 || value > 100) { - exceptionState.throwDOMException(IndexSizeError, "The value provided (" + String::number(value) + ") is not between 0 and 100."); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexOutsideRange("value", value, 0, ExceptionMessages::InclusiveBound, 100, ExceptionMessages::InclusiveBound)); return true; } return false; @@ -128,7 +129,7 @@ VTTCueBox::VTTCueBox(Document& document, VTTCue* cue) : HTMLDivElement(document) , m_cue(cue) { - setPseudo(AtomicString("-webkit-media-text-track-display", AtomicString::ConstructFromLiteral)); + setShadowPseudoId(AtomicString("-webkit-media-text-track-display", AtomicString::ConstructFromLiteral)); } void VTTCueBox::applyCSSProperties(const IntSize&) @@ -199,6 +200,12 @@ RenderObject* VTTCueBox::createRenderer(RenderStyle*) return new RenderVTTCue(this); } +void VTTCueBox::trace(Visitor* visitor) +{ + visitor->trace(m_cue); + HTMLDivElement::trace(visitor); +} + VTTCue::VTTCue(Document& document, double startTime, double endTime, const String& text) : TextTrackCue(startTime, endTime) , m_text(text) @@ -208,19 +215,29 @@ VTTCue::VTTCue(Document& document, double startTime, double endTime, const Strin , m_cueSize(100) , m_writingDirection(Horizontal) , m_cueAlignment(Middle) - , m_vttNodeTree(0) + , m_vttNodeTree(nullptr) , m_cueBackgroundBox(HTMLDivElement::create(document)) , m_displayDirection(CSSValueLtr) + , m_displaySize(undefinedSize) , m_snapToLines(true) , m_displayTreeShouldChange(true) , m_notifyRegion(true) { ScriptWrappable::init(this); + UseCounter::count(document, UseCounter::VTTCue); } VTTCue::~VTTCue() { - displayTreeInternal()->remove(ASSERT_NO_EXCEPTION); + // Using oilpan, if m_displayTree is in the document it will strongly keep + // the cue alive. Thus, if the cue is dead, either m_displayTree is not in + // the document or the entire document is dead too. +#if !ENABLE(OILPAN) + // FIXME: This is scary, we should make the life cycle smarter so the destructor + // doesn't need to do DOM mutations. + if (m_displayTree) + m_displayTree->remove(ASSERT_NO_EXCEPTION); +#endif } #ifndef NDEBUG @@ -230,11 +247,11 @@ String VTTCue::toString() const } #endif -PassRefPtr<VTTCueBox> VTTCue::displayTreeInternal() +VTTCueBox& VTTCue::ensureDisplayTree() { if (!m_displayTree) m_displayTree = VTTCueBox::create(document(), this); - return m_displayTree; + return *m_displayTree; } void VTTCue::cueDidChange() @@ -258,14 +275,8 @@ const String& VTTCue::vertical() const } } -void VTTCue::setVertical(const String& value, ExceptionState& exceptionState) +void VTTCue::setVertical(const String& value) { - // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-vertical - // On setting, the text track cue writing direction must be set to the value given - // in the first cell of the row in the table above whose second cell is a - // case-sensitive match for the new value, if any. If none of the values match, then - // the user agent must instead throw a SyntaxError exception. - WritingDirection direction = m_writingDirection; if (value == horizontalKeyword()) direction = Horizontal; @@ -274,7 +285,7 @@ void VTTCue::setVertical(const String& value, ExceptionState& exceptionState) else if (value == verticalGrowingRightKeyword()) direction = VerticalGrowingRight; else - exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedToSet("vertical", "TextTrackCue", "The value provided ('" + value + "') is invalid. Only 'rl', 'lr', and the empty string are accepted.")); + ASSERT_NOT_REACHED(); if (direction == m_writingDirection) return; @@ -300,7 +311,7 @@ void VTTCue::setLine(int position, ExceptionState& exceptionState) // On setting, if the text track cue snap-to-lines flag is not set, and the new // value is negative or greater than 100, then throw an IndexSizeError exception. if (!m_snapToLines && (position < 0 || position > 100)) { - exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::failedToSet("line", "TextTrackCue", "The snap-to-lines flag is not set, and the value provided (" + String::number(position) + ") is not between 0 and 100.")); + exceptionState.throwDOMException(IndexSizeError, "The snap-to-lines flag is not set, and the value provided (" + String::number(position) + ") is not between 0 and 100."); return; } @@ -367,14 +378,8 @@ const String& VTTCue::align() const } } -void VTTCue::setAlign(const String& value, ExceptionState& exceptionState) +void VTTCue::setAlign(const String& value) { - // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-align - // On setting, the text track cue alignment must be set to the value given in the - // first cell of the row in the table above whose second cell is a case-sensitive - // match for the new value, if any. If none of the values match, then the user - // agent must instead throw a SyntaxError exception. - CueAlignment alignment = m_cueAlignment; if (value == startKeyword()) alignment = Start; @@ -387,7 +392,7 @@ void VTTCue::setAlign(const String& value, ExceptionState& exceptionState) else if (value == rightKeyword()) alignment = Right; else - exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedToSet("align", "TextTrackCue", "The value provided ('" + value + "') is invalid. Only 'start', 'middle', 'end', 'left', and 'right' are accepted.")); + ASSERT_NOT_REACHED(); if (alignment == m_cueAlignment) return; @@ -405,7 +410,7 @@ void VTTCue::setText(const String& text) cueWillChange(); // Clear the document fragment but don't bother to create it again just yet as we can do that // when it is requested. - m_vttNodeTree = 0; + m_vttNodeTree = nullptr; m_text = text; cueDidChange(); } @@ -419,7 +424,7 @@ void VTTCue::createVTTNodeTree() void VTTCue::copyVTTNodeToDOMTree(ContainerNode* vttNode, ContainerNode* parent) { for (Node* node = vttNode->firstChild(); node; node = node->nextSibling()) { - RefPtr<Node> clonedNode; + RefPtrWillBeRawPtr<Node> clonedNode; if (node->isVTTElement()) clonedNode = toVTTElement(node)->createEquivalentHTMLElement(document()); else @@ -430,19 +435,18 @@ void VTTCue::copyVTTNodeToDOMTree(ContainerNode* vttNode, ContainerNode* parent) } } -PassRefPtr<DocumentFragment> VTTCue::getCueAsHTML() +PassRefPtrWillBeRawPtr<DocumentFragment> VTTCue::getCueAsHTML() { createVTTNodeTree(); - RefPtr<DocumentFragment> clonedFragment = DocumentFragment::create(document()); + RefPtrWillBeRawPtr<DocumentFragment> clonedFragment = DocumentFragment::create(document()); copyVTTNodeToDOMTree(m_vttNodeTree.get(), clonedFragment.get()); return clonedFragment.release(); } -PassRefPtr<DocumentFragment> VTTCue::createCueRenderingTree() +PassRefPtrWillBeRawPtr<DocumentFragment> VTTCue::createCueRenderingTree() { - RefPtr<DocumentFragment> clonedFragment; createVTTNodeTree(); - clonedFragment = DocumentFragment::create(document()); + RefPtrWillBeRawPtr<DocumentFragment> clonedFragment = DocumentFragment::create(document()); m_vttNodeTree->cloneChildNodes(clonedFragment.get()); return clonedFragment.release(); } @@ -550,6 +554,9 @@ void VTTCue::calculateDisplayParameters() // Steps 10.2, 10.3 m_displayDirection = determineTextDirection(m_vttNodeTree.get()); + if (m_displayDirection == CSSValueRtl) + UseCounter::count(document(), UseCounter::VTTCueRenderRtl); + // 10.4 If the text track cue writing direction is horizontal, then let // block-flow be 'tb'. Otherwise, if the text track cue writing direction is // vertical growing left, then let block-flow be 'lr'. Otherwise, the text @@ -621,7 +628,7 @@ void VTTCue::calculateDisplayParameters() else m_displayPosition.first = 100 - m_textPosition - m_displaySize / 2; break; - case NumberOfAlignments: + default: ASSERT_NOT_REACHED(); } } else { @@ -638,7 +645,7 @@ void VTTCue::calculateDisplayParameters() case Middle: m_displayPosition.second = m_textPosition - m_displaySize / 2; break; - case NumberOfAlignments: + default: ASSERT_NOT_REACHED(); } } @@ -675,10 +682,8 @@ void VTTCue::markFutureAndPastNodes(ContainerNode* root, double previousTimestam for (Node* child = root->firstChild(); child; child = NodeTraversal::next(*child, root)) { if (child->nodeName() == timestampTag) { - unsigned position = 0; - String timestamp = child->nodeValue(); double currentTimestamp; - bool check = VTTParser::collectTimeStamp(timestamp, &position, currentTimestamp); + bool check = VTTParser::collectTimeStamp(child->nodeValue(), currentTimestamp); ASSERT_UNUSED(check, check); if (currentTimestamp > movieTime) @@ -706,16 +711,16 @@ void VTTCue::updateDisplayTree(double movieTime) m_cueBackgroundBox->removeChildren(); // Update the two sets containing past and future WebVTT objects. - RefPtr<DocumentFragment> referenceTree = createCueRenderingTree(); + RefPtrWillBeRawPtr<DocumentFragment> referenceTree = createCueRenderingTree(); markFutureAndPastNodes(referenceTree.get(), startTime(), movieTime); m_cueBackgroundBox->appendChild(referenceTree, ASSERT_NO_EXCEPTION); } -PassRefPtr<VTTCueBox> VTTCue::getDisplayTree(const IntSize& videoSize) +PassRefPtrWillBeRawPtr<VTTCueBox> VTTCue::getDisplayTree(const IntSize& videoSize) { - RefPtr<VTTCueBox> displayTree = displayTreeInternal(); + RefPtrWillBeRawPtr<VTTCueBox> displayTree(ensureDisplayTree()); if (!m_displayTreeShouldChange || !track()->isRendered()) - return displayTree; + return displayTree.release(); // 10.1 - 10.10 calculateDisplayParameters(); @@ -732,7 +737,7 @@ PassRefPtr<VTTCueBox> VTTCue::getDisplayTree(const IntSize& videoSize) // background box. // Note: This is contained by default in m_cueBackgroundBox. - m_cueBackgroundBox->setPseudo(cueShadowPseudoId()); + m_cueBackgroundBox->setShadowPseudoId(cueShadowPseudoId()); displayTree->appendChild(m_cueBackgroundBox); // FIXME(BUG 79916): Runs of children of WebVTT Ruby Objects that are not @@ -752,7 +757,7 @@ PassRefPtr<VTTCueBox> VTTCue::getDisplayTree(const IntSize& videoSize) // 10.15. Let cue's text track cue display state have the CSS boxes in // boxes. - return displayTree; + return displayTree.release(); } void VTTCue::removeDisplayTree() @@ -764,12 +769,33 @@ void VTTCue::removeDisplayTree() region->willRemoveVTTCueBox(m_displayTree.get()); } - displayTreeInternal()->remove(ASSERT_NO_EXCEPTION); + if (m_displayTree) + m_displayTree->remove(ASSERT_NO_EXCEPTION); } void VTTCue::updateDisplay(const IntSize& videoSize, HTMLDivElement& container) { - RefPtr<VTTCueBox> displayBox = getDisplayTree(videoSize); + UseCounter::count(document(), UseCounter::VTTCueRender); + + if (m_writingDirection != Horizontal) + UseCounter::count(document(), UseCounter::VTTCueRenderVertical); + + if (!m_snapToLines) + UseCounter::count(document(), UseCounter::VTTCueRenderSnapToLinesFalse); + + if (m_linePosition != undefinedPosition) + UseCounter::count(document(), UseCounter::VTTCueRenderLineNotAuto); + + if (m_textPosition != 50) + UseCounter::count(document(), UseCounter::VTTCueRenderPositionNot50); + + if (m_cueSize != 100) + UseCounter::count(document(), UseCounter::VTTCueRenderSizeNot100); + + if (m_cueAlignment != Middle) + UseCounter::count(document(), UseCounter::VTTCueRenderAlignNotMiddle); + + RefPtrWillBeRawPtr<VTTCueBox> displayBox = getDisplayTree(videoSize); VTTRegion* region = 0; if (track()->regions()) region = track()->regions()->getRegionById(regionId()); @@ -778,14 +804,14 @@ void VTTCue::updateDisplay(const IntSize& videoSize, HTMLDivElement& container) // If cue has an empty text track cue region identifier or there is no // WebVTT region whose region identifier is identical to cue's text // track cue region identifier, run the following substeps: - if (displayBox->hasChildNodes() && !container.contains(displayBox.get())) { + if (displayBox->hasChildren() && !container.contains(displayBox.get())) { // Note: the display tree of a cue is removed when the active flag of the cue is unset. container.appendChild(displayBox); } } else { // Let region be the WebVTT region whose region identifier // matches the text track cue region identifier of cue. - RefPtr<HTMLDivElement> regionNode = region->getDisplayTree(document()); + RefPtrWillBeRawPtr<HTMLDivElement> regionNode = region->getDisplayTree(document()); // Append the region to the viewport, if it was not already. if (!container.contains(regionNode.get())) @@ -833,42 +859,65 @@ std::pair<double, double> VTTCue::getPositionCoordinates() const return coordinates; } -VTTCue::CueSetting VTTCue::settingName(const String& name) +VTTCue::CueSetting VTTCue::settingName(VTTScanner& input) { - DEFINE_STATIC_LOCAL(const String, verticalKeyword, ("vertical")); - DEFINE_STATIC_LOCAL(const String, lineKeyword, ("line")); - DEFINE_STATIC_LOCAL(const String, positionKeyword, ("position")); - DEFINE_STATIC_LOCAL(const String, sizeKeyword, ("size")); - DEFINE_STATIC_LOCAL(const String, alignKeyword, ("align")); - DEFINE_STATIC_LOCAL(const String, regionIdKeyword, ("region")); - - if (name == verticalKeyword) - return Vertical; - if (name == lineKeyword) - return Line; - if (name == positionKeyword) - return Position; - if (name == sizeKeyword) - return Size; - if (name == alignKeyword) - return Align; - if (RuntimeEnabledFeatures::webVTTRegionsEnabled() && name == regionIdKeyword) - return RegionId; - + CueSetting parsedSetting = None; + if (input.scan("vertical")) + parsedSetting = Vertical; + else if (input.scan("line")) + parsedSetting = Line; + else if (input.scan("position")) + parsedSetting = Position; + else if (input.scan("size")) + parsedSetting = Size; + else if (input.scan("align")) + parsedSetting = Align; + else if (RuntimeEnabledFeatures::webVTTRegionsEnabled() && input.scan("region")) + parsedSetting = RegionId; + // Verify that a ':' follows. + if (parsedSetting != None && input.scan(':')) + return parsedSetting; return None; } -void VTTCue::parseSettings(const String& input) +// Used for 'position' and 'size'. +static bool scanPercentage(VTTScanner& input, const VTTScanner::Run& valueRun, int& number) { - unsigned position = 0; + // 1. If value contains any characters other than U+0025 PERCENT SIGN + // characters (%) and characters in the range U+0030 DIGIT ZERO (0) to + // U+0039 DIGIT NINE (9), then jump to the step labeled next setting. + // 2. If value does not contain at least one character in the range U+0030 + // DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump to the step + // labeled next setting. + if (!input.scanDigits(number)) + return false; + + // 3. If any character in value other than the last character is a U+0025 + // PERCENT SIGN character (%), then jump to the step labeled next + // setting. + // 4. If the last character in value is not a U+0025 PERCENT SIGN character + // (%), then jump to the step labeled next setting. + if (!input.scan('%') || !input.isAt(valueRun.end())) + return false; + + // 5. Ignoring the trailing percent sign, interpret value as an integer, + // and let number be that number. + // 6. If number is not in the range 0 ≤ number ≤ 100, then jump to the step + // labeled next setting. + return number >= 0 && number <= 100; +} + +void VTTCue::parseSettings(const String& inputString) +{ + VTTScanner input(inputString); - while (position < input.length()) { + while (!input.isAtEnd()) { // The WebVTT cue settings part of a WebVTT cue consists of zero or more of the following components, in any order, // separated from each other by one or more U+0020 SPACE characters or U+0009 CHARACTER TABULATION (tab) characters. - while (position < input.length() && VTTParser::isValidSettingDelimiter(input[position])) - position++; - if (position >= input.length()) + input.skipWhile<VTTParser::isValidSettingDelimiter>(); + + if (input.isAtEnd()) break; // When the user agent is to parse the WebVTT settings given by a string input for a text track cue cue, @@ -877,48 +926,38 @@ void VTTCue::parseSettings(const String& input) // 2. For each token setting in the list settings, run the following substeps: // 1. If setting does not contain a U+003A COLON character (:), or if the first U+003A COLON character (:) // in setting is either the first or last character of setting, then jump to the step labeled next setting. - unsigned endOfSetting = position; - String setting = VTTParser::collectWord(input, &endOfSetting); - CueSetting name; - size_t colonOffset = setting.find(':', 1); - if (colonOffset == kNotFound || !colonOffset || colonOffset == setting.length() - 1) - goto NextSetting; - - // 2. Let name be the leading substring of setting up to and excluding the first U+003A COLON character (:) in that string. - name = settingName(setting.substring(0, colonOffset)); + // 2. Let name be the leading substring of setting up to and excluding the first U+003A COLON character (:) in that string. + CueSetting name = settingName(input); // 3. Let value be the trailing substring of setting starting from the character immediately after the first U+003A COLON character (:) in that string. - position += colonOffset + 1; - if (position >= input.length()) - break; + VTTScanner::Run valueRun = input.collectUntil<VTTParser::isValidSettingDelimiter>(); // 4. Run the appropriate substeps that apply for the value of name, as follows: switch (name) { - case Vertical: - { + case Vertical: { // If name is a case-sensitive match for "vertical" // 1. If value is a case-sensitive match for the string "rl", then let cue's text track cue writing direction // be vertical growing left. - String writingDirection = VTTParser::collectWord(input, &position); - if (writingDirection == verticalGrowingLeftKeyword()) + if (input.scanRun(valueRun, verticalGrowingLeftKeyword())) m_writingDirection = VerticalGrowingLeft; // 2. Otherwise, if value is a case-sensitive match for the string "lr", then let cue's text track cue writing // direction be vertical growing right. - else if (writingDirection == verticalGrowingRightKeyword()) + else if (input.scanRun(valueRun, verticalGrowingRightKeyword())) m_writingDirection = VerticalGrowingRight; - } break; - case Line: - { + } + case Line: { // 1-2 - Collect chars that are either '-', '%', or a digit. // 1. If value contains any characters other than U+002D HYPHEN-MINUS characters (-), U+0025 PERCENT SIGN // characters (%), and characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump // to the step labeled next setting. - StringBuilder linePositionBuilder; - while (position < input.length() && (input[position] == '-' || input[position] == '%' || isASCIIDigit(input[position]))) - linePositionBuilder.append(input[position++]); - if (position < input.length() && !VTTParser::isValidSettingDelimiter(input[position])) + bool isNegative = input.scan('-'); + int linePosition; + unsigned numDigits = input.scanDigits(linePosition); + bool isPercentage = input.scan('%'); + + if (!input.isAt(valueRun.end())) break; // 2. If value does not contain at least one character in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT @@ -927,134 +966,83 @@ void VTTCue::parseSettings(const String& input) // jump to the step labeled next setting. // 4. If any character in value other than the last character is a U+0025 PERCENT SIGN character (%), then // jump to the step labeled next setting. - String linePosition = linePositionBuilder.toString(); - if (linePosition.find('-', 1) != kNotFound || linePosition.reverseFind("%", linePosition.length() - 2) != kNotFound) - break; // 5. If the first character in value is a U+002D HYPHEN-MINUS character (-) and the last character in value is a // U+0025 PERCENT SIGN character (%), then jump to the step labeled next setting. - if (linePosition[0] == '-' && linePosition[linePosition.length() - 1] == '%') + if (!numDigits || (isPercentage && isNegative)) break; // 6. Ignoring the trailing percent sign, if any, interpret value as a (potentially signed) integer, and // let number be that number. - // NOTE: toInt ignores trailing non-digit characters, such as '%'. - bool validNumber; - int number = linePosition.toInt(&validNumber); - if (!validNumber) - break; - // 7. If the last character in value is a U+0025 PERCENT SIGN character (%), but number is not in the range // 0 ≤ number ≤ 100, then jump to the step labeled next setting. // 8. Let cue's text track cue line position be number. // 9. If the last character in value is a U+0025 PERCENT SIGN character (%), then let cue's text track cue // snap-to-lines flag be false. Otherwise, let it be true. - if (linePosition[linePosition.length() - 1] == '%') { - if (number < 0 || number > 100) + if (isPercentage) { + if (linePosition < 0 || linePosition > 100) break; - // 10 - If '%' then set snap-to-lines flag to false. m_snapToLines = false; + } else { + if (isNegative) + linePosition = -linePosition; + m_snapToLines = true; } - - m_linePosition = number; - } + m_linePosition = linePosition; break; - case Position: - { - // 1. If value contains any characters other than U+0025 PERCENT SIGN characters (%) and characters in the range - // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump to the step labeled next setting. - // 2. If value does not contain at least one character in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), - // then jump to the step labeled next setting. + } + case Position: { int number; - if (!VTTParser::collectDigitsToInt(input, &position, number)) - break; - if (position >= input.length()) - break; - - // 3. If any character in value other than the last character is a U+0025 PERCENT SIGN character (%), then jump - // to the step labeled next setting. - // 4. If the last character in value is not a U+0025 PERCENT SIGN character (%), then jump to the step labeled - // next setting. - if (input[position++] != '%') - break; - if (position < input.length() && !VTTParser::isValidSettingDelimiter(input[position])) - break; - - // 5. Ignoring the trailing percent sign, interpret value as an integer, and let number be that number. - // 6. If number is not in the range 0 ≤ number ≤ 100, then jump to the step labeled next setting. - // NOTE: toInt ignores trailing non-digit characters, such as '%'. - if (number < 0 || number > 100) + // Steps 1 - 6. + if (!scanPercentage(input, valueRun, number)) break; // 7. Let cue's text track cue text position be number. m_textPosition = number; - } break; - case Size: - { - // 1. If value contains any characters other than U+0025 PERCENT SIGN characters (%) and characters in the - // range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump to the step labeled next setting. - // 2. If value does not contain at least one character in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT - // NINE (9), then jump to the step labeled next setting. + } + case Size: { int number; - if (!VTTParser::collectDigitsToInt(input, &position, number)) - break; - if (position >= input.length()) - break; - - // 3. If any character in value other than the last character is a U+0025 PERCENT SIGN character (%), - // then jump to the step labeled next setting. - // 4. If the last character in value is not a U+0025 PERCENT SIGN character (%), then jump to the step - // labeled next setting. - if (input[position++] != '%') - break; - if (position < input.length() && !VTTParser::isValidSettingDelimiter(input[position])) - break; - - // 5. Ignoring the trailing percent sign, interpret value as an integer, and let number be that number. - // 6. If number is not in the range 0 ≤ number ≤ 100, then jump to the step labeled next setting. - if (number < 0 || number > 100) + // Steps 1 - 6. + if (!scanPercentage(input, valueRun, number)) break; // 7. Let cue's text track cue size be number. m_cueSize = number; - } break; - case Align: - { - String cueAlignment = VTTParser::collectWord(input, &position); - + } + case Align: { // 1. If value is a case-sensitive match for the string "start", then let cue's text track cue alignment be start alignment. - if (cueAlignment == startKeyword()) + if (input.scanRun(valueRun, startKeyword())) m_cueAlignment = Start; // 2. If value is a case-sensitive match for the string "middle", then let cue's text track cue alignment be middle alignment. - else if (cueAlignment == middleKeyword()) + else if (input.scanRun(valueRun, middleKeyword())) m_cueAlignment = Middle; // 3. If value is a case-sensitive match for the string "end", then let cue's text track cue alignment be end alignment. - else if (cueAlignment == endKeyword()) + else if (input.scanRun(valueRun, endKeyword())) m_cueAlignment = End; // 4. If value is a case-sensitive match for the string "left", then let cue's text track cue alignment be left alignment. - else if (cueAlignment == leftKeyword()) + else if (input.scanRun(valueRun, leftKeyword())) m_cueAlignment = Left; // 5. If value is a case-sensitive match for the string "right", then let cue's text track cue alignment be right alignment. - else if (cueAlignment == rightKeyword()) + else if (input.scanRun(valueRun, rightKeyword())) m_cueAlignment = Right; - } break; + } case RegionId: - m_regionId = VTTParser::collectWord(input, &position); + m_regionId = input.extractString(valueRun); break; case None: break; } -NextSetting: - position = endOfSetting; + // Make sure the entire run is consumed. + input.skipRun(valueRun); } // If cue's line position is not auto or cue's size is not 100 or cue's @@ -1084,6 +1072,7 @@ CSSValueID VTTCue::getCSSWritingMode() const int VTTCue::getCSSSize() const { + ASSERT(m_displaySize != undefinedSize); return m_displaySize; } @@ -1107,4 +1096,12 @@ Document& VTTCue::document() const return m_cueBackgroundBox->document(); } +void VTTCue::trace(Visitor* visitor) +{ + visitor->trace(m_vttNodeTree); + visitor->trace(m_cueBackgroundBox); + visitor->trace(m_displayTree); + TextTrackCue::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.h b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.h index 05e6f8ecf1b..a43112dce4b 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.h +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.h @@ -32,42 +32,46 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/track/TextTrackCue.h" +#include "platform/heap/Handle.h" namespace WebCore { class Document; class ExecutionContext; class VTTCue; +class VTTScanner; class VTTCueBox FINAL : public HTMLDivElement { public: - static PassRefPtr<VTTCueBox> create(Document& document, VTTCue* cue) + static PassRefPtrWillBeRawPtr<VTTCueBox> create(Document& document, VTTCue* cue) { - return adoptRef(new VTTCueBox(document, cue)); + return adoptRefWillBeNoop(new VTTCueBox(document, cue)); } VTTCue* getCue() const { return m_cue; } void applyCSSProperties(const IntSize& videoSize); + virtual void trace(Visitor*) OVERRIDE; + private: VTTCueBox(Document&, VTTCue*); virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE; - VTTCue* m_cue; + RawPtrWillBeMember<VTTCue> m_cue; }; class VTTCue FINAL : public TextTrackCue, public ScriptWrappable { public: - static PassRefPtr<VTTCue> create(Document& document, double startTime, double endTime, const String& text) + static PassRefPtrWillBeRawPtr<VTTCue> create(Document& document, double startTime, double endTime, const String& text) { - return adoptRef(new VTTCue(document, startTime, endTime, text)); + return adoptRefWillBeRefCountedGarbageCollected(new VTTCue(document, startTime, endTime, text)); } virtual ~VTTCue(); const String& vertical() const; - void setVertical(const String&, ExceptionState&); + void setVertical(const String&); bool snapToLines() const { return m_snapToLines; } void setSnapToLines(bool); @@ -82,15 +86,15 @@ public: void setSize(int, ExceptionState&); const String& align() const; - void setAlign(const String&, ExceptionState&); + void setAlign(const String&); const String& text() const { return m_text; } void setText(const String&); void parseSettings(const String&); - PassRefPtr<DocumentFragment> getCueAsHTML(); - PassRefPtr<DocumentFragment> createCueRenderingTree(); + PassRefPtrWillBeRawPtr<DocumentFragment> getCueAsHTML(); + PassRefPtrWillBeRawPtr<DocumentFragment> createCueRenderingTree(); const String& regionId() const { return m_regionId; } void setRegionId(const String&); @@ -136,13 +140,15 @@ public: virtual String toString() const OVERRIDE; #endif + virtual void trace(Visitor*) OVERRIDE; + private: VTTCue(Document&, double startTime, double endTime, const String& text); Document& document() const; - PassRefPtr<VTTCueBox> displayTreeInternal(); - PassRefPtr<VTTCueBox> getDisplayTree(const IntSize& videoSize); + VTTCueBox& ensureDisplayTree(); + PassRefPtrWillBeRawPtr<VTTCueBox> getDisplayTree(const IntSize& videoSize); virtual void cueDidChange() OVERRIDE; @@ -162,7 +168,7 @@ private: Align, RegionId }; - CueSetting settingName(const String&); + CueSetting settingName(VTTScanner&); String m_text; int m_linePosition; @@ -173,9 +179,9 @@ private: CueAlignment m_cueAlignment; String m_regionId; - RefPtr<DocumentFragment> m_vttNodeTree; - RefPtr<HTMLDivElement> m_cueBackgroundBox; - RefPtr<VTTCueBox> m_displayTree; + RefPtrWillBeMember<DocumentFragment> m_vttNodeTree; + RefPtrWillBeMember<HTMLDivElement> m_cueBackgroundBox; + RefPtrWillBeMember<VTTCueBox> m_displayTree; CSSValueID m_displayDirection; int m_displaySize; @@ -186,11 +192,8 @@ private: bool m_notifyRegion : 1; }; -inline VTTCue* toVTTCue(TextTrackCue* cue) -{ - // VTTCue is currently the only TextTrackCue subclass. - return static_cast<VTTCue*>(cue); -} +// VTTCue is currently the only TextTrackCue subclass. +DEFINE_TYPE_CASTS(VTTCue, TextTrackCue, cue, true, true); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.idl b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.idl index 8b958174353..3ca0307dfa3 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTCue.idl @@ -27,18 +27,21 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum DirectionSetting { "" /* horizontal */, "rl", "lr" }; +enum AlignSetting { "start", "middle", "end", "left", "right" }; + [ Constructor(double startTime, double endTime, DOMString text), ConstructorCallWith=Document, - RuntimeEnabled=VideoTrack, + SetWrapperReferenceFrom=owner, ] interface VTTCue : TextTrackCue { [RuntimeEnabled=WebVTTRegions] attribute DOMString regionId; - [RaisesException=Setter] attribute DOMString vertical; + attribute DirectionSetting vertical; attribute boolean snapToLines; [RaisesException=Setter] attribute long line; [RaisesException=Setter] attribute long position; [RaisesException=Setter] attribute long size; - [RaisesException=Setter] attribute DOMString align; + attribute AlignSetting align; attribute DOMString text; DocumentFragment getCueAsHTML(); }; diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.cpp index e9b350a1304..c56084ce40e 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/html/track/vtt/VTTElement.h" -#include "HTMLElementFactory.h" +#include "core/HTMLElementFactory.h" namespace WebCore { @@ -71,21 +71,21 @@ VTTElement::VTTElement(VTTNodeType nodeType, Document* document) { } -PassRefPtr<VTTElement> VTTElement::create(VTTNodeType nodeType, Document* document) +PassRefPtrWillBeRawPtr<VTTElement> VTTElement::create(VTTNodeType nodeType, Document* document) { - return adoptRef(new VTTElement(nodeType, document)); + return adoptRefWillBeNoop(new VTTElement(nodeType, document)); } -PassRefPtr<Element> VTTElement::cloneElementWithoutAttributesAndChildren() +PassRefPtrWillBeRawPtr<Element> VTTElement::cloneElementWithoutAttributesAndChildren() { - RefPtr<VTTElement> clone = create(static_cast<VTTNodeType>(m_webVTTNodeType), &document()); + RefPtrWillBeRawPtr<VTTElement> clone = create(static_cast<VTTNodeType>(m_webVTTNodeType), &document()); clone->setLanguage(m_language); - return clone; + return clone.release(); } -PassRefPtr<HTMLElement> VTTElement::createEquivalentHTMLElement(Document& document) +PassRefPtrWillBeRawPtr<HTMLElement> VTTElement::createEquivalentHTMLElement(Document& document) { - RefPtr<HTMLElement> htmlElement; + RefPtrWillBeRawPtr<HTMLElement> htmlElement = nullptr; switch (m_webVTTNodeType) { case VTTNodeTypeClass: case VTTNodeTypeLanguage: diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.h b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.h index 2fe08c79abe..6705add645b 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.h +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTElement.h @@ -41,11 +41,11 @@ enum VTTNodeType { class VTTElement FINAL : public Element { public: - static PassRefPtr<VTTElement> create(const VTTNodeType, Document*); - static PassRefPtr<VTTElement> create(const QualifiedName&, Document*); - PassRefPtr<HTMLElement> createEquivalentHTMLElement(Document&); + static PassRefPtrWillBeRawPtr<VTTElement> create(const VTTNodeType, Document*); + static PassRefPtrWillBeRawPtr<VTTElement> create(const QualifiedName&, Document*); + PassRefPtrWillBeRawPtr<HTMLElement> createEquivalentHTMLElement(Document&); - virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() OVERRIDE; + virtual PassRefPtrWillBeRawPtr<Element> cloneElementWithoutAttributesAndChildren() OVERRIDE; void setVTTNodeType(VTTNodeType type) { m_webVTTNodeType = static_cast<unsigned>(type); } VTTNodeType webVTTNodeType() const { return static_cast<VTTNodeType>(m_webVTTNodeType); } @@ -79,7 +79,7 @@ private: AtomicString m_language; }; -DEFINE_NODE_TYPE_CASTS(VTTElement, isVTTElement()); +DEFINE_ELEMENT_TYPE_CASTS(VTTElement, isVTTElement()); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp index e1b4b2a372d..ef09051af16 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp @@ -35,103 +35,45 @@ #include "core/dom/ProcessingInstruction.h" #include "core/dom/Text.h" #include "core/html/track/vtt/VTTElement.h" +#include "core/html/track/vtt/VTTScanner.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/text/SegmentedString.h" #include "wtf/text/WTFString.h" namespace WebCore { +using namespace HTMLNames; + const double secondsPerHour = 3600; const double secondsPerMinute = 60; const double secondsPerMillisecond = 0.001; const unsigned fileIdentifierLength = 6; -static unsigned scanDigits(const String& input, unsigned* position) -{ - unsigned startPosition = *position; - while (*position < input.length() && isASCIIDigit(input[*position])) - (*position)++; - return *position - startPosition; -} - -unsigned VTTParser::collectDigitsToInt(const String& input, unsigned* position, int& number) -{ - unsigned startPosition = *position; - unsigned numDigits = scanDigits(input, position); - if (!numDigits) { - number = 0; - return 0; - } - bool validNumber; - if (input.is8Bit()) - number = charactersToInt(input.characters8() + startPosition, numDigits, &validNumber); - else - number = charactersToInt(input.characters16() + startPosition, numDigits, &validNumber); - - // Since we know that scanDigits only scanned valid (ASCII) digits (and - // hence that's what got passed to charactersToInt()), the remaining - // failure mode for charactersToInt() is overflow, so if |validNumber| is - // not true, then set |number| to the maximum int value. - if (!validNumber) - number = std::numeric_limits<int>::max(); - return numDigits; -} - -String VTTParser::collectWord(const String& input, unsigned* position) +bool VTTParser::parseFloatPercentageValue(VTTScanner& valueScanner, float& percentage) { - StringBuilder string; - while (*position < input.length() && !isASpace(input[*position])) - string.append(input[(*position)++]); - return string.toString(); -} - -void VTTParser::skipWhiteSpace(const String& line, unsigned* position) -{ - while (*position < line.length() && isASpace(line[*position])) - (*position)++; -} - -bool VTTParser::parseFloatPercentageValue(const String& value, float& percentage) -{ - // '%' must be present and at the end of the setting value. - if (value.isEmpty() || value[value.length() - 1] != '%') + float number; + if (!valueScanner.scanFloat(number)) return false; - - unsigned position = 0; - unsigned digitsBeforeDot = scanDigits(value, &position); - unsigned digitsAfterDot = 0; - if (value[position] == '.') { - position++; - - digitsAfterDot = scanDigits(value, &position); - } - - // At least one digit required. - if (!digitsBeforeDot && !digitsAfterDot) + // '%' must be present and at the end of the setting value. + if (!valueScanner.scan('%')) return false; - - float number = value.toFloat(); if (number < 0 || number > 100) return false; - percentage = number; return true; } -bool VTTParser::parseFloatPercentageValuePair(const String& value, char delimiter, FloatPoint& valuePair) +bool VTTParser::parseFloatPercentageValuePair(VTTScanner& valueScanner, char delimiter, FloatPoint& valuePair) { - // The delimiter can't be the first or second value because a pair of - // percentages (x%,y%) implies that at least the first two characters - // are the first percentage value. - size_t delimiterOffset = value.find(delimiter, 2); - if (delimiterOffset == kNotFound || delimiterOffset == value.length() - 1) + float firstCoord; + if (!parseFloatPercentageValue(valueScanner, firstCoord)) return false; - float firstCoord; - if (!parseFloatPercentageValue(value.substring(0, delimiterOffset), firstCoord)) + if (!valueScanner.scan(delimiter)) return false; float secondCoord; - if (!parseFloatPercentageValue(value.substring(delimiterOffset + 1, value.length() - 1), secondCoord)) + if (!parseFloatPercentageValue(valueScanner, secondCoord)) return false; valuePair = FloatPoint(firstCoord, secondCoord); @@ -148,13 +90,13 @@ VTTParser::VTTParser(VTTParserClient* client, Document& document) { } -void VTTParser::getNewCues(Vector<RefPtr<VTTCue> >& outputCues) +void VTTParser::getNewCues(WillBeHeapVector<RefPtrWillBeMember<VTTCue> >& outputCues) { - outputCues = m_cuelist; - m_cuelist.clear(); + outputCues = m_cueList; + m_cueList.clear(); } -void VTTParser::getNewRegions(Vector<RefPtr<VTTRegion> >& outputRegions) +void VTTParser::getNewRegions(WillBeHeapVector<RefPtrWillBeMember<VTTRegion> >& outputRegions) { outputRegions = m_regionList; m_regionList.clear(); @@ -301,41 +243,35 @@ VTTParser::ParseState VTTParser::collectCueId(const String& line) { if (line.contains("-->")) return collectTimingsAndSettings(line); - m_currentId = line; + m_currentId = AtomicString(line); return TimingsAndSettings; } VTTParser::ParseState VTTParser::collectTimingsAndSettings(const String& line) { + VTTScanner input(line); + // Collect WebVTT cue timings and settings. (5.3 WebVTT cue timings and settings parsing.) // Steps 1 - 3 - Let input be the string being parsed and position be a pointer into input. - unsigned position = 0; - skipWhiteSpace(line, &position); + input.skipWhile<isASpace>(); // Steps 4 - 5 - Collect a WebVTT timestamp. If that fails, then abort and return failure. Otherwise, let cue's text track cue start time be the collected time. - if (!collectTimeStamp(line, &position, m_currentStartTime)) - return BadCue; - if (position >= line.length()) + if (!collectTimeStamp(input, m_currentStartTime)) return BadCue; - - skipWhiteSpace(line, &position); + input.skipWhile<isASpace>(); // Steps 6 - 9 - If the next three characters are not "-->", abort and return failure. - if (line.find("-->", position) == kNotFound) + if (!input.scan("-->")) return BadCue; - position += 3; - if (position >= line.length()) - return BadCue; - - skipWhiteSpace(line, &position); + input.skipWhile<isASpace>(); // Steps 10 - 11 - Collect a WebVTT timestamp. If that fails, then abort and return failure. Otherwise, let cue's text track cue end time be the collected time. - if (!collectTimeStamp(line, &position, m_currentEndTime)) + if (!collectTimeStamp(input, m_currentEndTime)) return BadCue; - skipWhiteSpace(line, &position); + input.skipWhile<isASpace>(); // Step 12 - Parse the WebVTT settings for the cue (conducted in TextTrackCue). - m_currentSettings = line.substring(position, line.length()-1); + m_currentSettings = input.restOfInputAsString(); return CueText; } @@ -381,31 +317,33 @@ VTTParser::ParseState VTTParser::ignoreBadCue(const String& line) // A helper class for the construction of a "cue fragment" from the cue text. class VTTTreeBuilder { + STACK_ALLOCATED(); public: - VTTTreeBuilder(Document& document) - : m_document(document) { } + explicit VTTTreeBuilder(Document& document) + : m_document(&document) { } - PassRefPtr<DocumentFragment> buildFromString(const String& cueText); + PassRefPtrWillBeRawPtr<DocumentFragment> buildFromString(const String& cueText); private: void constructTreeFromToken(Document&); + Document& document() const { return *m_document; } VTTToken m_token; - RefPtr<ContainerNode> m_currentNode; + RefPtrWillBeMember<ContainerNode> m_currentNode; Vector<AtomicString> m_languageStack; - Document& m_document; + RawPtrWillBeMember<Document> m_document; }; -PassRefPtr<DocumentFragment> VTTTreeBuilder::buildFromString(const String& cueText) +PassRefPtrWillBeRawPtr<DocumentFragment> VTTTreeBuilder::buildFromString(const String& cueText) { // Cue text processing based on // 5.4 WebVTT cue text parsing rules, and // 5.5 WebVTT cue text DOM construction rules - RefPtr<DocumentFragment> fragment = DocumentFragment::create(m_document); + RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(document()); if (cueText.isEmpty()) { - fragment->parserAppendChild(Text::create(m_document, "")); + fragment->parserAppendChild(Text::create(document(), "")); return fragment; } @@ -415,12 +353,12 @@ PassRefPtr<DocumentFragment> VTTTreeBuilder::buildFromString(const String& cueTe m_languageStack.clear(); while (tokenizer.nextToken(m_token)) - constructTreeFromToken(m_document); + constructTreeFromToken(document()); return fragment.release(); } -PassRefPtr<DocumentFragment> VTTParser::createDocumentFragmentFromCueText(Document& document, const String& cueText) +PassRefPtrWillBeRawPtr<DocumentFragment> VTTParser::createDocumentFragmentFromCueText(Document& document, const String& cueText) { VTTTreeBuilder treeBuilder(document); return treeBuilder.buildFromString(cueText); @@ -428,18 +366,18 @@ PassRefPtr<DocumentFragment> VTTParser::createDocumentFragmentFromCueText(Docume void VTTParser::createNewCue() { - RefPtr<VTTCue> cue = VTTCue::create(*m_document, m_currentStartTime, m_currentEndTime, m_currentContent.toString()); + RefPtrWillBeRawPtr<VTTCue> cue = VTTCue::create(*m_document, m_currentStartTime, m_currentEndTime, m_currentContent.toString()); cue->setId(m_currentId); cue->parseSettings(m_currentSettings); - m_cuelist.append(cue); + m_cueList.append(cue); if (m_client) m_client->newCuesParsed(); } void VTTParser::resetCueValues() { - m_currentId = emptyString(); + m_currentId = emptyAtom; m_currentSettings = emptyString(); m_currentStartTime = 0; m_currentEndTime = 0; @@ -452,7 +390,7 @@ void VTTParser::createNewRegion(const String& headerValue) return; // Steps 12.5.1 - 12.5.9 - Construct and initialize a WebVTT Region object. - RefPtr<VTTRegion> region = VTTRegion::create(); + RefPtrWillBeRawPtr<VTTRegion> region = VTTRegion::create(); region->setRegionSettings(headerValue); // Step 12.5.10 If the text track list of regions regions contains a region @@ -468,7 +406,13 @@ void VTTParser::createNewRegion(const String& headerValue) m_regionList.append(region); } -bool VTTParser::collectTimeStamp(const String& line, unsigned* position, double& timeStamp) +bool VTTParser::collectTimeStamp(const String& line, double& timeStamp) +{ + VTTScanner input(line); + return collectTimeStamp(input, timeStamp); +} + +bool VTTParser::collectTimeStamp(VTTScanner& input, double& timeStamp) { // Collect a WebVTT timestamp (5.3 WebVTT cue timings and settings parsing.) // Steps 1 - 4 - Initial checks, let most significant units be minutes. @@ -478,25 +422,21 @@ bool VTTParser::collectTimeStamp(const String& line, unsigned* position, double& // Steps 5 - 7 - Collect a sequence of characters that are 0-9. // If not 2 characters or value is greater than 59, interpret as hours. int value1; - unsigned value1Digits = collectDigitsToInt(line, position, value1); + unsigned value1Digits = input.scanDigits(value1); if (!value1Digits) return false; if (value1Digits != 2 || value1 > 59) mode = Hours; // Steps 8 - 11 - Collect the next sequence of 0-9 after ':' (must be 2 chars). - if (*position >= line.length() || line[(*position)++] != ':') - return false; int value2; - if (collectDigitsToInt(line, position, value2) != 2) + if (!input.scan(':') || input.scanDigits(value2) != 2) return false; // Step 12 - Detect whether this timestamp includes hours. int value3; - if (mode == Hours || (*position < line.length() && line[*position] == ':')) { - if (*position >= line.length() || line[(*position)++] != ':') - return false; - if (collectDigitsToInt(line, position, value3) != 2) + if (mode == Hours || input.match(':')) { + if (!input.scan(':') || input.scanDigits(value3) != 2) return false; } else { value3 = value2; @@ -505,10 +445,8 @@ bool VTTParser::collectTimeStamp(const String& line, unsigned* position, double& } // Steps 13 - 17 - Collect next sequence of 0-9 after '.' (must be 3 chars). - if (*position >= line.length() || line[(*position)++] != '.') - return false; int value4; - if (collectDigitsToInt(line, position, value4) != 3) + if (!input.scan('.') || input.scanDigits(value4) != 3) return false; if (value2 > 59 || value3 > 59) return false; @@ -553,8 +491,7 @@ void VTTTreeBuilder::constructTreeFromToken(Document& document) switch (m_token.type()) { case VTTTokenTypes::Character: { - RefPtr<Text> child = Text::create(document, m_token.characters()); - m_currentNode->parserAppendChild(child); + m_currentNode->parserAppendChild(Text::create(document, m_token.characters())); break; } case VTTTokenTypes::StartTag: { @@ -567,7 +504,7 @@ void VTTTreeBuilder::constructTreeFromToken(Document& document) if (nodeType == VTTNodeTypeRubyText && currentType != VTTNodeTypeRuby) break; - RefPtr<VTTElement> child = VTTElement::create(nodeType, &document); + RefPtrWillBeRawPtr<VTTElement> child = VTTElement::create(nodeType, &document); if (!m_token.classes().isEmpty()) child->setAttribute(classAttr, m_token.classes()); @@ -611,10 +548,9 @@ void VTTTreeBuilder::constructTreeFromToken(Document& document) break; } case VTTTokenTypes::TimestampTag: { - unsigned position = 0; String charactersString = m_token.characters(); double parsedTimeStamp; - if (VTTParser::collectTimeStamp(charactersString, &position, parsedTimeStamp)) + if (VTTParser::collectTimeStamp(charactersString, parsedTimeStamp)) m_currentNode->parserAppendChild(ProcessingInstruction::create(document, "timestamp", charactersString)); break; } @@ -623,5 +559,11 @@ void VTTTreeBuilder::constructTreeFromToken(Document& document) } } +void VTTParser::trace(Visitor* visitor) +{ + visitor->trace(m_document); + visitor->trace(m_cueList); + visitor->trace(m_regionList); } +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.h b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.h index df4e584cae9..3fca1af5e74 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.h +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTParser.h @@ -31,22 +31,21 @@ #ifndef VTTParser_h #define VTTParser_h -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" +#include "core/HTMLNames.h" #include "core/dom/DocumentFragment.h" -#include "core/fetch/TextResourceDecoder.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/html/track/vtt/BufferedLineReader.h" #include "core/html/track/vtt/VTTCue.h" #include "core/html/track/vtt/VTTRegion.h" #include "core/html/track/vtt/VTTTokenizer.h" +#include "platform/heap/Handle.h" #include "wtf/PassOwnPtr.h" #include "wtf/text/StringBuilder.h" namespace WebCore { -using namespace HTMLNames; - class Document; +class VTTScanner; class VTTParserClient { public: @@ -57,7 +56,7 @@ public: virtual void fileFailedToParse() = 0; }; -class VTTParser FINAL { +class VTTParser FINAL : public NoBaseWillBeGarbageCollectedFinalized<VTTParser> { public: enum ParseState { Initial, @@ -68,54 +67,53 @@ public: BadCue }; - static PassOwnPtr<VTTParser> create(VTTParserClient* client, Document& document) + static PassOwnPtrWillBeRawPtr<VTTParser> create(VTTParserClient* client, Document& document) { - return adoptPtr(new VTTParser(client, document)); + return adoptPtrWillBeNoop(new VTTParser(client, document)); } static inline bool isRecognizedTag(const AtomicString& tagName) { - return tagName == iTag - || tagName == bTag - || tagName == uTag - || tagName == rubyTag - || tagName == rtTag; + return tagName == HTMLNames::iTag + || tagName == HTMLNames::bTag + || tagName == HTMLNames::uTag + || tagName == HTMLNames::rubyTag + || tagName == HTMLNames::rtTag; } - - static inline bool isASpace(char c) + static inline bool isASpace(UChar c) { // WebVTT space characters are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF), U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN (CR). return c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'; } - static inline bool isValidSettingDelimiter(char c) + static inline bool isValidSettingDelimiter(UChar c) { // ... a WebVTT cue consists of zero or more of the following components, in any order, separated from each other by one or more // U+0020 SPACE characters or U+0009 CHARACTER TABULATION (tab) characters. return c == ' ' || c == '\t'; } - static unsigned collectDigitsToInt(const String& input, unsigned* position, int& number); - static String collectWord(const String&, unsigned*); - static bool collectTimeStamp(const String&, unsigned*, double& timeStamp); + static bool collectTimeStamp(const String&, double& timeStamp); // Useful functions for parsing percentage settings. - static bool parseFloatPercentageValue(const String&, float&); - static bool parseFloatPercentageValuePair(const String&, char, FloatPoint&); + static bool parseFloatPercentageValue(VTTScanner& valueScanner, float& percentage); + static bool parseFloatPercentageValuePair(VTTScanner&, char, FloatPoint&); // Create the DocumentFragment representation of the WebVTT cue text. - static PassRefPtr<DocumentFragment> createDocumentFragmentFromCueText(Document&, const String&); + static PassRefPtrWillBeRawPtr<DocumentFragment> createDocumentFragmentFromCueText(Document&, const String&); // Input data to the parser to parse. void parseBytes(const char* data, unsigned length); void flush(); // Transfers ownership of last parsed cues to caller. - void getNewCues(Vector<RefPtr<VTTCue> >&); - void getNewRegions(Vector<RefPtr<VTTRegion> >&); + void getNewCues(WillBeHeapVector<RefPtrWillBeMember<VTTCue> >&); + void getNewRegions(WillBeHeapVector<RefPtrWillBeMember<VTTRegion> >&); + + void trace(Visitor*); private: VTTParser(VTTParserClient*, Document&); - Document* m_document; + RawPtrWillBeMember<Document> m_document; ParseState m_state; void parse(); @@ -133,11 +131,11 @@ private: void collectMetadataHeader(const String&); void createNewRegion(const String& headerValue); - static void skipWhiteSpace(const String&, unsigned*); + static bool collectTimeStamp(VTTScanner& input, double& timeStamp); BufferedLineReader m_lineReader; OwnPtr<TextResourceDecoder> m_decoder; - String m_currentId; + AtomicString m_currentId; double m_currentStartTime; double m_currentEndTime; StringBuilder m_currentContent; @@ -145,9 +143,9 @@ private: VTTParserClient* m_client; - Vector<RefPtr<VTTCue> > m_cuelist; + WillBeHeapVector<RefPtrWillBeMember<VTTCue> > m_cueList; - Vector<RefPtr<VTTRegion> > m_regionList; + WillBeHeapVector<RefPtrWillBeMember<VTTRegion> > m_regionList; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.cpp index 4f39fb51cc9..26b32a39864 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.cpp @@ -37,6 +37,7 @@ #include "core/dom/DOMTokenList.h" #include "core/html/HTMLDivElement.h" #include "core/html/track/vtt/VTTParser.h" +#include "core/html/track/vtt/VTTScanner.h" #include "core/rendering/RenderInline.h" #include "core/rendering/RenderObject.h" #include "platform/Logging.h" @@ -67,14 +68,10 @@ static const float lineHeight = 5.33; // Default scrolling animation time period (s). static const float scrollTime = 0.433; -static bool isInfiniteOrNonNumberOrNonPercentage(double value, const char* method, ExceptionState& exceptionState) +static bool isNonPercentage(double value, const char* method, ExceptionState& exceptionState) { - if (!std::isfinite(value)) { - exceptionState.throwTypeError(ExceptionMessages::notAFiniteNumber(value)); - return true; - } if (value < 0 || value > 100) { - exceptionState.throwDOMException(IndexSizeError, "The value provided (" + String::number(value) + ") is not between 0 and 100."); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexOutsideRange("value", value, 0.0, ExceptionMessages::InclusiveBound, 100.0, ExceptionMessages::InclusiveBound)); return true; } return false; @@ -87,7 +84,7 @@ VTTRegion::VTTRegion() , m_regionAnchor(FloatPoint(defaultAnchorPointX, defaultAnchorPointY)) , m_viewportAnchor(FloatPoint(defaultAnchorPointX, defaultAnchorPointY)) , m_scroll(defaultScroll) - , m_track(0) + , m_track(nullptr) , m_currentTop(0) , m_scrollTimer(this, &VTTRegion::scrollTimerFired) { @@ -109,7 +106,7 @@ void VTTRegion::setId(const String& id) void VTTRegion::setWidth(double value, ExceptionState& exceptionState) { - if (isInfiniteOrNonNumberOrNonPercentage(value, "width", exceptionState)) + if (isNonPercentage(value, "width", exceptionState)) return; m_width = value; @@ -127,7 +124,7 @@ void VTTRegion::setHeight(long value, ExceptionState& exceptionState) void VTTRegion::setRegionAnchorX(double value, ExceptionState& exceptionState) { - if (isInfiniteOrNonNumberOrNonPercentage(value, "regionAnchorX", exceptionState)) + if (isNonPercentage(value, "regionAnchorX", exceptionState)) return; m_regionAnchor.setX(value); @@ -135,7 +132,7 @@ void VTTRegion::setRegionAnchorX(double value, ExceptionState& exceptionState) void VTTRegion::setRegionAnchorY(double value, ExceptionState& exceptionState) { - if (isInfiniteOrNonNumberOrNonPercentage(value, "regionAnchorY", exceptionState)) + if (isNonPercentage(value, "regionAnchorY", exceptionState)) return; m_regionAnchor.setY(value); @@ -143,7 +140,7 @@ void VTTRegion::setRegionAnchorY(double value, ExceptionState& exceptionState) void VTTRegion::setViewportAnchorX(double value, ExceptionState& exceptionState) { - if (isInfiniteOrNonNumberOrNonPercentage(value, "viewportAnchorX", exceptionState)) + if (isNonPercentage(value, "viewportAnchorX", exceptionState)) return; m_viewportAnchor.setX(value); @@ -151,7 +148,7 @@ void VTTRegion::setViewportAnchorX(double value, ExceptionState& exceptionState) void VTTRegion::setViewportAnchorY(double value, ExceptionState& exceptionState) { - if (isInfiniteOrNonNumberOrNonPercentage(value, "viewportAnchorY", exceptionState)) + if (isNonPercentage(value, "viewportAnchorY", exceptionState)) return; m_viewportAnchor.setY(value); @@ -190,83 +187,102 @@ void VTTRegion::updateParametersFromRegion(VTTRegion* region) setScroll(region->scroll(), ASSERT_NO_EXCEPTION); } -void VTTRegion::setRegionSettings(const String& input) +void VTTRegion::setRegionSettings(const String& inputString) { - m_settings = input; - unsigned position = 0; + m_settings = inputString; + + VTTScanner input(inputString); - while (position < input.length()) { - while (position < input.length() && VTTParser::isValidSettingDelimiter(input[position])) - position++; + while (!input.isAtEnd()) { + input.skipWhile<VTTParser::isValidSettingDelimiter>(); - if (position >= input.length()) + if (input.isAtEnd()) break; - parseSetting(input, &position); + // Scan the name part. + RegionSetting name = scanSettingName(input); + + // Verify that we're looking at a '='. + if (name == None || !input.scan('=')) { + input.skipUntil<VTTParser::isASpace>(); + continue; + } + + // Scan the value part. + parseSettingValue(name, input); } } -VTTRegion::RegionSetting VTTRegion::getSettingFromString(const String& setting) +VTTRegion::RegionSetting VTTRegion::scanSettingName(VTTScanner& input) { - DEFINE_STATIC_LOCAL(const AtomicString, idKeyword, ("id", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, heightKeyword, ("height", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, widthKeyword, ("width", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, regionAnchorKeyword, ("regionanchor", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, viewportAnchorKeyword, ("viewportanchor", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, scrollKeyword, ("scroll", AtomicString::ConstructFromLiteral)); - - if (setting == idKeyword) + if (input.scan("id")) return Id; - if (setting == heightKeyword) + if (input.scan("height")) return Height; - if (setting == widthKeyword) + if (input.scan("width")) return Width; - if (setting == viewportAnchorKeyword) + if (input.scan("viewportanchor")) return ViewportAnchor; - if (setting == regionAnchorKeyword) + if (input.scan("regionanchor")) return RegionAnchor; - if (setting == scrollKeyword) + if (input.scan("scroll")) return Scroll; return None; } -void VTTRegion::parseSettingValue(RegionSetting setting, const String& value) +static inline bool parsedEntireRun(const VTTScanner& input, const VTTScanner::Run& run) +{ + return input.isAt(run.end()); +} + +void VTTRegion::parseSettingValue(RegionSetting setting, VTTScanner& input) { DEFINE_STATIC_LOCAL(const AtomicString, scrollUpValueKeyword, ("up", AtomicString::ConstructFromLiteral)); + VTTScanner::Run valueRun = input.collectUntil<VTTParser::isASpace>(); + switch (setting) { - case Id: - if (value.find("-->") == kNotFound) - m_id = value; + case Id: { + String stringValue = input.extractString(valueRun); + if (stringValue.find("-->") == kNotFound) + m_id = stringValue; break; + } case Width: { float floatWidth; - if (VTTParser::parseFloatPercentageValue(value, floatWidth)) + if (VTTParser::parseFloatPercentageValue(input, floatWidth) && parsedEntireRun(input, valueRun)) m_width = floatWidth; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid Width"); break; } case Height: { - unsigned position = 0; int number; - if (VTTParser::collectDigitsToInt(value, &position, number) && position == value.length()) + if (input.scanDigits(number) && parsedEntireRun(input, valueRun)) m_heightInLines = number; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid Height"); break; } - case RegionAnchor: - if (!VTTParser::parseFloatPercentageValuePair(value, ',', m_regionAnchor)) + case RegionAnchor: { + FloatPoint anchor; + if (VTTParser::parseFloatPercentageValuePair(input, ',', anchor) && parsedEntireRun(input, valueRun)) + m_regionAnchor = anchor; + else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid RegionAnchor"); break; - case ViewportAnchor: - if (!VTTParser::parseFloatPercentageValuePair(value, ',', m_viewportAnchor)) + } + case ViewportAnchor: { + FloatPoint anchor; + if (VTTParser::parseFloatPercentageValuePair(input, ',', anchor) && parsedEntireRun(input, valueRun)) + m_viewportAnchor = anchor; + else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid ViewportAnchor"); break; + } case Scroll: - if (value == scrollUpValueKeyword) + if (input.scanRun(valueRun, scrollUpValueKeyword)) m_scroll = true; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid Scroll"); @@ -274,20 +290,8 @@ void VTTRegion::parseSettingValue(RegionSetting setting, const String& value) case None: break; } -} - -void VTTRegion::parseSetting(const String& input, unsigned* position) -{ - String setting = VTTParser::collectWord(input, position); - size_t equalOffset = setting.find('=', 1); - if (equalOffset == kNotFound || !equalOffset || equalOffset == setting.length() - 1) - return; - - RegionSetting name = getSettingFromString(setting.substring(0, equalOffset)); - String value = setting.substring(equalOffset + 1, setting.length() - 1); - - parseSettingValue(name, value); + input.skipRun(valueRun); } const AtomicString& VTTRegion::textTrackCueContainerShadowPseudoId() @@ -314,7 +318,7 @@ const AtomicString& VTTRegion::textTrackRegionShadowPseudoId() return trackRegionShadowPseudoId; } -PassRefPtr<HTMLDivElement> VTTRegion::getDisplayTree(Document& document) +PassRefPtrWillBeRawPtr<HTMLDivElement> VTTRegion::getDisplayTree(Document& document) { if (!m_regionDisplayTree) { m_regionDisplayTree = HTMLDivElement::create(document); @@ -331,13 +335,13 @@ void VTTRegion::willRemoveVTTCueBox(VTTCueBox* box) double boxHeight = box->getBoundingClientRect()->bottom() - box->getBoundingClientRect()->top(); - m_cueContainer->classList()->remove(textTrackCueContainerScrollingClass(), ASSERT_NO_EXCEPTION); + m_cueContainer->classList().remove(textTrackCueContainerScrollingClass(), ASSERT_NO_EXCEPTION); m_currentTop += boxHeight; m_cueContainer->setInlineStyleProperty(CSSPropertyTop, m_currentTop, CSSPrimitiveValue::CSS_PX); } -void VTTRegion::appendVTTCueBox(PassRefPtr<VTTCueBox> displayBox) +void VTTRegion::appendVTTCueBox(PassRefPtrWillBeRawPtr<VTTCueBox> displayBox) { ASSERT(m_cueContainer); @@ -362,14 +366,14 @@ void VTTRegion::displayLastVTTCueBox() // If it's a scrolling region, add the scrolling class. if (isScrollingRegion()) - m_cueContainer->classList()->add(textTrackCueContainerScrollingClass(), ASSERT_NO_EXCEPTION); + m_cueContainer->classList().add(textTrackCueContainerScrollingClass(), ASSERT_NO_EXCEPTION); float regionBottom = m_regionDisplayTree->getBoundingClientRect()->bottom(); // Find first cue that is not entirely displayed and scroll it upwards. - for (size_t i = 0; i < m_cueContainer->childNodeCount() && !m_scrollTimer.isActive(); ++i) { - float childTop = toHTMLDivElement(m_cueContainer->childNode(i))->getBoundingClientRect()->top(); - float childBottom = toHTMLDivElement(m_cueContainer->childNode(i))->getBoundingClientRect()->bottom(); + for (Element* child = ElementTraversal::firstWithin(*m_cueContainer); child && !m_scrollTimer.isActive(); child = ElementTraversal::nextSibling(*child)) { + float childTop = toHTMLDivElement(child)->getBoundingClientRect()->top(); + float childBottom = toHTMLDivElement(child)->getBoundingClientRect()->bottom(); if (regionBottom >= childBottom) continue; @@ -429,11 +433,11 @@ void VTTRegion::prepareRegionDisplayTree() 0.0, CSSPrimitiveValue::CSS_PX); - m_cueContainer->setPseudo(textTrackCueContainerShadowPseudoId()); + m_cueContainer->setShadowPseudoId(textTrackCueContainerShadowPseudoId()); m_regionDisplayTree->appendChild(m_cueContainer); // 7.5 Every WebVTT region object is initialised with the following CSS - m_regionDisplayTree->setPseudo(textTrackRegionShadowPseudoId()); + m_regionDisplayTree->setShadowPseudoId(textTrackRegionShadowPseudoId()); } void VTTRegion::startTimer() @@ -444,7 +448,7 @@ void VTTRegion::startTimer() return; double duration = isScrollingRegion() ? scrollTime : 0; - m_scrollTimer.startOneShot(duration); + m_scrollTimer.startOneShot(duration, FROM_HERE); } void VTTRegion::stopTimer() @@ -463,4 +467,11 @@ void VTTRegion::scrollTimerFired(Timer<VTTRegion>*) displayLastVTTCueBox(); } +void VTTRegion::trace(Visitor* visitor) +{ + visitor->trace(m_cueContainer); + visitor->trace(m_regionDisplayTree); + visitor->trace(m_track); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.h b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.h index f9452c22498..ab2121eab97 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.h +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.h @@ -35,6 +35,7 @@ #include "core/html/track/TextTrack.h" #include "platform/Timer.h" #include "platform/geometry/FloatPoint.h" +#include "platform/heap/Handle.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefCounted.h" @@ -43,12 +44,13 @@ namespace WebCore { class ExceptionState; class HTMLDivElement; class VTTCueBox; +class VTTScanner; -class VTTRegion : public RefCounted<VTTRegion> { +class VTTRegion FINAL : public RefCountedWillBeGarbageCollectedFinalized<VTTRegion> { public: - static PassRefPtr<VTTRegion> create() + static PassRefPtrWillBeRawPtr<VTTRegion> create() { - return adoptRef(new VTTRegion()); + return adoptRefWillBeNoop(new VTTRegion()); } virtual ~VTTRegion(); @@ -87,12 +89,14 @@ public: bool isScrollingRegion() { return m_scroll; } - PassRefPtr<HTMLDivElement> getDisplayTree(Document&); + PassRefPtrWillBeRawPtr<HTMLDivElement> getDisplayTree(Document&); - void appendVTTCueBox(PassRefPtr<VTTCueBox>); + void appendVTTCueBox(PassRefPtrWillBeRawPtr<VTTCueBox>); void displayLastVTTCueBox(); void willRemoveVTTCueBox(VTTCueBox*); + void trace(Visitor*); + private: VTTRegion(); @@ -112,9 +116,8 @@ private: ViewportAnchor, Scroll }; - RegionSetting getSettingFromString(const String&); - void parseSettingValue(RegionSetting, const String&); - void parseSetting(const String&, unsigned*); + RegionSetting scanSettingName(VTTScanner&); + void parseSettingValue(RegionSetting, VTTScanner&); static const AtomicString& textTrackCueContainerShadowPseudoId(); static const AtomicString& textTrackCueContainerScrollingClass(); @@ -130,14 +133,14 @@ private: // The cue container is the container that is scrolled up to obtain the // effect of scrolling cues when this is enabled for the regions. - RefPtr<HTMLDivElement> m_cueContainer; - RefPtr<HTMLDivElement> m_regionDisplayTree; + RefPtrWillBeMember<HTMLDivElement> m_cueContainer; + RefPtrWillBeMember<HTMLDivElement> m_regionDisplayTree; // The member variable track can be a raw pointer as it will never // reference a destroyed TextTrack, as this member variable // is cleared in the TextTrack destructor and it is generally // set/reset within the addRegion and removeRegion methods. - TextTrack* m_track; + RawPtrWillBeMember<TextTrack> m_track; // Keep track of the current numeric value of the css "top" property. double m_currentTop; diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.idl b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.idl index 398f7404b97..1a28e70b4da 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegion.idl @@ -25,7 +25,9 @@ [ Constructor, - RuntimeEnabled=WebVTTRegions + RuntimeEnabled=WebVTTRegions, + TypeChecking=Unrestricted, + WillBeGarbageCollected, ] interface VTTRegion { readonly attribute TextTrack track; @@ -38,4 +40,3 @@ [RaisesException=Setter] attribute double viewportAnchorY; [RaisesException=Setter] attribute DOMString scroll; }; - diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.cpp index 914da521ae7..41bf33ad8b5 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.cpp +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.cpp @@ -58,7 +58,7 @@ VTTRegion* VTTRegionList::getRegionById(const String& id) const return 0; } -void VTTRegionList::add(PassRefPtr<VTTRegion> region) +void VTTRegionList::add(PassRefPtrWillBeRawPtr<VTTRegion> region) { m_list.append(region); } @@ -73,9 +73,9 @@ bool VTTRegionList::remove(VTTRegion* region) return true; } -void VTTRegionList::clear() +void VTTRegionList::trace(Visitor* visitor) { - m_list.clear(); + visitor->trace(m_list); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.h b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.h index 35e1b8e8d47..edb87d601b3 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.h +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.h @@ -33,28 +33,27 @@ namespace WebCore { -class VTTRegionList : public RefCounted<VTTRegionList> { +class VTTRegionList FINAL : public RefCountedWillBeGarbageCollected<VTTRegionList> { public: - static PassRefPtr<VTTRegionList> create() + static PassRefPtrWillBeRawPtr<VTTRegionList> create() { - return adoptRef(new VTTRegionList()); + return adoptRefWillBeNoop(new VTTRegionList()); } - ~VTTRegionList() { } - unsigned long length() const; VTTRegion* item(unsigned index) const; VTTRegion* getRegionById(const String&) const; - void add(PassRefPtr<VTTRegion>); + void add(PassRefPtrWillBeRawPtr<VTTRegion>); bool remove(VTTRegion*); + void trace(Visitor*); + private: VTTRegionList(); - void clear(); - Vector<RefPtr<VTTRegion> > m_list; + WillBeHeapVector<RefPtrWillBeMember<VTTRegion> > m_list; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.idl b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.idl index 4a06653bba0..cdd3d4dd131 100644 --- a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.idl +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTRegionList.idl @@ -24,7 +24,8 @@ */ [ - RuntimeEnabled=WebVTTRegions + RuntimeEnabled=WebVTTRegions, + WillBeGarbageCollected, ] interface VTTRegionList { readonly attribute unsigned long length; getter VTTRegion item(unsigned long index); diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.cpp new file mode 100644 index 00000000000..590178f8864 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2013, Opera Software ASA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER 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 "core/html/track/vtt/VTTScanner.h" + +namespace WebCore { + +VTTScanner::VTTScanner(const String& line) : m_is8Bit(line.is8Bit()) +{ + if (m_is8Bit) { + m_data.characters8 = line.characters8(); + m_end.characters8 = m_data.characters8 + line.length(); + } else { + m_data.characters16 = line.characters16(); + m_end.characters16 = m_data.characters16 + line.length(); + } +} + +bool VTTScanner::scan(char c) +{ + if (!match(c)) + return false; + advance(); + return true; +} + +bool VTTScanner::scan(const LChar* characters, size_t charactersCount) +{ + unsigned matchLength = m_is8Bit ? m_end.characters8 - m_data.characters8 : m_end.characters16 - m_data.characters16; + if (matchLength < charactersCount) + return false; + bool matched; + if (m_is8Bit) + matched = WTF::equal(m_data.characters8, characters, charactersCount); + else + matched = WTF::equal(m_data.characters16, characters, charactersCount); + if (matched) + advance(charactersCount); + return matched; +} + +bool VTTScanner::scanRun(const Run& run, const String& toMatch) +{ + ASSERT(run.start() == position()); + ASSERT(run.start() <= end()); + ASSERT(run.end() >= run.start()); + ASSERT(run.end() <= end()); + size_t matchLength = run.length(); + if (toMatch.length() > matchLength) + return false; + bool matched; + if (m_is8Bit) + matched = WTF::equal(toMatch.impl(), m_data.characters8, matchLength); + else + matched = WTF::equal(toMatch.impl(), m_data.characters16, matchLength); + if (matched) + seekTo(run.end()); + return matched; +} + +void VTTScanner::skipRun(const Run& run) +{ + ASSERT(run.start() <= end()); + ASSERT(run.end() >= run.start()); + ASSERT(run.end() <= end()); + seekTo(run.end()); +} + +String VTTScanner::extractString(const Run& run) +{ + ASSERT(run.start() == position()); + ASSERT(run.start() <= end()); + ASSERT(run.end() >= run.start()); + ASSERT(run.end() <= end()); + String s; + if (m_is8Bit) + s = String(m_data.characters8, run.length()); + else + s = String(m_data.characters16, run.length()); + seekTo(run.end()); + return s; +} + +String VTTScanner::restOfInputAsString() +{ + Run rest(position(), end(), m_is8Bit); + return extractString(rest); +} + +unsigned VTTScanner::scanDigits(int& number) +{ + Run runOfDigits = collectWhile<isASCIIDigit>(); + if (runOfDigits.isEmpty()) { + number = 0; + return 0; + } + bool validNumber; + size_t numDigits = runOfDigits.length(); + if (m_is8Bit) + number = charactersToInt(m_data.characters8, numDigits, &validNumber); + else + number = charactersToInt(m_data.characters16, numDigits, &validNumber); + + // Since we know that scanDigits only scanned valid (ASCII) digits (and + // hence that's what got passed to charactersToInt()), the remaining + // failure mode for charactersToInt() is overflow, so if |validNumber| is + // not true, then set |number| to the maximum int value. + if (!validNumber) + number = std::numeric_limits<int>::max(); + // Consume the digits. + seekTo(runOfDigits.end()); + return numDigits; +} + +bool VTTScanner::scanFloat(float& number) +{ + Run integerRun = collectWhile<isASCIIDigit>(); + seekTo(integerRun.end()); + Run decimalRun(position(), position(), m_is8Bit); + if (scan('.')) { + decimalRun = collectWhile<isASCIIDigit>(); + seekTo(decimalRun.end()); + } + + // At least one digit required. + if (integerRun.isEmpty() && decimalRun.isEmpty()) { + // Restore to starting position. + seekTo(integerRun.start()); + return false; + } + + size_t lengthOfFloat = Run(integerRun.start(), position(), m_is8Bit).length(); + bool validNumber; + if (m_is8Bit) + number = charactersToFloat(integerRun.start(), lengthOfFloat, &validNumber); + else + number = charactersToFloat(reinterpret_cast<const UChar*>(integerRun.start()), lengthOfFloat, &validNumber); + + if (!validNumber) + number = std::numeric_limits<float>::max(); + return true; +} + +} diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.h b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.h new file mode 100644 index 00000000000..aa097e780ec --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScanner.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013, Opera Software ASA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER 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 VTTScanner_h +#define VTTScanner_h + +#include "platform/ParsingUtilities.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +// Helper class for "scanning" an input string and performing parsing of +// "micro-syntax"-like constructs. +// +// There's two primary operations: match and scan. +// +// The 'match' operation matches an explicitly or implicitly specified sequence +// against the characters ahead of the current input pointer, and returns true +// if the sequence can be matched. +// +// The 'scan' operation performs a 'match', and if the match is successful it +// advance the input pointer past the matched sequence. +class VTTScanner { + WTF_MAKE_NONCOPYABLE(VTTScanner); +public: + explicit VTTScanner(const String& line); + + typedef const LChar* Position; + + class Run { + public: + Run(Position start, Position end, bool is8Bit) + : m_start(start), m_end(end), m_is8Bit(is8Bit) { } + + Position start() const { return m_start; } + Position end() const { return m_end; } + + bool isEmpty() const { return m_start == m_end; } + size_t length() const; + + private: + Position m_start; + Position m_end; + bool m_is8Bit; + }; + + // Check if the input pointer points at the specified position. + bool isAt(Position checkPosition) const { return position() == checkPosition; } + // Check if the input pointer points at the end of the input. + bool isAtEnd() const { return position() == end(); } + // Match the character |c| against the character at the input pointer (~lookahead). + bool match(char c) const { return !isAtEnd() && currentChar() == c; } + // Scan the character |c|. + bool scan(char); + // Scan the first |charactersCount| characters of the string |characters|. + bool scan(const LChar* characters, size_t charactersCount); + + // Scan the literal |characters|. + template<unsigned charactersCount> + bool scan(const char (&characters)[charactersCount]); + + // Skip (advance the input pointer) as long as the specified + // |characterPredicate| returns true, and the input pointer is not passed + // the end of the input. + template<bool characterPredicate(UChar)> + void skipWhile(); + + // Like skipWhile, but using a negated predicate. + template<bool characterPredicate(UChar)> + void skipUntil(); + + // Return the run of characters for which the specified + // |characterPredicate| returns true. The start of the run will be the + // current input pointer. + template<bool characterPredicate(UChar)> + Run collectWhile(); + + // Like collectWhile, but using a negated predicate. + template<bool characterPredicate(UChar)> + Run collectUntil(); + + // Scan the string |toMatch|, using the specified |run| as the sequence to + // match against. + bool scanRun(const Run&, const String& toMatch); + + // Skip to the end of the specified |run|. + void skipRun(const Run&); + + // Return the String made up of the characters in |run|, and advance the + // input pointer to the end of the run. + String extractString(const Run&); + + // Return a String constructed from the rest of the input (between input + // pointer and end of input), and advance the input pointer accordingly. + String restOfInputAsString(); + + // Scan a set of ASCII digits from the input. Return the number of digits + // scanned, and set |number| to the computed value. If the digits make up a + // number that does not fit the 'int' type, |number| is set to INT_MAX. + // Note: Does not handle sign. + unsigned scanDigits(int& number); + + // Scan a floating point value on one of the forms: \d+\.? \d+\.\d+ \.\d+ + bool scanFloat(float& number); + +protected: + Position position() const { return m_data.characters8; } + Position end() const { return m_end.characters8; } + void seekTo(Position); + UChar currentChar() const; + void advance(unsigned amount = 1); + // Adapt a UChar-predicate to an LChar-predicate. + // (For use with skipWhile/Until from ParsingUtilities.h). + template<bool characterPredicate(UChar)> + static inline bool LCharPredicateAdapter(LChar c) { return characterPredicate(c); } + union { + const LChar* characters8; + const UChar* characters16; + } m_data; + union { + const LChar* characters8; + const UChar* characters16; + } m_end; + bool m_is8Bit; +}; + +inline size_t VTTScanner::Run::length() const +{ + if (m_is8Bit) + return m_end - m_start; + return reinterpret_cast<const UChar*>(m_end) - reinterpret_cast<const UChar*>(m_start); +} + +template<unsigned charactersCount> +inline bool VTTScanner::scan(const char (&characters)[charactersCount]) +{ + return scan(reinterpret_cast<const LChar*>(characters), charactersCount - 1); +} + +template<bool characterPredicate(UChar)> +inline void VTTScanner::skipWhile() +{ + if (m_is8Bit) + ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8); + else + ::skipWhile<UChar, characterPredicate>(m_data.characters16, m_end.characters16); +} + +template<bool characterPredicate(UChar)> +inline void VTTScanner::skipUntil() +{ + if (m_is8Bit) + ::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(m_data.characters8, m_end.characters8); + else + ::skipUntil<UChar, characterPredicate>(m_data.characters16, m_end.characters16); +} + +template<bool characterPredicate(UChar)> +inline VTTScanner::Run VTTScanner::collectWhile() +{ + if (m_is8Bit) { + const LChar* current = m_data.characters8; + ::skipWhile<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8); + return Run(position(), current, m_is8Bit); + } + const UChar* current = m_data.characters16; + ::skipWhile<UChar, characterPredicate>(current, m_end.characters16); + return Run(position(), reinterpret_cast<Position>(current), m_is8Bit); +} + +template<bool characterPredicate(UChar)> +inline VTTScanner::Run VTTScanner::collectUntil() +{ + if (m_is8Bit) { + const LChar* current = m_data.characters8; + ::skipUntil<LChar, LCharPredicateAdapter<characterPredicate> >(current, m_end.characters8); + return Run(position(), current, m_is8Bit); + } + const UChar* current = m_data.characters16; + ::skipUntil<UChar, characterPredicate>(current, m_end.characters16); + return Run(position(), reinterpret_cast<Position>(current), m_is8Bit); +} + +inline void VTTScanner::seekTo(Position position) +{ + ASSERT(position <= end()); + m_data.characters8 = position; +} + +inline UChar VTTScanner::currentChar() const +{ + ASSERT(position() < end()); + return m_is8Bit ? *m_data.characters8 : *m_data.characters16; +} + +inline void VTTScanner::advance(unsigned amount) +{ + ASSERT(position() < end()); + if (m_is8Bit) + m_data.characters8 += amount; + else + m_data.characters16 += amount; +} + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScannerTest.cpp b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScannerTest.cpp new file mode 100644 index 00000000000..d5bcfb8f52f --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/track/vtt/VTTScannerTest.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2013, Opera Software ASA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER 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 "core/html/track/vtt/VTTScanner.h" + +#include "wtf/text/WTFString.h" + +#include <gtest/gtest.h> + +using WebCore::VTTScanner; + +namespace { + +TEST(VTTScanner, Constructor) +{ + String data8("foo"); + EXPECT_TRUE(data8.is8Bit()); + VTTScanner scanner8(data8); + EXPECT_FALSE(scanner8.isAtEnd()); + + String data16(data8); + data16.ensure16Bit(); + EXPECT_FALSE(data16.is8Bit()); + VTTScanner scanner16(data16); + EXPECT_FALSE(scanner16.isAtEnd()); + + VTTScanner scannerEmpty(emptyString()); + EXPECT_TRUE(scannerEmpty.isAtEnd()); +} + +void scanSequenceHelper1(const String& input) +{ + VTTScanner scanner(input); + EXPECT_FALSE(scanner.isAtEnd()); + EXPECT_TRUE(scanner.match('f')); + EXPECT_FALSE(scanner.match('o')); + + EXPECT_TRUE(scanner.scan('f')); + EXPECT_FALSE(scanner.match('f')); + EXPECT_TRUE(scanner.match('o')); + + EXPECT_FALSE(scanner.scan('e')); + EXPECT_TRUE(scanner.scan('o')); + + EXPECT_TRUE(scanner.scan('e')); + EXPECT_FALSE(scanner.match('e')); + + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Run TESTFUNC with DATA in Latin and then UTF-16. (Requires DATA being Latin.) +#define TEST_WITH(TESTFUNC, DATA) do { \ + String data8(DATA); \ + EXPECT_TRUE(data8.is8Bit()); \ + TESTFUNC(data8); \ + \ + String data16(data8); \ + data16.ensure16Bit(); \ + EXPECT_FALSE(data16.is8Bit()); \ + TESTFUNC(data16); \ +} while (false) + + +// Exercises match(c) and scan(c). +TEST(VTTScanner, BasicOperations1) +{ + TEST_WITH(scanSequenceHelper1, "foe"); +} + +void scanSequenceHelper2(const String& input) +{ + VTTScanner scanner(input); + EXPECT_FALSE(scanner.isAtEnd()); + EXPECT_FALSE(scanner.scan("fe")); + + EXPECT_TRUE(scanner.scan("fo")); + EXPECT_FALSE(scanner.isAtEnd()); + + EXPECT_FALSE(scanner.scan("ee")); + + EXPECT_TRUE(scanner.scan('e')); + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Exercises scan(<literal>[, length]). +TEST(VTTScanner, BasicOperations2) +{ + TEST_WITH(scanSequenceHelper2, "foe"); +} + +bool lowerCaseAlpha(UChar c) +{ + return c >= 'a' && c <= 'z'; +} + +void scanWithPredicate(const String& input) +{ + VTTScanner scanner(input); + EXPECT_FALSE(scanner.isAtEnd()); + // Collect "bad". + VTTScanner::Run lcRun = scanner.collectWhile<lowerCaseAlpha>(); + // collectWhile doesn't move the scan position. + EXPECT_TRUE(scanner.match('b')); + // Consume "bad". + scanner.skipWhile<lowerCaseAlpha>(); + EXPECT_TRUE(scanner.match('A')); + EXPECT_TRUE(scanner.isAt(lcRun.end())); + + // Consume "A". + EXPECT_TRUE(scanner.scan('A')); + + // Collect "bing". + lcRun = scanner.collectWhile<lowerCaseAlpha>(); + // collectWhile doesn't move the scan position. + EXPECT_FALSE(scanner.isAtEnd()); + // Consume "bing". + scanner.skipWhile<lowerCaseAlpha>(); + EXPECT_TRUE(scanner.isAt(lcRun.end())); + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests skipWhile() and collectWhile(). +TEST(VTTScanner, PredicateScanning) +{ + TEST_WITH(scanWithPredicate, "badAbing"); +} + +void scanWithInvPredicate(const String& input) +{ + VTTScanner scanner(input); + EXPECT_FALSE(scanner.isAtEnd()); + // Collect "BAD". + VTTScanner::Run ucRun = scanner.collectUntil<lowerCaseAlpha>(); + // collectUntil doesn't move the scan position. + EXPECT_TRUE(scanner.match('B')); + // Consume "BAD". + scanner.skipUntil<lowerCaseAlpha>(); + EXPECT_TRUE(scanner.match('a')); + EXPECT_TRUE(scanner.isAt(ucRun.end())); + + // Consume "a". + EXPECT_TRUE(scanner.scan('a')); + + // Collect "BING". + ucRun = scanner.collectUntil<lowerCaseAlpha>(); + // collectUntil doesn't move the scan position. + EXPECT_FALSE(scanner.isAtEnd()); + // Consume "BING". + scanner.skipUntil<lowerCaseAlpha>(); + EXPECT_TRUE(scanner.isAt(ucRun.end())); + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests skipUntil() and collectUntil(). +TEST(VTTScanner, InversePredicateScanning) +{ + TEST_WITH(scanWithInvPredicate, "BADaBING"); +} + +void scanRuns(const String& input) +{ + String fooString("foo"); + String barString("bar"); + VTTScanner scanner(input); + EXPECT_FALSE(scanner.isAtEnd()); + VTTScanner::Run word = scanner.collectWhile<lowerCaseAlpha>(); + EXPECT_FALSE(scanner.scanRun(word, barString)); + EXPECT_TRUE(scanner.scanRun(word, fooString)); + + EXPECT_TRUE(scanner.match(':')); + EXPECT_TRUE(scanner.scan(':')); + + // Skip 'baz'. + scanner.skipRun(scanner.collectWhile<lowerCaseAlpha>()); + + EXPECT_TRUE(scanner.match(':')); + EXPECT_TRUE(scanner.scan(':')); + + word = scanner.collectWhile<lowerCaseAlpha>(); + EXPECT_FALSE(scanner.scanRun(word, fooString)); + EXPECT_TRUE(scanner.scanRun(word, barString)); + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests scanRun/skipRun. +TEST(VTTScanner, RunScanning) +{ + TEST_WITH(scanRuns, "foo:baz:bar"); +} + +void scanRunsToStrings(const String& input) +{ + VTTScanner scanner(input); + EXPECT_FALSE(scanner.isAtEnd()); + VTTScanner::Run word = scanner.collectWhile<lowerCaseAlpha>(); + String fooString = scanner.extractString(word); + EXPECT_EQ(fooString, "foo"); + EXPECT_TRUE(scanner.isAt(word.end())); + + EXPECT_TRUE(scanner.match(':')); + EXPECT_TRUE(scanner.scan(':')); + + word = scanner.collectWhile<lowerCaseAlpha>(); + String barString = scanner.extractString(word); + EXPECT_EQ(barString, "bar"); + EXPECT_TRUE(scanner.isAt(word.end())); + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests extractString. +TEST(VTTScanner, ExtractString) +{ + TEST_WITH(scanRunsToStrings, "foo:bar"); +} + +void tailStringExtract(const String& input) +{ + VTTScanner scanner(input); + EXPECT_TRUE(scanner.scan("foo")); + EXPECT_TRUE(scanner.scan(':')); + String barSuffix = scanner.restOfInputAsString(); + EXPECT_EQ(barSuffix, "bar"); + + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests restOfInputAsString(). +TEST(VTTScanner, ExtractRestAsString) +{ + TEST_WITH(tailStringExtract, "foo:bar"); +} + +void scanDigits1(const String& input) +{ + VTTScanner scanner(input); + EXPECT_TRUE(scanner.scan("foo")); + int number; + EXPECT_EQ(scanner.scanDigits(number), 0u); + EXPECT_EQ(number, 0); + EXPECT_TRUE(scanner.scan(' ')); + EXPECT_EQ(scanner.scanDigits(number), 3u); + EXPECT_TRUE(scanner.match(' ')); + EXPECT_EQ(number, 123); + + EXPECT_TRUE(scanner.scan(' ')); + EXPECT_TRUE(scanner.scan("bar")); + EXPECT_TRUE(scanner.scan(' ')); + + EXPECT_EQ(scanner.scanDigits(number), 5u); + EXPECT_EQ(number, 45678); + + EXPECT_TRUE(scanner.isAtEnd()); +} + +void scanDigits2(const String& input) +{ + VTTScanner scanner(input); + int number; + EXPECT_EQ(scanner.scanDigits(number), 0u); + EXPECT_EQ(number, 0); + EXPECT_TRUE(scanner.scan('-')); + EXPECT_EQ(scanner.scanDigits(number), 3u); + EXPECT_EQ(number, 654); + + EXPECT_TRUE(scanner.scan(' ')); + + EXPECT_EQ(scanner.scanDigits(number), 19u); + EXPECT_EQ(number, std::numeric_limits<int>::max()); + + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests scanDigits(). +TEST(VTTScanner, ScanDigits) +{ + TEST_WITH(scanDigits1, "foo 123 bar 45678"); + TEST_WITH(scanDigits2, "-654 1000000000000000000"); +} + +void scanFloatValue(const String& input) +{ + VTTScanner scanner(input); + float value; + // "1." + EXPECT_TRUE(scanner.scanFloat(value)); + EXPECT_EQ(value, 1.0f); + EXPECT_TRUE(scanner.scan(' ')); + + // "1.0" + EXPECT_TRUE(scanner.scanFloat(value)); + EXPECT_EQ(value, 1.0f); + EXPECT_TRUE(scanner.scan(' ')); + + // ".0" + EXPECT_TRUE(scanner.scanFloat(value)); + EXPECT_EQ(value, 0.0f); + EXPECT_TRUE(scanner.scan(' ')); + + // "." (invalid) + EXPECT_FALSE(scanner.scanFloat(value)); + EXPECT_TRUE(scanner.match('.')); + EXPECT_TRUE(scanner.scan('.')); + EXPECT_TRUE(scanner.scan(' ')); + + // "1.0000" + EXPECT_TRUE(scanner.scanFloat(value)); + EXPECT_EQ(value, 1.0f); + EXPECT_TRUE(scanner.scan(' ')); + + // "01.000" + EXPECT_TRUE(scanner.scanFloat(value)); + EXPECT_EQ(value, 1.0f); + + EXPECT_TRUE(scanner.isAtEnd()); +} + +// Tests scanFloat(). +TEST(VTTScanner, ScanFloat) +{ + TEST_WITH(scanFloatValue, "1. 1.0 .0 . 1.0000 01.000"); +} + +#undef TEST_WITH + +} // namespace |