summaryrefslogtreecommitdiff
path: root/Source/WebCore/html
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html')
-rw-r--r--Source/WebCore/html/ClassList.cpp4
-rw-r--r--Source/WebCore/html/ColorInputType.cpp2
-rw-r--r--Source/WebCore/html/DOMTokenList.cpp3
-rw-r--r--Source/WebCore/html/DOMURL.cpp32
-rw-r--r--Source/WebCore/html/DOMURL.h4
-rw-r--r--Source/WebCore/html/DOMURL.idl3
-rw-r--r--Source/WebCore/html/FTPDirectoryDocument.cpp28
-rw-r--r--Source/WebCore/html/HTMLAnchorElement.cpp14
-rw-r--r--Source/WebCore/html/HTMLAnchorElement.h4
-rw-r--r--Source/WebCore/html/HTMLAppletElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLAppletElement.h2
-rw-r--r--Source/WebCore/html/HTMLButtonElement.cpp7
-rw-r--r--Source/WebCore/html/HTMLButtonElement.h3
-rw-r--r--Source/WebCore/html/HTMLElement.cpp14
-rw-r--r--Source/WebCore/html/HTMLElement.idl2
-rw-r--r--Source/WebCore/html/HTMLEmbedElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLEmbedElement.h2
-rw-r--r--Source/WebCore/html/HTMLFormControlElement.cpp10
-rw-r--r--Source/WebCore/html/HTMLFormControlElement.h3
-rw-r--r--Source/WebCore/html/HTMLInputElement.cpp34
-rw-r--r--Source/WebCore/html/HTMLInputElement.h12
-rw-r--r--Source/WebCore/html/HTMLLabelElement.cpp8
-rw-r--r--Source/WebCore/html/HTMLLabelElement.h2
-rw-r--r--Source/WebCore/html/HTMLMediaElement.cpp267
-rw-r--r--Source/WebCore/html/HTMLMediaElement.h21
-rw-r--r--Source/WebCore/html/HTMLMediaElement.idl29
-rw-r--r--Source/WebCore/html/HTMLObjectElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLObjectElement.h2
-rw-r--r--Source/WebCore/html/HTMLOptionElement.cpp9
-rw-r--r--Source/WebCore/html/HTMLPlugInElement.cpp22
-rw-r--r--Source/WebCore/html/HTMLPlugInElement.h7
-rw-r--r--Source/WebCore/html/HTMLProgressElement.cpp36
-rw-r--r--Source/WebCore/html/HTMLProgressElement.h19
-rw-r--r--Source/WebCore/html/HTMLPropertiesCollection.cpp15
-rw-r--r--Source/WebCore/html/HTMLSelectElement.cpp22
-rw-r--r--Source/WebCore/html/HTMLSummaryElement.cpp8
-rw-r--r--Source/WebCore/html/HTMLSummaryElement.h1
-rw-r--r--Source/WebCore/html/HTMLTableCellElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLTableCellElement.h2
-rw-r--r--Source/WebCore/html/HTMLTableColElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLTableColElement.h2
-rw-r--r--Source/WebCore/html/HTMLTableElement.cpp6
-rw-r--r--Source/WebCore/html/HTMLTableElement.h6
-rw-r--r--Source/WebCore/html/HTMLTableSectionElement.cpp2
-rw-r--r--Source/WebCore/html/HTMLTableSectionElement.h2
-rw-r--r--Source/WebCore/html/HTMLTextAreaElement.h5
-rw-r--r--Source/WebCore/html/HTMLTrackElement.idl2
-rw-r--r--Source/WebCore/html/HTMLVideoElement.cpp8
-rw-r--r--Source/WebCore/html/HTMLVideoElement.h1
-rw-r--r--Source/WebCore/html/InputType.cpp6
-rw-r--r--Source/WebCore/html/InputType.h1
-rw-r--r--Source/WebCore/html/MediaController.cpp37
-rw-r--r--Source/WebCore/html/MediaController.h5
-rw-r--r--Source/WebCore/html/NumberInputType.cpp8
-rw-r--r--Source/WebCore/html/PublicURLManager.h16
-rw-r--r--Source/WebCore/html/RangeInputType.cpp76
-rw-r--r--Source/WebCore/html/RangeInputType.h7
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp4
-rw-r--r--Source/WebCore/html/canvas/Float32Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Float64Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Int16Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Int32Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Int8Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Uint16Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Uint32Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Uint8Array.idl7
-rw-r--r--Source/WebCore/html/canvas/Uint8ClampedArray.idl7
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.cpp46
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.h1
-rw-r--r--Source/WebCore/html/parser/HTMLConstructionSite.cpp22
-rw-r--r--Source/WebCore/html/parser/HTMLConstructionSite.h9
-rw-r--r--Source/WebCore/html/parser/HTMLElementStack.cpp37
-rw-r--r--Source/WebCore/html/parser/HTMLElementStack.h3
-rw-r--r--Source/WebCore/html/parser/HTMLEntityParser.cpp6
-rw-r--r--Source/WebCore/html/parser/HTMLFormattingElementList.cpp2
-rw-r--r--Source/WebCore/html/parser/HTMLInputStream.h2
-rw-r--r--Source/WebCore/html/parser/HTMLParserIdioms.cpp107
-rw-r--r--Source/WebCore/html/parser/HTMLParserIdioms.h2
-rw-r--r--Source/WebCore/html/parser/HTMLSourceTracker.cpp4
-rw-r--r--Source/WebCore/html/parser/HTMLStackItem.h9
-rw-r--r--Source/WebCore/html/parser/HTMLTreeBuilder.cpp22
-rw-r--r--Source/WebCore/html/shadow/CalendarPickerElement.cpp11
-rw-r--r--Source/WebCore/html/shadow/CalendarPickerElement.h1
-rw-r--r--Source/WebCore/html/shadow/ContentDistributor.cpp1
-rw-r--r--Source/WebCore/html/shadow/ContentDistributor.h2
-rw-r--r--Source/WebCore/html/shadow/DateTimeEditElement.cpp472
-rw-r--r--Source/WebCore/html/shadow/DateTimeEditElement.h117
-rw-r--r--Source/WebCore/html/shadow/DateTimeFieldElement.cpp136
-rw-r--r--Source/WebCore/html/shadow/DateTimeFieldElement.h88
-rw-r--r--Source/WebCore/html/shadow/DateTimeFieldElements.cpp173
-rw-r--r--Source/WebCore/html/shadow/DateTimeFieldElements.h119
-rw-r--r--Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp178
-rw-r--r--Source/WebCore/html/shadow/DateTimeNumericFieldElement.h81
-rw-r--r--Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.cpp108
-rw-r--r--Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.h63
-rw-r--r--Source/WebCore/html/shadow/InsertionPoint.cpp6
-rw-r--r--Source/WebCore/html/shadow/MediaControlElements.cpp27
-rw-r--r--Source/WebCore/html/shadow/MediaControlElements.h25
-rw-r--r--Source/WebCore/html/shadow/MediaControlRootElement.h2
-rw-r--r--Source/WebCore/html/shadow/ProgressShadowElement.cpp38
-rw-r--r--Source/WebCore/html/shadow/ProgressShadowElement.h12
-rw-r--r--Source/WebCore/html/shadow/SliderThumbElement.cpp47
-rw-r--r--Source/WebCore/html/shadow/SliderThumbElement.h5
-rw-r--r--Source/WebCore/html/shadow/TextControlInnerElements.cpp61
-rw-r--r--Source/WebCore/html/shadow/TextControlInnerElements.h9
-rw-r--r--Source/WebCore/html/shadow/TextFieldDecorationElement.cpp9
-rw-r--r--Source/WebCore/html/shadow/TextFieldDecorationElement.h2
-rw-r--r--Source/WebCore/html/track/TextTrack.cpp4
-rw-r--r--Source/WebCore/html/track/TextTrackCue.cpp6
-rw-r--r--Source/WebCore/html/track/TextTrackCueList.cpp3
110 files changed, 2414 insertions, 584 deletions
diff --git a/Source/WebCore/html/ClassList.cpp b/Source/WebCore/html/ClassList.cpp
index 2ea838202..a325a1226 100644
--- a/Source/WebCore/html/ClassList.cpp
+++ b/Source/WebCore/html/ClassList.cpp
@@ -131,14 +131,14 @@ String ClassList::toString() const
void ClassList::reset(const String& newClassName)
{
- if (!m_classNamesForQuirksMode.isNull())
+ if (m_element->document()->inQuirksMode())
m_classNamesForQuirksMode.set(newClassName, false);
}
const SpaceSplitString& ClassList::classNames() const
{
ASSERT(m_element->hasClass());
- if (!m_classNamesForQuirksMode.isNull())
+ if (m_element->document()->inQuirksMode())
return m_classNamesForQuirksMode;
return m_element->attributeData()->classNames();
}
diff --git a/Source/WebCore/html/ColorInputType.cpp b/Source/WebCore/html/ColorInputType.cpp
index 3e75c6e65..c4eb524e5 100644
--- a/Source/WebCore/html/ColorInputType.cpp
+++ b/Source/WebCore/html/ColorInputType.cpp
@@ -168,7 +168,7 @@ bool ColorInputType::shouldRespectListAttribute()
bool ColorInputType::typeMismatchFor(const String& value) const
{
- return isValidColorString(value);
+ return !isValidColorString(value);
}
void ColorInputType::didChooseColor(const Color& color)
diff --git a/Source/WebCore/html/DOMTokenList.cpp b/Source/WebCore/html/DOMTokenList.cpp
index 5c41f74b5..7132b1169 100644
--- a/Source/WebCore/html/DOMTokenList.cpp
+++ b/Source/WebCore/html/DOMTokenList.cpp
@@ -56,8 +56,9 @@ String DOMTokenList::addToken(const AtomicString& input, const AtomicString& tok
StringBuilder builder;
builder.append(input);
- if (input[input.length()-1] != ' ')
+ if (!isHTMLSpace(input[input.length() - 1]))
builder.append(' ');
+
builder.append(token);
return builder.toString();
}
diff --git a/Source/WebCore/html/DOMURL.cpp b/Source/WebCore/html/DOMURL.cpp
index 4f9780dcd..f6586264f 100644
--- a/Source/WebCore/html/DOMURL.cpp
+++ b/Source/WebCore/html/DOMURL.cpp
@@ -42,6 +42,11 @@
#include <wtf/PassOwnPtr.h>
#include <wtf/MainThread.h>
+#if ENABLE(MEDIA_SOURCE)
+#include "MediaSource.h"
+#include "MediaSourceRegistry.h"
+#endif
+
#if ENABLE(MEDIA_STREAM)
#include "MediaStream.h"
#include "MediaStreamRegistry.h"
@@ -49,6 +54,26 @@
namespace WebCore {
+#if ENABLE(MEDIA_SOURCE)
+String DOMURL::createObjectURL(ScriptExecutionContext* scriptExecutionContext, MediaSource* source)
+{
+ // Since WebWorkers cannot obtain MediaSource objects, we should be on the main thread.
+ ASSERT(isMainThread());
+
+ if (!scriptExecutionContext || !source)
+ return String();
+
+ KURL publicURL = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin());
+ if (publicURL.isEmpty())
+ return String();
+
+ MediaSourceRegistry::registry().registerMediaSourceURL(publicURL, source);
+ scriptExecutionContext->publicURLManager().sourceURLs().add(publicURL.string());
+
+ return publicURL.string();
+}
+#endif
+
#if ENABLE(MEDIA_STREAM)
String DOMURL::createObjectURL(ScriptExecutionContext* scriptExecutionContext, MediaStream* stream)
{
@@ -98,6 +123,13 @@ void DOMURL::revokeObjectURL(ScriptExecutionContext* scriptExecutionContext, con
blobURLs.remove(url.string());
}
+#if ENABLE(MEDIA_SOURCE)
+ HashSet<String>& sourceURLs = scriptExecutionContext->publicURLManager().sourceURLs();
+ if (sourceURLs.contains(url.string())) {
+ MediaSourceRegistry::registry().unregisterMediaSourceURL(url);
+ sourceURLs.remove(url.string());
+ }
+#endif
#if ENABLE(MEDIA_STREAM)
HashSet<String>& streamURLs = scriptExecutionContext->publicURLManager().streamURLs();
if (streamURLs.contains(url.string())) {
diff --git a/Source/WebCore/html/DOMURL.h b/Source/WebCore/html/DOMURL.h
index 25ae013eb..d71fb93f3 100644
--- a/Source/WebCore/html/DOMURL.h
+++ b/Source/WebCore/html/DOMURL.h
@@ -36,6 +36,7 @@
namespace WebCore {
class Blob;
+class MediaSource;
class MediaStream;
class ScriptExecutionContext;
@@ -49,6 +50,9 @@ public:
static String createObjectURL(ScriptExecutionContext*, Blob*);
static void revokeObjectURL(ScriptExecutionContext*, const String&);
+#if ENABLE(MEDIA_SOURCE)
+ static String createObjectURL(ScriptExecutionContext*, MediaSource*);
+#endif
#if ENABLE(MEDIA_STREAM)
static String createObjectURL(ScriptExecutionContext*, MediaStream*);
#endif
diff --git a/Source/WebCore/html/DOMURL.idl b/Source/WebCore/html/DOMURL.idl
index ed04c23d5..b36e8f7ce 100644
--- a/Source/WebCore/html/DOMURL.idl
+++ b/Source/WebCore/html/DOMURL.idl
@@ -33,6 +33,9 @@ module html {
JSNoStaticTables,
InterfaceName=URL
] DOMURL {
+#if defined(ENABLE_MEDIA_SOURCE) && ENABLE_MEDIA_SOURCE
+ [CallWith=ScriptExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(in MediaSource? source);
+#endif
#if defined(ENABLE_MEDIA_STREAM) && ENABLE_MEDIA_STREAM
[CallWith=ScriptExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(in MediaStream? stream);
#endif
diff --git a/Source/WebCore/html/FTPDirectoryDocument.cpp b/Source/WebCore/html/FTPDirectoryDocument.cpp
index 18689c97f..8fefc201e 100644
--- a/Source/WebCore/html/FTPDirectoryDocument.cpp
+++ b/Source/WebCore/html/FTPDirectoryDocument.cpp
@@ -36,10 +36,11 @@
#include "Settings.h"
#include "SharedBuffer.h"
#include "Text.h"
-#include <wtf/text/CString.h>
-#include <wtf/text/WTFString.h>
#include <wtf/CurrentTime.h>
+#include <wtf/GregorianDateTime.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
#include <wtf/unicode/CharacterNames.h>
using namespace std;
@@ -219,26 +220,23 @@ static String processFileDateString(const FTPTime& fileTime)
}
// If it was today or yesterday, lets just do that - but we have to compare to the current time
- struct tm now;
- getCurrentLocalTime(&now);
-
- // localtime does "year = current year - 1900", compensate for that for readability and comparison purposes
- now.tm_year += 1900;
+ GregorianDateTime now;
+ now.setToCurrentLocalTime();
- if (fileTime.tm_year == now.tm_year) {
- if (fileTime.tm_mon == now.tm_mon) {
- if (fileTime.tm_mday == now.tm_mday)
+ if (fileTime.tm_year == now.year()) {
+ if (fileTime.tm_mon == now.month()) {
+ if (fileTime.tm_mday == now.monthDay())
return "Today" + timeOfDay;
- if (fileTime.tm_mday == now.tm_mday - 1)
+ if (fileTime.tm_mday == now.monthDay() - 1)
return "Yesterday" + timeOfDay;
}
- if (now.tm_mday == 1 && (now.tm_mon == fileTime.tm_mon + 1 || (now.tm_mon == 0 && fileTime.tm_mon == 11)) &&
+ if (now.monthDay() == 1 && (now.month() == fileTime.tm_mon + 1 || (now.month() == 0 && fileTime.tm_mon == 11)) &&
wasLastDayOfMonth(fileTime.tm_year, fileTime.tm_mon, fileTime.tm_mday))
return "Yesterday" + timeOfDay;
}
- if (fileTime.tm_year == now.tm_year - 1 && fileTime.tm_mon == 12 && fileTime.tm_mday == 31 && now.tm_mon == 1 && now.tm_mday == 1)
+ if (fileTime.tm_year == now.year() - 1 && fileTime.tm_mon == 12 && fileTime.tm_mday == 31 && now.month() == 1 && now.monthDay() == 1)
return "Yesterday" + timeOfDay;
static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
@@ -252,7 +250,7 @@ static String processFileDateString(const FTPTime& fileTime)
if (fileTime.tm_year > -1)
dateString = String(months[month]) + " " + String::number(fileTime.tm_mday) + ", " + String::number(fileTime.tm_year);
else
- dateString = String(months[month]) + " " + String::number(fileTime.tm_mday) + ", " + String::number(now.tm_year);
+ dateString = String(months[month]) + " " + String::number(fileTime.tm_mday) + ", " + String::number(now.year());
return dateString + timeOfDay;
}
@@ -368,7 +366,7 @@ void FTPDirectoryDocumentParser::append(const SegmentedString& source)
m_dest = m_buffer;
SegmentedString str = source;
while (!str.isEmpty()) {
- UChar c = *str;
+ UChar c = str.currentChar();
if (c == '\r') {
*m_dest++ = '\n';
diff --git a/Source/WebCore/html/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp
index d31188f12..9f50c7feb 100644
--- a/Source/WebCore/html/HTMLAnchorElement.cpp
+++ b/Source/WebCore/html/HTMLAnchorElement.cpp
@@ -569,24 +569,14 @@ bool isEnterKeyKeydownEvent(Event* event)
return event->type() == eventNames().keydownEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter";
}
-bool isMiddleMouseButtonEvent(Event* event)
-{
- return event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == MiddleButton;
-}
-
bool isLinkClick(Event* event)
{
return event->type() == eventNames().clickEvent && (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button() != RightButton);
}
-void handleLinkClick(Event* event, Document* document, const String& url, const String& target, bool hideReferrer)
+bool HTMLAnchorElement::willRespondToMouseClickEvents()
{
- event->setDefaultHandled();
-
- Frame* frame = document->frame();
- if (!frame)
- return;
- frame->loader()->urlSelected(document->completeURL(url), target, event, false, false, hideReferrer ? NeverSendReferrer : MaybeSendReferrer);
+ return isLink() || HTMLElement::willRespondToMouseClickEvents();
}
#if ENABLE(MICRODATA)
diff --git a/Source/WebCore/html/HTMLAnchorElement.h b/Source/WebCore/html/HTMLAnchorElement.h
index 9a875c25b..6afe5a5c5 100644
--- a/Source/WebCore/html/HTMLAnchorElement.h
+++ b/Source/WebCore/html/HTMLAnchorElement.h
@@ -94,6 +94,8 @@ public:
bool isLiveLink() const;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
bool hasRel(uint32_t relation) const;
void setRel(const String&);
@@ -155,9 +157,7 @@ inline LinkHash HTMLAnchorElement::visitedLinkHash() const
// Functions shared with the other anchor elements (i.e., SVG).
bool isEnterKeyKeydownEvent(Event*);
-bool isMiddleMouseButtonEvent(Event*);
bool isLinkClick(Event*);
-void handleLinkClick(Event*, Document*, const String& url, const String& target, bool hideReferrer = false);
} // namespace WebCore
diff --git a/Source/WebCore/html/HTMLAppletElement.cpp b/Source/WebCore/html/HTMLAppletElement.cpp
index 5bd5fd5aa..afc7268dd 100644
--- a/Source/WebCore/html/HTMLAppletElement.cpp
+++ b/Source/WebCore/html/HTMLAppletElement.cpp
@@ -81,7 +81,7 @@ RenderObject* HTMLAppletElement::createRenderer(RenderArena*, RenderStyle* style
return new (document()->renderArena()) RenderApplet(this);
}
-RenderWidget* HTMLAppletElement::renderWidgetForJSBindings()
+RenderWidget* HTMLAppletElement::renderWidgetForJSBindings() const
{
if (!canEmbedJava())
return 0;
diff --git a/Source/WebCore/html/HTMLAppletElement.h b/Source/WebCore/html/HTMLAppletElement.h
index ee4e30cf0..4c7275c72 100644
--- a/Source/WebCore/html/HTMLAppletElement.h
+++ b/Source/WebCore/html/HTMLAppletElement.h
@@ -39,7 +39,7 @@ private:
virtual bool rendererIsNeeded(const NodeRenderingContext&) OVERRIDE;
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
- virtual RenderWidget* renderWidgetForJSBindings();
+ virtual RenderWidget* renderWidgetForJSBindings() const;
virtual void updateWidget(PluginCreationOption) OVERRIDE;
bool canEmbedJava() const;
diff --git a/Source/WebCore/html/HTMLButtonElement.cpp b/Source/WebCore/html/HTMLButtonElement.cpp
index d82a1a737..ecb4a21ba 100644
--- a/Source/WebCore/html/HTMLButtonElement.cpp
+++ b/Source/WebCore/html/HTMLButtonElement.cpp
@@ -153,6 +153,13 @@ void HTMLButtonElement::defaultEventHandler(Event* event)
HTMLFormControlElement::defaultEventHandler(event);
}
+bool HTMLButtonElement::willRespondToMouseClickEvents()
+{
+ if (!disabled() && form() && (m_type == SUBMIT || m_type == RESET))
+ return true;
+ return HTMLFormControlElement::willRespondToMouseClickEvents();
+}
+
bool HTMLButtonElement::isSuccessfulSubmitButton() const
{
// HTML spec says that buttons must have names to be considered successful.
diff --git a/Source/WebCore/html/HTMLButtonElement.h b/Source/WebCore/html/HTMLButtonElement.h
index 7bf99b7b8..92ca0a3f6 100644
--- a/Source/WebCore/html/HTMLButtonElement.h
+++ b/Source/WebCore/html/HTMLButtonElement.h
@@ -36,6 +36,8 @@ public:
String value() const;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
private:
HTMLButtonElement(const QualifiedName& tagName, Document*, HTMLFormElement*);
@@ -48,6 +50,7 @@ private:
virtual void parseAttribute(const Attribute&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void defaultEventHandler(Event*);
+
virtual bool appendFormData(FormDataList&, bool);
virtual bool isEnumeratable() const { return true; }
diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp
index d873d9b7f..b707ef234 100644
--- a/Source/WebCore/html/HTMLElement.cpp
+++ b/Source/WebCore/html/HTMLElement.cpp
@@ -1010,16 +1010,24 @@ void HTMLElement::getItemRefElements(Vector<HTMLElement*>& itemRefElements)
if (!fastHasAttribute(itemscopeAttr))
return;
- if (!fastHasAttribute(itemrefAttr)) {
+ if (!fastHasAttribute(itemrefAttr) || !itemRef()->length()) {
itemRefElements.append(this);
return;
}
DOMSettableTokenList* itemRefs = itemRef();
RefPtr<DOMSettableTokenList> processedItemRef = DOMSettableTokenList::create();
- Node* rootNode = treeScope()->rootNode();
- for (Node* current = rootNode->firstChild(); current; current = current->traverseNextNode(rootNode)) {
+ Node* rootNode;
+ if (inDocument())
+ rootNode = document();
+ else {
+ rootNode = this;
+ while (Node* parent = rootNode->parentNode())
+ rootNode = parent;
+ }
+
+ for (Node* current = rootNode; current; current = current->traverseNextNode(rootNode)) {
if (!current->isHTMLElement())
continue;
HTMLElement* element = toHTMLElement(current);
diff --git a/Source/WebCore/html/HTMLElement.idl b/Source/WebCore/html/HTMLElement.idl
index 4f5f236f6..9501d3a6a 100644
--- a/Source/WebCore/html/HTMLElement.idl
+++ b/Source/WebCore/html/HTMLElement.idl
@@ -32,8 +32,6 @@ module html {
attribute [Reflect] DOMString lang;
attribute boolean translate;
attribute [Reflect] DOMString dir;
- attribute [Reflect=class] DOMString className;
- readonly attribute DOMTokenList classList;
attribute long tabIndex;
attribute boolean draggable;
diff --git a/Source/WebCore/html/HTMLEmbedElement.cpp b/Source/WebCore/html/HTMLEmbedElement.cpp
index 15e32eef7..3bc2d933d 100644
--- a/Source/WebCore/html/HTMLEmbedElement.cpp
+++ b/Source/WebCore/html/HTMLEmbedElement.cpp
@@ -68,7 +68,7 @@ static inline RenderWidget* findWidgetRenderer(const Node* n)
return 0;
}
-RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings()
+RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() const
{
document()->updateLayoutIgnorePendingStylesheets();
return findWidgetRenderer(this);
diff --git a/Source/WebCore/html/HTMLEmbedElement.h b/Source/WebCore/html/HTMLEmbedElement.h
index ba828a172..bda2e9149 100644
--- a/Source/WebCore/html/HTMLEmbedElement.h
+++ b/Source/WebCore/html/HTMLEmbedElement.h
@@ -43,7 +43,7 @@ private:
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
virtual const QualifiedName& imageSourceAttributeName() const;
- virtual RenderWidget* renderWidgetForJSBindings();
+ virtual RenderWidget* renderWidgetForJSBindings() const;
virtual void updateWidget(PluginCreationOption);
diff --git a/Source/WebCore/html/HTMLFormControlElement.cpp b/Source/WebCore/html/HTMLFormControlElement.cpp
index d52d0ba85..2d47ac8c4 100644
--- a/Source/WebCore/html/HTMLFormControlElement.cpp
+++ b/Source/WebCore/html/HTMLFormControlElement.cpp
@@ -482,6 +482,16 @@ 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 b132cbe0b..d129bc2c2 100644
--- a/Source/WebCore/html/HTMLFormControlElement.h
+++ b/Source/WebCore/html/HTMLFormControlElement.h
@@ -81,7 +81,8 @@ public:
virtual const AtomicString& formControlType() const OVERRIDE = 0;
virtual bool isEnabledFormControl() const { return !disabled(); }
- virtual bool isReadOnlyFormControl() const { return readOnly(); }
+ virtual bool shouldMatchReadOnlySelector() const OVERRIDE;
+ virtual bool shouldMatchReadWriteSelector() const OVERRIDE;
virtual bool canTriggerImplicitSubmission() const { return false; }
diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp
index 59c6205a8..e07067c66 100644
--- a/Source/WebCore/html/HTMLInputElement.cpp
+++ b/Source/WebCore/html/HTMLInputElement.cpp
@@ -313,6 +313,13 @@ StepRange HTMLInputElement::createStepRange(AnyStepHandling anyStepHandling) con
return m_inputType->createStepRange(anyStepHandling);
}
+#if ENABLE(DATALIST_ELEMENT)
+Decimal HTMLInputElement::findClosestTickMarkValue(const Decimal& value)
+{
+ return m_inputType->findClosestTickMarkValue(value);
+}
+#endif
+
void HTMLInputElement::stepUp(int n, ExceptionCode& ec)
{
m_inputType->stepUp(n, ec);
@@ -619,6 +626,12 @@ void HTMLInputElement::parseAttribute(const Attribute& attribute)
} else if (attribute.name() == typeAttr) {
updateType();
} else if (attribute.name() == valueAttr) {
+ // Changes to the value attribute may change whether or not this element has a default value.
+ // If this field is autocomplete=off that might affect the return value of needsSuspensionCallback.
+ if (m_autocomplete == Off) {
+ unregisterForSuspensionCallbackIfNeeded();
+ registerForSuspensionCallbackIfNeeded();
+ }
// We only need to setChanged if the form is looking at the default value right now.
if (!hasDirtyValue()) {
updatePlaceholderVisibility(false);
@@ -1160,6 +1173,15 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
HTMLTextFormControlElement::defaultEventHandler(evt);
}
+bool HTMLInputElement::willRespondToMouseClickEvents()
+{
+ // FIXME: Consider implementing willRespondToMouseClickEvents() in InputType if more accurate results are necessary.
+ if (!disabled())
+ return true;
+
+ return HTMLTextFormControlElement::willRespondToMouseClickEvents();
+}
+
bool HTMLInputElement::isURLAttribute(const Attribute& attribute) const
{
return attribute.name() == srcAttr || attribute.name() == formactionAttr || HTMLTextFormControlElement::isURLAttribute(attribute);
@@ -1363,7 +1385,17 @@ bool HTMLInputElement::isOutOfRange() const
bool HTMLInputElement::needsSuspensionCallback()
{
- return m_autocomplete == Off || m_inputType->shouldResetOnDocumentActivation();
+ if (m_inputType->shouldResetOnDocumentActivation())
+ return true;
+
+ // Sensitive input elements are marked with autocomplete=off, and we want to wipe them out
+ // when going back; returning true here arranges for us to call reset at the time
+ // the page is restored. Non-empty textual default values indicate that the field
+ // is not really sensitive -- there's no default value for an account number --
+ // and we would see unexpected results if we reset to something other than blank.
+ bool isSensitive = m_autocomplete == Off && !(m_inputType->isTextType() && !defaultValue().isEmpty());
+
+ return isSensitive;
}
void HTMLInputElement::registerForSuspensionCallbackIfNeeded()
diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h
index fa4aa9153..dc32159f2 100644
--- a/Source/WebCore/html/HTMLInputElement.h
+++ b/Source/WebCore/html/HTMLInputElement.h
@@ -72,6 +72,10 @@ public:
bool getAllowedValueStep(Decimal*) const;
StepRange createStepRange(AnyStepHandling) const;
+#if ENABLE(DATALIST_ELEMENT)
+ Decimal findClosestTickMarkValue(const Decimal&);
+#endif
+
// Implementations of HTMLInputElement::stepUp() and stepDown().
void stepUp(int, ExceptionCode&);
void stepDown(int, ExceptionCode&);
@@ -232,6 +236,8 @@ public:
void addSearchResult();
void onSearch();
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
#if ENABLE(DATALIST_ELEMENT)
HTMLElement* list() const;
HTMLDataListElement* dataList() const;
@@ -400,5 +406,11 @@ private:
#endif
};
+inline bool isHTMLInputElement(Node* node)
+{
+ ASSERT(node);
+ return node->hasTagName(HTMLNames::inputTag);
+}
+
} //namespace
#endif
diff --git a/Source/WebCore/html/HTMLLabelElement.cpp b/Source/WebCore/html/HTMLLabelElement.cpp
index c1021b358..242fb0cbd 100644
--- a/Source/WebCore/html/HTMLLabelElement.cpp
+++ b/Source/WebCore/html/HTMLLabelElement.cpp
@@ -147,6 +147,14 @@ void HTMLLabelElement::defaultEventHandler(Event* evt)
HTMLElement::defaultEventHandler(evt);
}
+bool HTMLLabelElement::willRespondToMouseClickEvents()
+{
+ if (control() && control()->willRespondToMouseClickEvents())
+ return true;
+
+ return HTMLElement::willRespondToMouseClickEvents();
+}
+
void HTMLLabelElement::focus(bool)
{
// to match other browsers, always restore previous selection
diff --git a/Source/WebCore/html/HTMLLabelElement.h b/Source/WebCore/html/HTMLLabelElement.h
index a821b2507..f48c6805e 100644
--- a/Source/WebCore/html/HTMLLabelElement.h
+++ b/Source/WebCore/html/HTMLLabelElement.h
@@ -36,6 +36,8 @@ public:
LabelableElement* control();
HTMLFormElement* form() const;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
private:
HTMLLabelElement(const QualifiedName&, Document*);
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index cc025c12b..fadcfe7c6 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -111,6 +111,11 @@
#include "DisplaySleepDisabler.h"
#endif
+#if ENABLE(MEDIA_SOURCE)
+#include "MediaSource.h"
+#include "MediaSourceRegistry.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -145,7 +150,7 @@ static const char* boolString(bool val)
#if ENABLE(MEDIA_SOURCE)
// URL protocol used to signal that the media source API is being used.
-static const char* mediaSourceURLProtocol = "x-media-source";
+static const char* mediaSourceBlobProtocol = "blob";
#endif
using namespace HTMLNames;
@@ -219,9 +224,6 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
, m_preload(MediaPlayer::Auto)
, m_displayMode(Unknown)
, m_processingMediaPlayerCallback(0)
-#if ENABLE(MEDIA_SOURCE)
- , m_sourceState(SOURCE_CLOSED)
-#endif
, m_cachedTime(MediaPlayer::invalidTime())
, m_cachedTimeWallClockUpdateTime(0)
, m_minimumWallClockTimeToCacheMediaTime(0)
@@ -272,7 +274,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
}
#if ENABLE(MEDIA_SOURCE)
- m_mediaSourceURL.setProtocol(mediaSourceURLProtocol);
+ m_mediaSourceURL.setProtocol(mediaSourceBlobProtocol);
m_mediaSourceURL.setPath(createCanonicalUUIDString());
#endif
@@ -421,14 +423,6 @@ void HTMLMediaElement::parseAttribute(const Attribute& attribute)
setAttributeEventListener(eventNames().webkitbeginfullscreenEvent, createAttributeEventListener(this, attribute));
else if (attribute.name() == onwebkitendfullscreenAttr)
setAttributeEventListener(eventNames().webkitendfullscreenEvent, createAttributeEventListener(this, attribute));
-#if ENABLE(MEDIA_SOURCE)
- else if (attribute.name() == onwebkitsourcecloseAttr)
- setAttributeEventListener(eventNames().webkitsourcecloseEvent, createAttributeEventListener(this, attribute));
- else if (attribute.name() == onwebkitsourceendedAttr)
- setAttributeEventListener(eventNames().webkitsourceendedEvent, createAttributeEventListener(this, attribute));
- else if (attribute.name() == onwebkitsourceopenAttr)
- setAttributeEventListener(eventNames().webkitsourceopenEvent, createAttributeEventListener(this, attribute));
-#endif
else
HTMLElement::parseAttribute(attribute);
}
@@ -693,6 +687,10 @@ void HTMLMediaElement::prepareForLoad()
if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE)
scheduleEvent(eventNames().abortEvent);
+#if ENABLE(MEDIA_SOURCE)
+ setSourceState(MediaSource::closedKeyword());
+#endif
+
#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
createMediaPlayer();
#else
@@ -702,11 +700,6 @@ void HTMLMediaElement::prepareForLoad()
createMediaPlayerProxy();
#endif
-#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
-#endif
-
// 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps
if (m_networkState != NETWORK_EMPTY) {
m_networkState = NETWORK_EMPTY;
@@ -927,10 +920,16 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content
}
#if ENABLE(MEDIA_SOURCE)
- // If this is a media source URL, make sure it is the one for this media element.
- if (url.protocolIs(mediaSourceURLProtocol) && url != m_mediaSourceURL) {
- mediaLoadingFailed(MediaPlayer::FormatError);
- return;
+ if (url.protocolIs(mediaSourceBlobProtocol)) {
+ if (m_mediaSource)
+ m_mediaSource->setReadyState(MediaSource::closedKeyword());
+
+ m_mediaSource = MediaSourceRegistry::registry().lookupMediaSource(url.string());
+
+ if (m_mediaSource) {
+ m_mediaSource->setMediaPlayer(m_player.get());
+ m_mediaSourceURL = url;
+ }
}
#endif
@@ -1432,8 +1431,7 @@ void HTMLMediaElement::noneSupported()
scheduleEvent(eventNames().errorEvent);
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
+ setSourceState(MediaSource::closedKeyword());
#endif
// 8 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
@@ -1464,8 +1462,7 @@ void HTMLMediaElement::mediaEngineError(PassRefPtr<MediaError> err)
scheduleEvent(eventNames().errorEvent);
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
+ setSourceState(MediaSource::closedKeyword());
#endif
// 4 - Set the element's networkState attribute to the NETWORK_EMPTY value and queue a
@@ -1581,7 +1578,6 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
if (state == MediaPlayer::Idle) {
if (m_networkState > NETWORK_IDLE) {
changeNetworkStateFromLoadingToIdle();
- scheduleEvent(eventNames().suspendEvent);
setShouldDelayLoadEvent(false);
} else {
m_networkState = NETWORK_IDLE;
@@ -1613,6 +1609,7 @@ void HTMLMediaElement::changeNetworkStateFromLoadingToIdle()
// Schedule one last progress event so we guarantee that at least one is fired
// for files that load very quickly.
scheduleEvent(eventNames().progressEvent);
+ scheduleEvent(eventNames().suspendEvent);
m_networkState = NETWORK_IDLE;
}
@@ -1750,7 +1747,7 @@ void HTMLMediaElement::mediaPlayerSourceOpened()
{
beginProcessingMediaPlayerCallback();
- setSourceState(SOURCE_OPEN);
+ setSourceState(MediaSource::openKeyword());
endProcessingMediaPlayerCallback();
}
@@ -1759,22 +1756,6 @@ String HTMLMediaElement::mediaPlayerSourceURL() const
{
return m_mediaSourceURL.string();
}
-
-bool HTMLMediaElement::isValidSourceId(const String& id, ExceptionCode& ec) const
-{
- if (id.isNull() || id.isEmpty()) {
- ec = INVALID_ACCESS_ERR;
- return false;
- }
-
- if (!m_sourceIDs.contains(id)) {
- ec = SYNTAX_ERR;
- return false;
- }
-
- return true;
-}
-
#endif
#if ENABLE(ENCRYPTED_MEDIA)
@@ -1998,8 +1979,8 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec)
#if ENABLE(MEDIA_SOURCE)
// 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_sourceState != SOURCE_CLOSED)
- noSeekRequired = false;
+ if (m_mediaSource && m_mediaSource->readyState() != MediaSource::closedKeyword())
+ noSeekRequired = false;
#endif
if (noSeekRequired) {
@@ -2021,8 +2002,8 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec)
m_sentEndEvent = false;
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState == SOURCE_ENDED)
- setSourceState(SOURCE_OPEN);
+ if (m_mediaSource && m_mediaSource->readyState() == MediaSource::endedKeyword())
+ setSourceState(MediaSource::openKeyword());
#endif
// 8 - Set the current playback position to the given new playback position
@@ -2370,175 +2351,12 @@ void HTMLMediaElement::pauseInternal()
}
#if ENABLE(MEDIA_SOURCE)
-
-void HTMLMediaElement::webkitSourceAddId(const String& id, const String& type, ExceptionCode& ec)
-{
- if (id.isNull() || id.isEmpty()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (m_sourceIDs.contains(id)) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (type.isNull() || type.isEmpty()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- ContentType contentType(type);
- Vector<String> codecs = contentType.codecs();
-
- if (!codecs.size()) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
-
- switch (m_player->sourceAddId(id, contentType.type(), codecs)) {
- case MediaPlayer::Ok:
- m_sourceIDs.add(id);
- return;
- case MediaPlayer::NotSupported:
- ec = NOT_SUPPORTED_ERR;
- return;
- case MediaPlayer::ReachedIdLimit:
- ec = QUOTA_EXCEEDED_ERR;
- return;
- }
-
- ASSERT_NOT_REACHED();
-}
-
-void HTMLMediaElement::webkitSourceRemoveId(const String& id, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState == SOURCE_CLOSED) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!m_player->sourceRemoveId(id))
- ASSERT_NOT_REACHED();
-
- m_sourceIDs.remove(id);
-}
-
-PassRefPtr<TimeRanges> HTMLMediaElement::webkitSourceBuffered(const String& id, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return 0;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState == SOURCE_CLOSED) {
- ec = INVALID_STATE_ERR;
- return 0;
- }
-
- return m_player->sourceBuffered(id);
-}
-
-void HTMLMediaElement::webkitSourceAppend(const String& id, PassRefPtr<Uint8Array> data, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!data.get()) {
- ec = INVALID_ACCESS_ERR;
- return;
- }
-
- if (!data->length())
- return;
-
- if (!m_player->sourceAppend(id, data->data(), data->length())) {
- ec = SYNTAX_ERR;
- return;
- }
-}
-
-void HTMLMediaElement::webkitSourceAbort(const String& id, ExceptionCode& ec)
-{
- if (!isValidSourceId(id, ec))
- return;
-
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!m_player->sourceAbort(id))
- ASSERT_NOT_REACHED();
-}
-
-void HTMLMediaElement::webkitSourceEndOfStream(unsigned short status, ExceptionCode& ec)
-{
- if (!m_player || m_currentSrc != m_mediaSourceURL || m_sourceState != SOURCE_OPEN) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- MediaPlayer::EndOfStreamStatus eosStatus = MediaPlayer::EosNoError;
-
- switch (status) {
- case EOS_NO_ERROR:
- eosStatus = MediaPlayer::EosNoError;
- break;
- case EOS_NETWORK_ERR:
- eosStatus = MediaPlayer::EosNetworkError;
- break;
- case EOS_DECODE_ERR:
- eosStatus = MediaPlayer::EosDecodeError;
- break;
- default:
- ec = SYNTAX_ERR;
- return;
- }
-
- setSourceState(SOURCE_ENDED);
- m_player->sourceEndOfStream(eosStatus);
-}
-
-HTMLMediaElement::SourceState HTMLMediaElement::webkitSourceState() const
+void HTMLMediaElement::setSourceState(const String& state)
{
- return m_sourceState;
-}
+ if (!m_mediaSource)
+ return;
-void HTMLMediaElement::setSourceState(SourceState state)
-{
- SourceState oldState = m_sourceState;
- m_sourceState = static_cast<SourceState>(state);
-
- if (m_sourceState == oldState)
- return;
-
- if (m_sourceState == SOURCE_CLOSED) {
- m_sourceIDs.clear();
- scheduleEvent(eventNames().webkitsourcecloseEvent);
- return;
- }
-
- if (oldState == SOURCE_OPEN && m_sourceState == SOURCE_ENDED) {
- scheduleEvent(eventNames().webkitsourceendedEvent);
- return;
- }
-
- if (m_sourceState == SOURCE_OPEN) {
- scheduleEvent(eventNames().webkitsourceopenEvent);
- return;
- }
+ m_mediaSource->setReadyState(state);
}
#endif
@@ -3351,7 +3169,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*)
invalidateCachedTime();
// 4.8.10.9 step 14 & 15. Needed if no ReadyState change is associated with the seek.
- if (m_seeking && m_readyState >= HAVE_CURRENT_DATA)
+ if (m_seeking && m_readyState >= HAVE_CURRENT_DATA && !m_player->seeking())
finishSeek();
// Always call scheduleTimeupdateEvent when the media engine reports a time discontinuity,
@@ -3793,8 +3611,7 @@ void HTMLMediaElement::userCancelledLoad()
scheduleEvent(eventNames().abortEvent);
#if ENABLE(MEDIA_SOURCE)
- if (m_sourceState != SOURCE_CLOSED)
- setSourceState(SOURCE_CLOSED);
+ setSourceState(MediaSource::closedKeyword());
#endif
// 4 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
@@ -3910,6 +3727,15 @@ void HTMLMediaElement::defaultEventHandler(Event* event)
#endif
}
+bool HTMLMediaElement::willRespondToMouseClickEvents()
+{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ return true;
+#else
+ return HTMLElement::willRespondToMouseClickEvents();
+#endif
+}
+
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
void HTMLMediaElement::ensureMediaPlayer()
@@ -4298,6 +4124,11 @@ void HTMLMediaElement::createMediaPlayer()
m_player = MediaPlayer::create(this);
+#if ENABLE(MEDIA_SOURCE)
+ if (m_mediaSource)
+ m_mediaSource->setMediaPlayer(m_player.get());
+#endif
+
#if ENABLE(WEB_AUDIO)
if (m_audioSourceNode) {
// When creating the player, make sure its AudioSourceProvider knows about the MediaElementAudioSourceNode.
diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h
index 335bfbd36..bdc614989 100644
--- a/Source/WebCore/html/HTMLMediaElement.h
+++ b/Source/WebCore/html/HTMLMediaElement.h
@@ -175,20 +175,7 @@ public:
#if ENABLE(MEDIA_SOURCE)
// Media Source.
const KURL& webkitMediaSourceURL() const { return m_mediaSourceURL; }
- void webkitSourceAddId(const String&, const String&, ExceptionCode&);
- void webkitSourceRemoveId(const String&, ExceptionCode&);
- PassRefPtr<TimeRanges> webkitSourceBuffered(const String&, ExceptionCode&);
- void webkitSourceAppend(const String&, PassRefPtr<Uint8Array> data, ExceptionCode&);
- void webkitSourceAbort(const String&, ExceptionCode&);
- enum EndOfStreamStatus { EOS_NO_ERROR, EOS_NETWORK_ERR, EOS_DECODE_ERR };
- void webkitSourceEndOfStream(unsigned short, ExceptionCode&);
- enum SourceState { SOURCE_CLOSED, SOURCE_OPEN, SOURCE_ENDED };
- SourceState webkitSourceState() const;
- void setSourceState(SourceState);
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitsourceopen);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitsourceended);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitsourceclose);
+ void setSourceState(const String&);
#endif
#if ENABLE(ENCRYPTED_MEDIA)
@@ -328,6 +315,8 @@ public:
virtual bool dispatchEvent(PassRefPtr<Event>);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
protected:
HTMLMediaElement(const QualifiedName&, Document*, bool);
virtual ~HTMLMediaElement();
@@ -418,7 +407,6 @@ private:
#if ENABLE(MEDIA_SOURCE)
virtual void mediaPlayerSourceOpened();
virtual String mediaPlayerSourceURL() const;
- bool isValidSourceId(const String&, ExceptionCode&) const;
#endif
#if ENABLE(ENCRYPTED_MEDIA)
@@ -596,8 +584,7 @@ private:
#if ENABLE(MEDIA_SOURCE)
KURL m_mediaSourceURL;
- SourceState m_sourceState;
- HashSet<String> m_sourceIDs;
+ RefPtr<MediaSource> m_mediaSource;
#endif
mutable float m_cachedTime;
diff --git a/Source/WebCore/html/HTMLMediaElement.idl b/Source/WebCore/html/HTMLMediaElement.idl
index ac0fa467b..9d0ae8a77 100644
--- a/Source/WebCore/html/HTMLMediaElement.idl
+++ b/Source/WebCore/html/HTMLMediaElement.idl
@@ -98,35 +98,6 @@ module html {
#if defined(ENABLE_MEDIA_SOURCE) && ENABLE_MEDIA_SOURCE
// URL passed to src attribute to enable the media source logic.
readonly attribute [V8EnabledAtRuntime=mediaSource, URL] DOMString webkitMediaSourceURL;
-
- // Manages IDs for appending media to the source.
- [V8EnabledAtRuntime=mediaSource] void webkitSourceAddId(in DOMString id, in DOMString type) raises (DOMException);
- [V8EnabledAtRuntime=mediaSource] void webkitSourceRemoveId(in DOMString id) raises (DOMException);
-
- // Returns the time ranges buffered for a specific source ID.
- [V8EnabledAtRuntime=mediaSource] TimeRanges webkitSourceBuffered(in DOMString id) raises (DOMException);
-
- // Appends segment data.
- [V8EnabledAtRuntime=mediaSource] void webkitSourceAppend(in DOMString id, in Uint8Array data) raises (DOMException);
-
- // Aborts the current segment.
- [V8EnabledAtRuntime=mediaSource] void webkitSourceAbort(in DOMString id) raises (DOMException);
-
- // Signals the end of stream.
- [V8EnabledAtRuntime=mediaSource] const unsigned short EOS_NO_ERROR = 0; // End of stream reached w/o error.
- [V8EnabledAtRuntime=mediaSource] const unsigned short EOS_NETWORK_ERR = 1; // A network error triggered end of stream.
- [V8EnabledAtRuntime=mediaSource] const unsigned short EOS_DECODE_ERR = 2; // A decode error triggered end of stream.
- [V8EnabledAtRuntime=mediaSource] void webkitSourceEndOfStream(in unsigned short status) raises (DOMException);
-
- // Indicates the current state of the media source.
- [V8EnabledAtRuntime=mediaSource] const unsigned short SOURCE_CLOSED = 0;
- [V8EnabledAtRuntime=mediaSource] const unsigned short SOURCE_OPEN = 1;
- [V8EnabledAtRuntime=mediaSource] const unsigned short SOURCE_ENDED = 2;
- readonly attribute [V8EnabledAtRuntime=mediaSource] unsigned short webkitSourceState;
-
- attribute [V8EnabledAtRuntime=mediaSource] EventListener onwebkitsourceopen;
- attribute [V8EnabledAtRuntime=mediaSource] EventListener onwebkitsourceended;
- attribute [V8EnabledAtRuntime=mediaSource] EventListener onwebkitsourceclose;
#endif
#if defined(ENABLE_ENCRYPTED_MEDIA) && ENABLE_ENCRYPTED_MEDIA
diff --git a/Source/WebCore/html/HTMLObjectElement.cpp b/Source/WebCore/html/HTMLObjectElement.cpp
index 5715d2382..cf185a8d3 100644
--- a/Source/WebCore/html/HTMLObjectElement.cpp
+++ b/Source/WebCore/html/HTMLObjectElement.cpp
@@ -73,7 +73,7 @@ PassRefPtr<HTMLObjectElement> HTMLObjectElement::create(const QualifiedName& tag
return adoptRef(new HTMLObjectElement(tagName, document, form, createdByParser));
}
-RenderWidget* HTMLObjectElement::renderWidgetForJSBindings()
+RenderWidget* HTMLObjectElement::renderWidgetForJSBindings() const
{
document()->updateLayoutIgnorePendingStylesheets();
return renderPart(); // This will return 0 if the renderer is not a RenderPart.
diff --git a/Source/WebCore/html/HTMLObjectElement.h b/Source/WebCore/html/HTMLObjectElement.h
index e12785d10..e3b49b4bd 100644
--- a/Source/WebCore/html/HTMLObjectElement.h
+++ b/Source/WebCore/html/HTMLObjectElement.h
@@ -82,7 +82,7 @@ private:
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
virtual const QualifiedName& imageSourceAttributeName() const;
- virtual RenderWidget* renderWidgetForJSBindings();
+ virtual RenderWidget* renderWidgetForJSBindings() const;
virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
diff --git a/Source/WebCore/html/HTMLOptionElement.cpp b/Source/WebCore/html/HTMLOptionElement.cpp
index bb68a9d32..8fcc22c27 100644
--- a/Source/WebCore/html/HTMLOptionElement.cpp
+++ b/Source/WebCore/html/HTMLOptionElement.cpp
@@ -329,7 +329,14 @@ String HTMLOptionElement::textIndentedToRespectGroupLabel() const
bool HTMLOptionElement::disabled() const
{
- return ownElementDisabled() || (parentNode() && parentNode()->isHTMLElement() && static_cast<HTMLElement*>(parentNode())->disabled());
+ if (ownElementDisabled())
+ return true;
+
+ if (!parentNode() || !parentNode()->isHTMLElement())
+ return false;
+
+ HTMLElement* parentElement = static_cast<HTMLElement*>(parentNode());
+ return parentElement->hasTagName(optgroupTag) && parentElement->disabled();
}
Node::InsertionNotificationRequest HTMLOptionElement::insertedInto(ContainerNode* insertionPoint)
diff --git a/Source/WebCore/html/HTMLPlugInElement.cpp b/Source/WebCore/html/HTMLPlugInElement.cpp
index 5bdf60d44..1b5843483 100644
--- a/Source/WebCore/html/HTMLPlugInElement.cpp
+++ b/Source/WebCore/html/HTMLPlugInElement.cpp
@@ -33,10 +33,12 @@
#include "FrameTree.h"
#include "HTMLNames.h"
#include "Page.h"
+#include "PluginViewBase.h"
#include "RenderEmbeddedObject.h"
#include "RenderWidget.h"
#include "Settings.h"
#include "Widget.h"
+#include <wtf/UnusedParam.h>
#if ENABLE(NETSCAPE_PLUGIN_API)
#include "npruntime_impl.h"
@@ -125,7 +127,7 @@ bool HTMLPlugInElement::guardedDispatchBeforeLoadEvent(const String& sourceURL)
return beforeLoadAllowedLoad;
}
-Widget* HTMLPlugInElement::pluginWidget()
+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.
@@ -190,6 +192,24 @@ void HTMLPlugInElement::defaultEventHandler(Event* event)
HTMLFrameOwnerElement::defaultEventHandler(event);
}
+bool HTMLPlugInElement::isKeyboardFocusable(KeyboardEvent* event) const
+{
+ UNUSED_PARAM(event);
+ if (!document()->page())
+ return false;
+
+ const PluginViewBase* plugin = pluginWidget() && pluginWidget()->isPluginViewBase() ? static_cast<const PluginViewBase*>(pluginWidget()) : 0;
+ if (plugin)
+ return plugin->supportsKeyboardFocus();
+
+ return false;
+}
+
+bool HTMLPlugInElement::isPluginElement() const
+{
+ return true;
+}
+
#if ENABLE(NETSCAPE_PLUGIN_API)
NPObject* HTMLPlugInElement::getNPObject()
diff --git a/Source/WebCore/html/HTMLPlugInElement.h b/Source/WebCore/html/HTMLPlugInElement.h
index 067e9aef9..94887748d 100644
--- a/Source/WebCore/html/HTMLPlugInElement.h
+++ b/Source/WebCore/html/HTMLPlugInElement.h
@@ -45,7 +45,7 @@ public:
PassScriptInstance getInstance();
- Widget* pluginWidget();
+ Widget* pluginWidget() const;
#if ENABLE(NETSCAPE_PLUGIN_API)
NPObject* getNPObject();
@@ -72,7 +72,10 @@ private:
virtual void defaultEventHandler(Event*);
- virtual RenderWidget* renderWidgetForJSBindings() = 0;
+ virtual RenderWidget* renderWidgetForJSBindings() const = 0;
+
+ virtual bool isKeyboardFocusable(KeyboardEvent*) const;
+ virtual bool isPluginElement() const;
private:
mutable ScriptInstance m_instance;
diff --git a/Source/WebCore/html/HTMLProgressElement.cpp b/Source/WebCore/html/HTMLProgressElement.cpp
index 742b09ffa..48b5b886e 100644
--- a/Source/WebCore/html/HTMLProgressElement.cpp
+++ b/Source/WebCore/html/HTMLProgressElement.cpp
@@ -43,6 +43,7 @@ const double HTMLProgressElement::InvalidPosition = -2;
HTMLProgressElement::HTMLProgressElement(const QualifiedName& tagName, Document* document)
: LabelableElement(tagName, document)
+ , m_hasAuthorShadowRoot(false)
{
ASSERT(hasTagName(progressTag));
}
@@ -58,8 +59,11 @@ PassRefPtr<HTMLProgressElement> HTMLProgressElement::create(const QualifiedName&
return progress;
}
-RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyle*)
+RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyle* style)
{
+ if (!style->hasAppearance() || hasAuthorShadowRoot())
+ return RenderObject::createObject(this, style);
+
return new (arena) RenderProgress(this);
}
@@ -68,6 +72,21 @@ bool HTMLProgressElement::childShouldCreateRenderer(const NodeRenderingContext&
return childContext.isOnUpperEncapsulationBoundary() && HTMLElement::childShouldCreateRenderer(childContext);
}
+RenderProgress* HTMLProgressElement::renderProgress() const
+{
+ if (renderer() && renderer()->isProgress())
+ return static_cast<RenderProgress*>(renderer());
+
+ RenderObject* renderObject = userAgentShadowRoot()->firstChild()->renderer();
+ ASSERT(!renderObject || renderObject->isProgress());
+ return static_cast<RenderProgress*>(renderObject);
+}
+
+void HTMLProgressElement::willAddAuthorShadowRoot()
+{
+ m_hasAuthorShadowRoot = true;
+}
+
bool HTMLProgressElement::supportsFocus() const
{
return Node::supportsFocus() && !disabled();
@@ -134,10 +153,9 @@ bool HTMLProgressElement::isDeterminate() const
void HTMLProgressElement::didElementStateChange()
{
m_value->setWidthPercentage(position() * 100);
- if (renderer() && renderer()->isProgress()) {
- RenderProgress* render = toRenderProgress(renderer());
+ if (RenderProgress* render = renderProgress()) {
bool wasDeterminate = render->isDeterminate();
- renderer()->updateFromElement();
+ render->updateFromElement();
if (wasDeterminate != isDeterminate())
setNeedsStyleRecalc();
}
@@ -145,14 +163,18 @@ void HTMLProgressElement::didElementStateChange()
void HTMLProgressElement::createShadowSubtree()
{
- ASSERT(!shadow());
+ ASSERT(!userAgentShadowRoot());
+
+ RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::UserAgentShadowRoot, ASSERT_NO_EXCEPTION);
+
+ RefPtr<ProgressInnerElement> inner = ProgressInnerElement::create(document());
+ root->appendChild(inner);
RefPtr<ProgressBarElement> bar = ProgressBarElement::create(document());
m_value = ProgressValueElement::create(document());
bar->appendChild(m_value, ASSERT_NO_EXCEPTION);
- RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::UserAgentShadowRoot, ASSERT_NO_EXCEPTION);
- root->appendChild(bar, ASSERT_NO_EXCEPTION);
+ inner->appendChild(bar, ASSERT_NO_EXCEPTION);
}
} // namespace
diff --git a/Source/WebCore/html/HTMLProgressElement.h b/Source/WebCore/html/HTMLProgressElement.h
index 72180b93d..6660d9d85 100644
--- a/Source/WebCore/html/HTMLProgressElement.h
+++ b/Source/WebCore/html/HTMLProgressElement.h
@@ -27,6 +27,7 @@
namespace WebCore {
class ProgressValueElement;
+class RenderProgress;
class HTMLProgressElement : public LabelableElement {
public:
@@ -35,6 +36,8 @@ public:
static PassRefPtr<HTMLProgressElement> create(const QualifiedName&, Document*);
+ bool hasAuthorShadowRoot() const { return m_hasAuthorShadowRoot; }
+
double value() const;
void setValue(double, ExceptionCode&);
@@ -51,12 +54,15 @@ private:
HTMLProgressElement(const QualifiedName&, Document*);
virtual ~HTMLProgressElement();
+ virtual void willAddAuthorShadowRoot() OVERRIDE;
+
virtual bool supportLabels() const OVERRIDE { return true; }
virtual bool supportsFocus() const;
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE;
+ RenderProgress* renderProgress() const;
virtual void parseAttribute(const Attribute&) OVERRIDE;
@@ -66,8 +72,21 @@ private:
void createShadowSubtree();
RefPtr<ProgressValueElement> m_value;
+ bool m_hasAuthorShadowRoot;
};
+inline bool isHTMLProgressElement(Node* node)
+{
+ ASSERT(node);
+ return node->hasTagName(HTMLNames::progressTag);
+}
+
+inline HTMLProgressElement* toHTMLProgressElement(Node* node)
+{
+ ASSERT(!node || isHTMLProgressElement(node));
+ return static_cast<HTMLProgressElement*>(node);
+}
+
} // namespace
#endif
diff --git a/Source/WebCore/html/HTMLPropertiesCollection.cpp b/Source/WebCore/html/HTMLPropertiesCollection.cpp
index b67c4c16a..7e81766db 100644
--- a/Source/WebCore/html/HTMLPropertiesCollection.cpp
+++ b/Source/WebCore/html/HTMLPropertiesCollection.cpp
@@ -69,14 +69,14 @@ void HTMLPropertiesCollection::updateRefElements() const
toHTMLElement(base())->getItemRefElements(m_itemRefElements);
}
-static Node* nextNodeWithProperty(Node* base, Node* node)
+static Node* nextNodeWithProperty(Node* rootNode, Node* previous, Node* ownerNode)
{
// An Microdata item may contain properties which in turn are items themselves. Properties can
// also themselves be groups of name-value pairs, by putting the itemscope attribute on the element
// that declares the property. If the property has an itemscope attribute specified then we need
// to traverse the next sibling.
- return node == base || (node->isHTMLElement() && !toHTMLElement(node)->fastHasAttribute(itemscopeAttr))
- ? node->traverseNextNode(base) : node->traverseNextSibling(base);
+ return previous == ownerNode || (previous->isHTMLElement() && !toHTMLElement(previous)->fastHasAttribute(itemscopeAttr))
+ ? previous->traverseNextNode(rootNode) : previous->traverseNextSibling(rootNode);
}
Element* HTMLPropertiesCollection::virtualItemAfter(unsigned& offsetInArray, Element* previousItem) const
@@ -90,13 +90,14 @@ Element* HTMLPropertiesCollection::virtualItemAfter(unsigned& offsetInArray, Ele
return 0;
}
-HTMLElement* HTMLPropertiesCollection::virtualItemAfter(HTMLElement* base, Element* previous) const
+HTMLElement* HTMLPropertiesCollection::virtualItemAfter(HTMLElement* rootNode, Element* previous) const
{
Node* current;
- current = previous ? nextNodeWithProperty(base, previous) : base;
+ Node* ownerNode = this->ownerNode();
+ current = previous ? nextNodeWithProperty(rootNode, previous, ownerNode) : rootNode;
- for (; current; current = nextNodeWithProperty(base, current)) {
- if (!current->isHTMLElement())
+ for (; current; current = nextNodeWithProperty(rootNode, current, ownerNode)) {
+ if (current == ownerNode || !current->isHTMLElement())
continue;
HTMLElement* element = toHTMLElement(current);
if (element->fastHasAttribute(itempropAttr) && element->itemProp()->length()) {
diff --git a/Source/WebCore/html/HTMLSelectElement.cpp b/Source/WebCore/html/HTMLSelectElement.cpp
index 83ccec5c3..98c99b830 100644
--- a/Source/WebCore/html/HTMLSelectElement.cpp
+++ b/Source/WebCore/html/HTMLSelectElement.cpp
@@ -1292,11 +1292,13 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toSize(localOffset));
if (listIndex >= 0) {
+ if (!disabled()) {
#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
- updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent->shiftKey());
+ updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent->shiftKey());
#else
- updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent->shiftKey());
+ updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent->shiftKey());
#endif
+ }
if (Frame* frame = document()->frame())
frame->eventHandler()->setMouseDownMayStartAutoscroll();
@@ -1310,13 +1312,15 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toSize(localOffset));
if (listIndex >= 0) {
- if (m_multiple) {
- setActiveSelectionEndIndex(listIndex);
- updateListBoxSelection(false);
- } else {
- setActiveSelectionAnchorIndex(listIndex);
- setActiveSelectionEndIndex(listIndex);
- updateListBoxSelection(true);
+ if (!disabled()) {
+ if (m_multiple) {
+ setActiveSelectionEndIndex(listIndex);
+ updateListBoxSelection(false);
+ } else {
+ setActiveSelectionAnchorIndex(listIndex);
+ setActiveSelectionEndIndex(listIndex);
+ updateListBoxSelection(true);
+ }
}
event->setDefaultHandled();
}
diff --git a/Source/WebCore/html/HTMLSummaryElement.cpp b/Source/WebCore/html/HTMLSummaryElement.cpp
index 74ff5e6d7..e3b37b505 100644
--- a/Source/WebCore/html/HTMLSummaryElement.cpp
+++ b/Source/WebCore/html/HTMLSummaryElement.cpp
@@ -157,6 +157,14 @@ void HTMLSummaryElement::defaultEventHandler(Event* event)
HTMLElement::defaultEventHandler(event);
}
+bool HTMLSummaryElement::willRespondToMouseClickEvents()
+{
+ if (isMainSummary() && renderer())
+ return true;
+
+ return HTMLElement::willRespondToMouseClickEvents();
+}
+
}
#endif
diff --git a/Source/WebCore/html/HTMLSummaryElement.h b/Source/WebCore/html/HTMLSummaryElement.h
index 49a2d0bac..2c8a93fb5 100644
--- a/Source/WebCore/html/HTMLSummaryElement.h
+++ b/Source/WebCore/html/HTMLSummaryElement.h
@@ -31,6 +31,7 @@ class HTMLSummaryElement : public HTMLElement {
public:
static PassRefPtr<HTMLSummaryElement> create(const QualifiedName&, Document*);
bool isMainSummary() const;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
private:
HTMLSummaryElement(const QualifiedName&, Document*);
diff --git a/Source/WebCore/html/HTMLTableCellElement.cpp b/Source/WebCore/html/HTMLTableCellElement.cpp
index c75ecc8a1..294607d77 100644
--- a/Source/WebCore/html/HTMLTableCellElement.cpp
+++ b/Source/WebCore/html/HTMLTableCellElement.cpp
@@ -114,7 +114,7 @@ void HTMLTableCellElement::parseAttribute(const Attribute& attribute)
HTMLTablePartElement::parseAttribute(attribute);
}
-StylePropertySet* HTMLTableCellElement::additionalAttributeStyle()
+const StylePropertySet* HTMLTableCellElement::additionalAttributeStyle()
{
if (HTMLTableElement* table = findParentTable())
return table->additionalCellStyle();
diff --git a/Source/WebCore/html/HTMLTableCellElement.h b/Source/WebCore/html/HTMLTableCellElement.h
index 5213e1c16..1850974cf 100644
--- a/Source/WebCore/html/HTMLTableCellElement.h
+++ b/Source/WebCore/html/HTMLTableCellElement.h
@@ -57,7 +57,7 @@ private:
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) OVERRIDE;
- virtual StylePropertySet* additionalAttributeStyle() OVERRIDE;
+ virtual const StylePropertySet* additionalAttributeStyle() OVERRIDE;
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
diff --git a/Source/WebCore/html/HTMLTableColElement.cpp b/Source/WebCore/html/HTMLTableColElement.cpp
index 651a3bc71..2830dfa48 100644
--- a/Source/WebCore/html/HTMLTableColElement.cpp
+++ b/Source/WebCore/html/HTMLTableColElement.cpp
@@ -81,7 +81,7 @@ void HTMLTableColElement::parseAttribute(const Attribute& attribute)
HTMLTablePartElement::parseAttribute(attribute);
}
-StylePropertySet* HTMLTableColElement::additionalAttributeStyle()
+const StylePropertySet* HTMLTableColElement::additionalAttributeStyle()
{
if (!hasLocalName(colgroupTag))
return 0;
diff --git a/Source/WebCore/html/HTMLTableColElement.h b/Source/WebCore/html/HTMLTableColElement.h
index 1916d250a..64069d9e1 100644
--- a/Source/WebCore/html/HTMLTableColElement.h
+++ b/Source/WebCore/html/HTMLTableColElement.h
@@ -45,7 +45,7 @@ private:
virtual void parseAttribute(const Attribute&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) OVERRIDE;
- virtual StylePropertySet* additionalAttributeStyle() OVERRIDE;
+ virtual const StylePropertySet* additionalAttributeStyle() OVERRIDE;
int m_span;
};
diff --git a/Source/WebCore/html/HTMLTableElement.cpp b/Source/WebCore/html/HTMLTableElement.cpp
index 6232609fe..283786b72 100644
--- a/Source/WebCore/html/HTMLTableElement.cpp
+++ b/Source/WebCore/html/HTMLTableElement.cpp
@@ -432,7 +432,7 @@ static StylePropertySet* leakBorderStyle(int value)
return style.release().leakRef();
}
-StylePropertySet* HTMLTableElement::additionalAttributeStyle()
+const StylePropertySet* HTMLTableElement::additionalAttributeStyle()
{
if (m_frameAttr)
return 0;
@@ -518,7 +518,7 @@ PassRefPtr<StylePropertySet> HTMLTableElement::createSharedCellStyle()
return style.release();
}
-StylePropertySet* HTMLTableElement::additionalCellStyle()
+const StylePropertySet* HTMLTableElement::additionalCellStyle()
{
if (!m_sharedCellStyle)
m_sharedCellStyle = createSharedCellStyle();
@@ -542,7 +542,7 @@ static StylePropertySet* leakGroupBorderStyle(int rows)
return style.release().leakRef();
}
-StylePropertySet* HTMLTableElement::additionalGroupStyle(bool rows)
+const StylePropertySet* HTMLTableElement::additionalGroupStyle(bool rows)
{
if (m_rulesAttr != GroupsRules)
return 0;
diff --git a/Source/WebCore/html/HTMLTableElement.h b/Source/WebCore/html/HTMLTableElement.h
index 2b05053ad..f11c467a8 100644
--- a/Source/WebCore/html/HTMLTableElement.h
+++ b/Source/WebCore/html/HTMLTableElement.h
@@ -65,8 +65,8 @@ public:
String rules() const;
String summary() const;
- StylePropertySet* additionalCellStyle();
- StylePropertySet* additionalGroupStyle(bool rows);
+ const StylePropertySet* additionalCellStyle();
+ const StylePropertySet* additionalGroupStyle(bool rows);
private:
HTMLTableElement(const QualifiedName&, Document*);
@@ -77,7 +77,7 @@ private:
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
// Used to obtain either a solid or outset border decl and to deal with the frame and rules attributes.
- virtual StylePropertySet* additionalAttributeStyle() OVERRIDE;
+ virtual const StylePropertySet* additionalAttributeStyle() OVERRIDE;
virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
diff --git a/Source/WebCore/html/HTMLTableSectionElement.cpp b/Source/WebCore/html/HTMLTableSectionElement.cpp
index 60e54289c..582fcbbea 100644
--- a/Source/WebCore/html/HTMLTableSectionElement.cpp
+++ b/Source/WebCore/html/HTMLTableSectionElement.cpp
@@ -47,7 +47,7 @@ PassRefPtr<HTMLTableSectionElement> HTMLTableSectionElement::create(const Qualif
return adoptRef(new HTMLTableSectionElement(tagName, document));
}
-StylePropertySet* HTMLTableSectionElement::additionalAttributeStyle()
+const StylePropertySet* HTMLTableSectionElement::additionalAttributeStyle()
{
if (HTMLTableElement* table = findParentTable())
return table->additionalGroupStyle(true);
diff --git a/Source/WebCore/html/HTMLTableSectionElement.h b/Source/WebCore/html/HTMLTableSectionElement.h
index 7156a70f0..075d052bf 100644
--- a/Source/WebCore/html/HTMLTableSectionElement.h
+++ b/Source/WebCore/html/HTMLTableSectionElement.h
@@ -56,7 +56,7 @@ public:
private:
HTMLTableSectionElement(const QualifiedName& tagName, Document*);
- virtual StylePropertySet* additionalAttributeStyle() OVERRIDE;
+ virtual const StylePropertySet* additionalAttributeStyle() OVERRIDE;
};
} //namespace
diff --git a/Source/WebCore/html/HTMLTextAreaElement.h b/Source/WebCore/html/HTMLTextAreaElement.h
index 18ebead28..4e6db563e 100644
--- a/Source/WebCore/html/HTMLTextAreaElement.h
+++ b/Source/WebCore/html/HTMLTextAreaElement.h
@@ -123,6 +123,11 @@ private:
mutable bool m_wasModifiedByUser;
};
+inline bool isHTMLTextAreaElement(Node* node)
+{
+ return node->hasTagName(HTMLNames::textareaTag);
+}
+
} //namespace
#endif
diff --git a/Source/WebCore/html/HTMLTrackElement.idl b/Source/WebCore/html/HTMLTrackElement.idl
index 0107df5a3..3e98fed66 100644
--- a/Source/WebCore/html/HTMLTrackElement.idl
+++ b/Source/WebCore/html/HTMLTrackElement.idl
@@ -28,8 +28,8 @@ module html {
Conditional=VIDEO_TRACK,
V8EnabledAtRuntime=webkitVideoTrack
] HTMLTrackElement : HTMLElement {
- attribute [Reflect, URL] DOMString src;
attribute DOMString kind;
+ attribute [Reflect, URL] DOMString src;
attribute DOMString srclang;
attribute DOMString label;
attribute [Reflect] boolean default;
diff --git a/Source/WebCore/html/HTMLVideoElement.cpp b/Source/WebCore/html/HTMLVideoElement.cpp
index eebe53367..0e0e22f71 100644
--- a/Source/WebCore/html/HTMLVideoElement.cpp
+++ b/Source/WebCore/html/HTMLVideoElement.cpp
@@ -87,14 +87,6 @@ void HTMLVideoElement::attach()
#endif
}
-void HTMLVideoElement::detach()
-{
- HTMLMediaElement::detach();
-
- if (!shouldDisplayPosterImage() && m_imageLoader)
- m_imageLoader.clear();
-}
-
void HTMLVideoElement::collectStyleForAttribute(const Attribute& attribute, StylePropertySet* style)
{
if (attribute.name() == widthAttr)
diff --git a/Source/WebCore/html/HTMLVideoElement.h b/Source/WebCore/html/HTMLVideoElement.h
index b4c0391a7..dbe52a403 100644
--- a/Source/WebCore/html/HTMLVideoElement.h
+++ b/Source/WebCore/html/HTMLVideoElement.h
@@ -75,7 +75,6 @@ private:
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
#endif
virtual void attach();
- virtual void detach();
virtual void parseAttribute(const Attribute&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) OVERRIDE;
diff --git a/Source/WebCore/html/InputType.cpp b/Source/WebCore/html/InputType.cpp
index 09a895b50..674572e21 100644
--- a/Source/WebCore/html/InputType.cpp
+++ b/Source/WebCore/html/InputType.cpp
@@ -908,6 +908,12 @@ String InputType::defaultToolTip() const
void InputType::listAttributeTargetChanged()
{
}
+
+Decimal InputType::findClosestTickMarkValue(const Decimal&)
+{
+ ASSERT_NOT_REACHED();
+ return Decimal::nan();
+}
#endif
bool InputType::supportsIndeterminateAppearance() const
diff --git a/Source/WebCore/html/InputType.h b/Source/WebCore/html/InputType.h
index 0245ba888..a73ddba27 100644
--- a/Source/WebCore/html/InputType.h
+++ b/Source/WebCore/html/InputType.h
@@ -281,6 +281,7 @@ public:
virtual String defaultToolTip() const;
#if ENABLE(DATALIST_ELEMENT)
virtual void listAttributeTargetChanged();
+ virtual Decimal findClosestTickMarkValue(const Decimal&);
#endif
// Parses the specified string for the type, and return
diff --git a/Source/WebCore/html/MediaController.cpp b/Source/WebCore/html/MediaController.cpp
index 39fd09d4c..393ca8ade 100644
--- a/Source/WebCore/html/MediaController.cpp
+++ b/Source/WebCore/html/MediaController.cpp
@@ -32,6 +32,7 @@
#include "ExceptionCode.h"
#include "HTMLMediaElement.h"
#include "TimeRanges.h"
+#include <wtf/CurrentTime.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/AtomicString.h>
@@ -56,6 +57,8 @@ MediaController::MediaController(ScriptExecutionContext* context)
, m_closedCaptionsVisible(false)
, m_clock(Clock::create())
, m_scriptExecutionContext(context)
+ , m_timeupdateTimer(this, &MediaController::timeupdateTimerFired)
+ , m_previousTimeupdateTime(0)
{
}
@@ -171,6 +174,8 @@ void MediaController::setCurrentTime(float time, ExceptionCode& code)
// 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, code);
+
+ scheduleTimeupdateEvent();
}
void MediaController::play()
@@ -395,14 +400,17 @@ void MediaController::updatePlaybackState()
case WAITING:
eventName = eventNames().waitingEvent;
m_clock->stop();
+ m_timeupdateTimer.stop();
break;
case ENDED:
eventName = eventNames().endedEvent;
m_clock->stop();
+ m_timeupdateTimer.stop();
break;
case PLAYING:
eventName = eventNames().playingEvent;
m_clock->start();
+ startTimeupdateTimer();
break;
default:
ASSERT_NOT_REACHED();
@@ -605,4 +613,33 @@ const AtomicString& MediaController::interfaceName() const
return eventNames().interfaceForMediaController;
}
+// The spec says to fire periodic timeupdate events (those sent while playing) every
+// "15 to 250ms", we choose the slowest frequency
+static const double maxTimeupdateEventFrequency = 0.25;
+
+void MediaController::startTimeupdateTimer()
+{
+ if (m_timeupdateTimer.isActive())
+ return;
+
+ m_timeupdateTimer.startRepeating(maxTimeupdateEventFrequency);
+}
+
+void MediaController::timeupdateTimerFired(Timer<MediaController>*)
+{
+ scheduleTimeupdateEvent();
+}
+
+void MediaController::scheduleTimeupdateEvent()
+{
+ double now = WTF::currentTime();
+ double timedelta = now - m_previousTimeupdateTime;
+
+ if (timedelta < maxTimeupdateEventFrequency)
+ return;
+
+ scheduleEvent(eventNames().timeupdateEvent);
+ m_previousTimeupdateTime = now;
+}
+
#endif
diff --git a/Source/WebCore/html/MediaController.h b/Source/WebCore/html/MediaController.h
index d32b71279..d293ccb1d 100644
--- a/Source/WebCore/html/MediaController.h
+++ b/Source/WebCore/html/MediaController.h
@@ -125,6 +125,9 @@ private:
void asyncEventTimerFired(Timer<MediaController>*);
void clearPositionTimerFired(Timer<MediaController>*);
bool hasEnded() const;
+ void scheduleTimeupdateEvent();
+ void timeupdateTimerFired(Timer<MediaController>*);
+ void startTimeupdateTimer();
// EventTarget
virtual void refEventTarget() { ref(); }
@@ -152,6 +155,8 @@ private:
bool m_closedCaptionsVisible;
PassRefPtr<Clock> m_clock;
ScriptExecutionContext* m_scriptExecutionContext;
+ Timer<MediaController> m_timeupdateTimer;
+ double m_previousTimeupdateTime;
};
} // namespace WebCore
diff --git a/Source/WebCore/html/NumberInputType.cpp b/Source/WebCore/html/NumberInputType.cpp
index 8beff28af..82f12d1fd 100644
--- a/Source/WebCore/html/NumberInputType.cpp
+++ b/Source/WebCore/html/NumberInputType.cpp
@@ -239,13 +239,7 @@ String NumberInputType::localizeValue(const String& proposedValue) const
// We don't localize scientific notations.
if (proposedValue.find(isE) != notFound)
return proposedValue;
- // FIXME: The following three lines should be removed when we
- // remove the second argument of convertToLocalizedNumber().
- // Note: parseToDoubleForNumberTypeWithDecimalPlaces set zero to decimalPlaces
- // if currentValue isn't valid floating pointer number.
- unsigned decimalPlace;
- parseToDoubleForNumberTypeWithDecimalPlaces(proposedValue, &decimalPlace);
- return convertToLocalizedNumber(proposedValue, decimalPlace);
+ return convertToLocalizedNumber(proposedValue);
}
String NumberInputType::visibleValue() const
diff --git a/Source/WebCore/html/PublicURLManager.h b/Source/WebCore/html/PublicURLManager.h
index 258ac067a..f5e7b20aa 100644
--- a/Source/WebCore/html/PublicURLManager.h
+++ b/Source/WebCore/html/PublicURLManager.h
@@ -37,6 +37,11 @@
#include "MediaStreamRegistry.h"
#endif
+#if ENABLE(MEDIA_SOURCE)
+#include "MediaSource.h"
+#include "MediaSourceRegistry.h"
+#endif
+
namespace WebCore {
class ScriptExecutionContext;
@@ -56,18 +61,29 @@ public:
for (HashSet<String>::iterator iter = m_streamURLs.begin(); iter != streamURLsEnd; ++iter)
MediaStreamRegistry::registry().unregisterMediaStreamURL(KURL(ParsedURLString, *iter));
#endif
+#if ENABLE(MEDIA_SOURCE)
+ HashSet<String>::iterator sourceURLsEnd = m_sourceURLs.end();
+ for (HashSet<String>::iterator iter = m_sourceURLs.begin(); iter != sourceURLsEnd; ++iter)
+ MediaSourceRegistry::registry().unregisterMediaSourceURL(KURL(ParsedURLString, *iter));
+#endif
}
HashSet<String>& blobURLs() { return m_blobURLs; }
#if ENABLE(MEDIA_STREAM)
HashSet<String>& streamURLs() { return m_streamURLs; }
#endif
+#if ENABLE(MEDIA_SOURCE)
+ HashSet<String>& sourceURLs() { return m_sourceURLs; }
+#endif
private:
HashSet<String> m_blobURLs;
#if ENABLE(MEDIA_STREAM)
HashSet<String> m_streamURLs;
#endif
+#if ENABLE(MEDIA_SOURCE)
+ HashSet<String> m_sourceURLs;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/html/RangeInputType.cpp b/Source/WebCore/html/RangeInputType.cpp
index 901a9acc1..ae696e6df 100644
--- a/Source/WebCore/html/RangeInputType.cpp
+++ b/Source/WebCore/html/RangeInputType.cpp
@@ -55,6 +55,12 @@
#include "TouchList.h"
#endif
+#if ENABLE(DATALIST_ELEMENT)
+#include "HTMLDataListElement.h"
+#include "HTMLOptionElement.h"
+#include <wtf/NonCopyingSort.h>
+#endif
+
namespace WebCore {
using namespace HTMLNames;
@@ -76,6 +82,14 @@ PassOwnPtr<InputType> RangeInputType::create(HTMLInputElement* element)
return adoptPtr(new RangeInputType(element));
}
+RangeInputType::RangeInputType(HTMLInputElement* element)
+ : InputType(element)
+#if ENABLE(DATALIST_ELEMENT)
+ , m_tickMarkValuesDirty(true)
+#endif
+{
+}
+
bool RangeInputType::isRangeControl() const
{
return true;
@@ -319,8 +333,70 @@ HTMLElement* RangeInputType::sliderThumbElement() const
#if ENABLE(DATALIST_ELEMENT)
void RangeInputType::listAttributeTargetChanged()
{
+ m_tickMarkValuesDirty = true;
element()->setNeedsStyleRecalc();
}
+
+static bool decimalCompare(const Decimal& a, const Decimal& b)
+{
+ return a < b;
+}
+
+void RangeInputType::updateTickMarkValues()
+{
+ if (!m_tickMarkValuesDirty)
+ return;
+ m_tickMarkValues.clear();
+ m_tickMarkValuesDirty = false;
+ HTMLDataListElement* dataList = element()->dataList();
+ if (!dataList)
+ return;
+ RefPtr<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);
+ String optionValue = optionElement->value();
+ if (!element()->isValidValue(optionValue))
+ continue;
+ m_tickMarkValues.append(parseToNumber(optionValue, Decimal::nan()));
+ }
+ m_tickMarkValues.shrinkToFit();
+ nonCopyingSort(m_tickMarkValues.begin(), m_tickMarkValues.end(), decimalCompare);
+}
+
+Decimal RangeInputType::findClosestTickMarkValue(const Decimal& value)
+{
+ updateTickMarkValues();
+ if (!m_tickMarkValues.size())
+ return Decimal::nan();
+
+ size_t left = 0;
+ size_t right = m_tickMarkValues.size();
+ size_t middle;
+ while (true) {
+ ASSERT(left <= right);
+ middle = left + (right - left) / 2;
+ if (!middle)
+ break;
+ if (middle == m_tickMarkValues.size() - 1 && m_tickMarkValues[middle] < value) {
+ middle++;
+ break;
+ }
+ if (m_tickMarkValues[middle - 1] <= value && m_tickMarkValues[middle] >= value)
+ break;
+
+ if (m_tickMarkValues[middle] < value)
+ left = middle;
+ else
+ right = middle;
+ }
+ const Decimal closestLeft = middle ? m_tickMarkValues[middle - 1] : Decimal::infinity(Decimal::Negative);
+ const Decimal closestRight = middle != m_tickMarkValues.size() ? m_tickMarkValues[middle] : Decimal::infinity(Decimal::Positive);
+ if (closestRight - value < value - closestLeft)
+ return closestRight;
+ return closestLeft;
+}
#endif
} // namespace WebCore
diff --git a/Source/WebCore/html/RangeInputType.h b/Source/WebCore/html/RangeInputType.h
index 69d2ec7c6..8367b6fef 100644
--- a/Source/WebCore/html/RangeInputType.h
+++ b/Source/WebCore/html/RangeInputType.h
@@ -42,7 +42,7 @@ public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- RangeInputType(HTMLInputElement* element) : InputType(element) { }
+ RangeInputType(HTMLInputElement*);
virtual bool isRangeControl() const OVERRIDE;
virtual const AtomicString& formControlType() const OVERRIDE;
virtual double valueAsDouble() const OVERRIDE;
@@ -72,6 +72,11 @@ private:
virtual HTMLElement* sliderThumbElement() const OVERRIDE;
#if ENABLE(DATALIST_ELEMENT)
virtual void listAttributeTargetChanged() OVERRIDE;
+ void updateTickMarkValues();
+ virtual Decimal findClosestTickMarkValue(const Decimal&) OVERRIDE;
+
+ bool m_tickMarkValuesDirty;
+ Vector<Decimal> m_tickMarkValues;
#endif
};
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index aced0bd0b..722c9c53d 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -1996,6 +1996,10 @@ void CanvasRenderingContext2D::setFont(const String& newFont)
if (parsedStyle->isEmpty())
return;
+ RefPtr<CSSValue> fontValue = parsedStyle->getPropertyCSSValue(CSSPropertyFont);
+ if (fontValue && fontValue->isInheritedValue())
+ return;
+
// The parse succeeded.
realizeSaves();
modifiableState().m_unparsedFont = newFont;
diff --git a/Source/WebCore/html/canvas/Float32Array.idl b/Source/WebCore/html/canvas/Float32Array.idl
index 8eaebe4de..b445eb40d 100644
--- a/Source/WebCore/html/canvas/Float32Array.idl
+++ b/Source/WebCore/html/canvas/Float32Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=float
] Float32Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 4;
@@ -43,6 +44,6 @@ module html {
// void set(in Float32Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Float64Array.idl b/Source/WebCore/html/canvas/Float64Array.idl
index abfeb2178..da4b483a1 100644
--- a/Source/WebCore/html/canvas/Float64Array.idl
+++ b/Source/WebCore/html/canvas/Float64Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=double
] Float64Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 8;
@@ -43,6 +44,6 @@ module html {
// void set(in Float64Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Int16Array.idl b/Source/WebCore/html/canvas/Int16Array.idl
index f6d089ea3..9f98bea93 100644
--- a/Source/WebCore/html/canvas/Int16Array.idl
+++ b/Source/WebCore/html/canvas/Int16Array.idl
@@ -25,14 +25,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=short
] Int16Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 2;
@@ -42,6 +43,6 @@ module html {
// void set(in Int16Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Int32Array.idl b/Source/WebCore/html/canvas/Int32Array.idl
index f98835a2c..87cd7587c 100644
--- a/Source/WebCore/html/canvas/Int32Array.idl
+++ b/Source/WebCore/html/canvas/Int32Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=int
] Int32Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 4;
@@ -43,6 +44,6 @@ module html {
// void set(in Int32Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Int8Array.idl b/Source/WebCore/html/canvas/Int8Array.idl
index 00faa4fc3..10cf12003 100644
--- a/Source/WebCore/html/canvas/Int8Array.idl
+++ b/Source/WebCore/html/canvas/Int8Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=signed char
] Int8Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 1;
@@ -43,6 +44,6 @@ module html {
// void set(in Int8Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Uint16Array.idl b/Source/WebCore/html/canvas/Uint16Array.idl
index 79e05efc4..72998a35d 100644
--- a/Source/WebCore/html/canvas/Uint16Array.idl
+++ b/Source/WebCore/html/canvas/Uint16Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=unsigned short
] Uint16Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 2;
@@ -42,6 +43,6 @@ module html {
// void set(in Uint16Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Uint32Array.idl b/Source/WebCore/html/canvas/Uint32Array.idl
index 67e61b29f..65c44bef9 100644
--- a/Source/WebCore/html/canvas/Uint32Array.idl
+++ b/Source/WebCore/html/canvas/Uint32Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=unsigned int
] Uint32Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 4;
@@ -42,6 +43,6 @@ module html {
// void set(in Uint32Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Uint8Array.idl b/Source/WebCore/html/canvas/Uint8Array.idl
index 260a3273e..f6ef9377d 100644
--- a/Source/WebCore/html/canvas/Uint8Array.idl
+++ b/Source/WebCore/html/canvas/Uint8Array.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=unsigned char
] Uint8Array : ArrayBufferView {
const unsigned long BYTES_PER_ELEMENT = 1;
@@ -42,6 +43,6 @@ module html {
// void set(in Uint8Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/Uint8ClampedArray.idl b/Source/WebCore/html/canvas/Uint8ClampedArray.idl
index cadd66364..c646e57e9 100644
--- a/Source/WebCore/html/canvas/Uint8ClampedArray.idl
+++ b/Source/WebCore/html/canvas/Uint8ClampedArray.idl
@@ -26,14 +26,15 @@
module html {
interface [
- CustomConstructor,
+ ConstructorTemplate=TypedArray,
ConstructorParameters=1,
NumericIndexedGetter,
CustomIndexedSetter,
JSGenerateToNativeObject,
JSNoStaticTables,
CustomToJSObject,
- DoNotCheckConstants
+ DoNotCheckConstants,
+ TypedArray=unsigned char
] Uint8ClampedArray : Uint8Array {
const unsigned long BYTES_PER_ELEMENT = 1;
@@ -43,6 +44,6 @@ module html {
// FIXME: Missing other setters!
// void set(in Uint8ClampedArray array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
- [Custom] void set();
+ void set();
};
}
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
index c0abf0fba..1ee6215fd 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -548,6 +548,7 @@ void WebGLRenderingContext::setupFlags()
m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
}
+ m_isRobustnessEXTSupported = m_context->getExtensions()->isEnabled("GL_EXT_robustness");
}
bool WebGLRenderingContext::allowPrivilegedExtensions() const
@@ -2975,21 +2976,30 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
switch (baseType) {
case GraphicsContext3D::FLOAT: {
GC3Dfloat value[16] = {0};
- m_context->getUniformfv(objectOrZero(program), location, value);
+ if (m_isRobustnessEXTSupported)
+ m_context->getExtensions()->getnUniformfvEXT(objectOrZero(program), location, 16, value);
+ else
+ m_context->getUniformfv(objectOrZero(program), location, value);
if (length == 1)
return WebGLGetInfo(value[0]);
return WebGLGetInfo(Float32Array::create(value, length));
}
case GraphicsContext3D::INT: {
GC3Dint value[4] = {0};
- m_context->getUniformiv(objectOrZero(program), location, value);
+ if (m_isRobustnessEXTSupported)
+ m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4, value);
+ else
+ m_context->getUniformiv(objectOrZero(program), location, value);
if (length == 1)
return WebGLGetInfo(value[0]);
return WebGLGetInfo(Int32Array::create(value, length));
}
case GraphicsContext3D::BOOL: {
GC3Dint value[4] = {0};
- m_context->getUniformiv(objectOrZero(program), location, value);
+ if (m_isRobustnessEXTSupported)
+ m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4, value);
+ else
+ m_context->getUniformiv(objectOrZero(program), location, value);
if (length > 1) {
bool boolValue[16] = {0};
for (unsigned j = 0; j < length; j++)
@@ -3290,26 +3300,34 @@ void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC
return;
}
// Calculate array size, taking into consideration of PACK_ALIGNMENT.
- unsigned int totalBytesRequired;
- unsigned int padding;
- GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
- if (error != GraphicsContext3D::NO_ERROR) {
- synthesizeGLError(error, "readPixels", "invalid dimensions");
- return;
- }
- if (pixels->byteLength() < totalBytesRequired) {
- synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
- return;
+ unsigned int totalBytesRequired = 0;
+ unsigned int padding = 0;
+ if (!m_isRobustnessEXTSupported) {
+ GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
+ if (error != GraphicsContext3D::NO_ERROR) {
+ synthesizeGLError(error, "readPixels", "invalid dimensions");
+ return;
+ }
+ if (pixels->byteLength() < totalBytesRequired) {
+ synthesizeGLError(GraphicsContext3D::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 (m_isRobustnessEXTSupported)
+ m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels->byteLength(), data);
+ else
+ m_context->readPixels(x, y, width, height, format, type, data);
}
#if OS(DARWIN) || OS(QNX)
+ if (m_isRobustnessEXTSupported) // we haven't computed padding
+ m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
// FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
// on QC & Imagination QNX is fixed, i.e., when alpha is off, readPixels should
// set alpha to 255 instead of 0.
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h
index 4c890ea21..c72ac590a 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h
@@ -494,6 +494,7 @@ public:
bool m_isErrorGeneratedOnOutOfBoundsAccesses;
bool m_isResourceSafe;
bool m_isDepthStencilSupported;
+ bool m_isRobustnessEXTSupported;
bool m_synthesizedErrorsToConsole;
int m_numGLErrorsToConsoleAllowed;
diff --git a/Source/WebCore/html/parser/HTMLConstructionSite.cpp b/Source/WebCore/html/parser/HTMLConstructionSite.cpp
index 62678722c..fc9d7c664 100644
--- a/Source/WebCore/html/parser/HTMLConstructionSite.cpp
+++ b/Source/WebCore/html/parser/HTMLConstructionSite.cpp
@@ -70,15 +70,6 @@ static bool hasImpliedEndTag(const HTMLStackItem* item)
|| item->hasTagName(rtTag);
}
-static bool causesFosterParenting(const HTMLStackItem* item)
-{
- return item->hasTagName(tableTag)
- || item->hasTagName(tbodyTag)
- || item->hasTagName(tfootTag)
- || item->hasTagName(theadTag)
- || item->hasTagName(trTag);
-}
-
static inline bool isAllWhitespace(const String& string)
{
return string.isAllSpecialCharacters<isHTMLSpace>();
@@ -277,9 +268,9 @@ void HTMLConstructionSite::insertCommentOnHTMLHtmlElement(AtomicHTMLToken* token
void HTMLConstructionSite::insertHTMLHeadElement(AtomicHTMLToken* token)
{
ASSERT(!shouldFosterParent());
- m_head = createHTMLElement(token);
- attachLater(currentNode(), m_head);
- m_openElements.pushHTMLHeadElement(HTMLStackItem::create(m_head, token));
+ m_head = HTMLStackItem::create(createHTMLElement(token), token);
+ attachLater(currentNode(), m_head->element());
+ m_openElements.pushHTMLHeadElement(m_head);
}
void HTMLConstructionSite::insertHTMLBodyElement(AtomicHTMLToken* token)
@@ -476,7 +467,10 @@ void HTMLConstructionSite::findFosterSite(HTMLConstructionSiteTask& task)
HTMLElementStack::ElementRecord* lastTableElementRecord = m_openElements.topmost(tableTag.localName());
if (lastTableElementRecord) {
Element* lastTableElement = lastTableElementRecord->element();
- if (ContainerNode* parent = lastTableElement->parentNode()) {
+ ContainerNode* parent = lastTableElement->parentNode();
+ // When parsing HTML fragments, we skip step 4.2 ("Let root be a new html element with no attributes") for efficiency,
+ // and instead use the DocumentFragment as a root node. So we must treat the root node (DocumentFragment) as if it is a html element here.
+ if (parent && (parent->isElementNode() || (m_isParsingFragment && parent == m_openElements.rootNode()))) {
task.parent = parent;
task.nextChild = lastTableElement;
return;
@@ -492,7 +486,7 @@ bool HTMLConstructionSite::shouldFosterParent() const
{
return m_redirectAttachToFosterParent
&& currentStackItem()->isElementNode()
- && causesFosterParenting(currentStackItem());
+ && currentStackItem()->causesFosterParenting();
}
void HTMLConstructionSite::fosterParent(PassRefPtr<Node> node)
diff --git a/Source/WebCore/html/parser/HTMLConstructionSite.h b/Source/WebCore/html/parser/HTMLConstructionSite.h
index 656e7987b..60572bdd8 100644
--- a/Source/WebCore/html/parser/HTMLConstructionSite.h
+++ b/Source/WebCore/html/parser/HTMLConstructionSite.h
@@ -97,7 +97,6 @@ public:
void insertHTMLHtmlStartTagInBody(AtomicHTMLToken*);
void insertHTMLBodyStartTagInBody(AtomicHTMLToken*);
- PassRefPtr<Element> createHTMLElement(AtomicHTMLToken*);
PassRefPtr<HTMLStackItem> createElementFromSavedToken(HTMLStackItem*);
bool shouldFosterParent() const;
@@ -114,12 +113,13 @@ public:
Element* currentElement() const { return m_openElements.top(); }
ContainerNode* currentNode() const { return m_openElements.topNode(); }
HTMLStackItem* currentStackItem() const { return m_openElements.topStackItem(); }
- Element* oneBelowTop() const { return m_openElements.oneBelowTop(); }
+ HTMLStackItem* oneBelowTop() const { return m_openElements.oneBelowTop(); }
HTMLElementStack* openElements() const { return &m_openElements; }
HTMLFormattingElementList* activeFormattingElements() const { return &m_activeFormattingElements; }
- Element* head() const { return m_head.get(); }
+ Element* head() const { return m_head->element(); }
+ HTMLStackItem* headStackItem() const { return m_head.get(); }
void setForm(HTMLFormElement*);
HTMLFormElement* form() const { return m_form.get(); }
@@ -154,6 +154,7 @@ private:
void findFosterSite(HTMLConstructionSiteTask&);
+ PassRefPtr<Element> createHTMLElement(AtomicHTMLToken*);
PassRefPtr<Element> createElement(AtomicHTMLToken*, const AtomicString& namespaceURI);
void mergeAttributesFromTokenIntoElement(AtomicHTMLToken*, Element*);
@@ -166,7 +167,7 @@ private:
// and a Document in all other cases.
ContainerNode* m_attachmentRoot;
- RefPtr<Element> m_head;
+ RefPtr<HTMLStackItem> m_head;
RefPtr<HTMLFormElement> m_form;
mutable HTMLElementStack m_openElements;
mutable HTMLFormattingElementList m_activeFormattingElements;
diff --git a/Source/WebCore/html/parser/HTMLElementStack.cpp b/Source/WebCore/html/parser/HTMLElementStack.cpp
index df074ffd3..62ed6f4e3 100644
--- a/Source/WebCore/html/parser/HTMLElementStack.cpp
+++ b/Source/WebCore/html/parser/HTMLElementStack.cpp
@@ -210,13 +210,13 @@ void HTMLElementStack::popAll()
void HTMLElementStack::pop()
{
- ASSERT(!top()->hasTagName(HTMLNames::headTag));
+ ASSERT(!topStackItem()->hasTagName(HTMLNames::headTag));
popCommon();
}
void HTMLElementStack::popUntil(const AtomicString& tagName)
{
- while (!top()->hasLocalName(tagName)) {
+ while (!topStackItem()->hasLocalName(tagName)) {
// pop() will ASSERT at <body> if callers fail to check that there is an
// element with localName |tagName| on the stack of open elements.
pop();
@@ -314,7 +314,7 @@ void HTMLElementStack::pushRootNode(PassRefPtr<HTMLStackItem> rootItem)
void HTMLElementStack::pushHTMLHtmlElement(PassRefPtr<HTMLStackItem> item)
{
- ASSERT(item->element()->hasTagName(HTMLNames::htmlTag));
+ ASSERT(item->hasTagName(HTMLNames::htmlTag));
pushRootNodeCommon(item);
}
@@ -328,7 +328,7 @@ void HTMLElementStack::pushRootNodeCommon(PassRefPtr<HTMLStackItem> rootItem)
void HTMLElementStack::pushHTMLHeadElement(PassRefPtr<HTMLStackItem> item)
{
- ASSERT(item->element()->hasTagName(HTMLNames::headTag));
+ ASSERT(item->hasTagName(HTMLNames::headTag));
ASSERT(!m_headElement);
m_headElement = item->element();
pushCommon(item);
@@ -336,7 +336,7 @@ void HTMLElementStack::pushHTMLHeadElement(PassRefPtr<HTMLStackItem> item)
void HTMLElementStack::pushHTMLBodyElement(PassRefPtr<HTMLStackItem> item)
{
- ASSERT(item->element()->hasTagName(HTMLNames::bodyTag));
+ ASSERT(item->hasTagName(HTMLNames::bodyTag));
ASSERT(!m_bodyElement);
m_bodyElement = item->element();
pushCommon(item);
@@ -344,9 +344,9 @@ void HTMLElementStack::pushHTMLBodyElement(PassRefPtr<HTMLStackItem> item)
void HTMLElementStack::push(PassRefPtr<HTMLStackItem> item)
{
- ASSERT(!item->element()->hasTagName(HTMLNames::htmlTag));
- ASSERT(!item->element()->hasTagName(HTMLNames::headTag));
- ASSERT(!item->element()->hasTagName(HTMLNames::bodyTag));
+ ASSERT(!item->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!item->hasTagName(HTMLNames::headTag));
+ ASSERT(!item->hasTagName(HTMLNames::bodyTag));
ASSERT(m_rootNode);
pushCommon(item);
}
@@ -356,9 +356,9 @@ void HTMLElementStack::insertAbove(PassRefPtr<HTMLStackItem> item, ElementRecord
ASSERT(item);
ASSERT(recordBelow);
ASSERT(m_top);
- ASSERT(!item->element()->hasTagName(HTMLNames::htmlTag));
- ASSERT(!item->element()->hasTagName(HTMLNames::headTag));
- ASSERT(!item->element()->hasTagName(HTMLNames::bodyTag));
+ ASSERT(!item->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!item->hasTagName(HTMLNames::headTag));
+ ASSERT(!item->hasTagName(HTMLNames::bodyTag));
ASSERT(m_rootNode);
if (recordBelow == m_top) {
push(item);
@@ -383,21 +383,16 @@ HTMLElementStack::ElementRecord* HTMLElementStack::topRecord() const
return m_top.get();
}
-Element* HTMLElementStack::oneBelowTop() const
+HTMLStackItem* HTMLElementStack::oneBelowTop() const
{
// We should never call this if there are fewer than 2 elements on the stack.
ASSERT(m_top);
ASSERT(m_top->next());
if (m_top->next()->stackItem()->isElementNode())
- return m_top->next()->element();
+ return m_top->next()->stackItem().get();
return 0;
}
-Element* HTMLElementStack::bottom() const
-{
- return htmlElement();
-}
-
void HTMLElementStack::removeHTMLHeadElement(Element* element)
{
ASSERT(m_headElement == element);
@@ -576,9 +571,9 @@ void HTMLElementStack::pushCommon(PassRefPtr<HTMLStackItem> item)
void HTMLElementStack::popCommon()
{
- ASSERT(!top()->hasTagName(HTMLNames::htmlTag));
- ASSERT(!top()->hasTagName(HTMLNames::headTag) || !m_headElement);
- ASSERT(!top()->hasTagName(HTMLNames::bodyTag) || !m_bodyElement);
+ ASSERT(!topStackItem()->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!topStackItem()->hasTagName(HTMLNames::headTag) || !m_headElement);
+ ASSERT(!topStackItem()->hasTagName(HTMLNames::bodyTag) || !m_bodyElement);
top()->finishParsingChildren();
m_top = m_top->releaseNext();
diff --git a/Source/WebCore/html/parser/HTMLElementStack.h b/Source/WebCore/html/parser/HTMLElementStack.h
index f19bc3001..620c5a194 100644
--- a/Source/WebCore/html/parser/HTMLElementStack.h
+++ b/Source/WebCore/html/parser/HTMLElementStack.h
@@ -98,9 +98,8 @@ public:
return m_top->stackItem().get();
}
- Element* oneBelowTop() const;
+ HTMLStackItem* oneBelowTop() const;
ElementRecord* topRecord() const;
- Element* bottom() const;
ElementRecord* find(Element*) const;
ElementRecord* topmost(const AtomicString& tagName) const;
diff --git a/Source/WebCore/html/parser/HTMLEntityParser.cpp b/Source/WebCore/html/parser/HTMLEntityParser.cpp
index 442cedbc2..18718054b 100644
--- a/Source/WebCore/html/parser/HTMLEntityParser.cpp
+++ b/Source/WebCore/html/parser/HTMLEntityParser.cpp
@@ -87,7 +87,7 @@ public:
StringBuilder consumedCharacters;
HTMLEntitySearch entitySearch;
while (!source.isEmpty()) {
- cc = *source;
+ cc = source.currentChar();
entitySearch.advance(cc);
if (!entitySearch.isEntityPrefix())
break;
@@ -114,13 +114,13 @@ public:
const int length = entitySearch.mostRecentMatch()->length;
const UChar* reference = entitySearch.mostRecentMatch()->entity;
for (int i = 0; i < length; ++i) {
- cc = *source;
+ cc = source.currentChar();
ASSERT_UNUSED(reference, cc == *reference++);
consumedCharacters.append(cc);
source.advanceAndASSERT(cc);
ASSERT(!source.isEmpty());
}
- cc = *source;
+ cc = source.currentChar();
}
if (entitySearch.mostRecentMatch()->lastCharacter() == ';'
|| !additionalAllowedCharacter
diff --git a/Source/WebCore/html/parser/HTMLFormattingElementList.cpp b/Source/WebCore/html/parser/HTMLFormattingElementList.cpp
index 1a45fb469..e7dd0dae1 100644
--- a/Source/WebCore/html/parser/HTMLFormattingElementList.cpp
+++ b/Source/WebCore/html/parser/HTMLFormattingElementList.cpp
@@ -59,7 +59,7 @@ Element* HTMLFormattingElementList::closestElementInScopeWithName(const AtomicSt
const Entry& entry = m_entries[m_entries.size() - i];
if (entry.isMarker())
return 0;
- if (entry.element()->hasLocalName(targetName))
+ if (entry.stackItem()->hasLocalName(targetName))
return entry.element();
}
return 0;
diff --git a/Source/WebCore/html/parser/HTMLInputStream.h b/Source/WebCore/html/parser/HTMLInputStream.h
index da6932fd4..593290bcf 100644
--- a/Source/WebCore/html/parser/HTMLInputStream.h
+++ b/Source/WebCore/html/parser/HTMLInputStream.h
@@ -74,7 +74,7 @@ public:
{
// FIXME: This should use InputStreamPreprocessor::endOfFileMarker
// once InputStreamPreprocessor is split off into its own header.
- static const UChar endOfFileMarker = 0;
+ static const LChar endOfFileMarker = 0;
m_last->append(SegmentedString(String(&endOfFileMarker, 1)));
m_last->close();
}
diff --git a/Source/WebCore/html/parser/HTMLParserIdioms.cpp b/Source/WebCore/html/parser/HTMLParserIdioms.cpp
index c3becc360..f0eb0ebb7 100644
--- a/Source/WebCore/html/parser/HTMLParserIdioms.cpp
+++ b/Source/WebCore/html/parser/HTMLParserIdioms.cpp
@@ -34,13 +34,13 @@
namespace WebCore {
-String stripLeadingAndTrailingHTMLSpaces(const String& string)
+template <typename CharType>
+static String stripLeadingAndTrailingHTMLSpaces(String string, CharType characters, unsigned length)
{
- const UChar* characters = string.characters();
- unsigned length = string.length();
+ unsigned numLeadingSpaces = 0;
+ unsigned numTrailingSpaces = 0;
- unsigned numLeadingSpaces;
- for (numLeadingSpaces = 0; numLeadingSpaces < length; ++numLeadingSpaces) {
+ for (; numLeadingSpaces < length; ++numLeadingSpaces) {
if (isNotHTMLSpace(characters[numLeadingSpaces]))
break;
}
@@ -48,17 +48,32 @@ String stripLeadingAndTrailingHTMLSpaces(const String& string)
if (numLeadingSpaces == length)
return string.isNull() ? string : emptyAtom.string();
- unsigned numTrailingSpaces;
- for (numTrailingSpaces = 0; numTrailingSpaces < length; ++numTrailingSpaces) {
+ for (; numTrailingSpaces < length; ++numTrailingSpaces) {
if (isNotHTMLSpace(characters[length - numTrailingSpaces - 1]))
break;
}
ASSERT(numLeadingSpaces + numTrailingSpaces < length);
+ if (!(numLeadingSpaces | numTrailingSpaces))
+ return string;
+
return string.substring(numLeadingSpaces, length - (numLeadingSpaces + numTrailingSpaces));
}
+String stripLeadingAndTrailingHTMLSpaces(const String& string)
+{
+ unsigned length = string.length();
+
+ if (!length)
+ return string.isNull() ? string : emptyAtom.string();
+
+ if (string.is8Bit())
+ return stripLeadingAndTrailingHTMLSpaces(string, string.characters8(), length);
+
+ return stripLeadingAndTrailingHTMLSpaces(string, string.characters(), length);
+}
+
String serializeForNumberType(const Decimal& number)
{
if (number.isZero()) {
@@ -137,84 +152,6 @@ double parseToDoubleForNumberType(const String& string)
return parseToDoubleForNumberType(string, std::numeric_limits<double>::quiet_NaN());
}
-double parseToDoubleForNumberTypeWithDecimalPlaces(const String& string, unsigned *decimalPlaces, double fallbackValue)
-{
- if (decimalPlaces)
- *decimalPlaces = 0;
-
- double value = parseToDoubleForNumberType(string, std::numeric_limits<double>::quiet_NaN());
- if (!isfinite(value))
- return fallbackValue;
-
- if (!decimalPlaces)
- return value;
-
- size_t dotIndex = string.find('.');
- size_t eIndex = string.find('e');
- if (eIndex == notFound)
- eIndex = string.find('E');
-
- unsigned baseDecimalPlaces = 0;
- if (dotIndex != notFound) {
- if (eIndex == notFound)
- baseDecimalPlaces = string.length() - dotIndex - 1;
- else
- baseDecimalPlaces = eIndex - dotIndex - 1;
- }
-
- int exponent = 0;
- if (eIndex != notFound) {
- unsigned cursor = eIndex + 1, cursorSaved;
- int digit, exponentSign;
- int32_t exponent32;
- size_t length = string.length();
-
- // Not using String.toInt() in order to perform the same computation as dtoa() does.
- exponentSign = 0;
- switch (digit = string[cursor]) {
- case '-':
- exponentSign = 1;
- case '+':
- digit = string[++cursor];
- }
- if (digit >= '0' && digit <= '9') {
- while (cursor < length && digit == '0')
- digit = string[++cursor];
- if (digit > '0' && digit <= '9') {
- exponent32 = digit - '0';
- cursorSaved = cursor;
- while (cursor < length && (digit = string[++cursor]) >= '0' && digit <= '9')
- exponent32 = (10 * exponent32) + digit - '0';
- if (cursor - cursorSaved > 8 || exponent32 > 19999)
- /* Avoid confusion from exponents
- * so large that e might overflow.
- */
- exponent = 19999; /* safe for 16 bit ints */
- else
- exponent = static_cast<int>(exponent32);
- if (exponentSign)
- exponent = -exponent;
- } else
- exponent = 0;
- }
- }
-
- int intDecimalPlaces = baseDecimalPlaces - exponent;
- if (intDecimalPlaces < 0)
- *decimalPlaces = 0;
- else if (intDecimalPlaces > 19999)
- *decimalPlaces = 19999;
- else
- *decimalPlaces = static_cast<unsigned>(intDecimalPlaces);
-
- return value;
-}
-
-double parseToDoubleForNumberTypeWithDecimalPlaces(const String& string, unsigned *decimalPlaces)
-{
- return parseToDoubleForNumberTypeWithDecimalPlaces(string, decimalPlaces, std::numeric_limits<double>::quiet_NaN());
-}
-
// http://www.whatwg.org/specs/web-apps/current-work/#rules-for-parsing-integers
bool parseHTMLInteger(const String& input, int& value)
{
diff --git a/Source/WebCore/html/parser/HTMLParserIdioms.h b/Source/WebCore/html/parser/HTMLParserIdioms.h
index 5f0186d44..577e02e85 100644
--- a/Source/WebCore/html/parser/HTMLParserIdioms.h
+++ b/Source/WebCore/html/parser/HTMLParserIdioms.h
@@ -51,8 +51,6 @@ Decimal parseToDecimalForNumberType(const String&);
Decimal parseToDecimalForNumberType(const String&, const Decimal& fallbackValue);
double parseToDoubleForNumberType(const String&);
double parseToDoubleForNumberType(const String&, double fallbackValue);
-double parseToDoubleForNumberTypeWithDecimalPlaces(const String&, unsigned*);
-double parseToDoubleForNumberTypeWithDecimalPlaces(const String&, unsigned*, double fallbackValue);
// http://www.whatwg.org/specs/web-apps/current-work/#rules-for-parsing-integers
bool parseHTMLInteger(const String&, int&);
diff --git a/Source/WebCore/html/parser/HTMLSourceTracker.cpp b/Source/WebCore/html/parser/HTMLSourceTracker.cpp
index e7c68764b..b042dd657 100644
--- a/Source/WebCore/html/parser/HTMLSourceTracker.cpp
+++ b/Source/WebCore/html/parser/HTMLSourceTracker.cpp
@@ -71,12 +71,12 @@ String HTMLSourceTracker::sourceForToken(const HTMLToken& token)
size_t i = 0;
for ( ; i < length && !m_previousSource.isEmpty(); ++i) {
- source.append(*m_previousSource);
+ source.append(m_previousSource.currentChar());
m_previousSource.advance();
}
for ( ; i < length; ++i) {
ASSERT(!m_currentSource.isEmpty());
- source.append(*m_currentSource);
+ source.append(m_currentSource.currentChar());
m_currentSource.advance();
}
diff --git a/Source/WebCore/html/parser/HTMLStackItem.h b/Source/WebCore/html/parser/HTMLStackItem.h
index 05b221042..371ac43f4 100644
--- a/Source/WebCore/html/parser/HTMLStackItem.h
+++ b/Source/WebCore/html/parser/HTMLStackItem.h
@@ -70,6 +70,15 @@ public:
bool hasLocalName(const AtomicString& name) const { return m_token->name() == name; }
bool hasTagName(const QualifiedName& name) const { return m_token->name() == name.localName() && m_namespaceURI == name.namespaceURI(); }
+ bool causesFosterParenting()
+ {
+ return hasTagName(HTMLNames::tableTag)
+ || hasTagName(HTMLNames::tbodyTag)
+ || hasTagName(HTMLNames::tfootTag)
+ || hasTagName(HTMLNames::theadTag)
+ || hasTagName(HTMLNames::trTag);
+ }
+
private:
HTMLStackItem(PassRefPtr<ContainerNode> node, ItemType type)
: m_node(node)
diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
index 3526acafc..a7f14519e 100644
--- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
+++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
@@ -710,14 +710,15 @@ static void adjustForeignAttributes(AtomicHTMLToken* token)
static PrefixedNameToQualifiedNameMap* map = 0;
if (!map) {
map = new PrefixedNameToQualifiedNameMap;
+
QualifiedName** attrs = XLinkNames::getXLinkAttrs();
- addNamesWithPrefix(map, "xlink", attrs, XLinkNames::XLinkAttrsCount);
+ addNamesWithPrefix(map, xlinkAtom, attrs, XLinkNames::XLinkAttrsCount);
attrs = XMLNames::getXMLAttrs();
- addNamesWithPrefix(map, "xml", attrs, XMLNames::XMLAttrsCount);
+ addNamesWithPrefix(map, xmlAtom, attrs, XMLNames::XMLAttrsCount);
- map->add("xmlns", XMLNSNames::xmlnsAttr);
- map->add("xmlns:xlink", QualifiedName("xmlns", "xlink", XMLNSNames::xmlnsNamespaceURI));
+ map->add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
+ map->add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom, XMLNSNames::xmlnsNamespaceURI));
}
for (unsigned i = 0; i < token->attributes().size(); ++i) {
@@ -1189,7 +1190,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
|| token->name() == titleTag) {
parseError(token);
ASSERT(m_tree.head());
- m_tree.openElements()->pushHTMLHeadElement(HTMLStackItem::create(m_tree.head(), token));
+ m_tree.openElements()->pushHTMLHeadElement(m_tree.headStackItem());
processStartTagForInHead(token);
m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
return;
@@ -1542,7 +1543,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
}
// 4.
ASSERT(furthestBlock->isAbove(formattingElementRecord));
- RefPtr<ContainerNode> commonAncestor = formattingElementRecord->next()->node();
+ RefPtr<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
// 5.
HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
// 6.
@@ -1584,17 +1585,12 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
lastNode = node;
}
// 7
- const AtomicString& commonAncestorTag = commonAncestor->localName();
if (ContainerNode* parent = lastNode->element()->parentNode())
parent->parserRemoveChild(lastNode->element());
- // FIXME: If this moves to HTMLConstructionSite, this check should use
- // causesFosterParenting(tagName) instead.
- if (commonAncestorTag == tableTag
- || commonAncestorTag == trTag
- || isTableBodyContextTag(commonAncestorTag))
+ if (commonAncestor->causesFosterParenting())
m_tree.fosterParent(lastNode->element());
else {
- commonAncestor->parserAddChild(lastNode->element());
+ commonAncestor->node()->parserAddChild(lastNode->element());
ASSERT(lastNode->stackItem()->isElementNode());
ASSERT(lastNode->element()->parentNode());
if (lastNode->element()->parentNode()->attached() && !lastNode->element()->attached())
diff --git a/Source/WebCore/html/shadow/CalendarPickerElement.cpp b/Source/WebCore/html/shadow/CalendarPickerElement.cpp
index b7ea32f28..e70151df6 100644
--- a/Source/WebCore/html/shadow/CalendarPickerElement.cpp
+++ b/Source/WebCore/html/shadow/CalendarPickerElement.cpp
@@ -104,6 +104,15 @@ void CalendarPickerElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool CalendarPickerElement::willRespondToMouseClickEvents()
+{
+ const HTMLInputElement* input = hostInput();
+ if (renderer() && !input->readOnly() && !input->disabled())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseClickEvents();
+}
+
void CalendarPickerElement::openPopup()
{
if (m_popup)
@@ -139,7 +148,7 @@ void CalendarPickerElement::detach()
IntSize CalendarPickerElement::contentSize()
{
- return IntSize(100, 100);
+ return IntSize(0, 0);
}
void CalendarPickerElement::writeDocument(DocumentWriter& writer)
diff --git a/Source/WebCore/html/shadow/CalendarPickerElement.h b/Source/WebCore/html/shadow/CalendarPickerElement.h
index e6f6a4d1d..cbf213fc5 100644
--- a/Source/WebCore/html/shadow/CalendarPickerElement.h
+++ b/Source/WebCore/html/shadow/CalendarPickerElement.h
@@ -46,6 +46,7 @@ public:
virtual ~CalendarPickerElement();
void openPopup();
void closePopup();
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
private:
CalendarPickerElement(Document*);
diff --git a/Source/WebCore/html/shadow/ContentDistributor.cpp b/Source/WebCore/html/shadow/ContentDistributor.cpp
index b3fdd32ad..324a5d0ed 100644
--- a/Source/WebCore/html/shadow/ContentDistributor.cpp
+++ b/Source/WebCore/html/shadow/ContentDistributor.cpp
@@ -49,7 +49,6 @@ InsertionPoint* ContentDistributor::findInsertionPointFor(const Node* key) const
return m_nodeToInsertionPoint.get(key);
}
-
void ContentDistributor::distribute(Element* host)
{
ASSERT(needsDistribution());
diff --git a/Source/WebCore/html/shadow/ContentDistributor.h b/Source/WebCore/html/shadow/ContentDistributor.h
index 3077cff41..214e54fce 100644
--- a/Source/WebCore/html/shadow/ContentDistributor.h
+++ b/Source/WebCore/html/shadow/ContentDistributor.h
@@ -60,6 +60,8 @@ public:
InsertionPoint* findInsertionPointFor(const Node* key) const;
+ void setValidity(Validity validity) { m_validity = validity; }
+
void distribute(Element* host);
bool invalidate(Element* host);
void finishInivalidation();
diff --git a/Source/WebCore/html/shadow/DateTimeEditElement.cpp b/Source/WebCore/html/shadow/DateTimeEditElement.cpp
new file mode 100644
index 000000000..0ed1dacc3
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeEditElement.cpp
@@ -0,0 +1,472 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeEditElement.h"
+
+#include "DateComponents.h"
+#include "DateTimeFieldElements.h"
+#include "DateTimeFormat.h"
+#include "DateTimeSymbolicFieldElement.h"
+#include "EventHandler.h"
+#include "HTMLNames.h"
+#include "KeyboardEvent.h"
+#include "LocalizedDate.h"
+#include "LocalizedNumber.h"
+#include "MouseEvent.h"
+#include "StepRange.h"
+#include "Text.h"
+#include <wtf/DateMath.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+class DateTimeEditBuilder : private DateTimeFormat::TokenHandler {
+ WTF_MAKE_NONCOPYABLE(DateTimeEditBuilder);
+
+public:
+ DateTimeEditBuilder(DateTimeEditElement&, const StepRange&);
+
+ bool build(const String&);
+ bool needSecondField() const;
+
+private:
+ bool needMillisecondField() const;
+ bool needMinuteField() const;
+ bool shouldMillisecondFieldReadOnly() const;
+ bool shouldMinuteFieldReadOnly() const;
+ bool shouldSecondFieldReadOnly() const;
+
+ // DateTimeFormat::TokenHandler functions.
+ virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL;
+ virtual void visitLiteral(const String&) OVERRIDE FINAL;
+
+ DateTimeEditElement& m_editElement;
+ const StepRange& m_stepRange;
+};
+
+DateTimeEditBuilder::DateTimeEditBuilder(DateTimeEditElement& elemnt, const StepRange& stepRange)
+ : m_editElement(elemnt)
+ , m_stepRange(stepRange)
+{
+}
+
+bool DateTimeEditBuilder::build(const String& formatString)
+{
+ m_editElement.resetLayout();
+ return DateTimeFormat::parse(formatString, *this);
+}
+
+bool DateTimeEditBuilder::needMillisecondField() const
+{
+ return !m_stepRange.minimum().remainder(static_cast<int>(msPerSecond)).isZero()
+ || !m_stepRange.step().remainder(static_cast<int>(msPerSecond)).isZero();
+}
+
+bool DateTimeEditBuilder::needMinuteField() const
+{
+ return !m_stepRange.minimum().remainder(static_cast<int>(msPerHour)).isZero()
+ || !m_stepRange.step().remainder(static_cast<int>(msPerHour)).isZero();
+}
+
+bool DateTimeEditBuilder::needSecondField() const
+{
+ return !m_stepRange.minimum().remainder(static_cast<int>(msPerMinute)).isZero()
+ || !m_stepRange.step().remainder(static_cast<int>(msPerMinute)).isZero();
+}
+
+void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int)
+{
+ Document* const document = m_editElement.document();
+
+ switch (fieldType) {
+ case DateTimeFormat::FieldTypeHour11:
+ m_editElement.addField(DateTimeHourFieldElement::create(document, m_editElement, 0, 11));
+ return;
+
+ case DateTimeFormat::FieldTypeHour12:
+ m_editElement.addField(DateTimeHourFieldElement::create(document, m_editElement, 1, 12));
+ return;
+
+ case DateTimeFormat::FieldTypeHour23:
+ m_editElement.addField(DateTimeHourFieldElement::create(document, m_editElement, 0, 23));
+ return;
+
+ case DateTimeFormat::FieldTypeHour24:
+ m_editElement.addField(DateTimeHourFieldElement::create(document, m_editElement, 1, 24));
+ return;
+
+ case DateTimeFormat::FieldTypeMinute: {
+ RefPtr<DateTimeNumericFieldElement> field = DateTimeMinuteFieldElement::create(document, m_editElement);
+ m_editElement.addField(field);
+ if (shouldMinuteFieldReadOnly())
+ field->setReadOnly();
+ return;
+ }
+
+ case DateTimeFormat::FieldTypePeriod:
+ m_editElement.addField(DateTimeAMPMFieldElement::create(document, m_editElement, timeAMPMLabels()));
+ return;
+
+ case DateTimeFormat::FieldTypeSecond: {
+ RefPtr<DateTimeSecondFieldElement> field = DateTimeSecondFieldElement::create(document, m_editElement);
+ m_editElement.addField(field);
+ if (shouldSecondFieldReadOnly())
+ field->setReadOnly();
+
+ if (needMillisecondField()) {
+ visitLiteral(localizedDecimalSeparator());
+ visitField(DateTimeFormat::FieldTypeFractionalSecond, 3);
+ }
+ return;
+ }
+
+ case DateTimeFormat::FieldTypeFractionalSecond: {
+ RefPtr<DateTimeMillisecondFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement);
+ m_editElement.addField(field);
+ if (shouldMillisecondFieldReadOnly())
+ field->setReadOnly();
+ return;
+ }
+
+ default:
+ return;
+ }
+}
+
+bool DateTimeEditBuilder::shouldMillisecondFieldReadOnly() const
+{
+ return m_stepRange.step().remainder(static_cast<int>(msPerSecond)).isZero();
+}
+
+bool DateTimeEditBuilder::shouldMinuteFieldReadOnly() const
+{
+ return m_stepRange.step().remainder(static_cast<int>(msPerHour)).isZero();
+}
+
+bool DateTimeEditBuilder::shouldSecondFieldReadOnly() const
+{
+ return m_stepRange.step().remainder(static_cast<int>(msPerMinute)).isZero();
+}
+
+void DateTimeEditBuilder::visitLiteral(const String& text)
+{
+ ASSERT(text.length());
+ m_editElement.appendChild(Text::create(m_editElement.document(), text));
+}
+
+// ----------------------------
+
+DateTimeEditElement::EditControlOwner::~EditControlOwner()
+{
+}
+
+DateTimeEditElement::DateTimeEditElement(Document* document, EditControlOwner& editControlOwner)
+ : HTMLDivElement(divTag, document)
+ , m_editControlOwner(&editControlOwner)
+ , m_spinButton(0)
+ , m_focusFieldIndex(invalidFieldIndex)
+{
+ DEFINE_STATIC_LOCAL(AtomicString, dateTimeEditPseudoId, ("-webkit-datetime-edit"));
+ setShadowPseudoId(dateTimeEditPseudoId);
+}
+
+DateTimeEditElement::~DateTimeEditElement()
+{
+ for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
+ m_fields[fieldIndex]->removeEventHandler();
+
+ if (m_spinButton)
+ m_spinButton->removeStepActionHandler();
+}
+
+void DateTimeEditElement::addField(PassRefPtr<DateTimeFieldElement> field)
+{
+ if (m_fields.size() == m_fields.capacity())
+ return;
+ m_fields.append(field.get());
+ appendChild(field);
+}
+
+PassRefPtr<DateTimeEditElement> DateTimeEditElement::create(Document* document, EditControlOwner& editControlOwner, const StepRange& stepRange)
+{
+ RefPtr<DateTimeEditElement> container = adoptRef(new DateTimeEditElement(document, editControlOwner));
+ container->layout(stepRange);
+ return container.release();
+}
+
+void DateTimeEditElement::disabledStateChanged()
+{
+ updateUIState();
+}
+
+DateTimeFieldElement* DateTimeEditElement::fieldAt(size_t fieldIndex) const
+{
+ return fieldIndex < m_fields.size() ? m_fields[fieldIndex] : 0;
+}
+
+void DateTimeEditElement::focusFieldAt(size_t newFocusFieldIndex)
+{
+ if (m_focusFieldIndex == newFocusFieldIndex)
+ return;
+
+ DateTimeFieldElement* const newFocusField = fieldAt(newFocusFieldIndex);
+ if (newFocusField && newFocusField->isReadOnly())
+ return;
+
+ DateTimeFieldElement* const currentFocusField = fieldAt(m_focusFieldIndex);
+
+ if (currentFocusField)
+ currentFocusField->setFocus(false);
+
+ if (!newFocusField) {
+ m_focusFieldIndex = invalidFieldIndex;
+ return;
+ }
+
+ m_focusFieldIndex = newFocusFieldIndex;
+ newFocusField->setFocus(true);
+}
+
+void DateTimeEditElement::handleKeyboardEvent(KeyboardEvent* keyboardEvent)
+{
+ if (isDisabled() || isReadOnly())
+ return;
+
+ if (!fieldAt(m_focusFieldIndex))
+ return;
+
+ if (keyboardEvent->type() != eventNames().keydownEvent)
+ return;
+
+ const String& keyIdentifier = keyboardEvent->keyIdentifier();
+
+ if (keyIdentifier == "Left") {
+ keyboardEvent->setDefaultHandled();
+ const size_t fieldIndex = previousFieldIndex();
+ if (fieldAt(fieldIndex))
+ focusFieldAt(fieldIndex);
+ return;
+ }
+
+ if (keyIdentifier == "Right") {
+ keyboardEvent->setDefaultHandled();
+ const size_t fieldIndex = nextFieldIndex();
+ if (fieldAt(fieldIndex))
+ focusFieldAt(fieldIndex);
+ return;
+ }
+
+ if (keyIdentifier == "U+0009") {
+ const size_t fieldIndex = keyboardEvent->getModifierState("Shift") ? previousFieldIndex() : nextFieldIndex();
+ if (fieldAt(fieldIndex)) {
+ keyboardEvent->setDefaultHandled();
+ focusFieldAt(fieldIndex);
+ return;
+ }
+ }
+}
+
+void DateTimeEditElement::fieldValueChanged()
+{
+ if (m_editControlOwner)
+ m_editControlOwner->editControlValueChanged();
+}
+
+void DateTimeEditElement::focusOnNextField()
+{
+ if (m_focusFieldIndex != invalidFieldIndex)
+ focusFieldAt(nextFieldIndex());
+}
+
+void DateTimeEditElement::handleMouseEvent(MouseEvent* mouseEvent)
+{
+ if (isDisabled() || isReadOnly())
+ return;
+
+ if (mouseEvent->type() != eventNames().mousedownEvent || mouseEvent->button() != LeftButton)
+ return;
+
+ Node* const relatedTarget = mouseEvent->target()->toNode();
+ for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
+ if (m_fields[fieldIndex] == relatedTarget) {
+ mouseEvent->setDefaultHandled();
+ focusFieldAt(fieldIndex);
+ if (m_editControlOwner)
+ m_editControlOwner->editControlMouseFocus();
+ break;
+ }
+ }
+}
+
+bool DateTimeEditElement::isDisabled() const
+{
+ return m_editControlOwner && m_editControlOwner->isEditControlOwnerDisabled();
+}
+
+bool DateTimeEditElement::isReadOnly() const
+{
+ return m_editControlOwner && m_editControlOwner->isEditControlOwnerReadOnly();
+}
+
+void DateTimeEditElement::layout(const StepRange& stepRange)
+{
+ DateTimeFieldElement* const focusField = fieldAt(m_focusFieldIndex);
+ focusFieldAt(invalidFieldIndex);
+
+ DateTimeEditBuilder builder(*this, stepRange);
+ const String dateTimeFormat = builder.needSecondField() ? localizedTimeFormatText() : localizedShortTimeFormatText();
+ if (!builder.build(dateTimeFormat) || m_fields.isEmpty())
+ builder.build(builder.needSecondField() ? "HH:mm:ss" : "HH:mm");
+
+ RefPtr<SpinButtonElement> spinButton = SpinButtonElement::create(document(), *this);
+ m_spinButton = spinButton.get();
+ appendChild(spinButton);
+
+ if (focusField) {
+ for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
+ if (focusField == m_fields[fieldIndex]) {
+ focusFieldAt(fieldIndex);
+ break;
+ }
+ }
+ }
+}
+
+size_t DateTimeEditElement::nextFieldIndex() const
+{
+ ASSERT(m_focusFieldIndex != invalidFieldIndex);
+ for (size_t fieldIndex = m_focusFieldIndex + 1; fieldIndex < m_fields.size(); ++fieldIndex) {
+ if (!m_fields[fieldIndex]->isReadOnly())
+ return fieldIndex;
+ }
+ return m_fields.size();
+}
+
+size_t DateTimeEditElement::previousFieldIndex() const
+{
+ ASSERT(m_focusFieldIndex != invalidFieldIndex);
+ size_t fieldIndex = m_focusFieldIndex;
+ while (fieldIndex > 0) {
+ --fieldIndex;
+ if (!m_fields[fieldIndex]->isReadOnly())
+ return fieldIndex;
+ }
+ return invalidFieldIndex;
+}
+
+void DateTimeEditElement::readOnlyStateChanged()
+{
+ updateUIState();
+}
+
+void DateTimeEditElement::resetLayout()
+{
+ m_fields.shrink(0);
+ m_spinButton = 0;
+ m_focusFieldIndex = invalidFieldIndex;
+ removeChildren();
+}
+
+void DateTimeEditElement::defaultEventHandler(Event* event)
+{
+ if (event->type() == eventNames().focusEvent) {
+ if (!isDisabled() && !isReadOnly() && m_focusFieldIndex == invalidFieldIndex)
+ focusFieldAt(0);
+ return;
+ }
+
+ if (event->type() == eventNames().blurEvent) {
+ focusFieldAt(invalidFieldIndex);
+ return;
+ }
+
+ if (event->isMouseEvent()) {
+ handleMouseEvent(static_cast<MouseEvent*>(event));
+ } else if (event->isKeyboardEvent())
+ handleKeyboardEvent(static_cast<KeyboardEvent*>(event));
+
+ if (event->defaultHandled())
+ return;
+
+ DateTimeFieldElement* const focusField = fieldAt(m_focusFieldIndex);
+ if (!focusField)
+ return;
+
+ focusField->defaultEventHandler(event);
+}
+
+void DateTimeEditElement::setValueAsDate(const DateComponents& date)
+{
+ for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
+ m_fields[fieldIndex]->setValueAsDate(date);
+}
+
+void DateTimeEditElement::setEmptyValue(const DateComponents& dateForReadOnlyField)
+{
+ for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
+ m_fields[fieldIndex]->setEmptyValue(dateForReadOnlyField, DateTimeFieldElement::DispatchNoEvent);
+}
+
+void DateTimeEditElement::spinButtonStepDown()
+{
+ if (DateTimeFieldElement* const focusField = fieldAt(m_focusFieldIndex))
+ focusField->stepDown();
+}
+
+void DateTimeEditElement::spinButtonStepUp()
+{
+ if (DateTimeFieldElement* const focusField = fieldAt(m_focusFieldIndex))
+ focusField->stepUp();
+}
+
+void DateTimeEditElement::updateUIState()
+{
+ if (isDisabled() || isReadOnly()) {
+ m_spinButton->releaseCapture();
+ focusFieldAt(invalidFieldIndex);
+ }
+}
+
+double DateTimeEditElement::valueAsDouble() const
+{
+ double value = 0;
+
+ for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
+ const DateTimeFieldElement* const field = m_fields[fieldIndex];
+ if (!field->hasValue())
+ return std::numeric_limits<double>::quiet_NaN();
+ value += field->valueAsDouble();
+ }
+
+ return value;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeEditElement.h b/Source/WebCore/html/shadow/DateTimeEditElement.h
new file mode 100644
index 000000000..462faa4a6
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeEditElement.h
@@ -0,0 +1,117 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DateTimeEditElement_h
+#define DateTimeEditElement_h
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeFieldElement.h"
+#include "TextControlInnerElements.h"
+
+namespace WebCore {
+
+class DateComponents;
+class DateTimeEditLayouter;
+class KeyboardEvent;
+class MouseEvent;
+class StepRange;
+
+// DateTimeEditElement class contains numberic field and symbolc field for
+// representing date and time, such as
+// - Year, Month, Day Of Month
+// - Hour, Minute, Second, Millisecond, AM/PM
+class DateTimeEditElement : public HTMLDivElement, public DateTimeFieldElement::FieldEventHandler, private SpinButtonElement::StepActionHandler {
+ WTF_MAKE_NONCOPYABLE(DateTimeEditElement);
+
+public:
+ // EditControlOwner implementer must call removeEditControlOwner when
+ // it doesn't handle event, e.g. at destruction.
+ class EditControlOwner {
+ public:
+ virtual ~EditControlOwner();
+ virtual void editControlMouseFocus() = 0;
+ virtual void editControlValueChanged() = 0;
+ virtual bool isEditControlOwnerDisabled() const = 0;
+ virtual bool isEditControlOwnerReadOnly() const = 0;
+ };
+
+ static PassRefPtr<DateTimeEditElement> create(Document*, EditControlOwner&, const StepRange&);
+
+ virtual ~DateTimeEditElement();
+ void addField(PassRefPtr<DateTimeFieldElement>);
+ virtual void defaultEventHandler(Event*) OVERRIDE;
+ void disabledStateChanged();
+ void layout(const StepRange&);
+ void readOnlyStateChanged();
+ void removeEditControlOwner() { m_editControlOwner = 0; }
+ void resetLayout();
+ void setEmptyValue(const DateComponents& dateForReadOnlyField);
+ void setValueAsDate(const DateComponents&);
+ double valueAsDouble() const;
+
+private:
+ static const size_t invalidFieldIndex = static_cast<size_t>(-1);
+
+ // Datetime can be represent at most five fields, such as
+ // 1. year
+ // 2. month
+ // 3. day-of-month
+ // 4. hour
+ // 5. minute
+ // 6. second
+ // 7. millisecond
+ // 8. AM/PM
+ static const int maximumNumberOfFields = 8;
+
+ DateTimeEditElement(Document*, EditControlOwner&);
+
+ DateTimeFieldElement* fieldAt(size_t) const;
+ void focusFieldAt(size_t);
+ void handleKeyboardEvent(KeyboardEvent*);
+ void handleMouseEvent(MouseEvent*);
+ bool isDisabled() const;
+ bool isReadOnly() const;
+ size_t nextFieldIndex() const;
+ size_t previousFieldIndex() const;
+ void updateUIState();
+
+ // DateTimeFieldElement::FieldEventHandler functions.
+ virtual void fieldValueChanged() OVERRIDE FINAL;
+ virtual void focusOnNextField() OVERRIDE FINAL;
+
+ // SpinButtonElement::StepActionHandler functions.
+ virtual void spinButtonStepDown() OVERRIDE FINAL;
+ virtual void spinButtonStepUp() OVERRIDE FINAL;
+
+ Vector<DateTimeFieldElement*, maximumNumberOfFields> m_fields;
+ EditControlOwner* m_editControlOwner;
+ SpinButtonElement* m_spinButton;
+ size_t m_focusFieldIndex;
+};
+
+} // namespace WebCore
+
+#endif
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeFieldElement.cpp b/Source/WebCore/html/shadow/DateTimeFieldElement.cpp
new file mode 100644
index 000000000..702e4900c
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeFieldElement.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeFieldElement.h"
+
+#include "DateComponents.h"
+#include "HTMLNames.h"
+#include "KeyboardEvent.h"
+#include "Text.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+DateTimeFieldElement::FieldEventHandler::~FieldEventHandler()
+{
+}
+
+DateTimeFieldElement::DateTimeFieldElement(Document* document, FieldEventHandler& fieldEventHandler)
+ : HTMLElement(spanTag, document)
+ , m_fieldEventHandler(&fieldEventHandler)
+{
+}
+
+void DateTimeFieldElement::defaultEventHandler(Event* event)
+{
+ if (event->isKeyboardEvent()) {
+ KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event);
+ handleKeyboardEvent(keyboardEvent);
+ if (keyboardEvent->defaultHandled())
+ return;
+ defaultKeyboardEventHandler(keyboardEvent);
+ if (keyboardEvent->defaultHandled())
+ return;
+ }
+
+ HTMLElement::defaultEventHandler(event);
+}
+
+void DateTimeFieldElement::defaultKeyboardEventHandler(KeyboardEvent* keyboardEvent)
+{
+ if (keyboardEvent->type() != eventNames().keydownEvent)
+ return;
+
+ const String& keyIdentifier = keyboardEvent->keyIdentifier();
+
+ if (keyIdentifier == "Down") {
+ keyboardEvent->setDefaultHandled();
+ stepDown();
+ return;
+ }
+
+ if (keyIdentifier == "Up") {
+ keyboardEvent->setDefaultHandled();
+ stepUp();
+ return;
+ }
+
+ if (keyIdentifier == "U+0008") {
+ keyboardEvent->setDefaultHandled();
+ setEmptyValue(DateComponents(), DispatchEvent);
+ return;
+ }
+}
+
+void DateTimeFieldElement::focusOnNextField()
+{
+ if (m_fieldEventHandler)
+ m_fieldEventHandler->focusOnNextField();
+}
+
+void DateTimeFieldElement::initialize(const AtomicString& shadowPseudoId)
+{
+ setShadowPseudoId(shadowPseudoId);
+ appendChild(Text::create(document(), visibleValue()));
+}
+
+bool DateTimeFieldElement::isReadOnly() const
+{
+ return fastHasAttribute(readonlyAttr);
+}
+
+void DateTimeFieldElement::setReadOnly()
+{
+ // Set HTML attribute readonly to change apperance.
+ setBooleanAttribute(readonlyAttr, true);
+ setNeedsStyleRecalc();
+}
+
+void DateTimeFieldElement::updateVisibleValue(EventBehavior eventBehavior)
+{
+ Text* const textNode = toText(firstChild());
+ const String newVisibleValue = visibleValue();
+ ASSERT(newVisibleValue.length() > 0);
+
+ if (textNode->wholeText() == newVisibleValue)
+ return;
+
+ textNode->replaceWholeText(newVisibleValue, ASSERT_NO_EXCEPTION);
+
+ if (eventBehavior == DispatchEvent && m_fieldEventHandler)
+ m_fieldEventHandler->fieldValueChanged();
+}
+
+double DateTimeFieldElement::valueAsDouble() const
+{
+ return hasValue() ? valueAsInteger() * unitInMillisecond() : std::numeric_limits<double>::quiet_NaN();
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeFieldElement.h b/Source/WebCore/html/shadow/DateTimeFieldElement.h
new file mode 100644
index 000000000..066b61ffa
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeFieldElement.h
@@ -0,0 +1,88 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DateTimeFieldElement_h
+#define DateTimeFieldElement_h
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+
+#include "HTMLDivElement.h"
+
+namespace WebCore {
+
+class DateComponents;
+
+// DateTimeFieldElement is base class of date time field element.
+class DateTimeFieldElement : public HTMLElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeFieldElement);
+
+public:
+ enum EventBehavior {
+ DispatchNoEvent,
+ DispatchEvent,
+ };
+
+ // FieldEventHandler implementer must call removeEventHandler when
+ // it doesn't handle event, e.g. at destruction.
+ class FieldEventHandler {
+ public:
+ virtual ~FieldEventHandler();
+ virtual void fieldValueChanged() = 0;
+ virtual void focusOnNextField() = 0;
+ };
+
+ virtual void defaultEventHandler(Event*) OVERRIDE;
+ virtual bool hasValue() const = 0;
+ bool isReadOnly() const;
+ void removeEventHandler() { m_fieldEventHandler = 0; }
+ void setReadOnly();
+ virtual void setEmptyValue(const DateComponents& dateForReadOnlyField, EventBehavior = DispatchNoEvent) = 0;
+ virtual void setValueAsDate(const DateComponents&) = 0;
+ virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) = 0;
+ virtual void stepDown() = 0;
+ virtual void stepUp() = 0;
+ virtual String value() const = 0;
+ double valueAsDouble() const;
+ virtual int valueAsInteger() const = 0;
+ virtual String visibleValue() const = 0;
+
+protected:
+ DateTimeFieldElement(Document*, FieldEventHandler&);
+ void focusOnNextField();
+ virtual void handleKeyboardEvent(KeyboardEvent*) = 0;
+ void initialize(const AtomicString&);
+ virtual double unitInMillisecond() const = 0;
+ void updateVisibleValue(EventBehavior);
+
+private:
+ void defaultKeyboardEventHandler(KeyboardEvent*);
+
+ FieldEventHandler* m_fieldEventHandler;
+};
+
+} // namespace WebCore
+
+#endif
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeFieldElements.cpp b/Source/WebCore/html/shadow/DateTimeFieldElements.cpp
new file mode 100644
index 000000000..1ff7fa5c7
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeFieldElements.cpp
@@ -0,0 +1,173 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeFieldElements.h"
+
+#include "DateComponents.h"
+#include <wtf/DateMath.h>
+
+namespace WebCore {
+
+DateTimeAMPMFieldElement::DateTimeAMPMFieldElement(Document* document, FieldEventHandler& fieldEventHandler, const Vector<String>& ampmLabels)
+ : DateTimeSymbolicFieldElement(document, fieldEventHandler, ampmLabels)
+{
+}
+
+PassRefPtr<DateTimeAMPMFieldElement> DateTimeAMPMFieldElement::create(Document* document, FieldEventHandler& fieldEventHandler, const Vector<String>& ampmLabels)
+{
+ DEFINE_STATIC_LOCAL(AtomicString, ampmPsuedoId, ("-webkit-datetime-edit-ampm-field"));
+ RefPtr<DateTimeAMPMFieldElement> field = adoptRef(new DateTimeAMPMFieldElement(document, fieldEventHandler, ampmLabels));
+ field->initialize(ampmPsuedoId);
+ return field.release();
+}
+
+void DateTimeAMPMFieldElement::setValueAsDate(const DateComponents& date)
+{
+ setValueAsInteger(date.hour() >= 12 ? 1 : 0);
+}
+
+double DateTimeAMPMFieldElement::unitInMillisecond() const
+{
+ return msPerHour * 12;
+}
+
+// ----------------------------
+
+DateTimeHourFieldElement::DateTimeHourFieldElement(Document* document, FieldEventHandler& fieldEventHandler, int minimum, int maximum)
+ : DateTimeNumericFieldElement(document, fieldEventHandler, minimum, maximum)
+ , m_alignment(maximum + maximum % 2)
+{
+ ASSERT((!minimum && (maximum == 11 || maximum == 23)) || (minimum == 1 && (maximum == 12 || maximum == 24)));
+}
+
+PassRefPtr<DateTimeHourFieldElement> DateTimeHourFieldElement::create(Document* document, FieldEventHandler& fieldEventHandler, int minimum, int maximum)
+{
+ DEFINE_STATIC_LOCAL(AtomicString, hourPsuedoId, ("-webkit-datetime-edit-hour-field"));
+ RefPtr<DateTimeHourFieldElement> field = adoptRef(new DateTimeHourFieldElement(document, fieldEventHandler, minimum, maximum));
+ field->initialize(hourPsuedoId);
+ return field.release();
+}
+
+void DateTimeHourFieldElement::setValueAsDate(const DateComponents& date)
+{
+ setValueAsInteger(date.hour());
+}
+
+void DateTimeHourFieldElement::setValueAsInteger(int valueAsHour23, EventBehavior eventBehavior)
+{
+ const int value = Range(0, 23).clampValue(valueAsHour23) % m_alignment;
+ DateTimeNumericFieldElement::setValueAsInteger(range().minimum && !value ? m_alignment : value, eventBehavior);
+}
+
+double DateTimeHourFieldElement::unitInMillisecond() const
+{
+ return msPerHour;
+}
+
+int DateTimeHourFieldElement::valueAsInteger() const
+{
+ return hasValue() ? DateTimeNumericFieldElement::valueAsInteger() % m_alignment : -1;
+}
+
+// ----------------------------
+
+DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement(Document* document, FieldEventHandler& fieldEventHandler)
+ : DateTimeNumericFieldElement(document, fieldEventHandler, 0, 999)
+{
+}
+
+PassRefPtr<DateTimeMillisecondFieldElement> DateTimeMillisecondFieldElement::create(Document* document, FieldEventHandler& fieldEventHandler)
+{
+ DEFINE_STATIC_LOCAL(AtomicString, millisecondPsuedoId, ("-webkit-datetime-edit-millisecond-field"));
+ RefPtr<DateTimeMillisecondFieldElement> field = adoptRef(new DateTimeMillisecondFieldElement(document, fieldEventHandler));
+ field->initialize(millisecondPsuedoId);
+ return field.release();
+}
+
+void DateTimeMillisecondFieldElement::setValueAsDate(const DateComponents& date)
+{
+ setValueAsInteger(date.millisecond());
+}
+
+double DateTimeMillisecondFieldElement::unitInMillisecond() const
+{
+ return 1;
+}
+
+// ----------------------------
+
+DateTimeMinuteFieldElement::DateTimeMinuteFieldElement(Document* document, FieldEventHandler& fieldEventHandler)
+ : DateTimeNumericFieldElement(document, fieldEventHandler, 0, 59)
+{
+}
+
+PassRefPtr<DateTimeMinuteFieldElement> DateTimeMinuteFieldElement::create(Document* document, FieldEventHandler& fieldEventHandler)
+{
+ DEFINE_STATIC_LOCAL(AtomicString, minutePsuedoId, ("-webkit-datetime-edit-minute-field"));
+ RefPtr<DateTimeMinuteFieldElement> field = adoptRef(new DateTimeMinuteFieldElement(document, fieldEventHandler));
+ field->initialize(minutePsuedoId);
+ return field.release();
+}
+
+void DateTimeMinuteFieldElement::setValueAsDate(const DateComponents& date)
+{
+ setValueAsInteger(date.minute());
+}
+
+double DateTimeMinuteFieldElement::unitInMillisecond() const
+{
+ return msPerMinute;
+}
+
+// ----------------------------
+
+DateTimeSecondFieldElement::DateTimeSecondFieldElement(Document* document, FieldEventHandler& fieldEventHandler)
+ : DateTimeNumericFieldElement(document, fieldEventHandler, 0, 59)
+{
+}
+
+PassRefPtr<DateTimeSecondFieldElement> DateTimeSecondFieldElement::create(Document* document, FieldEventHandler& fieldEventHandler)
+{
+ DEFINE_STATIC_LOCAL(AtomicString, secondPsuedoId, ("-webkit-datetime-edit-second-field"));
+ RefPtr<DateTimeSecondFieldElement> field = adoptRef(new DateTimeSecondFieldElement(document, fieldEventHandler));
+ field->initialize(secondPsuedoId);
+ return field.release();
+}
+
+void DateTimeSecondFieldElement::setValueAsDate(const DateComponents& date)
+{
+ setValueAsInteger(date.second());
+}
+
+double DateTimeSecondFieldElement::unitInMillisecond() const
+{
+ return msPerSecond;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeFieldElements.h b/Source/WebCore/html/shadow/DateTimeFieldElements.h
new file mode 100644
index 000000000..57bc1efa5
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeFieldElements.h
@@ -0,0 +1,119 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DateTimeFieldElements_h
+#define DateTimeFieldElements_h
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeNumericFieldElement.h"
+#include "DateTimeSymbolicFieldElement.h"
+
+namespace WebCore {
+
+class DateTimeAMPMFieldElement : public DateTimeSymbolicFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeAMPMFieldElement);
+
+public:
+ static PassRefPtr<DateTimeAMPMFieldElement> create(Document*, FieldEventHandler&, const Vector<String>&);
+
+private:
+ DateTimeAMPMFieldElement(Document*, FieldEventHandler&, const Vector<String>&);
+
+ // DateTimeFieldElement functions.
+ virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL;
+ virtual double unitInMillisecond() const OVERRIDE FINAL;
+};
+
+
+// DateTimeHourFieldElement is used for hour field of date time format
+// supporting following patterns:
+// - 0 to 11
+// - 1 to 12
+// - 0 to 23
+// - 1 to 24
+class DateTimeHourFieldElement : public DateTimeNumericFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeHourFieldElement);
+
+public:
+ static PassRefPtr<DateTimeHourFieldElement> create(Document*, FieldEventHandler&, int minimum, int maximum);
+
+private:
+ DateTimeHourFieldElement(Document*, FieldEventHandler&, int minimum, int maximum);
+
+ // DateTimeFieldElement functions.
+ virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL;
+ virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL;
+ virtual double unitInMillisecond() const OVERRIDE FINAL;
+ virtual int valueAsInteger() const OVERRIDE FINAL;
+
+ const int m_alignment;
+};
+
+class DateTimeMillisecondFieldElement : public DateTimeNumericFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeMillisecondFieldElement);
+
+public:
+ static PassRefPtr<DateTimeMillisecondFieldElement> create(Document*, FieldEventHandler&);
+
+private:
+ DateTimeMillisecondFieldElement(Document*, FieldEventHandler&);
+
+ // DateTimeFieldElement functions.
+ virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL;
+ virtual double unitInMillisecond() const OVERRIDE FINAL;
+};
+
+class DateTimeMinuteFieldElement : public DateTimeNumericFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeMinuteFieldElement);
+
+public:
+ static PassRefPtr<DateTimeMinuteFieldElement> create(Document*, FieldEventHandler&);
+
+private:
+ DateTimeMinuteFieldElement(Document*, FieldEventHandler&);
+
+ // DateTimeFieldElement functions.
+ virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL;
+ virtual double unitInMillisecond() const OVERRIDE FINAL;
+};
+
+class DateTimeSecondFieldElement : public DateTimeNumericFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeSecondFieldElement);
+
+public:
+ static PassRefPtr<DateTimeSecondFieldElement> create(Document*, FieldEventHandler&);
+
+private:
+ DateTimeSecondFieldElement(Document*, FieldEventHandler&);
+
+ // DateTimeFieldElement functions.
+ virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL;
+ virtual double unitInMillisecond() const OVERRIDE FINAL;
+};
+
+} // namespace WebCore
+
+#endif
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp b/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp
new file mode 100644
index 000000000..d522e1579
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeNumericFieldElement.cpp
@@ -0,0 +1,178 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeNumericFieldElement.h"
+
+#include "KeyboardEvent.h"
+#include "LocalizedNumber.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+static const DOMTimeStamp typeAheadTimeout = 1000;
+
+static size_t displaySizeOfNumber(int value)
+{
+ ASSERT(value >= 0);
+
+ if (!value)
+ return 1;
+
+ int numberOfDigits = 0;
+ while (value) {
+ value /= 10;
+ ++numberOfDigits;
+ }
+
+ return numberOfDigits;
+}
+
+DateTimeNumericFieldElement::Range::Range(int minimum, int maximum)
+ : maximum(maximum)
+ , minimum(minimum)
+{
+ ASSERT(minimum <= maximum);
+}
+
+int DateTimeNumericFieldElement::Range::clampValue(int value) const
+{
+ return std::min(std::max(value, minimum), maximum);
+}
+
+DateTimeNumericFieldElement::DateTimeNumericFieldElement(Document* document, FieldEventHandler& fieldEventHandler, int minimum, int maximum)
+ : DateTimeFieldElement(document, fieldEventHandler)
+ , m_lastDigitCharTime(0)
+ , m_range(minimum, maximum)
+ , m_value(0)
+ , m_hasValue(false)
+{
+}
+
+void DateTimeNumericFieldElement::handleKeyboardEvent(KeyboardEvent* keyboardEvent)
+{
+ if (isReadOnly())
+ return;
+
+ if (keyboardEvent->type() != eventNames().keypressEvent)
+ return;
+
+ UChar charCode = static_cast<UChar>(keyboardEvent->charCode());
+ if (charCode < ' ')
+ return;
+
+ DOMTimeStamp delta = keyboardEvent->timeStamp() - m_lastDigitCharTime;
+ m_lastDigitCharTime = 0;
+
+ String number = convertFromLocalizedNumber(String(&charCode, 1));
+ const int digit = number[0] - '0';
+ if (digit < 0 || digit > 9)
+ return;
+
+ keyboardEvent->setDefaultHandled();
+ setValueAsInteger(m_hasValue && delta < typeAheadTimeout ? m_value * 10 + digit : digit, DispatchEvent);
+ if (m_value * 10 > m_range.maximum)
+ focusOnNextField();
+ else
+ m_lastDigitCharTime = keyboardEvent->timeStamp();
+}
+
+bool DateTimeNumericFieldElement::hasValue() const
+{
+ return m_hasValue;
+}
+
+void DateTimeNumericFieldElement::setEmptyValue(const DateComponents& dateForReadOnlyField, EventBehavior eventBehavior)
+{
+ m_lastDigitCharTime = 0;
+
+ if (isReadOnly()) {
+ setValueAsDate(dateForReadOnlyField);
+ return;
+ }
+
+ m_hasValue = false;
+ m_value = 0;
+ updateVisibleValue(eventBehavior);
+}
+
+void DateTimeNumericFieldElement::setValueAsInteger(int value, EventBehavior eventBehavior)
+{
+ m_value = clampValue(value);
+ m_hasValue = true;
+ updateVisibleValue(eventBehavior);
+ m_lastDigitCharTime = 0;
+}
+
+void DateTimeNumericFieldElement::stepDown()
+{
+ if (m_hasValue)
+ setValueAsInteger(m_value == m_range.minimum ? m_range.maximum : clampValue(m_value - 1), DispatchEvent);
+ else
+ setValueAsInteger(m_range.maximum, DispatchEvent);
+}
+
+void DateTimeNumericFieldElement::stepUp()
+{
+ if (m_hasValue)
+ setValueAsInteger(m_value == m_range.maximum ? m_range.minimum : clampValue(m_value + 1), DispatchEvent);
+ else
+ setValueAsInteger(m_range.minimum, DispatchEvent);
+}
+
+String DateTimeNumericFieldElement::value() const
+{
+ if (!m_hasValue)
+ return emptyString();
+
+ if (m_range.maximum > 999)
+ return convertToLocalizedNumber(String::number(m_value));
+
+ if (m_range.maximum > 99)
+ return convertToLocalizedNumber(String::format("%03d", m_value));
+
+ return convertToLocalizedNumber(String::format("%02d", m_value));
+}
+
+int DateTimeNumericFieldElement::valueAsInteger() const
+{
+ return m_hasValue ? m_value : -1;
+}
+
+String DateTimeNumericFieldElement::visibleValue() const
+{
+ if (m_hasValue)
+ return value();
+
+ StringBuilder builder;
+ for (int numberOfDashs = std::max(displaySizeOfNumber(m_range.maximum), displaySizeOfNumber(m_range.minimum)); numberOfDashs; --numberOfDashs)
+ builder.append('-');
+ return builder.toString();
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h b/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h
new file mode 100644
index 000000000..7cb398250
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeNumericFieldElement.h
@@ -0,0 +1,81 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DateTimeNumericFieldElement_h
+#define DateTimeNumericFieldElement_h
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeFieldElement.h"
+
+namespace WebCore {
+
+// DateTimeNumericFieldElement represents numeric field of date time format,
+// such as:
+// - hour
+// - minute
+// - millisecond
+// - second
+// - year
+class DateTimeNumericFieldElement : public DateTimeFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeNumericFieldElement);
+
+protected:
+ struct Range {
+ Range(int minimum, int maximum);
+ int clampValue(int) const;
+
+ int maximum;
+ int minimum;
+ };
+
+ DateTimeNumericFieldElement(Document*, FieldEventHandler&, int minimum, int maximum);
+
+ int clampValue(int value) const { return m_range.clampValue(value); }
+ const Range& range() const { return m_range; }
+
+ // DateTimeFieldElement functions.
+ virtual bool hasValue() const OVERRIDE FINAL;
+ virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE;
+ virtual int valueAsInteger() const OVERRIDE;
+ virtual String visibleValue() const OVERRIDE FINAL;
+
+private:
+ // DateTimeFieldElement functions.
+ virtual void handleKeyboardEvent(KeyboardEvent*) OVERRIDE FINAL;
+ virtual void setEmptyValue(const DateComponents& dateForReadOnlyField, EventBehavior) OVERRIDE FINAL;
+ virtual void stepDown() OVERRIDE FINAL;
+ virtual void stepUp() OVERRIDE FINAL;
+ virtual String value() const OVERRIDE FINAL;
+
+ DOMTimeStamp m_lastDigitCharTime;
+ const Range m_range;
+ int m_value;
+ bool m_hasValue;
+};
+
+} // namespace WebCore
+
+#endif
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.cpp b/Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.cpp
new file mode 100644
index 000000000..08eb52229
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeSymbolicFieldElement.h"
+
+#include "KeyboardEvent.h"
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+DateTimeSymbolicFieldElement::DateTimeSymbolicFieldElement(Document* document, FieldEventHandler& fieldEventHandler, const Vector<String>& symbols)
+ : DateTimeFieldElement(document, fieldEventHandler)
+ , m_symbols(symbols)
+ , m_selectedIndex(-1)
+{
+ ASSERT(!symbols.isEmpty());
+}
+
+void DateTimeSymbolicFieldElement::handleKeyboardEvent(KeyboardEvent* keyboardEvent)
+{
+ if (keyboardEvent->type() != eventNames().keypressEvent)
+ return;
+
+ const UChar charCode = WTF::Unicode::toLower(keyboardEvent->charCode());
+ if (charCode < ' ')
+ return;
+
+ keyboardEvent->setDefaultHandled();
+ for (unsigned index = 0; index < m_symbols.size(); ++index) {
+ if (!m_symbols[index].isEmpty() && WTF::Unicode::toLower(m_symbols[index][0]) == charCode) {
+ setValueAsInteger(index, DispatchEvent);
+ return;
+ }
+ }
+}
+
+bool DateTimeSymbolicFieldElement::hasValue() const
+{
+ return m_selectedIndex >= 0;
+}
+
+void DateTimeSymbolicFieldElement::setEmptyValue(const DateComponents&, EventBehavior eventBehavior)
+{
+ m_selectedIndex = invalidIndex;
+ updateVisibleValue(eventBehavior);
+}
+
+void DateTimeSymbolicFieldElement::setValueAsInteger(int newSelectedIndex, EventBehavior eventBehavior)
+{
+ m_selectedIndex = std::max(0, std::min(newSelectedIndex, static_cast<int>(m_symbols.size() - 1)));
+ updateVisibleValue(eventBehavior);
+}
+
+void DateTimeSymbolicFieldElement::stepDown()
+{
+ const int size = m_symbols.size();
+ m_selectedIndex = hasValue() ? (m_selectedIndex + size - 1) % size : size - 1;
+ updateVisibleValue(DispatchEvent);
+}
+
+void DateTimeSymbolicFieldElement::stepUp()
+{
+ m_selectedIndex = hasValue() ? (m_selectedIndex + 1) % m_symbols.size() : 0;
+ updateVisibleValue(DispatchEvent);
+}
+
+String DateTimeSymbolicFieldElement::value() const
+{
+ return hasValue() ? m_symbols[m_selectedIndex] : emptyString();
+}
+
+int DateTimeSymbolicFieldElement::valueAsInteger() const
+{
+ return m_selectedIndex;
+}
+
+String DateTimeSymbolicFieldElement::visibleValue() const
+{
+ return hasValue() ? m_symbols[m_selectedIndex] : "--";
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.h b/Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.h
new file mode 100644
index 000000000..8329dd114
--- /dev/null
+++ b/Source/WebCore/html/shadow/DateTimeSymbolicFieldElement.h
@@ -0,0 +1,63 @@
+/*
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DateTimeSymbolicFieldElement_h
+#define DateTimeSymbolicFieldElement_h
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include "DateTimeFieldElement.h"
+
+namespace WebCore {
+
+// DateTimeSymbolicFieldElement represents non-numeric field of data time
+// format, such as: AM/PM, and month.
+class DateTimeSymbolicFieldElement : public DateTimeFieldElement {
+ WTF_MAKE_NONCOPYABLE(DateTimeSymbolicFieldElement);
+
+protected:
+ DateTimeSymbolicFieldElement(Document*, FieldEventHandler&, const Vector<String>&);
+ virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL;
+
+private:
+ static const int invalidIndex = -1;
+
+ // DateTimeFieldElement functions.
+ virtual void handleKeyboardEvent(KeyboardEvent*) OVERRIDE FINAL;
+ virtual bool hasValue() const OVERRIDE FINAL;
+ virtual void setEmptyValue(const DateComponents& dateForReadOnlyField, EventBehavior = DispatchNoEvent) OVERRIDE FINAL;
+ virtual void stepDown() OVERRIDE FINAL;
+ virtual void stepUp() OVERRIDE FINAL;
+ virtual String value() const OVERRIDE FINAL;
+ virtual int valueAsInteger() const OVERRIDE FINAL;
+ virtual String visibleValue() const OVERRIDE FINAL;
+
+ const Vector<String> m_symbols;
+ int m_selectedIndex;
+};
+
+} // namespace WebCore
+
+#endif
+#endif
diff --git a/Source/WebCore/html/shadow/InsertionPoint.cpp b/Source/WebCore/html/shadow/InsertionPoint.cpp
index fadbb457b..435796677 100644
--- a/Source/WebCore/html/shadow/InsertionPoint.cpp
+++ b/Source/WebCore/html/shadow/InsertionPoint.cpp
@@ -118,8 +118,10 @@ Node::InsertionNotificationRequest InsertionPoint::insertedInto(ContainerNode* i
{
HTMLElement::insertedInto(insertionPoint);
if (insertionPoint->inDocument()) {
- if (ShadowRoot* root = shadowRoot())
- root->owner()->invalidateDistribution(ElementShadow::InvalidateAndForceReattach);
+ if (ShadowRoot* root = shadowRoot()) {
+ root->owner()->setValidityUndetermined();
+ root->owner()->invalidateDistribution();
+ }
}
return InsertionDone;
diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp
index 2c4bd9e91..1b67afec3 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.cpp
+++ b/Source/WebCore/html/shadow/MediaControlElements.cpp
@@ -388,7 +388,6 @@ void MediaControlVolumeSliderContainerElement::defaultEventHandler(Event* event)
hide();
}
-
MediaControlElementType MediaControlVolumeSliderContainerElement::displayType() const
{
return MediaVolumeSliderContainer;
@@ -924,7 +923,15 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event)
m_controls->updateTimeDisplay();
}
-void MediaControlTimelineElement::setPosition(float currentTime)
+bool MediaControlTimelineElement::willRespondToMouseClickEvents()
+{
+ if (!attached())
+ return false;
+
+ return true;
+}
+
+void MediaControlTimelineElement::setPosition(float currentTime)
{
setValue(String::number(currentTime));
}
@@ -983,6 +990,22 @@ void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
mediaController()->setMuted(false);
}
+bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents()
+{
+ if (!attached())
+ return false;
+
+ return MediaControlInputElement::willRespondToMouseMoveEvents();
+}
+
+bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents()
+{
+ if (!attached())
+ return false;
+
+ return MediaControlInputElement::willRespondToMouseClickEvents();
+}
+
void MediaControlVolumeSliderElement::setVolume(float volume)
{
if (value().toFloat() != volume)
diff --git a/Source/WebCore/html/shadow/MediaControlElements.h b/Source/WebCore/html/shadow/MediaControlElements.h
index c1514e231..effdcee7f 100644
--- a/Source/WebCore/html/shadow/MediaControlElements.h
+++ b/Source/WebCore/html/shadow/MediaControlElements.h
@@ -116,6 +116,9 @@ public:
void makeOpaque();
void makeTransparent();
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+
private:
MediaControlPanelElement(Document*);
virtual MediaControlElementType displayType() const;
@@ -160,6 +163,8 @@ class MediaControlVolumeSliderContainerElement : public MediaControlElement {
public:
static PassRefPtr<MediaControlVolumeSliderContainerElement> create(Document*);
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+
private:
MediaControlVolumeSliderContainerElement(Document*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
@@ -218,11 +223,12 @@ class MediaControlMuteButtonElement : public MediaControlInputElement {
public:
void changedMute();
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+
protected:
MediaControlMuteButtonElement(Document*, MediaControlElementType);
virtual void defaultEventHandler(Event*);
-
private:
virtual void updateDisplayType();
};
@@ -233,6 +239,8 @@ class MediaControlPanelMuteButtonElement : public MediaControlMuteButtonElement
public:
static PassRefPtr<MediaControlPanelMuteButtonElement> create(Document*, MediaControls*);
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+
private:
MediaControlPanelMuteButtonElement(Document*, MediaControls*);
@@ -262,6 +270,7 @@ public:
static PassRefPtr<MediaControlPlayButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
virtual void updateDisplayType();
private:
@@ -289,6 +298,7 @@ private:
class MediaControlSeekButtonElement : public MediaControlInputElement {
public:
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
protected:
MediaControlSeekButtonElement(Document*, MediaControlElementType);
@@ -342,6 +352,7 @@ public:
static PassRefPtr<MediaControlRewindButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
private:
MediaControlRewindButtonElement(Document*);
@@ -356,6 +367,7 @@ public:
static PassRefPtr<MediaControlReturnToRealtimeButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
private:
MediaControlReturnToRealtimeButtonElement(Document*);
@@ -370,6 +382,7 @@ public:
static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
virtual void updateDisplayType();
private:
@@ -385,6 +398,7 @@ public:
static PassRefPtr<MediaControlTimelineElement> create(Document*, MediaControls*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
void setPosition(float);
void setDuration(float);
@@ -403,6 +417,8 @@ public:
static PassRefPtr<MediaControlVolumeSliderElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
void setVolume(float);
void setClearMutedOnUserInteraction(bool);
@@ -421,6 +437,7 @@ public:
static PassRefPtr<MediaControlFullscreenButtonElement> create(Document*, MediaControls*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
void setIsFullscreen(bool);
private:
@@ -448,7 +465,8 @@ public:
static PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
-
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+
private:
MediaControlFullscreenVolumeMinButtonElement(Document*);
@@ -462,7 +480,8 @@ public:
static PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
-
+ virtual bool willRespondToMouseClickEvents() OVERRIDE { return true; }
+
private:
MediaControlFullscreenVolumeMaxButtonElement(Document*);
diff --git a/Source/WebCore/html/shadow/MediaControlRootElement.h b/Source/WebCore/html/shadow/MediaControlRootElement.h
index f9f475c2e..5ce6ac7ea 100644
--- a/Source/WebCore/html/shadow/MediaControlRootElement.h
+++ b/Source/WebCore/html/shadow/MediaControlRootElement.h
@@ -114,6 +114,8 @@ public:
void bufferingProgressed();
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE { return true; }
+
private:
MediaControlRootElement(Document*);
diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.cpp b/Source/WebCore/html/shadow/ProgressShadowElement.cpp
index 800f22351..465d5ba8f 100644
--- a/Source/WebCore/html/shadow/ProgressShadowElement.cpp
+++ b/Source/WebCore/html/shadow/ProgressShadowElement.cpp
@@ -34,22 +34,20 @@
#if ENABLE(PROGRESS_ELEMENT)
#include "HTMLNames.h"
#include "HTMLProgressElement.h"
-#include "RenderObject.h"
+#include "RenderProgress.h"
namespace WebCore {
using namespace HTMLNames;
-ProgressShadowElement::ProgressShadowElement(Document* document)
+ProgressShadowElement::ProgressShadowElement(Document* document)
: HTMLDivElement(HTMLNames::divTag, document)
{
}
HTMLProgressElement* ProgressShadowElement::progressElement() const
{
- Element* element = shadowHost();
- ASSERT(!element || element->hasTagName(progressTag));
- return static_cast<HTMLProgressElement*>(element);
+ return toHTMLProgressElement(shadowHost());
}
bool ProgressShadowElement::rendererIsNeeded(const NodeRenderingContext& context)
@@ -58,6 +56,36 @@ bool ProgressShadowElement::rendererIsNeeded(const NodeRenderingContext& context
return progressRenderer && !progressRenderer->style()->hasAppearance() && HTMLDivElement::rendererIsNeeded(context);
}
+ProgressInnerElement::ProgressInnerElement(Document* document)
+ : ProgressShadowElement(document)
+{
+}
+
+PassRefPtr<ProgressInnerElement> ProgressInnerElement::create(Document* document)
+{
+ return adoptRef(new ProgressInnerElement(document));
+}
+
+const AtomicString& ProgressInnerElement::shadowPseudoId() const
+{
+ DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-progress-inner-element"));
+ return pseudId;
+}
+
+RenderObject* ProgressInnerElement::createRenderer(RenderArena* arena, RenderStyle*)
+{
+ return new (arena) RenderProgress(this);
+}
+
+bool ProgressInnerElement::rendererIsNeeded(const NodeRenderingContext& context)
+{
+ if (progressElement()->hasAuthorShadowRoot())
+ return HTMLDivElement::rendererIsNeeded(context);
+
+ RenderObject* progressRenderer = progressElement()->renderer();
+ return progressRenderer && !progressRenderer->style()->hasAppearance() && HTMLDivElement::rendererIsNeeded(context);
+}
+
const AtomicString& ProgressBarElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, pseudId, ("-webkit-progress-bar"));
diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.h b/Source/WebCore/html/shadow/ProgressShadowElement.h
index aff94fba3..4d03e43ab 100644
--- a/Source/WebCore/html/shadow/ProgressShadowElement.h
+++ b/Source/WebCore/html/shadow/ProgressShadowElement.h
@@ -45,7 +45,18 @@ public:
ProgressShadowElement(Document*);
HTMLProgressElement* progressElement() const;
+protected:
+ virtual bool rendererIsNeeded(const NodeRenderingContext&);
+};
+
+class ProgressInnerElement : public ProgressShadowElement {
+public:
+ ProgressInnerElement(Document*);
+
+ static PassRefPtr<ProgressInnerElement> create(Document*);
private:
+ virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
+ virtual const AtomicString& shadowPseudoId() const;
virtual bool rendererIsNeeded(const NodeRenderingContext&);
};
@@ -65,7 +76,6 @@ inline PassRefPtr<ProgressBarElement> ProgressBarElement::create(Document* docum
return adoptRef(new ProgressBarElement(document));
}
-
class ProgressValueElement : public ProgressShadowElement {
public:
ProgressValueElement(Document* document)
diff --git a/Source/WebCore/html/shadow/SliderThumbElement.cpp b/Source/WebCore/html/shadow/SliderThumbElement.cpp
index cccad81ef..baca86c7b 100644
--- a/Source/WebCore/html/shadow/SliderThumbElement.cpp
+++ b/Source/WebCore/html/shadow/SliderThumbElement.cpp
@@ -51,6 +51,8 @@ using namespace std;
namespace WebCore {
+using namespace HTMLNames;
+
inline static Decimal sliderPosition(HTMLInputElement* element)
{
const StepRange stepRange(element->createStepRange(RejectAny));
@@ -214,9 +216,14 @@ bool SliderThumbElement::isEnabledFormControl() const
return hostInput()->isEnabledFormControl();
}
-bool SliderThumbElement::isReadOnlyFormControl() const
+bool SliderThumbElement::shouldMatchReadOnlySelector() const
{
- return hostInput()->isReadOnlyFormControl();
+ return hostInput()->shouldMatchReadOnlySelector();
+}
+
+bool SliderThumbElement::shouldMatchReadWriteSelector() const
+{
+ return hostInput()->shouldMatchReadWriteSelector();
}
Node* SliderThumbElement::focusDelegate()
@@ -265,7 +272,21 @@ void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point)
const Decimal ratio = Decimal::fromDouble(static_cast<double>(position) / trackSize);
const Decimal fraction = isVertical || !renderBox()->style()->isLeftToRightDirection() ? Decimal(1) - ratio : ratio;
StepRange stepRange(input->createStepRange(RejectAny));
- const Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction));
+ Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction));
+
+#if ENABLE(DATALIST_ELEMENT)
+ const LayoutUnit snappingThreshold = renderer()->theme()->sliderTickSnappingThreshold();
+ if (snappingThreshold > 0) {
+ Decimal closest = input->findClosestTickMarkValue(value);
+ if (closest.isFinite()) {
+ double closestFraction = stepRange.proportionFromValue(closest).toDouble();
+ double closestRatio = isVertical || !renderBox()->style()->isLeftToRightDirection() ? 1.0 - closestFraction : closestFraction;
+ LayoutUnit closestPosition = trackSize * closestRatio;
+ if ((closestPosition - position).abs() <= snappingThreshold)
+ value = closest;
+ }
+ }
+#endif
// FIXME: This is no longer being set from renderer. Consider updating the method name.
input->setValueFromRenderer(serializeForNumberType(value));
@@ -303,7 +324,7 @@ void SliderThumbElement::defaultEventHandler(Event* event)
// FIXME: Should handle this readonly/disabled check in more general way.
// Missing this kind of check is likely to occur elsewhere if adding it in each shadow element.
HTMLInputElement* input = hostInput();
- if (!input || input->isReadOnlyFormControl() || !input->isEnabledFormControl()) {
+ if (!input || input->readOnly() || !input->isEnabledFormControl()) {
stopDragging();
HTMLDivElement::defaultEventHandler(event);
return;
@@ -331,6 +352,24 @@ void SliderThumbElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool SliderThumbElement::willRespondToMouseMoveEvents()
+{
+ const HTMLInputElement* input = hostInput();
+ if (input && !input->readOnly() && input->isEnabledFormControl() && m_inDragMode)
+ return true;
+
+ return HTMLDivElement::willRespondToMouseMoveEvents();
+}
+
+bool SliderThumbElement::willRespondToMouseClickEvents()
+{
+ const HTMLInputElement* input = hostInput();
+ if (input && !input->readOnly() && input->isEnabledFormControl())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseClickEvents();
+}
+
void SliderThumbElement::detach()
{
if (m_inDragMode) {
diff --git a/Source/WebCore/html/shadow/SliderThumbElement.h b/Source/WebCore/html/shadow/SliderThumbElement.h
index 36d64186f..04e41c7bf 100644
--- a/Source/WebCore/html/shadow/SliderThumbElement.h
+++ b/Source/WebCore/html/shadow/SliderThumbElement.h
@@ -54,6 +54,8 @@ public:
void dragFrom(const LayoutPoint&);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
virtual void detach();
virtual const AtomicString& shadowPseudoId() const;
HTMLInputElement* hostInput() const;
@@ -64,7 +66,8 @@ private:
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
virtual bool isEnabledFormControl() const;
- virtual bool isReadOnlyFormControl() const;
+ virtual bool shouldMatchReadOnlySelector() const OVERRIDE;
+ virtual bool shouldMatchReadWriteSelector() const OVERRIDE;
virtual Node* focusDelegate();
void startDragging();
void stopDragging();
diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.cpp b/Source/WebCore/html/shadow/TextControlInnerElements.cpp
index e3097bb5e..e06d56f2f 100644
--- a/Source/WebCore/html/shadow/TextControlInnerElements.cpp
+++ b/Source/WebCore/html/shadow/TextControlInnerElements.cpp
@@ -165,6 +165,11 @@ void SearchFieldResultsButtonElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool SearchFieldResultsButtonElement::willRespondToMouseClickEvents()
+{
+ return true;
+}
+
// ----------------------------
inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document* document)
@@ -198,7 +203,7 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
{
// If the element is visible, on mouseup, clear the value, and set selection
RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowHost()));
- if (input->disabled() || input->isReadOnlyFormControl()) {
+ if (input->disabled() || input->readOnly()) {
if (!event->defaultHandled())
HTMLDivElement::defaultEventHandler(event);
return;
@@ -234,6 +239,15 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
+{
+ const HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost());
+ if (!input->disabled() && !input->readOnly())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseClickEvents();
+}
+
// ----------------------------
inline SpinButtonElement::SpinButtonElement(Document* document, StepActionHandler& stepActionHandler)
@@ -279,7 +293,7 @@ void SpinButtonElement::defaultEventHandler(Event* event)
}
RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowHost()));
- if (input->disabled() || input->isReadOnlyFormControl()) {
+ if (input->disabled() || input->readOnly()) {
if (!event->defaultHandled())
HTMLDivElement::defaultEventHandler(event);
return;
@@ -328,6 +342,24 @@ void SpinButtonElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool SpinButtonElement::willRespondToMouseMoveEvents()
+{
+ const HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost());
+ if (renderBox() && !input->disabled() && !input->readOnly())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseMoveEvents();
+}
+
+bool SpinButtonElement::willRespondToMouseClickEvents()
+{
+ const HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost());
+ if (renderBox() && !input->disabled() && !input->readOnly())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseClickEvents();
+}
+
void SpinButtonElement::doStepAction(int amount)
{
if (!m_stepActionHandler)
@@ -350,6 +382,16 @@ void SpinButtonElement::releaseCapture()
}
}
+bool SpinButtonElement::shouldMatchReadOnlySelector() const
+{
+ return shadowHost()->shouldMatchReadOnlySelector();
+}
+
+bool SpinButtonElement::shouldMatchReadWriteSelector() const
+{
+ return shadowHost()->shouldMatchReadWriteSelector();
+}
+
void SpinButtonElement::startRepeatingTimer()
{
m_pressStartingState = m_upDownState;
@@ -365,7 +407,7 @@ void SpinButtonElement::stopRepeatingTimer()
void SpinButtonElement::step(int amount)
{
HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost());
- if (input->disabled() || input->isReadOnlyFormControl())
+ if (input->disabled() || input->readOnly())
return;
// On Mac OS, NSStepper updates the value for the button under the mouse
// cursor regardless of the button pressed at the beginning. So the
@@ -431,7 +473,7 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event)
// here, we take a temporary reference.
RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowHost()));
- if (input->disabled() || input->isReadOnlyFormControl()) {
+ if (input->disabled() || input->readOnly()) {
if (!event->defaultHandled())
HTMLDivElement::defaultEventHandler(event);
return;
@@ -479,6 +521,15 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool InputFieldSpeechButtonElement::willRespondToMouseClickEvents()
+{
+ const HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowHost());
+ if (!input->disabled() && !input->readOnly())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseClickEvents();
+}
+
void InputFieldSpeechButtonElement::setState(SpeechInputState state)
{
if (m_state != state) {
@@ -510,7 +561,7 @@ void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputR
// 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(static_cast<HTMLInputElement*>(shadowHost()));
- if (input->disabled() || input->isReadOnlyFormControl())
+ if (input->disabled() || input->readOnly())
return;
RefPtr<InputFieldSpeechButtonElement> holdRefButton(this);
diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.h b/Source/WebCore/html/shadow/TextControlInnerElements.h
index 33d5890a9..6336dcb63 100644
--- a/Source/WebCore/html/shadow/TextControlInnerElements.h
+++ b/Source/WebCore/html/shadow/TextControlInnerElements.h
@@ -66,6 +66,7 @@ public:
static PassRefPtr<SearchFieldResultsButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
private:
SearchFieldResultsButtonElement(Document*);
@@ -78,6 +79,7 @@ public:
static PassRefPtr<SearchFieldCancelButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
private:
SearchFieldCancelButtonElement(Document*);
@@ -113,6 +115,9 @@ public:
void step(int amount);
+ virtual bool willRespondToMouseMoveEvents() OVERRIDE;
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
private:
SpinButtonElement(Document*, StepActionHandler&);
@@ -120,7 +125,8 @@ private:
virtual void detach();
virtual bool isSpinButtonElement() const { return true; }
virtual bool isEnabledFormControl() const { return shadowHost()->isEnabledFormControl(); }
- virtual bool isReadOnlyFormControl() const { return shadowHost()->isReadOnlyFormControl(); }
+ virtual bool shouldMatchReadOnlySelector() const OVERRIDE;
+ virtual bool shouldMatchReadWriteSelector() const OVERRIDE;
virtual void defaultEventHandler(Event*);
void doStepAction(int);
void startRepeatingTimer();
@@ -153,6 +159,7 @@ public:
virtual void detach();
virtual void defaultEventHandler(Event*);
+ virtual bool willRespondToMouseClickEvents();
virtual bool isInputFieldSpeechButtonElement() const { return true; }
SpeechInputState state() const { return m_state; }
void startSpeechInput();
diff --git a/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp b/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp
index 09cc7b1d4..689aa0ad2 100644
--- a/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp
+++ b/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp
@@ -198,4 +198,13 @@ void TextFieldDecorationElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+bool TextFieldDecorationElement::willRespondToMouseClickEvents()
+{
+ const HTMLInputElement* input = hostInput();
+ if (!input->disabled() && !input->readOnly())
+ return true;
+
+ return HTMLDivElement::willRespondToMouseClickEvents();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/html/shadow/TextFieldDecorationElement.h b/Source/WebCore/html/shadow/TextFieldDecorationElement.h
index f2c827a45..2c8d822b3 100644
--- a/Source/WebCore/html/shadow/TextFieldDecorationElement.h
+++ b/Source/WebCore/html/shadow/TextFieldDecorationElement.h
@@ -71,6 +71,8 @@ public:
TextFieldDecorator* textFieldDecorator() { return m_textFieldDecorator; }
void decorate(HTMLInputElement*, bool visible);
+ virtual bool willRespondToMouseClickEvents() OVERRIDE;
+
private:
TextFieldDecorationElement(Document*, TextFieldDecorator*);
virtual bool isTextFieldDecoration() const OVERRIDE;
diff --git a/Source/WebCore/html/track/TextTrack.cpp b/Source/WebCore/html/track/TextTrack.cpp
index a6e7f844c..75d763cdd 100644
--- a/Source/WebCore/html/track/TextTrack.cpp
+++ b/Source/WebCore/html/track/TextTrack.cpp
@@ -198,6 +198,10 @@ void TextTrack::addCue(PassRefPtr<TextTrackCue> prpCue, ExceptionCode& ec)
RefPtr<TextTrackCue> cue = prpCue;
+ // TODO(93143): Add spec-compliant behavior for negative time values.
+ if (cue->startTime() < 0 || cue->endTime() < 0)
+ return;
+
// 4.8.10.12.4 Text track API
// The addCue(cue) method of TextTrack objects, when invoked, must run the following steps:
diff --git a/Source/WebCore/html/track/TextTrackCue.cpp b/Source/WebCore/html/track/TextTrackCue.cpp
index d2de4d3e5..7973fc5f5 100644
--- a/Source/WebCore/html/track/TextTrackCue.cpp
+++ b/Source/WebCore/html/track/TextTrackCue.cpp
@@ -168,7 +168,8 @@ void TextTrackCue::setId(const String& id)
void TextTrackCue::setStartTime(double value)
{
- if (m_startTime == value)
+ // TODO(93143): Add spec-compliant behavior for negative time values.
+ if (m_startTime == value || value < 0)
return;
cueWillChange();
@@ -178,7 +179,8 @@ void TextTrackCue::setStartTime(double value)
void TextTrackCue::setEndTime(double value)
{
- if (m_endTime == value)
+ // TODO(93143): Add spec-compliant behavior for negative time values.
+ if (m_endTime == value || value < 0)
return;
cueWillChange();
diff --git a/Source/WebCore/html/track/TextTrackCueList.cpp b/Source/WebCore/html/track/TextTrackCueList.cpp
index 391b2f651..45ef441b1 100644
--- a/Source/WebCore/html/track/TextTrackCueList.cpp
+++ b/Source/WebCore/html/track/TextTrackCueList.cpp
@@ -77,6 +77,9 @@ TextTrackCueList* TextTrackCueList::activeCues()
bool TextTrackCueList::add(PassRefPtr<TextTrackCue> cue)
{
+ ASSERT(cue->startTime() >= 0);
+ ASSERT(cue->endTime() >= 0);
+
return add(cue, 0, m_list.size());
}