summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-29 12:18:48 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-29 12:18:57 +0100
commit4c01d0526ba4dd8cff0c0ff22a6f0ab5eb973064 (patch)
treebed2fe914fe0f7ec70abfb47d2d84af8a3604d09 /Source/WebCore/html
parent01485457c9a5da3f1121015afd25bb53af77662e (diff)
Imported WebKit commit c60cfe0fc09efd257aa0111d7b133b02deb8a63e (http://svn.webkit.org/repository/webkit/trunk@136119)
New snapshot that includes the fix for installing the QtWebProcess into libexec Change-Id: I01344e079cbdac5678c4cba6ffcc05f4597cf0d7 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'Source/WebCore/html')
-rw-r--r--Source/WebCore/html/BaseDateAndTimeInputType.cpp5
-rw-r--r--Source/WebCore/html/BaseDateAndTimeInputType.h1
-rw-r--r--Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.cpp15
-rw-r--r--Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.h2
-rw-r--r--Source/WebCore/html/CollectionType.h29
-rw-r--r--Source/WebCore/html/FormAssociatedElement.cpp7
-rw-r--r--Source/WebCore/html/FormAssociatedElement.h1
-rw-r--r--Source/WebCore/html/HTMLCollection.cpp15
-rw-r--r--Source/WebCore/html/HTMLFontElement.cpp25
-rw-r--r--Source/WebCore/html/HTMLFormControlElement.cpp15
-rw-r--r--Source/WebCore/html/HTMLFormControlElement.h2
-rw-r--r--Source/WebCore/html/HTMLFormControlsCollection.cpp4
-rw-r--r--Source/WebCore/html/HTMLFormControlsCollection.h4
-rw-r--r--Source/WebCore/html/HTMLInputElement.cpp20
-rw-r--r--Source/WebCore/html/HTMLInputElement.h5
-rw-r--r--Source/WebCore/html/HTMLMediaElement.cpp34
-rw-r--r--Source/WebCore/html/HTMLMediaElement.h5
-rw-r--r--Source/WebCore/html/HTMLMediaElement.idl5
-rw-r--r--Source/WebCore/html/HTMLNameCollection.cpp9
-rw-r--r--Source/WebCore/html/HTMLNameCollection.h4
-rw-r--r--Source/WebCore/html/HTMLOptionElement.h2
-rw-r--r--Source/WebCore/html/HTMLOptionsCollection.cpp4
-rw-r--r--Source/WebCore/html/HTMLOptionsCollection.h4
-rw-r--r--Source/WebCore/html/HTMLPlugInElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLPlugInElement.h2
-rw-r--r--Source/WebCore/html/HTMLPlugInImageElement.cpp27
-rw-r--r--Source/WebCore/html/HTMLPlugInImageElement.h7
-rw-r--r--Source/WebCore/html/HTMLTableRowsCollection.cpp4
-rw-r--r--Source/WebCore/html/HTMLTableRowsCollection.h4
-rw-r--r--Source/WebCore/html/HTMLTextAreaElement.cpp10
-rw-r--r--Source/WebCore/html/HTMLTextAreaElement.h2
-rw-r--r--Source/WebCore/html/InputType.cpp24
-rw-r--r--Source/WebCore/html/InputType.h4
-rw-r--r--Source/WebCore/html/LabelsNodeList.h3
-rw-r--r--Source/WebCore/html/NumberInputType.cpp20
-rw-r--r--Source/WebCore/html/NumberInputType.h4
-rw-r--r--Source/WebCore/html/RadioNodeList.h3
-rw-r--r--Source/WebCore/html/RangeInputType.cpp1
-rw-r--r--Source/WebCore/html/TextFieldInputType.cpp7
-rw-r--r--Source/WebCore/html/TextFieldInputType.h1
-rw-r--r--Source/WebCore/html/ValidityState.cpp5
-rw-r--r--Source/WebCore/html/ValidityState.h1
-rw-r--r--Source/WebCore/html/ValidityState.idl1
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp15
-rw-r--r--Source/WebCore/html/parser/XSSAuditor.cpp9
-rw-r--r--Source/WebCore/html/shadow/ContentDistributor.cpp56
-rw-r--r--Source/WebCore/html/shadow/ContentDistributor.h32
-rw-r--r--Source/WebCore/html/shadow/MediaControlElements.cpp149
-rw-r--r--Source/WebCore/html/shadow/MediaControlElements.h11
-rw-r--r--Source/WebCore/html/shadow/MediaControlsApple.cpp11
-rw-r--r--Source/WebCore/html/shadow/MediaControlsApple.h1
-rw-r--r--Source/WebCore/html/shadow/SliderThumbElement.cpp64
-rw-r--r--Source/WebCore/html/shadow/SliderThumbElement.h16
-rw-r--r--Source/WebCore/html/track/TextTrack.cpp14
54 files changed, 486 insertions, 241 deletions
diff --git a/Source/WebCore/html/BaseDateAndTimeInputType.cpp b/Source/WebCore/html/BaseDateAndTimeInputType.cpp
index 00a1ffc38..2ad9fea79 100644
--- a/Source/WebCore/html/BaseDateAndTimeInputType.cpp
+++ b/Source/WebCore/html/BaseDateAndTimeInputType.cpp
@@ -180,5 +180,10 @@ String BaseDateAndTimeInputType::sanitizeValue(const String& proposedValue) cons
return typeMismatchFor(proposedValue) ? String() : proposedValue;
}
+bool BaseDateAndTimeInputType::supportsReadOnly() const
+{
+ return true;
+}
+
} // namespace WebCore
#endif
diff --git a/Source/WebCore/html/BaseDateAndTimeInputType.h b/Source/WebCore/html/BaseDateAndTimeInputType.h
index 63b26723e..bcc7b2310 100644
--- a/Source/WebCore/html/BaseDateAndTimeInputType.h
+++ b/Source/WebCore/html/BaseDateAndTimeInputType.h
@@ -66,6 +66,7 @@ private:
virtual String serializeWithMilliseconds(double) const;
virtual String localizeValue(const String&) const OVERRIDE;
virtual String convertFromVisibleValue(const String&) const OVERRIDE;
+ virtual bool supportsReadOnly() const OVERRIDE;
};
} // namespace WebCore
diff --git a/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.cpp b/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.cpp
index 4bd7cde2c..b55e9a5a7 100644
--- a/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.cpp
+++ b/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.cpp
@@ -41,6 +41,7 @@
#include "HTMLInputElement.h"
#include "HTMLOptionElement.h"
#include "KeyboardEvent.h"
+#include "LocalizedStrings.h"
#include "Page.h"
#include "PickerIndicatorElement.h"
#include "PlatformLocale.h"
@@ -168,6 +169,11 @@ BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType(
m_pickerIndicatorElement->removePickerIndicatorOwner();
}
+String BaseMultipleFieldsDateAndTimeInputType::badInputText() const
+{
+ return validationMessageBadInputForDateTimeText();
+}
+
void BaseMultipleFieldsDateAndTimeInputType::blur()
{
if (m_dateTimeEditElement)
@@ -273,6 +279,11 @@ void BaseMultipleFieldsDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* e
forwardEvent(event);
}
+bool BaseMultipleFieldsDateAndTimeInputType::hasBadInput() const
+{
+ return element()->value().isEmpty() && m_dateTimeEditElement && m_dateTimeEditElement->anyEditableFieldsHaveValues();
+}
+
bool BaseMultipleFieldsDateAndTimeInputType::isKeyboardFocusable(KeyboardEvent*) const
{
return false;
@@ -325,8 +336,10 @@ FormControlState BaseMultipleFieldsDateAndTimeInputType::saveFormControlState()
void BaseMultipleFieldsDateAndTimeInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
InputType::setValue(sanitizedValue, valueChanged, eventBehavior);
- if (valueChanged || (sanitizedValue.isEmpty() && m_dateTimeEditElement && m_dateTimeEditElement->anyEditableFieldsHaveValues()))
+ if (valueChanged || (sanitizedValue.isEmpty() && m_dateTimeEditElement && m_dateTimeEditElement->anyEditableFieldsHaveValues())) {
updateInnerTextValue();
+ element()->setNeedsValidityCheck();
+ }
}
bool BaseMultipleFieldsDateAndTimeInputType::shouldUseInputMethod() const
diff --git a/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.h b/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.h
index b5acc9e6b..bd41fffef 100644
--- a/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.h
+++ b/Source/WebCore/html/BaseMultipleFieldsDateAndTimeInputType.h
@@ -73,6 +73,7 @@ private:
virtual bool setupDateTimeChooserParameters(DateTimeChooserParameters&) OVERRIDE FINAL;
// InputType functions
+ virtual String badInputText() const OVERRIDE;
virtual void blur() OVERRIDE FINAL;
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) const OVERRIDE FINAL;
virtual void createShadowSubtree() OVERRIDE FINAL;
@@ -81,6 +82,7 @@ private:
virtual void focus(bool restorePreviousSelection) OVERRIDE FINAL;
virtual void forwardEvent(Event*) OVERRIDE FINAL;
virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE FINAL;
+ virtual bool hasBadInput() const OVERRIDE;
virtual bool hasCustomFocusLogic() const OVERRIDE FINAL;
virtual bool isKeyboardFocusable(KeyboardEvent*) const OVERRIDE FINAL;
virtual bool isMouseFocusable() const OVERRIDE FINAL;
diff --git a/Source/WebCore/html/CollectionType.h b/Source/WebCore/html/CollectionType.h
index f43d5df0d..9ec75c054 100644
--- a/Source/WebCore/html/CollectionType.h
+++ b/Source/WebCore/html/CollectionType.h
@@ -26,8 +26,7 @@
namespace WebCore {
enum CollectionType {
- // unnamed collection types cached in the document
-
+ // Unnamed HTMLCollection types cached in the document.
DocImages, // all <img> elements in the document
DocApplets, // all <object> and <applet> elements
DocEmbeds, // all <embed> elements
@@ -35,16 +34,13 @@ enum CollectionType {
DocLinks, // all <a> _and_ <area> elements with a value for href
DocAnchors, // all <a> elements with a value for name
DocScripts, // all <script> elements
-
DocAll, // "all" elements (IE)
- // named collection types cached in the document
-
+ // Named collection types cached in the document.
WindowNamedItems,
DocumentNamedItems,
- // types not cached in the document; these are types that can't be used on a document
-
+ // Unnamed HTMLCollection types cached in elements.
NodeChildren, // first-level children (IE)
TableTBodies, // all <tbody> elements in this table
TSectionRows, // all row elements in this table section
@@ -54,15 +50,12 @@ enum CollectionType {
SelectedOptions,
DataListOptions,
MapAreas,
-
#if ENABLE(MICRODATA)
ItemProperties, // Microdata item properties in the document
#endif
-
FormControls,
- // Live node lists.
-
+ // Live NodeList.
ChildNodeListType,
ClassNodeListType,
NameNodeListType,
@@ -73,22 +66,8 @@ enum CollectionType {
PropertyNodeListType,
};
-static const CollectionType FirstUnnamedDocumentCachedType = DocImages;
-static const unsigned NumUnnamedDocumentCachedTypes = WindowNamedItems - DocImages;
-
-static const CollectionType FirstNodeCollectionType = NodeChildren;
static const CollectionType FirstNodeListType = ChildNodeListType;
-inline bool isUnnamedDocumentCachedType(CollectionType type)
-{
- return static_cast<unsigned>(type) < NumUnnamedDocumentCachedTypes;
-}
-
-inline bool isNodeCollectionType(CollectionType type)
-{
- return type >= FirstNodeCollectionType;
-}
-
inline bool isNodeList(CollectionType type)
{
return type >= FirstNodeListType;
diff --git a/Source/WebCore/html/FormAssociatedElement.cpp b/Source/WebCore/html/FormAssociatedElement.cpp
index 3d889783e..8dfdae096 100644
--- a/Source/WebCore/html/FormAssociatedElement.cpp
+++ b/Source/WebCore/html/FormAssociatedElement.cpp
@@ -189,6 +189,11 @@ bool FormAssociatedElement::customError() const
return element->willValidate() && !m_customValidationMessage.isEmpty();
}
+bool FormAssociatedElement::hasBadInput() const
+{
+ return false;
+}
+
bool FormAssociatedElement::patternMismatch() const
{
return false;
@@ -222,7 +227,7 @@ bool FormAssociatedElement::typeMismatch() const
bool FormAssociatedElement::valid() const
{
bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
- || tooLong() || patternMismatch() || valueMissing() || customError();
+ || tooLong() || patternMismatch() || valueMissing() || hasBadInput() || customError();
return !someError;
}
diff --git a/Source/WebCore/html/FormAssociatedElement.h b/Source/WebCore/html/FormAssociatedElement.h
index 390e0ee75..d1dc9a59c 100644
--- a/Source/WebCore/html/FormAssociatedElement.h
+++ b/Source/WebCore/html/FormAssociatedElement.h
@@ -77,6 +77,7 @@ public:
// Override functions for patterMismatch, rangeOverflow, rangerUnderflow,
// stepMismatch, tooLong and valueMissing must call willValidate method.
+ virtual bool hasBadInput() const;
virtual bool patternMismatch() const;
virtual bool rangeOverflow() const;
virtual bool rangeUnderflow() const;
diff --git a/Source/WebCore/html/HTMLCollection.cpp b/Source/WebCore/html/HTMLCollection.cpp
index df20954de..278f7931a 100644
--- a/Source/WebCore/html/HTMLCollection.cpp
+++ b/Source/WebCore/html/HTMLCollection.cpp
@@ -29,6 +29,7 @@
#include "HTMLObjectElement.h"
#include "HTMLOptionElement.h"
#include "NodeList.h"
+#include "NodeRareData.h"
#if ENABLE(MICRODATA)
#include "HTMLPropertiesCollection.h"
@@ -179,7 +180,6 @@ HTMLCollection::HTMLCollection(Node* ownerNode, CollectionType type, ItemAfterOv
: LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type),
WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideType)
{
- document()->registerNodeListCache(this);
}
PassRefPtr<HTMLCollection> HTMLCollection::create(Node* base, CollectionType type)
@@ -189,16 +189,9 @@ PassRefPtr<HTMLCollection> HTMLCollection::create(Node* base, CollectionType typ
HTMLCollection::~HTMLCollection()
{
- if (isUnnamedDocumentCachedType(type())) {
- ASSERT(base()->isDocumentNode());
- static_cast<Document*>(base())->removeCachedHTMLCollection(this, type());
- } else if (isNodeCollectionType(type())) {
- ASSERT(base()->isElementNode());
- toElement(base())->removeCachedHTMLCollection(this, type());
- } else // HTMLNameCollection removes cache by itself.
- ASSERT(type() == WindowNamedItems || type() == DocumentNamedItems);
-
- document()->unregisterNodeListCache(this);
+ // HTMLNameCollection removes cache by itself.
+ if (type() != WindowNamedItems && type() != DocumentNamedItems)
+ ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type());
}
static inline bool isAcceptableElement(CollectionType type, Element* element)
diff --git a/Source/WebCore/html/HTMLFontElement.cpp b/Source/WebCore/html/HTMLFontElement.cpp
index a5bc8de31..1bad02e73 100644
--- a/Source/WebCore/html/HTMLFontElement.cpp
+++ b/Source/WebCore/html/HTMLFontElement.cpp
@@ -51,13 +51,14 @@ PassRefPtr<HTMLFontElement> HTMLFontElement::create(const QualifiedName& tagName
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#fonts-and-colors
-static bool parseFontSize(const String& input, int& size)
+template <typename CharacterType>
+static bool parseFontSize(const CharacterType* characters, unsigned length, int& size)
{
// Step 1
// Step 2
- const UChar* position = input.characters();
- const UChar* end = position + input.length();
+ const CharacterType* position = characters;
+ const CharacterType* end = characters + length;
// Step 3
while (position < end) {
@@ -106,7 +107,12 @@ static bool parseFontSize(const String& input, int& size)
return false;
// Step 8
- int value = charactersToIntStrict(digits.characters(), digits.length());
+ int value;
+
+ if (digits.is8Bit())
+ value = charactersToIntStrict(digits.characters8(), digits.length());
+ else
+ value = charactersToIntStrict(digits.characters16(), digits.length());
// Step 9
if (mode == RelativePlus)
@@ -126,6 +132,17 @@ static bool parseFontSize(const String& input, int& size)
return true;
}
+static bool parseFontSize(const String& input, int& size)
+{
+ if (input.isEmpty())
+ return false;
+
+ if (input.is8Bit())
+ return parseFontSize(input.characters8(), input.length(), size);
+
+ return parseFontSize(input.characters16(), input.length(), size);
+}
+
bool HTMLFontElement::cssValueFromFontSizeNumber(const String& s, int& size)
{
int num = 0;
diff --git a/Source/WebCore/html/HTMLFormControlElement.cpp b/Source/WebCore/html/HTMLFormControlElement.cpp
index 9b19f8c4d..d433946e8 100644
--- a/Source/WebCore/html/HTMLFormControlElement.cpp
+++ b/Source/WebCore/html/HTMLFormControlElement.cpp
@@ -172,8 +172,11 @@ static bool shouldAutofocus(HTMLFormControlElement* element)
return false;
if (element->document()->ignoreAutofocus())
return false;
- if (element->document()->isSandboxed(SandboxAutomaticFeatures))
+ 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(HTMLMessageSource, LogMessageType, ErrorMessageLevel, "Blocked autofocusing on a form control because the form's frame is sandboxed and the 'allow-script' permission is not set.");
return false;
+ }
if (element->hasAutofocused())
return false;
@@ -459,16 +462,6 @@ void HTMLFormControlElement::setCustomValidity(const String& error)
setNeedsValidityCheck();
}
-bool HTMLFormControlElement::shouldMatchReadOnlySelector() const
-{
- return readOnly();
-}
-
-bool HTMLFormControlElement::shouldMatchReadWriteSelector() const
-{
- return !readOnly();
-}
-
bool HTMLFormControlElement::validationMessageShadowTreeContains(Node* node) const
{
return m_validationMessage && m_validationMessage->shadowTreeContains(node);
diff --git a/Source/WebCore/html/HTMLFormControlElement.h b/Source/WebCore/html/HTMLFormControlElement.h
index ec6e885f5..185b37d92 100644
--- a/Source/WebCore/html/HTMLFormControlElement.h
+++ b/Source/WebCore/html/HTMLFormControlElement.h
@@ -81,8 +81,6 @@ public:
virtual const AtomicString& formControlType() const OVERRIDE = 0;
virtual bool isEnabledFormControl() const { return !disabled(); }
- virtual bool shouldMatchReadOnlySelector() const OVERRIDE;
- virtual bool shouldMatchReadWriteSelector() const OVERRIDE;
virtual bool canTriggerImplicitSubmission() const { return false; }
diff --git a/Source/WebCore/html/HTMLFormControlsCollection.cpp b/Source/WebCore/html/HTMLFormControlsCollection.cpp
index e73520901..aac92ba46 100644
--- a/Source/WebCore/html/HTMLFormControlsCollection.cpp
+++ b/Source/WebCore/html/HTMLFormControlsCollection.cpp
@@ -36,13 +36,13 @@ using namespace HTMLNames;
// Since the collections are to be "live", we have to do the
// calculation every time if anything has changed.
-HTMLFormControlsCollection::HTMLFormControlsCollection(Element* base)
+HTMLFormControlsCollection::HTMLFormControlsCollection(Node* base)
: HTMLCollection(base, FormControls, OverridesItemAfter)
{
ASSERT(base->hasTagName(formTag) || base->hasTagName(fieldsetTag));
}
-PassRefPtr<HTMLFormControlsCollection> HTMLFormControlsCollection::create(Element* base, CollectionType)
+PassRefPtr<HTMLFormControlsCollection> HTMLFormControlsCollection::create(Node* base, CollectionType)
{
return adoptRef(new HTMLFormControlsCollection(base));
}
diff --git a/Source/WebCore/html/HTMLFormControlsCollection.h b/Source/WebCore/html/HTMLFormControlsCollection.h
index 7846a504e..cef0f14d5 100644
--- a/Source/WebCore/html/HTMLFormControlsCollection.h
+++ b/Source/WebCore/html/HTMLFormControlsCollection.h
@@ -37,14 +37,14 @@ class QualifiedName;
class HTMLFormControlsCollection : public HTMLCollection {
public:
- static PassRefPtr<HTMLFormControlsCollection> create(Element*, CollectionType);
+ static PassRefPtr<HTMLFormControlsCollection> create(Node*, CollectionType);
virtual ~HTMLFormControlsCollection();
virtual Node* namedItem(const AtomicString& name) const;
private:
- HTMLFormControlsCollection(Element*);
+ HTMLFormControlsCollection(Node*);
virtual void updateNameCache() const;
diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp
index 4cae786f1..124af4e60 100644
--- a/Source/WebCore/html/HTMLInputElement.cpp
+++ b/Source/WebCore/html/HTMLInputElement.cpp
@@ -266,6 +266,11 @@ bool HTMLInputElement::valueMissing() const
return willValidate() && m_inputType->valueMissing(value());
}
+bool HTMLInputElement::hasBadInput() const
+{
+ return willValidate() && m_inputType->hasBadInput();
+}
+
bool HTMLInputElement::patternMismatch() const
{
return willValidate() && m_inputType->patternMismatch(value());
@@ -1391,11 +1396,6 @@ String HTMLInputElement::localizeValue(const String& proposedValue) const
return m_inputType->localizeValue(proposedValue);
}
-bool HTMLInputElement::hasUnacceptableValue() const
-{
- return m_inputType->hasUnacceptableValue();
-}
-
bool HTMLInputElement::isInRange() const
{
return m_inputType->isInRange(value());
@@ -1438,6 +1438,16 @@ bool HTMLInputElement::isRequiredFormControl() const
return m_inputType->supportsRequired() && required();
}
+bool HTMLInputElement::shouldMatchReadOnlySelector() const
+{
+ return m_inputType->supportsReadOnly() && readOnly();
+}
+
+bool HTMLInputElement::shouldMatchReadWriteSelector() const
+{
+ return m_inputType->supportsReadOnly() && !readOnly();
+}
+
void HTMLInputElement::addSearchResult()
{
m_inputType->addSearchResult();
diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h
index b0ac6ae96..f98b019f6 100644
--- a/Source/WebCore/html/HTMLInputElement.h
+++ b/Source/WebCore/html/HTMLInputElement.h
@@ -55,6 +55,7 @@ public:
virtual bool shouldAutocomplete() const;
// For ValidityState
+ virtual bool hasBadInput() const OVERRIDE;
virtual bool patternMismatch() const OVERRIDE;
virtual bool rangeUnderflow() const OVERRIDE;
virtual bool rangeOverflow() const;
@@ -288,6 +289,8 @@ public:
static Vector<FileChooserFileInfo> filesFromFileInputFormControlState(const FormControlState&);
+ virtual bool shouldMatchReadOnlySelector() const OVERRIDE;
+ virtual bool shouldMatchReadWriteSelector() const OVERRIDE;
virtual void setRangeText(const String& replacement, ExceptionCode&) OVERRIDE;
virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionCode&) OVERRIDE;
@@ -355,8 +358,6 @@ private:
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
- virtual bool hasUnacceptableValue() const;
-
virtual bool isInRange() const;
virtual bool isOutOfRange() const;
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index 027dd21d9..732b91717 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -316,6 +316,10 @@ HTMLMediaElement::~HTMLMediaElement()
if (m_mediaController)
m_mediaController->removeMediaElement(this);
+#if ENABLE(MEDIA_SOURCE)
+ setSourceState(MediaSource::closedKeyword());
+#endif
+
removeElementFromDocumentMap(this, document());
}
@@ -676,16 +680,14 @@ String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySy
return canPlay;
}
-void HTMLMediaElement::load(ExceptionCode& ec)
+void HTMLMediaElement::load()
{
RefPtr<HTMLMediaElement> protect(this); // loadInternal may result in a 'beforeload' event, which can make arbitrary DOM mutations.
LOG(Media, "HTMLMediaElement::load()");
- if (userGestureRequiredForLoad() && !ScriptController::processingUserGesture()) {
- ec = INVALID_STATE_ERR;
+ if (userGestureRequiredForLoad() && !ScriptController::processingUserGesture())
return;
- }
m_loadInitiatedByUserGesture = ScriptController::processingUserGesture();
if (m_loadInitiatedByUserGesture)
@@ -2996,6 +2998,22 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group) const
}
}
+void HTMLMediaElement::toggleTrackAtIndex(int index, bool exclusive)
+{
+ TextTrackList* trackList = textTracks();
+ if (!trackList || !trackList->length())
+ return;
+
+ for (int i = 0, length = trackList->length(); i < length; ++i) {
+ TextTrack* track = trackList->item(i);
+ track->setShowingByDefault(false);
+ if (i == index)
+ track->setMode(TextTrack::showingKeyword());
+ else if (exclusive || index == HTMLMediaElement::textTracksOffIndex())
+ track->setMode(TextTrack::disabledKeyword());
+ }
+}
+
void HTMLMediaElement::configureTextTracks()
{
TrackGroup captionAndSubtitleTracks(TrackGroup::CaptionsAndSubtitles);
@@ -3752,6 +3770,11 @@ void HTMLMediaElement::userCancelledLoad()
void HTMLMediaElement::clearMediaPlayer(int flags)
{
#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+
+#if ENABLE(MEDIA_SOURCE)
+ setSourceState(MediaSource::closedKeyword());
+#endif
+
m_player.clear();
#endif
stopPeriodicTimers();
@@ -3815,8 +3838,7 @@ void HTMLMediaElement::resume()
// m_error is only left at MEDIA_ERR_ABORTED when the document becomes inactive (it is set to
// MEDIA_ERR_ABORTED while the abortEvent is being sent, but cleared immediately afterwards).
// This behavior is not specified but it seems like a sensible thing to do.
- ExceptionCode ec;
- load(ec);
+ load();
}
if (renderer())
diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h
index c53129d62..80549c262 100644
--- a/Source/WebCore/html/HTMLMediaElement.h
+++ b/Source/WebCore/html/HTMLMediaElement.h
@@ -134,7 +134,7 @@ public:
void setPreload(const String&);
PassRefPtr<TimeRanges> buffered() const;
- void load(ExceptionCode&);
+ void load();
String canPlayType(const String& mimeType, const String& keySystem = String(), const KURL& = KURL()) const;
// ready state
@@ -245,6 +245,9 @@ public:
void configureTextTracks();
void configureTextTrackGroup(const TrackGroup&) const;
+ void toggleTrackAtIndex(int index, bool exclusive = true);
+ static int textTracksOffIndex() { return -1; }
+
bool userPrefersCaptions() const;
bool userIsInterestedInThisTrackKind(String) const;
bool textTracksAreReady() const;
diff --git a/Source/WebCore/html/HTMLMediaElement.idl b/Source/WebCore/html/HTMLMediaElement.idl
index ece0f5348..2ece5acaa 100644
--- a/Source/WebCore/html/HTMLMediaElement.idl
+++ b/Source/WebCore/html/HTMLMediaElement.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2010, 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,8 +43,7 @@ readonly attribute unsigned short networkState;
attribute DOMString preload;
readonly attribute TimeRanges buffered;
-void load()
- raises (DOMException);
+void load();
#if defined(ENABLE_ENCRYPTED_MEDIA) && ENABLE_ENCRYPTED_MEDIA
DOMString canPlayType(in [Optional=DefaultIsUndefined] DOMString type, in [Optional=DefaultIsUndefined, TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem);
#else
diff --git a/Source/WebCore/html/HTMLNameCollection.cpp b/Source/WebCore/html/HTMLNameCollection.cpp
index 36c7350a4..9e48527e9 100644
--- a/Source/WebCore/html/HTMLNameCollection.cpp
+++ b/Source/WebCore/html/HTMLNameCollection.cpp
@@ -27,12 +27,13 @@
#include "HTMLDocument.h"
#include "HTMLNames.h"
#include "HTMLObjectElement.h"
+#include "NodeRareData.h"
namespace WebCore {
using namespace HTMLNames;
-HTMLNameCollection::HTMLNameCollection(Document* document, CollectionType type, const AtomicString& name)
+HTMLNameCollection::HTMLNameCollection(Node* document, CollectionType type, const AtomicString& name)
: HTMLCollection(document, type, OverridesItemAfter)
, m_name(name)
{
@@ -43,10 +44,8 @@ HTMLNameCollection::~HTMLNameCollection()
ASSERT(base());
ASSERT(base()->isDocumentNode());
ASSERT(type() == WindowNamedItems || type() == DocumentNamedItems);
- if (type() == WindowNamedItems)
- static_cast<Document*>(base())->removeWindowNamedItemCache(this, m_name);
- else
- static_cast<Document*>(base())->removeDocumentNamedItemCache(this, m_name);
+
+ ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type(), m_name);
}
Element* HTMLNameCollection::virtualItemAfter(unsigned& offsetInArray, Element* previous) const
diff --git a/Source/WebCore/html/HTMLNameCollection.h b/Source/WebCore/html/HTMLNameCollection.h
index 4a7afebb7..1fb85b994 100644
--- a/Source/WebCore/html/HTMLNameCollection.h
+++ b/Source/WebCore/html/HTMLNameCollection.h
@@ -33,7 +33,7 @@ class Document;
class HTMLNameCollection : public HTMLCollection {
public:
- static PassRefPtr<HTMLNameCollection> create(Document* document, CollectionType type, const AtomicString& name)
+ static PassRefPtr<HTMLNameCollection> create(Node* document, CollectionType type, const AtomicString& name)
{
return adoptRef(new HTMLNameCollection(document, type, name));
}
@@ -41,7 +41,7 @@ public:
~HTMLNameCollection();
private:
- HTMLNameCollection(Document*, CollectionType, const AtomicString& name);
+ HTMLNameCollection(Node*, CollectionType, const AtomicString& name);
virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE;
diff --git a/Source/WebCore/html/HTMLOptionElement.h b/Source/WebCore/html/HTMLOptionElement.h
index 1bcb9433c..19f569b97 100644
--- a/Source/WebCore/html/HTMLOptionElement.h
+++ b/Source/WebCore/html/HTMLOptionElement.h
@@ -92,8 +92,6 @@ private:
String collectOptionInnerText() const;
- String m_value;
- String m_label;
bool m_disabled;
bool m_isSelected;
RefPtr<RenderStyle> m_style;
diff --git a/Source/WebCore/html/HTMLOptionsCollection.cpp b/Source/WebCore/html/HTMLOptionsCollection.cpp
index 06dda7a25..75b707e55 100644
--- a/Source/WebCore/html/HTMLOptionsCollection.cpp
+++ b/Source/WebCore/html/HTMLOptionsCollection.cpp
@@ -27,13 +27,13 @@
namespace WebCore {
-HTMLOptionsCollection::HTMLOptionsCollection(Element* select)
+HTMLOptionsCollection::HTMLOptionsCollection(Node* select)
: HTMLCollection(select, SelectOptions, DoesNotOverrideItemAfter)
{
ASSERT(select->hasTagName(HTMLNames::selectTag));
}
-PassRefPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(Element* select, CollectionType)
+PassRefPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(Node* select, CollectionType)
{
return adoptRef(new HTMLOptionsCollection(select));
}
diff --git a/Source/WebCore/html/HTMLOptionsCollection.h b/Source/WebCore/html/HTMLOptionsCollection.h
index 46e450df2..d76580fe7 100644
--- a/Source/WebCore/html/HTMLOptionsCollection.h
+++ b/Source/WebCore/html/HTMLOptionsCollection.h
@@ -35,7 +35,7 @@ typedef int ExceptionCode;
class HTMLOptionsCollection : public HTMLCollection {
public:
- static PassRefPtr<HTMLOptionsCollection> create(Element*, CollectionType);
+ static PassRefPtr<HTMLOptionsCollection> create(Node*, CollectionType);
void add(PassRefPtr<HTMLOptionElement>, ExceptionCode&);
void add(PassRefPtr<HTMLOptionElement>, int index, ExceptionCode&);
@@ -47,7 +47,7 @@ public:
void setLength(unsigned, ExceptionCode&);
private:
- HTMLOptionsCollection(Element*);
+ HTMLOptionsCollection(Node*);
};
} //namespace
diff --git a/Source/WebCore/html/HTMLPlugInElement.cpp b/Source/WebCore/html/HTMLPlugInElement.cpp
index bd99dbfd7..e2902ad71 100644
--- a/Source/WebCore/html/HTMLPlugInElement.cpp
+++ b/Source/WebCore/html/HTMLPlugInElement.cpp
@@ -201,7 +201,7 @@ void HTMLPlugInElement::defaultEventHandler(Event* event)
toRenderEmbeddedObject(r)->handleUnavailablePluginIndicatorEvent(event);
return;
}
- if (r->isSnapshottedPlugIn() && displayState() < Playing) {
+ if (r->isSnapshottedPlugIn() && displayState() < PlayingWithPendingMouseClick) {
toRenderSnapshottedPlugIn(r)->handleEvent(event);
return;
}
diff --git a/Source/WebCore/html/HTMLPlugInElement.h b/Source/WebCore/html/HTMLPlugInElement.h
index 379324f70..5a62d54f3 100644
--- a/Source/WebCore/html/HTMLPlugInElement.h
+++ b/Source/WebCore/html/HTMLPlugInElement.h
@@ -51,11 +51,13 @@ public:
enum DisplayState {
WaitingForSnapshot,
DisplayingSnapshot,
+ PlayingWithPendingMouseClick,
Playing
};
DisplayState displayState() const { return m_displayState; }
void setDisplayState(DisplayState state) { m_displayState = state; }
virtual void updateSnapshot(PassRefPtr<Image>) { }
+ virtual void dispatchPendingMouseClick() { }
#if ENABLE(NETSCAPE_PLUGIN_API)
NPObject* getNPObject();
diff --git a/Source/WebCore/html/HTMLPlugInImageElement.cpp b/Source/WebCore/html/HTMLPlugInImageElement.cpp
index b809a1340..421ac1b0f 100644
--- a/Source/WebCore/html/HTMLPlugInImageElement.cpp
+++ b/Source/WebCore/html/HTMLPlugInImageElement.cpp
@@ -27,6 +27,7 @@
#include "HTMLImageLoader.h"
#include "HTMLNames.h"
#include "Image.h"
+#include "MouseEvent.h"
#include "NodeRenderStyle.h"
#include "Page.h"
#include "RenderEmbeddedObject.h"
@@ -38,6 +39,9 @@
namespace WebCore {
+// This delay should not exceed the snapshot delay in PluginView.cpp
+static const double simulatedMouseClickTimerDelay = .75;
+
HTMLPlugInImageElement::HTMLPlugInImageElement(const QualifiedName& tagName, Document* document, bool createdByParser, PreferPlugInsForImagesOption preferPlugInsForImagesOption)
: HTMLPlugInElement(tagName, document)
// m_needsWidgetUpdate(!createdByParser) allows HTMLObjectElement to delay
@@ -47,6 +51,7 @@ HTMLPlugInImageElement::HTMLPlugInImageElement(const QualifiedName& tagName, Doc
, m_needsWidgetUpdate(!createdByParser)
, m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPreferPlugInsForImages)
, m_needsDocumentActivationCallbacks(false)
+ , m_simulatedMouseClickTimer(this, &HTMLPlugInImageElement::simulatedMouseClickTimerFired, simulatedMouseClickTimerDelay)
{
setHasCustomCallbacks();
@@ -257,4 +262,26 @@ void HTMLPlugInImageElement::updateSnapshot(PassRefPtr<Image> image)
setDisplayState(DisplayingSnapshot);
}
+void HTMLPlugInImageElement::setPendingClickEvent(PassRefPtr<MouseEvent> event)
+{
+ m_pendingClickEventFromSnapshot = event;
+}
+
+void HTMLPlugInImageElement::dispatchPendingMouseClick()
+{
+ ASSERT(!m_simulatedMouseClickTimer.isActive());
+ m_simulatedMouseClickTimer.restart();
+}
+
+void HTMLPlugInImageElement::simulatedMouseClickTimerFired(DeferrableOneShotTimer<HTMLPlugInImageElement>*)
+{
+ ASSERT(displayState() == PlayingWithPendingMouseClick);
+ ASSERT(m_pendingClickEventFromSnapshot);
+
+ dispatchSimulatedClick(m_pendingClickEventFromSnapshot.get(), SendMouseOverUpDownEvents, DoNotShowPressedLook);
+
+ setDisplayState(Playing);
+ m_pendingClickEventFromSnapshot = nullptr;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/html/HTMLPlugInImageElement.h b/Source/WebCore/html/HTMLPlugInImageElement.h
index 95fbd8a79..c5bf6fa1f 100644
--- a/Source/WebCore/html/HTMLPlugInImageElement.h
+++ b/Source/WebCore/html/HTMLPlugInImageElement.h
@@ -30,6 +30,7 @@ namespace WebCore {
class HTMLImageLoader;
class FrameLoader;
+class MouseEvent;
enum PluginCreationOption {
CreateAnyWidgetType,
@@ -58,6 +59,8 @@ public:
bool needsWidgetUpdate() const { return m_needsWidgetUpdate; }
void setNeedsWidgetUpdate(bool needsWidgetUpdate) { m_needsWidgetUpdate = needsWidgetUpdate; }
+ void setPendingClickEvent(PassRefPtr<MouseEvent>);
+
protected:
HTMLPlugInImageElement(const QualifiedName& tagName, Document*, bool createdByParser, PreferPlugInsForImagesOption);
@@ -91,11 +94,15 @@ private:
virtual bool useFallbackContent() const { return false; }
virtual void updateSnapshot(PassRefPtr<Image>) OVERRIDE;
+ virtual void dispatchPendingMouseClick() OVERRIDE;
+ void simulatedMouseClickTimerFired(DeferrableOneShotTimer<HTMLPlugInImageElement>*);
bool m_needsWidgetUpdate;
bool m_shouldPreferPlugInsForImages;
bool m_needsDocumentActivationCallbacks;
RefPtr<RenderStyle> m_customStyleForPageCache;
+ RefPtr<MouseEvent> m_pendingClickEventFromSnapshot;
+ DeferrableOneShotTimer<HTMLPlugInImageElement> m_simulatedMouseClickTimer;
};
} // namespace WebCore
diff --git a/Source/WebCore/html/HTMLTableRowsCollection.cpp b/Source/WebCore/html/HTMLTableRowsCollection.cpp
index d94038e63..98459366e 100644
--- a/Source/WebCore/html/HTMLTableRowsCollection.cpp
+++ b/Source/WebCore/html/HTMLTableRowsCollection.cpp
@@ -151,13 +151,13 @@ 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(Element* table)
+HTMLTableRowsCollection::HTMLTableRowsCollection(Node* table)
: HTMLCollection(table, TableRows, OverridesItemAfter)
{
ASSERT(table->hasTagName(tableTag));
}
-PassRefPtr<HTMLTableRowsCollection> HTMLTableRowsCollection::create(Element* table, CollectionType)
+PassRefPtr<HTMLTableRowsCollection> HTMLTableRowsCollection::create(Node* table, CollectionType)
{
return adoptRef(new HTMLTableRowsCollection(table));
}
diff --git a/Source/WebCore/html/HTMLTableRowsCollection.h b/Source/WebCore/html/HTMLTableRowsCollection.h
index c4312896f..1a54f0f1f 100644
--- a/Source/WebCore/html/HTMLTableRowsCollection.h
+++ b/Source/WebCore/html/HTMLTableRowsCollection.h
@@ -38,13 +38,13 @@ class HTMLTableRowElement;
class HTMLTableRowsCollection : public HTMLCollection {
public:
- static PassRefPtr<HTMLTableRowsCollection> create(Element*, CollectionType);
+ static PassRefPtr<HTMLTableRowsCollection> create(Node*, CollectionType);
static HTMLTableRowElement* rowAfter(HTMLTableElement*, HTMLTableRowElement*);
static HTMLTableRowElement* lastRow(HTMLTableElement*);
private:
- HTMLTableRowsCollection(Element*);
+ HTMLTableRowsCollection(Node*);
virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE;
};
diff --git a/Source/WebCore/html/HTMLTextAreaElement.cpp b/Source/WebCore/html/HTMLTextAreaElement.cpp
index 1632927dc..fa6da55c0 100644
--- a/Source/WebCore/html/HTMLTextAreaElement.cpp
+++ b/Source/WebCore/html/HTMLTextAreaElement.cpp
@@ -529,6 +529,16 @@ void HTMLTextAreaElement::attach()
fixPlaceholderRenderer(m_placeholder, innerTextElement());
}
+bool HTMLTextAreaElement::shouldMatchReadOnlySelector() const
+{
+ return readOnly();
+}
+
+bool HTMLTextAreaElement::shouldMatchReadWriteSelector() const
+{
+ return !readOnly();
+}
+
void HTMLTextAreaElement::updatePlaceholderText()
{
ExceptionCode ec = 0;
diff --git a/Source/WebCore/html/HTMLTextAreaElement.h b/Source/WebCore/html/HTMLTextAreaElement.h
index fcc19f8d4..3964ce2be 100644
--- a/Source/WebCore/html/HTMLTextAreaElement.h
+++ b/Source/WebCore/html/HTMLTextAreaElement.h
@@ -112,6 +112,8 @@ private:
virtual bool shouldUseInputMethod();
virtual void attach() OVERRIDE;
+ virtual bool shouldMatchReadOnlySelector() const OVERRIDE;
+ virtual bool shouldMatchReadWriteSelector() const OVERRIDE;
bool valueMissing(const String& value) const { return isRequiredFormControl() && !disabled() && !readOnly() && value.isEmpty(); }
bool tooLong(const String&, NeedsToCheckDirtyFlag) const;
diff --git a/Source/WebCore/html/InputType.cpp b/Source/WebCore/html/InputType.cpp
index 4a437e029..b16fa3b18 100644
--- a/Source/WebCore/html/InputType.cpp
+++ b/Source/WebCore/html/InputType.cpp
@@ -258,6 +258,11 @@ bool InputType::valueMissing(const String&) const
return false;
}
+bool InputType::hasBadInput() const
+{
+ return false;
+}
+
bool InputType::patternMismatch(const String&) const
{
return false;
@@ -346,6 +351,12 @@ bool InputType::stepMismatch(const String& value) const
return createStepRange(RejectAny).stepMismatch(numericValue);
}
+String InputType::badInputText() const
+{
+ ASSERT_NOT_REACHED();
+ return validationMessageTypeMismatchText();
+}
+
String InputType::typeMismatchText() const
{
return validationMessageTypeMismatchText();
@@ -368,6 +379,9 @@ String InputType::validationMessage() const
if (typeMismatch())
return typeMismatchText();
+ if (hasBadInput())
+ return badInputText();
+
if (patternMismatch(value))
return validationMessagePatternMismatchText();
@@ -689,11 +703,6 @@ String InputType::sanitizeValue(const String& proposedValue) const
return proposedValue;
}
-bool InputType::hasUnacceptableValue()
-{
- return false;
-}
-
bool InputType::receiveDroppedFiles(const DragData*)
{
ASSERT_NOT_REACHED();
@@ -861,6 +870,11 @@ bool InputType::supportsPlaceholder() const
return false;
}
+bool InputType::supportsReadOnly() const
+{
+ return false;
+}
+
void InputType::updateInnerTextValue()
{
}
diff --git a/Source/WebCore/html/InputType.h b/Source/WebCore/html/InputType.h
index fe4a9e4d9..333a256a0 100644
--- a/Source/WebCore/html/InputType.h
+++ b/Source/WebCore/html/InputType.h
@@ -156,6 +156,7 @@ public:
virtual bool typeMismatch() const;
virtual bool supportsRequired() const;
virtual bool valueMissing(const String&) const;
+ virtual bool hasBadInput() const;
virtual bool patternMismatch(const String&) const;
bool rangeUnderflow(const String&) const;
bool rangeOverflow(const String&) const;
@@ -170,6 +171,7 @@ public:
virtual StepRange createStepRange(AnyStepHandling) const;
virtual void stepUp(int, ExceptionCode&);
virtual void stepUpFromRenderer(int);
+ virtual String badInputText() const;
virtual String typeMismatchText() const;
virtual String valueMissingText() const;
virtual bool canSetStringValue() const;
@@ -178,7 +180,6 @@ public:
// Returing the null string means "use the default value."
// This function must be called only by HTMLInputElement::sanitizeValue().
virtual String sanitizeValue(const String&) const;
- virtual bool hasUnacceptableValue();
// Event handlers
@@ -267,6 +268,7 @@ public:
virtual bool isSteppable() const;
virtual bool shouldRespectHeightAndWidthAttributes();
virtual bool supportsPlaceholder() const;
+ virtual bool supportsReadOnly() const;
virtual void updateInnerTextValue();
virtual void updatePlaceholderText();
virtual void multipleAttributeChanged();
diff --git a/Source/WebCore/html/LabelsNodeList.h b/Source/WebCore/html/LabelsNodeList.h
index 9052eedd6..0da4f3c7e 100644
--- a/Source/WebCore/html/LabelsNodeList.h
+++ b/Source/WebCore/html/LabelsNodeList.h
@@ -32,8 +32,9 @@ namespace WebCore {
class LabelsNodeList : public LiveNodeList {
public:
- static PassRefPtr<LabelsNodeList> create(Node* forNode, const AtomicString&)
+ static PassRefPtr<LabelsNodeList> create(Node* forNode, CollectionType type, const AtomicString&)
{
+ ASSERT_UNUSED(type, type == LabelsNodeListType);
return adoptRef(new LabelsNodeList(forNode));
}
~LabelsNodeList();
diff --git a/Source/WebCore/html/NumberInputType.cpp b/Source/WebCore/html/NumberInputType.cpp
index 7498cc991..440ee7b9b 100644
--- a/Source/WebCore/html/NumberInputType.cpp
+++ b/Source/WebCore/html/NumberInputType.cpp
@@ -39,6 +39,7 @@
#include "HTMLParserIdioms.h"
#include "InputTypeNames.h"
#include "KeyboardEvent.h"
+#include "LocalizedStrings.h"
#include "PlatformLocale.h"
#include "RenderTextControl.h"
#include <limits>
@@ -213,16 +214,6 @@ String NumberInputType::serialize(const Decimal& value) const
return serializeForNumberType(value);
}
-void NumberInputType::handleBlurEvent()
-{
- // Reset the renderer value, which might be unmatched with the element value.
- element()->setFormControlValueMatchesRenderer(false);
-
- // We need to reset the renderer value explicitly because an unacceptable
- // renderer value should be purged before style calculation.
- updateInnerTextValue();
-}
-
static bool isE(UChar ch)
{
return ch == 'e' || ch == 'E';
@@ -260,14 +251,17 @@ String NumberInputType::sanitizeValue(const String& proposedValue) const
return isfinite(parseToDoubleForNumberType(proposedValue)) ? proposedValue : emptyString();
}
-bool NumberInputType::hasUnacceptableValue()
+bool NumberInputType::hasBadInput() const
{
- if (!element()->renderer())
- return false;
String standardValue = convertFromVisibleValue(element()->innerTextValue());
return !standardValue.isEmpty() && !isfinite(parseToDoubleForNumberType(standardValue));
}
+String NumberInputType::badInputText() const
+{
+ return validationMessageBadInputForNumberText();
+}
+
bool NumberInputType::shouldRespectSpeechAttribute()
{
return true;
diff --git a/Source/WebCore/html/NumberInputType.h b/Source/WebCore/html/NumberInputType.h
index 11cca557b..c77a9a78e 100644
--- a/Source/WebCore/html/NumberInputType.h
+++ b/Source/WebCore/html/NumberInputType.h
@@ -53,12 +53,12 @@ private:
virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE;
virtual Decimal parseToNumber(const String&, const Decimal&) const OVERRIDE;
virtual String serialize(const Decimal&) const OVERRIDE;
- virtual void handleBlurEvent() OVERRIDE;
virtual String localizeValue(const String&) const OVERRIDE;
virtual String visibleValue() const OVERRIDE;
virtual String convertFromVisibleValue(const String&) const OVERRIDE;
virtual String sanitizeValue(const String&) const OVERRIDE;
- virtual bool hasUnacceptableValue() OVERRIDE;
+ virtual bool hasBadInput() const OVERRIDE;
+ virtual String badInputText() const OVERRIDE;
virtual bool shouldRespectSpeechAttribute() OVERRIDE;
virtual bool supportsPlaceholder() const OVERRIDE;
virtual bool isNumberField() const OVERRIDE;
diff --git a/Source/WebCore/html/RadioNodeList.h b/Source/WebCore/html/RadioNodeList.h
index 23a527d35..57cad32d4 100644
--- a/Source/WebCore/html/RadioNodeList.h
+++ b/Source/WebCore/html/RadioNodeList.h
@@ -36,8 +36,9 @@ namespace WebCore {
class RadioNodeList : public LiveNodeList {
public:
- static PassRefPtr<RadioNodeList> create(Node* rootNode, const AtomicString& name)
+ static PassRefPtr<RadioNodeList> create(Node* rootNode, CollectionType type, const AtomicString& name)
{
+ ASSERT_UNUSED(type, type == RadioNodeListType);
return adoptRef(new RadioNodeList(rootNode, name));
}
diff --git a/Source/WebCore/html/RangeInputType.cpp b/Source/WebCore/html/RangeInputType.cpp
index c37f6b770..ed2a8a118 100644
--- a/Source/WebCore/html/RangeInputType.cpp
+++ b/Source/WebCore/html/RangeInputType.cpp
@@ -260,7 +260,6 @@ void RangeInputType::createShadowSubtree()
track->appendChild(SliderThumbElement::create(document), ec);
RefPtr<HTMLElement> container = SliderContainerElement::create(document);
container->appendChild(track.release(), ec);
- container->appendChild(TrackLimiterElement::create(document), ec);
element()->userAgentShadowRoot()->appendChild(container.release(), ec);
}
diff --git a/Source/WebCore/html/TextFieldInputType.cpp b/Source/WebCore/html/TextFieldInputType.cpp
index a5edcb0b3..4a95b89c9 100644
--- a/Source/WebCore/html/TextFieldInputType.cpp
+++ b/Source/WebCore/html/TextFieldInputType.cpp
@@ -329,6 +329,11 @@ void TextFieldInputType::readonlyAttributeChanged()
m_innerSpinButton->releaseCapture();
}
+bool TextFieldInputType::supportsReadOnly() const
+{
+ return true;
+}
+
bool TextFieldInputType::shouldUseInputMethod() const
{
return true;
@@ -458,7 +463,7 @@ void TextFieldInputType::subtreeHasChanged()
// sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
element()->setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element()->innerTextValue())));
element()->updatePlaceholderVisibility(false);
- // Recalc for :invalid and hasUnacceptableValue() change.
+ // Recalc for :invalid change.
element()->setNeedsStyleRecalc();
didSetValueByUserEdit(wasChanged ? ValueChangeStateChanged : ValueChangeStateNone);
diff --git a/Source/WebCore/html/TextFieldInputType.h b/Source/WebCore/html/TextFieldInputType.h
index b32aeaa68..a79887138 100644
--- a/Source/WebCore/html/TextFieldInputType.h
+++ b/Source/WebCore/html/TextFieldInputType.h
@@ -64,6 +64,7 @@ protected:
virtual void destroyShadowSubtree() OVERRIDE;
virtual void disabledAttributeChanged() OVERRIDE;
virtual void readonlyAttributeChanged() OVERRIDE;
+ virtual bool supportsReadOnly() const OVERRIDE;
virtual void handleBlurEvent() OVERRIDE;
virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE;
virtual void updateInnerTextValue() OVERRIDE;
diff --git a/Source/WebCore/html/ValidityState.cpp b/Source/WebCore/html/ValidityState.cpp
index 649765df9..f04ea76ef 100644
--- a/Source/WebCore/html/ValidityState.cpp
+++ b/Source/WebCore/html/ValidityState.cpp
@@ -76,6 +76,11 @@ bool ValidityState::stepMismatch() const
return m_control->stepMismatch();
}
+bool ValidityState::badInput() const
+{
+ return m_control->hasBadInput();
+}
+
bool ValidityState::customError() const
{
return m_control->customError();
diff --git a/Source/WebCore/html/ValidityState.h b/Source/WebCore/html/ValidityState.h
index 28f9ec640..452739a77 100644
--- a/Source/WebCore/html/ValidityState.h
+++ b/Source/WebCore/html/ValidityState.h
@@ -52,6 +52,7 @@ public:
bool rangeUnderflow() const;
bool rangeOverflow() const;
bool stepMismatch() const;
+ bool badInput() const;
bool customError() const;
bool valid() const;
diff --git a/Source/WebCore/html/ValidityState.idl b/Source/WebCore/html/ValidityState.idl
index dae343b9a..170c45e69 100644
--- a/Source/WebCore/html/ValidityState.idl
+++ b/Source/WebCore/html/ValidityState.idl
@@ -30,6 +30,7 @@
readonly attribute boolean rangeUnderflow;
readonly attribute boolean rangeOverflow;
readonly attribute boolean stepMismatch;
+ readonly attribute boolean badInput;
readonly attribute boolean customError;
readonly attribute boolean valid;
};
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index ef754f597..3eb38a105 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -2070,8 +2070,11 @@ void CanvasRenderingContext2D::setFont(const String& newFont)
if (parsedStyle->isEmpty())
return;
- RefPtr<CSSValue> fontValue = parsedStyle->getPropertyCSSValue(CSSPropertyFont);
- if (fontValue && fontValue->isInheritedValue())
+ String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
+
+ // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947.html,
+ // the "inherit" and "initial" values must be ignored.
+ if (fontValue == "inherit" || fontValue == "initial")
return;
// The parse succeeded.
@@ -2303,10 +2306,10 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
maskImageContext->translate(location.x() - maskRect.x(), location.y() - maskRect.y());
// We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) still work.
maskImageContext->scale(FloatSize((fontWidth > 0 ? (width / fontWidth) : 0), 1));
- maskImageContext->drawBidiText(font, textRun, FloatPoint(0, 0));
+ maskImageContext->drawBidiText(font, textRun, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady);
} else {
maskImageContext->translate(-maskRect.x(), -maskRect.y());
- maskImageContext->drawBidiText(font, textRun, location);
+ maskImageContext->drawBidiText(font, textRun, location, Font::UseFallbackIfFontNotReady);
}
GraphicsContextStateSaver stateSaver(*c);
@@ -2330,9 +2333,9 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
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, textRun, FloatPoint(0, 0));
+ c->drawBidiText(font, textRun, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady);
} else
- c->drawBidiText(font, textRun, location);
+ c->drawBidiText(font, textRun, location, Font::UseFallbackIfFontNotReady);
didDraw(textRect);
diff --git a/Source/WebCore/html/parser/XSSAuditor.cpp b/Source/WebCore/html/parser/XSSAuditor.cpp
index 19b6ca6e3..93becd993 100644
--- a/Source/WebCore/html/parser/XSSAuditor.cpp
+++ b/Source/WebCore/html/parser/XSSAuditor.cpp
@@ -542,13 +542,16 @@ String XSSAuditor::decodedSnippetForAttribute(const HTMLToken& token, const HTML
// 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
+ // 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 once a comma is seen.
+ // 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))) {
+ if (currentChar == '?'
+ || currentChar == '#'
+ || ((currentChar == '/' || currentChar == '\\') && (commaSeen || ++slashCount > 2))
+ || (currentChar == '<' && commaSeen)) {
decodedSnippet.truncate(currentLength);
break;
}
diff --git a/Source/WebCore/html/shadow/ContentDistributor.cpp b/Source/WebCore/html/shadow/ContentDistributor.cpp
index e3216839f..0c095e437 100644
--- a/Source/WebCore/html/shadow/ContentDistributor.cpp
+++ b/Source/WebCore/html/shadow/ContentDistributor.cpp
@@ -58,6 +58,40 @@ size_t ContentDistribution::find(const Node* node) const
return it.get()->value;
}
+ShadowRootContentDistributionData::ShadowRootContentDistributionData()
+ : m_insertionPointAssignedTo(0)
+ , m_numberOfShadowElementChildren(0)
+ , m_numberOfContentElementChildren(0)
+ , m_numberOfElementShadowChildren(0)
+ , m_insertionPointListIsValid(false)
+{
+}
+
+void ShadowRootContentDistributionData::invalidateInsertionPointList()
+{
+ m_insertionPointListIsValid = false;
+ m_insertionPointList.clear();
+}
+
+const Vector<InsertionPoint*>& ShadowRootContentDistributionData::ensureInsertionPointList(ShadowRoot* shadowRoot)
+{
+ if (m_insertionPointListIsValid)
+ return m_insertionPointList;
+
+ m_insertionPointListIsValid = true;
+ ASSERT(m_insertionPointList.isEmpty());
+
+ if (!shadowRoot->hasInsertionPoint())
+ return m_insertionPointList;
+
+ for (Node* node = shadowRoot; node; node = node->traverseNextNode(shadowRoot)) {
+ if (node->isInsertionPoint())
+ m_insertionPointList.append(toInsertionPoint(node));
+ }
+
+ return m_insertionPointList;
+}
+
ContentDistributor::ContentDistributor()
: m_validity(Undetermined)
{
@@ -107,17 +141,18 @@ void ContentDistributor::distribute(Element* host)
for (ShadowRoot* root = host->youngestShadowRoot(); root; root = root->olderShadowRoot()) {
HTMLShadowElement* firstActiveShadowInsertionPoint = 0;
- for (Node* node = root; node; node = node->traverseNextNode(root)) {
- if (!isActiveInsertionPoint(node))
+ const Vector<InsertionPoint*>& insertionPoints = root->insertionPointList();
+ for (size_t i = 0; i < insertionPoints.size(); ++i) {
+ InsertionPoint* point = insertionPoints[i];
+ if (!point->isActive())
continue;
- InsertionPoint* point = toInsertionPoint(node);
- if (isHTMLShadowElement(node)) {
+ if (isHTMLShadowElement(point)) {
if (!firstActiveShadowInsertionPoint)
- firstActiveShadowInsertionPoint = toHTMLShadowElement(node);
+ firstActiveShadowInsertionPoint = toHTMLShadowElement(point);
} else {
distributeSelectionsTo(point, pool, distributed);
- if (ElementShadow* shadow = node->parentNode()->isElementNode() ? toElement(node->parentNode())->shadow() : 0)
+ if (ElementShadow* shadow = point->parentNode()->isElementNode() ? toElement(point->parentNode())->shadow() : 0)
shadow->invalidateDistribution();
}
}
@@ -148,13 +183,10 @@ bool ContentDistributor::invalidate(Element* host)
for (ShadowRoot* root = host->youngestShadowRoot(); root; root = root->olderShadowRoot()) {
root->setAssignedTo(0);
-
- for (Node* node = root; node; node = node->traverseNextNode(root)) {
- if (!node->isInsertionPoint())
- continue;
+ const Vector<InsertionPoint*>& insertionPoints = root->insertionPointList();
+ for (size_t i = 0; i < insertionPoints.size(); ++i) {
needsReattach = needsReattach || true;
- InsertionPoint* point = toInsertionPoint(node);
- point->clearDistribution();
+ insertionPoints[i]->clearDistribution();
}
}
diff --git a/Source/WebCore/html/shadow/ContentDistributor.h b/Source/WebCore/html/shadow/ContentDistributor.h
index 97cffbcc7..cc2fc232e 100644
--- a/Source/WebCore/html/shadow/ContentDistributor.h
+++ b/Source/WebCore/html/shadow/ContentDistributor.h
@@ -68,6 +68,38 @@ private:
HashMap<const Node*, size_t> m_indices;
};
+class ShadowRootContentDistributionData {
+public:
+ ShadowRootContentDistributionData();
+
+ InsertionPoint* insertionPointAssignedTo() const { return m_insertionPointAssignedTo; }
+ void setInsertionPointAssignedTo(InsertionPoint* insertionPoint) { m_insertionPointAssignedTo = insertionPoint; }
+
+ void incrementNumberOfShadowElementChildren() { ++m_numberOfShadowElementChildren; invalidateInsertionPointList(); }
+ void decrementNumberOfShadowElementChildren() { ASSERT(m_numberOfShadowElementChildren > 0); --m_numberOfShadowElementChildren; invalidateInsertionPointList(); }
+ bool hasShadowElementChildren() const { return m_numberOfShadowElementChildren > 0; }
+
+ void incrementNumberOfContentElementChildren() { ++m_numberOfContentElementChildren; invalidateInsertionPointList(); }
+ void decrementNumberOfContentElementChildren() { ASSERT(m_numberOfContentElementChildren > 0); --m_numberOfContentElementChildren; invalidateInsertionPointList(); }
+ bool hasContentElementChildren() const { return m_numberOfContentElementChildren > 0; }
+
+ void incrementNumberOfElementShadowChildren() { ++m_numberOfElementShadowChildren; }
+ void decrementNumberOfElementShadowChildren() { ASSERT(m_numberOfElementShadowChildren > 0); --m_numberOfElementShadowChildren; }
+ unsigned numberOfElementShadowChildren() const { return m_numberOfElementShadowChildren; }
+ bool hasElementShadowChildren() const { return m_numberOfElementShadowChildren > 0; }
+
+ void invalidateInsertionPointList();
+ const Vector<InsertionPoint*>& ensureInsertionPointList(ShadowRoot*);
+
+private:
+ InsertionPoint* m_insertionPointAssignedTo;
+ unsigned m_numberOfShadowElementChildren;
+ unsigned m_numberOfContentElementChildren;
+ unsigned m_numberOfElementShadowChildren;
+ bool m_insertionPointListIsValid;
+ Vector<InsertionPoint*> m_insertionPointList;
+};
+
class ContentDistributor {
WTF_MAKE_NONCOPYABLE(ContentDistributor);
public:
diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp
index 2128bc232..6ae55f3d9 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.cpp
+++ b/Source/WebCore/html/shadow/MediaControlElements.cpp
@@ -36,6 +36,7 @@
#include "CSSValueKeywords.h"
#include "DOMTokenList.h"
#include "EventNames.h"
+#include "EventTarget.h"
#include "FloatConversion.h"
#include "FloatPoint.h"
#include "Frame.h"
@@ -63,6 +64,7 @@
#include "StyleResolver.h"
#include "Text.h"
#if ENABLE(VIDEO_TRACK)
+#include "TextTrack.h"
#include "TextTrackList.h"
#endif
@@ -77,6 +79,11 @@ static const float cSkipTime = 0.2f;
static const float cScanRepeatDelay = 1.5f;
static const float cScanMaximumRate = 8;
+#if ENABLE(VIDEO_TRACK)
+static const char* textTracksOffAttrValue = "-1"; // This must match HTMLMediaElement::textTracksOffIndex()
+static const int textTracksIndexNotFound = -2;
+#endif
+
HTMLMediaElement* toParentMediaElement(Node* node)
{
if (!node)
@@ -99,6 +106,26 @@ MediaControlElementType mediaControlElementType(Node* node)
return static_cast<MediaControlElement*>(element)->displayType();
}
+#if ENABLE(VIDEO_TRACK)
+static const AtomicString& trackIndexAttributeName()
+{
+ DEFINE_STATIC_LOCAL(AtomicString, name, ("x-webkit-track-index", AtomicString::ConstructFromLiteral));
+ return name;
+}
+
+static int trackListIndexForElement(Element* element)
+{
+ const AtomicString trackIndexAttributeValue = element->getAttribute(trackIndexAttributeName());
+ if (trackIndexAttributeValue.isNull() || trackIndexAttributeValue.isEmpty())
+ return textTracksIndexNotFound;
+ bool ok;
+ int trackIndex = trackIndexAttributeValue.toInt(&ok);
+ if (!ok)
+ return textTracksIndexNotFound;
+ return trackIndex;
+}
+#endif
+
// ----------------------------
MediaControlElement::MediaControlElement(Document* document)
@@ -884,8 +911,13 @@ const AtomicString& MediaControlClosedCaptionsContainerElement::shadowPseudoId()
inline MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document* document, MediaControls* controls)
: MediaControlInputElement(document, MediaShowClosedCaptionsButton)
+#if PLATFORM(MAC)
, m_controls(controls)
+#endif
{
+#if !PLATFORM(MAC)
+ UNUSED_PARAM(controls);
+#endif
}
PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(Document* document, MediaControls* controls)
@@ -901,18 +933,25 @@ PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClos
void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
{
- setDisplayType(mediaController()->closedCaptionsVisible() ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
+ bool captionsVisible = mediaController()->closedCaptionsVisible();
+ setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
+ setChecked(captionsVisible);
}
void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
- // FIXME: This is now incorrectly doing two things at once: showing the list of captions and toggling display.
- // https://bugs.webkit.org/show_bug.cgi?id=101670
+ // FIXME: It's not great that the shared code is dictating behavior of platform-specific
+ // UI. Not all ports may want the closed captions button to toggle a list of tracks, so
+ // we have to use #if.
+ // https://bugs.webkit.org/show_bug.cgi?id=101877
+#if !PLATFORM(MAC)
mediaController()->setClosedCaptionsVisible(!mediaController()->closedCaptionsVisible());
setChecked(mediaController()->closedCaptionsVisible());
- m_controls->toggleClosedCaptionTrackList();
updateDisplayType();
+#else
+ m_controls->toggleClosedCaptionTrackList();
+#endif
event->setDefaultHandled();
}
@@ -927,22 +966,52 @@ const AtomicString& MediaControlToggleClosedCaptionsButtonElement::shadowPseudoI
// ----------------------------
-inline MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListElement(Document* document)
+inline MediaControlClosedCaptionsTrackListElement::MediaControlClosedCaptionsTrackListElement(Document* document, MediaControls* controls)
: MediaControlElement(document)
+ , m_controls(controls)
{
}
-PassRefPtr<MediaControlClosedCaptionsTrackListElement> MediaControlClosedCaptionsTrackListElement::create(Document* document)
+PassRefPtr<MediaControlClosedCaptionsTrackListElement> MediaControlClosedCaptionsTrackListElement::create(Document* document, MediaControls* controls)
{
- RefPtr<MediaControlClosedCaptionsTrackListElement> element = adoptRef(new MediaControlClosedCaptionsTrackListElement(document));
+ ASSERT(controls);
+ RefPtr<MediaControlClosedCaptionsTrackListElement> element = adoptRef(new MediaControlClosedCaptionsTrackListElement(document, controls));
return element.release();
}
void MediaControlClosedCaptionsTrackListElement::defaultEventHandler(Event* event)
{
- // FIXME: Hook this up to actual text tracks.
- // https://bugs.webkit.org/show_bug.cgi?id=101670
- UNUSED_PARAM(event);
+#if ENABLE(VIDEO_TRACK)
+ if (event->type() == eventNames().clickEvent) {
+ // FIXME: Add modifier key for exclusivity override.
+ // http://webkit.org/b/103361
+
+ Node* target = event->target()->toNode();
+ if (!target || !target->isElementNode())
+ return;
+
+ // When we created the elements in the track list, we gave them a custom
+ // attribute representing the index in the HTMLMediaElement's list of tracks.
+ // Check if the event target has such a custom element and, if so,
+ // tell the HTMLMediaElement to enable that track.
+
+ int trackIndex = trackListIndexForElement(toElement(target));
+ if (trackIndex == textTracksIndexNotFound)
+ return;
+
+ HTMLMediaElement* mediaElement = toParentMediaElement(this);
+ if (!mediaElement)
+ return;
+
+ mediaElement->toggleTrackAtIndex(trackIndex);
+
+ // We've selected a track to display, so we can now close the menu.
+ m_controls->toggleClosedCaptionTrackList();
+ updateDisplay();
+ }
+
+ MediaControlElement::defaultEventHandler(event);
+#endif
}
const AtomicString& MediaControlClosedCaptionsTrackListElement::shadowPseudoId() const
@@ -954,8 +1023,50 @@ const AtomicString& MediaControlClosedCaptionsTrackListElement::shadowPseudoId()
void MediaControlClosedCaptionsTrackListElement::updateDisplay()
{
#if ENABLE(VIDEO_TRACK)
+ DEFINE_STATIC_LOCAL(AtomicString, selectedClassValue, ("selected", AtomicString::ConstructFromLiteral));
+
+ if (!mediaController()->hasClosedCaptions())
+ return;
+
+ HTMLMediaElement* mediaElement = toParentMediaElement(this);
+ if (!mediaElement)
+ return;
+
+ TextTrackList* trackList = mediaElement->textTracks();
+
+ if (!trackList || !trackList->length())
+ return;
+
+ bool captionsVisible = mediaElement->closedCaptionsVisible();
+ for (unsigned i = 0, length = menuItems.size(); i < length; ++i) {
+ RefPtr<Element> trackItem = menuItems[i];
+ int trackIndex = trackListIndexForElement(trackItem.get());
+ if (trackIndex != textTracksIndexNotFound) {
+ if (trackIndex == HTMLMediaElement::textTracksOffIndex()) {
+ if (captionsVisible)
+ trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
+ else
+ trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
+ } else {
+ TextTrack* track = trackList->item(trackIndex);
+ if (!track)
+ continue;
+ if (track->mode() == TextTrack::showingKeyword())
+ trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
+ else
+ trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
+ }
+ }
+ }
+#endif
+}
+
+void MediaControlClosedCaptionsTrackListElement::resetTrackListMenu()
+{
+#if ENABLE(VIDEO_TRACK)
// Remove any existing content.
removeChildren();
+ menuItems.clear();
if (!mediaController()->hasClosedCaptions())
return;
@@ -987,15 +1098,15 @@ void MediaControlClosedCaptionsTrackListElement::updateDisplay()
trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);
trackItem->appendChild(doc->createTextNode("Off"));
- // FIXME: These lists are not yet live. Mark the Off entry as the selected one for now.
- trackItem->setAttribute(classAttr, "selected");
+ trackItem->setAttribute(trackIndexAttributeName(), textTracksOffAttrValue, ASSERT_NO_EXCEPTION);
captionsList->appendChild(trackItem);
+ menuItems.append(trackItem);
trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);
trackItem->appendChild(doc->createTextNode("Off"));
- // FIXME: These lists are not yet live. Mark the Off entry as the selected one for now.
- trackItem->setAttribute(classAttr, "selected");
+ trackItem->setAttribute(trackIndexAttributeName(), textTracksOffAttrValue, ASSERT_NO_EXCEPTION);
subtitlesList->appendChild(trackItem);
+ menuItems.append(trackItem);
bool hasCaptions = false;
bool hasSubtitles = false;
@@ -1003,6 +1114,13 @@ void MediaControlClosedCaptionsTrackListElement::updateDisplay()
for (unsigned i = 0, length = trackList->length(); i < length; ++i) {
TextTrack* track = trackList->item(i);
trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);
+
+ // Add a custom attribute to the <li> element which will allow
+ // us to easily associate the user tapping here with the
+ // track. Since this list is rebuilt if the tracks change, we
+ // should always be in sync.
+ trackItem->setAttribute(trackIndexAttributeName(), String::number(i), ASSERT_NO_EXCEPTION);
+
AtomicString labelText = track->label();
if (labelText.isNull() || labelText.isEmpty())
labelText = displayNameForLanguageLocale(track->language());
@@ -1018,6 +1136,7 @@ void MediaControlClosedCaptionsTrackListElement::updateDisplay()
subtitlesList->appendChild(trackItem);
}
trackItem->appendChild(doc->createTextNode(labelText));
+ menuItems.append(trackItem);
}
captionsSection->appendChild(captionsList);
@@ -1027,6 +1146,8 @@ void MediaControlClosedCaptionsTrackListElement::updateDisplay()
appendChild(captionsSection);
if (hasSubtitles)
appendChild(subtitlesSection);
+
+ updateDisplay();
#endif
}
diff --git a/Source/WebCore/html/shadow/MediaControlElements.h b/Source/WebCore/html/shadow/MediaControlElements.h
index c3fbc8121..e05032854 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.h
+++ b/Source/WebCore/html/shadow/MediaControlElements.h
@@ -393,7 +393,9 @@ private:
MediaControlToggleClosedCaptionsButtonElement(Document*, MediaControls*);
virtual const AtomicString& shadowPseudoId() const;
+#if PLATFORM(MAC)
MediaControls* m_controls;
+#endif
};
// ----------------------------
@@ -415,18 +417,23 @@ private:
class MediaControlClosedCaptionsTrackListElement : public MediaControlElement {
public:
- static PassRefPtr<MediaControlClosedCaptionsTrackListElement> create(Document*);
+ static PassRefPtr<MediaControlClosedCaptionsTrackListElement> create(Document*, MediaControls*);
virtual void defaultEventHandler(Event*);
virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
void updateDisplay();
+ void resetTrackListMenu();
private:
- MediaControlClosedCaptionsTrackListElement(Document*);
+ MediaControlClosedCaptionsTrackListElement(Document*, MediaControls*);
virtual MediaControlElementType displayType() const { return MediaClosedCaptionsTrackList; }
virtual const AtomicString& shadowPseudoId() const;
+
+ typedef Vector<RefPtr<Element> > TrackMenuItems;
+ TrackMenuItems menuItems;
+ MediaControls* m_controls;
};
// ----------------------------
diff --git a/Source/WebCore/html/shadow/MediaControlsApple.cpp b/Source/WebCore/html/shadow/MediaControlsApple.cpp
index 6cc1c7f7d..93733aeb8 100644
--- a/Source/WebCore/html/shadow/MediaControlsApple.cpp
+++ b/Source/WebCore/html/shadow/MediaControlsApple.cpp
@@ -149,7 +149,7 @@ PassRefPtr<MediaControlsApple> MediaControlsApple::createControls(Document* docu
if (document->page()->theme()->supportsClosedCaptioning()) {
RefPtr<MediaControlClosedCaptionsContainerElement> closedCaptionsContainer = MediaControlClosedCaptionsContainerElement::create(document);
- RefPtr<MediaControlClosedCaptionsTrackListElement> closedCaptionsTrackList = MediaControlClosedCaptionsTrackListElement::create(document);
+ RefPtr<MediaControlClosedCaptionsTrackListElement> closedCaptionsTrackList = MediaControlClosedCaptionsTrackListElement::create(document, controls.get());
controls->m_closedCaptionsTrackList = closedCaptionsTrackList.get();
closedCaptionsContainer->appendChild(closedCaptionsTrackList.release(), ec, true);
if (ec)
@@ -289,6 +289,13 @@ void MediaControlsApple::makeTransparent()
m_closedCaptionsContainer->hide();
}
+void MediaControlsApple::changedClosedCaptionsVisibility()
+{
+ MediaControls::changedClosedCaptionsVisibility();
+ if (m_closedCaptionsTrackList)
+ m_closedCaptionsTrackList->updateDisplay();
+}
+
void MediaControlsApple::reset()
{
Page* page = document()->page();
@@ -323,7 +330,7 @@ void MediaControlsApple::reset()
if (m_mediaController->hasClosedCaptions()) {
m_toggleClosedCaptionsButton->show();
if (m_closedCaptionsTrackList)
- m_closedCaptionsTrackList->updateDisplay();
+ m_closedCaptionsTrackList->resetTrackListMenu();
} else
m_toggleClosedCaptionsButton->hide();
}
diff --git a/Source/WebCore/html/shadow/MediaControlsApple.h b/Source/WebCore/html/shadow/MediaControlsApple.h
index dc47306ec..a1ee8963c 100644
--- a/Source/WebCore/html/shadow/MediaControlsApple.h
+++ b/Source/WebCore/html/shadow/MediaControlsApple.h
@@ -58,6 +58,7 @@ public:
virtual void updateCurrentTimeDisplay() OVERRIDE;
virtual void updateStatusDisplay() OVERRIDE;
+ virtual void changedClosedCaptionsVisibility() OVERRIDE;
void toggleClosedCaptionTrackList();
private:
diff --git a/Source/WebCore/html/shadow/SliderThumbElement.cpp b/Source/WebCore/html/shadow/SliderThumbElement.cpp
index e63954e41..d6c1a3111 100644
--- a/Source/WebCore/html/shadow/SliderThumbElement.cpp
+++ b/Source/WebCore/html/shadow/SliderThumbElement.cpp
@@ -194,10 +194,11 @@ void RenderSliderContainer::layout()
double percentageOffset = sliderPosition(input).toDouble();
LayoutUnit availableExtent = isVertical ? track->contentHeight() : track->contentWidth();
+ availableExtent -= isVertical ? thumb->height() : thumb->width();
LayoutUnit offset = percentageOffset * availableExtent;
LayoutPoint thumbLocation = thumb->location();
if (isVertical)
- thumbLocation.setY(thumbLocation.y() + track->contentHeight() - offset);
+ thumbLocation.setY(thumbLocation.y() + track->contentHeight() - thumb->height() - offset);
else if (style()->isLeftToRightDirection())
thumbLocation.setX(thumbLocation.x() + offset);
else
@@ -271,16 +272,13 @@ void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point)
IntRect trackBoundingBox = trackElement->renderer()->absoluteBoundingBoxRectIgnoringTransforms();
IntRect inputBoundingBox = input->renderer()->absoluteBoundingBoxRectIgnoringTransforms();
if (isVertical) {
- trackSize = trackElement->renderBox()->contentHeight();
+ trackSize = trackElement->renderBox()->contentHeight() - renderBox()->height();
position = offset.y() - renderBox()->height() / 2 - trackBoundingBox.y() + inputBoundingBox.y() - renderBox()->marginBottom();
currentPosition = absoluteThumbOrigin.y() - absoluteSliderContentOrigin.y();
} else {
- trackSize = trackElement->renderBox()->contentWidth();
+ trackSize = trackElement->renderBox()->contentWidth() - renderBox()->width();
position = offset.x() - renderBox()->width() / 2 - trackBoundingBox.x() + inputBoundingBox.x();
- if (isLeftToRightDirection)
- position -= renderBox()->marginLeft();
- else
- position += renderBox()->width() - renderBox()->marginRight();
+ position -= isLeftToRightDirection ? renderBox()->marginLeft() : renderBox()->marginRight();
currentPosition = absoluteThumbOrigin.x() - absoluteSliderContentOrigin.x();
}
position = max<LayoutUnit>(0, min(position, trackSize));
@@ -438,58 +436,6 @@ const AtomicString& SliderThumbElement::shadowPseudoId() const
// --------------------------------
-inline TrackLimiterElement::TrackLimiterElement(Document* document)
- : HTMLDivElement(HTMLNames::divTag, document)
-{
-}
-
-PassRefPtr<TrackLimiterElement> TrackLimiterElement::create(Document* document)
-{
- RefPtr<TrackLimiterElement> element = adoptRef(new TrackLimiterElement(document));
-
- element->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden);
- element->setInlineStyleProperty(CSSPropertyPosition, CSSValueStatic);
-
- return element.release();
-}
-
-RenderObject* TrackLimiterElement::createRenderer(RenderArena* arena, RenderStyle*)
-{
- return new (arena) RenderSliderThumb(this);
-}
-
-const AtomicString& TrackLimiterElement::shadowPseudoId() const
-{
- HTMLInputElement* input = shadowHost()->toInputElement();
- if (!input)
- return sliderThumbShadowPseudoId();
-
- RenderStyle* sliderStyle = input->renderer()->style();
- switch (sliderStyle->appearance()) {
- case MediaSliderPart:
- case MediaSliderThumbPart:
- case MediaVolumeSliderPart:
- case MediaVolumeSliderThumbPart:
- case MediaFullScreenVolumeSliderPart:
- case MediaFullScreenVolumeSliderThumbPart:
- return mediaSliderThumbShadowPseudoId();
- default:
- return sliderThumbShadowPseudoId();
- }
-}
-
-TrackLimiterElement* trackLimiterElementOf(Node* node)
-{
- ASSERT(node);
- ShadowRoot* shadow = node->toInputElement()->userAgentShadowRoot();
- ASSERT(shadow);
- Node* limiter = shadow->firstChild()->lastChild();
- ASSERT(limiter);
- return static_cast<TrackLimiterElement*>(limiter);
-}
-
-// --------------------------------
-
inline SliderContainerElement::SliderContainerElement(Document* document)
: HTMLDivElement(HTMLNames::divTag, document)
{
diff --git a/Source/WebCore/html/shadow/SliderThumbElement.h b/Source/WebCore/html/shadow/SliderThumbElement.h
index f55ecef3d..869ad4b5d 100644
--- a/Source/WebCore/html/shadow/SliderThumbElement.h
+++ b/Source/WebCore/html/shadow/SliderThumbElement.h
@@ -115,22 +115,6 @@ private:
// --------------------------------
-class TrackLimiterElement : public HTMLDivElement {
-public:
- static PassRefPtr<TrackLimiterElement> create(Document*);
-
-private:
- TrackLimiterElement(Document*);
- virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// This always return a valid pointer.
-// An assertion fails if the specified node is not a range input.
-TrackLimiterElement* trackLimiterElementOf(Node*);
-
-// --------------------------------
-
class SliderContainerElement : public HTMLDivElement {
public:
static PassRefPtr<SliderContainerElement> create(Document*);
diff --git a/Source/WebCore/html/track/TextTrack.cpp b/Source/WebCore/html/track/TextTrack.cpp
index 95ab19080..6a6e90be6 100644
--- a/Source/WebCore/html/track/TextTrack.cpp
+++ b/Source/WebCore/html/track/TextTrack.cpp
@@ -259,20 +259,18 @@ void TextTrack::removeCue(TextTrackCue* cue, ExceptionCode& ec)
if (!cue)
return;
- // 4.8.10.12.4 Text track API
+ // 4.8.10.12.5 Text track API
// The removeCue(cue) method of TextTrack objects, when invoked, must run the following steps:
- // 1. If the given cue is not associated with the method's TextTrack
- // object's text track, then throw an InvalidStateError exception.
+ // 1. If the given cue is not currently listed in the method's TextTrack
+ // object's text track's text track list of cues, then throw a NotFoundError exception.
if (cue->track() != this) {
- ec = INVALID_STATE_ERR;
+ ec = NOT_FOUND_ERR;
return;
}
-
- // 2. If the given cue is not currently listed in the method's TextTrack
- // object's text track's text track list of cues, then throw a NotFoundError exception.
- // 3. Remove cue from the method's TextTrack object's text track's text track list of cues.
+
+ // 2. Remove cue from the method's TextTrack object's text track's text track list of cues.
if (!m_cues || !m_cues->remove(cue)) {
ec = INVALID_STATE_ERR;
return;