summaryrefslogtreecommitdiffstats
path: root/WebCore/html
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html')
-rw-r--r--WebCore/html/BaseDateAndTimeInputType.cpp148
-rw-r--r--WebCore/html/BaseDateAndTimeInputType.h65
-rw-r--r--WebCore/html/ButtonInputType.cpp5
-rw-r--r--WebCore/html/ButtonInputType.h1
-rw-r--r--WebCore/html/CheckboxInputType.cpp6
-rw-r--r--WebCore/html/CheckboxInputType.h1
-rw-r--r--WebCore/html/ColorInputType.cpp40
-rw-r--r--WebCore/html/ColorInputType.h3
-rw-r--r--WebCore/html/DOMFormData.cpp15
-rw-r--r--WebCore/html/DOMFormData.h6
-rw-r--r--WebCore/html/DOMFormData.idl2
-rw-r--r--WebCore/html/DOMTokenList.cpp20
-rw-r--r--WebCore/html/DateInputType.cpp46
-rw-r--r--WebCore/html/DateInputType.h13
-rw-r--r--WebCore/html/DateTimeInputType.cpp46
-rw-r--r--WebCore/html/DateTimeInputType.h13
-rw-r--r--WebCore/html/DateTimeLocalInputType.cpp58
-rw-r--r--WebCore/html/DateTimeLocalInputType.h15
-rw-r--r--WebCore/html/EmailInputType.cpp80
-rw-r--r--WebCore/html/EmailInputType.h2
-rw-r--r--WebCore/html/FTPDirectoryDocument.cpp5
-rw-r--r--WebCore/html/FileInputType.cpp6
-rw-r--r--WebCore/html/FileInputType.h1
-rw-r--r--WebCore/html/HTMLAnchorElement.cpp19
-rw-r--r--WebCore/html/HTMLAnchorElement.h2
-rw-r--r--WebCore/html/HTMLAnchorElement.idl2
-rw-r--r--WebCore/html/HTMLAreaElement.cpp14
-rw-r--r--WebCore/html/HTMLAreaElement.h1
-rw-r--r--WebCore/html/HTMLAttributeNames.in3
-rw-r--r--WebCore/html/HTMLBodyElement.cpp11
-rw-r--r--WebCore/html/HTMLBodyElement.h2
-rw-r--r--WebCore/html/HTMLCanvasElement.cpp4
-rw-r--r--WebCore/html/HTMLElement.cpp17
-rw-r--r--WebCore/html/HTMLEmbedElement.cpp25
-rw-r--r--WebCore/html/HTMLFormControlElement.cpp8
-rw-r--r--WebCore/html/HTMLFormControlElement.h6
-rw-r--r--WebCore/html/HTMLFormElement.cpp2
-rw-r--r--WebCore/html/HTMLFrameElementBase.cpp4
-rw-r--r--WebCore/html/HTMLFrameSetElement.cpp4
-rw-r--r--WebCore/html/HTMLHtmlElement.cpp14
-rw-r--r--WebCore/html/HTMLHtmlElement.h8
-rw-r--r--WebCore/html/HTMLIFrameElement.cpp7
-rw-r--r--WebCore/html/HTMLImageElement.cpp6
-rw-r--r--WebCore/html/HTMLImageLoader.cpp4
-rw-r--r--WebCore/html/HTMLInputElement.cpp898
-rw-r--r--WebCore/html/HTMLInputElement.h98
-rw-r--r--WebCore/html/HTMLInputElement.idl5
-rw-r--r--WebCore/html/HTMLLegendElement.cpp2
-rw-r--r--WebCore/html/HTMLLinkElement.cpp4
-rw-r--r--WebCore/html/HTMLMediaElement.cpp174
-rw-r--r--WebCore/html/HTMLMediaElement.h8
-rw-r--r--WebCore/html/HTMLObjectElement.cpp9
-rw-r--r--WebCore/html/HTMLOptGroupElement.cpp4
-rw-r--r--WebCore/html/HTMLOptionElement.cpp2
-rw-r--r--WebCore/html/HTMLPlugInElement.cpp9
-rw-r--r--WebCore/html/HTMLPlugInElement.h4
-rw-r--r--WebCore/html/HTMLSourceElement.cpp19
-rw-r--r--WebCore/html/HTMLSourceElement.h1
-rw-r--r--WebCore/html/HTMLTableCellElement.cpp18
-rw-r--r--WebCore/html/HTMLTableCellElement.h2
-rw-r--r--WebCore/html/HTMLTableColElement.cpp2
-rw-r--r--WebCore/html/HTMLTableElement.cpp5
-rw-r--r--WebCore/html/HTMLTablePartElement.cpp4
-rw-r--r--WebCore/html/HTMLTableRowElement.cpp2
-rw-r--r--WebCore/html/HTMLTableSectionElement.cpp2
-rw-r--r--WebCore/html/HTMLVideoElement.cpp1
-rw-r--r--WebCore/html/HiddenInputType.cpp5
-rw-r--r--WebCore/html/HiddenInputType.h1
-rw-r--r--WebCore/html/ImageDocument.cpp4
-rw-r--r--WebCore/html/ImageInputType.cpp5
-rw-r--r--WebCore/html/ImageInputType.h1
-rw-r--r--WebCore/html/InputType.cpp124
-rw-r--r--WebCore/html/InputType.h44
-rw-r--r--WebCore/html/IsIndexInputType.cpp5
-rw-r--r--WebCore/html/IsIndexInputType.h1
-rw-r--r--WebCore/html/MediaDocument.cpp4
-rw-r--r--WebCore/html/MonthInputType.cpp77
-rw-r--r--WebCore/html/MonthInputType.h16
-rw-r--r--WebCore/html/NumberInputType.cpp111
-rw-r--r--WebCore/html/NumberInputType.h14
-rw-r--r--WebCore/html/PluginDocument.cpp65
-rw-r--r--WebCore/html/PluginDocument.h28
-rw-r--r--WebCore/html/RadioInputType.cpp6
-rw-r--r--WebCore/html/RadioInputType.h1
-rw-r--r--WebCore/html/RangeInputType.cpp97
-rw-r--r--WebCore/html/RangeInputType.h13
-rw-r--r--WebCore/html/ResetInputType.cpp5
-rw-r--r--WebCore/html/ResetInputType.h1
-rw-r--r--WebCore/html/SubmitInputType.cpp5
-rw-r--r--WebCore/html/SubmitInputType.h1
-rw-r--r--WebCore/html/TextFieldInputType.cpp7
-rw-r--r--WebCore/html/TextFieldInputType.h1
-rw-r--r--WebCore/html/TimeInputType.cpp46
-rw-r--r--WebCore/html/TimeInputType.h13
-rw-r--r--WebCore/html/URLInputType.cpp12
-rw-r--r--WebCore/html/URLInputType.h2
-rw-r--r--WebCore/html/ValidityState.cpp7
-rw-r--r--WebCore/html/WeekInputType.cpp52
-rw-r--r--WebCore/html/WeekInputType.h14
-rw-r--r--WebCore/html/canvas/ArrayBuffer.cpp4
-rw-r--r--WebCore/html/canvas/ArrayBuffer.idl5
-rw-r--r--WebCore/html/canvas/ArrayBufferView.cpp4
-rw-r--r--WebCore/html/canvas/ArrayBufferView.idl2
-rw-r--r--WebCore/html/canvas/CanvasGradient.cpp4
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.cpp92
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.h2
-rw-r--r--WebCore/html/canvas/CanvasStyle.cpp97
-rw-r--r--WebCore/html/canvas/CanvasStyle.h21
-rw-r--r--WebCore/html/canvas/Float32Array.cpp4
-rw-r--r--WebCore/html/canvas/Float32Array.idl3
-rw-r--r--WebCore/html/canvas/Int16Array.cpp4
-rw-r--r--WebCore/html/canvas/Int16Array.idl3
-rw-r--r--WebCore/html/canvas/Int32Array.cpp4
-rw-r--r--WebCore/html/canvas/Int32Array.h2
-rw-r--r--WebCore/html/canvas/Int32Array.idl3
-rw-r--r--WebCore/html/canvas/Int8Array.cpp4
-rw-r--r--WebCore/html/canvas/Int8Array.idl3
-rw-r--r--WebCore/html/canvas/Uint16Array.cpp4
-rw-r--r--WebCore/html/canvas/Uint16Array.idl3
-rw-r--r--WebCore/html/canvas/Uint32Array.cpp4
-rw-r--r--WebCore/html/canvas/Uint32Array.idl3
-rw-r--r--WebCore/html/canvas/Uint8Array.cpp4
-rw-r--r--WebCore/html/canvas/Uint8Array.h2
-rw-r--r--WebCore/html/canvas/Uint8Array.idl3
-rw-r--r--WebCore/html/canvas/WebGLProgram.cpp2
-rw-r--r--WebCore/html/canvas/WebGLProgram.h9
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.cpp21
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.h4
-rw-r--r--WebCore/html/parser/CSSPreloadScanner.cpp79
-rw-r--r--WebCore/html/parser/HTMLConstructionSite.cpp14
-rw-r--r--WebCore/html/parser/HTMLConstructionSite.h1
-rw-r--r--WebCore/html/parser/HTMLDocumentParser.cpp32
-rw-r--r--WebCore/html/parser/HTMLDocumentParser.h3
-rw-r--r--WebCore/html/parser/HTMLElementStack.cpp17
-rw-r--r--WebCore/html/parser/HTMLElementStack.h2
-rw-r--r--WebCore/html/parser/HTMLParserIdioms.cpp4
-rw-r--r--WebCore/html/parser/HTMLParserIdioms.h13
-rw-r--r--WebCore/html/parser/HTMLPreloadScanner.cpp4
-rw-r--r--WebCore/html/parser/HTMLTreeBuilder.cpp6
139 files changed, 2145 insertions, 1171 deletions
diff --git a/WebCore/html/BaseDateAndTimeInputType.cpp b/WebCore/html/BaseDateAndTimeInputType.cpp
new file mode 100644
index 0000000..e1126d4
--- /dev/null
+++ b/WebCore/html/BaseDateAndTimeInputType.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BaseDateAndTimeInputType.h"
+
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include <limits>
+#include <wtf/MathExtras.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+using namespace std;
+
+static const double msecPerMinute = 60 * 1000;
+static const double msecPerSecond = 1000;
+
+double BaseDateAndTimeInputType::valueAsDate() const
+{
+ return parseToDouble(element()->value(), DateComponents::invalidMilliseconds());
+}
+
+void BaseDateAndTimeInputType::setValueAsDate(double value, ExceptionCode&) const
+{
+ element()->setValue(serialize(value));
+}
+
+double BaseDateAndTimeInputType::valueAsNumber() const
+{
+ return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN());
+}
+
+void BaseDateAndTimeInputType::setValueAsNumber(double newValue, ExceptionCode&) const
+{
+ element()->setValue(serialize(newValue));
+}
+
+bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const
+{
+ return !value.isEmpty() && !parseToDateComponents(value, 0);
+}
+
+bool BaseDateAndTimeInputType::typeMismatch() const
+{
+ return typeMismatchFor(element()->value());
+}
+
+bool BaseDateAndTimeInputType::rangeUnderflow(const String& value) const
+{
+ const double nan = numeric_limits<double>::quiet_NaN();
+ double doubleValue = parseToDouble(value, nan);
+ return isfinite(doubleValue) && doubleValue < minimum();
+}
+
+bool BaseDateAndTimeInputType::rangeOverflow(const String& value) const
+{
+ const double nan = numeric_limits<double>::quiet_NaN();
+ double doubleValue = parseToDouble(value, nan);
+ return isfinite(doubleValue) && doubleValue > maximum();
+}
+
+bool BaseDateAndTimeInputType::stepMismatch(const String& value, double step) const
+{
+ const double nan = numeric_limits<double>::quiet_NaN();
+ double doubleValue = parseToDouble(value, nan);
+ doubleValue = fabs(doubleValue - stepBase());
+ if (!isfinite(doubleValue))
+ return false;
+ ASSERT(round(doubleValue) == doubleValue);
+ ASSERT(round(step) == step);
+ return fmod(doubleValue, step);
+}
+
+double BaseDateAndTimeInputType::stepBase() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), defaultStepBase());
+}
+
+double BaseDateAndTimeInputType::parseToDouble(const String& src, double defaultValue) const
+{
+ DateComponents date;
+ if (!parseToDateComponents(src, &date))
+ return defaultValue;
+ double msec = date.millisecondsSinceEpoch();
+ ASSERT(isfinite(msec));
+ return msec;
+}
+
+bool BaseDateAndTimeInputType::parseToDateComponents(const String& source, DateComponents* out) const
+{
+ if (source.isEmpty())
+ return false;
+ DateComponents ignoredResult;
+ if (!out)
+ out = &ignoredResult;
+ return parseToDateComponentsInternal(source.characters(), source.length(), out);
+}
+
+String BaseDateAndTimeInputType::serialize(double value) const
+{
+ if (!isfinite(value))
+ return String();
+ DateComponents date;
+ if (!setMillisecondToDateComponents(value, &date))
+ return String();
+ double step;
+ if (!element()->getAllowedValueStep(&step))
+ return date.toString();
+ if (!fmod(step, msecPerMinute))
+ return date.toString(DateComponents::None);
+ if (!fmod(step, msecPerSecond))
+ return date.toString(DateComponents::Second);
+ return date.toString(DateComponents::Millisecond);
+}
+
+} // namespace WebCore
diff --git a/WebCore/html/BaseDateAndTimeInputType.h b/WebCore/html/BaseDateAndTimeInputType.h
new file mode 100644
index 0000000..83c1e93
--- /dev/null
+++ b/WebCore/html/BaseDateAndTimeInputType.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BaseDateAndTimeInputType_h
+#define BaseDateAndTimeInputType_h
+
+#include "TextFieldInputType.h"
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+// A super class of date, datetime, datetime-local, month, time, and week types.
+class BaseDateAndTimeInputType : public TextFieldInputType {
+protected:
+ BaseDateAndTimeInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ virtual double parseToDouble(const String&, double) const;
+ virtual bool parseToDateComponents(const String&, DateComponents*) const;
+ // A helper for parseToDateComponents().
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const = 0;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const = 0;
+
+private:
+ virtual double valueAsDate() const;
+ virtual void setValueAsDate(double, ExceptionCode&) const;
+ virtual double valueAsNumber() const;
+ virtual void setValueAsNumber(double, ExceptionCode&) const;
+ virtual bool typeMismatchFor(const String&) const;
+ virtual bool typeMismatch() const;
+ virtual bool rangeUnderflow(const String&) const;
+ virtual bool rangeOverflow(const String&) const;
+ virtual bool stepMismatch(const String&, double) const;
+ virtual double stepBase() const;
+ virtual String serialize(double) const;
+};
+
+} // namespace WebCore
+
+#endif // BaseDateAndTimeInputType_h
diff --git a/WebCore/html/ButtonInputType.cpp b/WebCore/html/ButtonInputType.cpp
index 7f56970..deaf30f 100644
--- a/WebCore/html/ButtonInputType.cpp
+++ b/WebCore/html/ButtonInputType.cpp
@@ -45,4 +45,9 @@ const AtomicString& ButtonInputType::formControlType() const
return InputTypeNames::button();
}
+bool ButtonInputType::supportsValidation() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/ButtonInputType.h b/WebCore/html/ButtonInputType.h
index 99b3574..7efbad2 100644
--- a/WebCore/html/ButtonInputType.h
+++ b/WebCore/html/ButtonInputType.h
@@ -42,6 +42,7 @@ public:
private:
ButtonInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool supportsValidation() const;
};
} // namespace WebCore
diff --git a/WebCore/html/CheckboxInputType.cpp b/WebCore/html/CheckboxInputType.cpp
index 1c7ea4b..572dde0 100644
--- a/WebCore/html/CheckboxInputType.cpp
+++ b/WebCore/html/CheckboxInputType.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "CheckboxInputType.h"
+#include "HTMLInputElement.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -45,4 +46,9 @@ const AtomicString& CheckboxInputType::formControlType() const
return InputTypeNames::checkbox();
}
+bool CheckboxInputType::valueMissing(const String&) const
+{
+ return !element()->checked();
+}
+
} // namespace WebCore
diff --git a/WebCore/html/CheckboxInputType.h b/WebCore/html/CheckboxInputType.h
index 6a152e9..e041a07 100644
--- a/WebCore/html/CheckboxInputType.h
+++ b/WebCore/html/CheckboxInputType.h
@@ -42,6 +42,7 @@ public:
private:
CheckboxInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool valueMissing(const String&) const;
};
} // namespace WebCore
diff --git a/WebCore/html/ColorInputType.cpp b/WebCore/html/ColorInputType.cpp
index c68acea..56bfd08 100644
--- a/WebCore/html/ColorInputType.cpp
+++ b/WebCore/html/ColorInputType.cpp
@@ -31,10 +31,28 @@
#include "config.h"
#include "ColorInputType.h"
+#include "Color.h"
+#include "HTMLInputElement.h"
#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
+static bool isValidColorString(const String& value)
+{
+ if (value.isEmpty())
+ return false;
+ if (value[0] == '#') {
+ // We don't accept #rgb and #aarrggbb formats.
+ if (value.length() != 7)
+ return false;
+ }
+ // This accepts named colors such as "white".
+ // FIXME: Reject named colors, accept only #rrggbb.
+ Color color(value);
+ return color.isValid() && !color.hasAlpha();
+}
+
PassOwnPtr<InputType> ColorInputType::create(HTMLInputElement* element)
{
return adoptPtr(new ColorInputType(element));
@@ -45,4 +63,26 @@ const AtomicString& ColorInputType::formControlType() const
return InputTypeNames::color();
}
+bool ColorInputType::typeMismatchFor(const String& value) const
+{
+ // FIXME: Should not accept an empty value. Remove it when we implement value
+ // sanitization for type=color.
+ if (value.isEmpty())
+ return false;
+ return !isValidColorString(value);
+}
+
+bool ColorInputType::typeMismatch() const
+{
+ // FIXME: Should return false. We don't implement value sanitization for
+ // type=color yet.
+ String value = element()->value();
+ return !value.isEmpty() && !isValidColorString(value);
+}
+
+bool ColorInputType::supportsRequired() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/ColorInputType.h b/WebCore/html/ColorInputType.h
index 7259346..ea3798b 100644
--- a/WebCore/html/ColorInputType.h
+++ b/WebCore/html/ColorInputType.h
@@ -42,6 +42,9 @@ public:
private:
ColorInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool typeMismatchFor(const String&) const;
+ virtual bool typeMismatch() const;
+ virtual bool supportsRequired() const;
};
} // namespace WebCore
diff --git a/WebCore/html/DOMFormData.cpp b/WebCore/html/DOMFormData.cpp
index f848898..0ece637 100644
--- a/WebCore/html/DOMFormData.cpp
+++ b/WebCore/html/DOMFormData.cpp
@@ -32,6 +32,8 @@
#include "DOMFormData.h"
#include "Blob.h"
+#include "HTMLFormControlElement.h"
+#include "HTMLFormElement.h"
#include "PlatformString.h"
#include "TextEncoding.h"
@@ -42,6 +44,19 @@ DOMFormData::DOMFormData(const TextEncoding& encoding)
{
}
+DOMFormData::DOMFormData(HTMLFormElement* form)
+ : FormDataList(UTF8Encoding())
+{
+ if (!form)
+ return;
+
+ for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
+ HTMLFormControlElement* control = form->associatedElements()[i];
+ if (!control->disabled())
+ control->appendFormData(*this, true);
+ }
+}
+
void DOMFormData::append(const String& name, const String& value)
{
if (!name.isEmpty())
diff --git a/WebCore/html/DOMFormData.h b/WebCore/html/DOMFormData.h
index 6c24858..967d64d 100644
--- a/WebCore/html/DOMFormData.h
+++ b/WebCore/html/DOMFormData.h
@@ -39,18 +39,20 @@
namespace WebCore {
class Blob;
+class HTMLFormElement;
class TextEncoding;
class DOMFormData : public FormDataList, public RefCounted<DOMFormData> {
public:
- static PassRefPtr<DOMFormData> create() { return adoptRef(new DOMFormData(UTF8Encoding())); }
+ static PassRefPtr<DOMFormData> create(HTMLFormElement* form) { return adoptRef(new DOMFormData(form)); }
static PassRefPtr<DOMFormData> create(const TextEncoding& encoding) { return adoptRef(new DOMFormData(encoding)); }
void append(const String& name, const String& value);
void append(const String& name, Blob*);
private:
- DOMFormData(const TextEncoding&);
+ explicit DOMFormData(const TextEncoding&);
+ explicit DOMFormData(HTMLFormElement*);
};
} // namespace WebCore
diff --git a/WebCore/html/DOMFormData.idl b/WebCore/html/DOMFormData.idl
index c339381..4418428 100644
--- a/WebCore/html/DOMFormData.idl
+++ b/WebCore/html/DOMFormData.idl
@@ -32,6 +32,8 @@ module html {
interface [
CanBeConstructed,
+ CustomConstructFunction,
+ V8CustomConstructor,
GenerateNativeConverter,
GenerateToJS
] DOMFormData {
diff --git a/WebCore/html/DOMTokenList.cpp b/WebCore/html/DOMTokenList.cpp
index 8ee45a2..aa0a74b 100644
--- a/WebCore/html/DOMTokenList.cpp
+++ b/WebCore/html/DOMTokenList.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Google Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,8 +27,9 @@
#include "Element.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "SpaceSplitString.h"
-#include "StringBuilder.h"
+#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -43,7 +44,7 @@ static bool validateToken(const AtomicString& token, ExceptionCode& ec)
unsigned length = token.length();
for (unsigned i = 0; i < length; ++i) {
- if (isClassWhitespace(token[i])) {
+ if (isHTMLSpace(token[i])) {
ec = INVALID_CHARACTER_ERR;
return false;
}
@@ -71,7 +72,7 @@ void DOMTokenList::deref()
unsigned DOMTokenList::length() const
{
- return classNames().size();
+ return m_element->hasClass() ? classNames().size() : 0;
}
const AtomicString DOMTokenList::item(unsigned index) const
@@ -90,7 +91,7 @@ bool DOMTokenList::contains(const AtomicString& token, ExceptionCode& ec) const
bool DOMTokenList::containsInternal(const AtomicString& token) const
{
- return classNames().contains(token);
+ return m_element->hasClass() && classNames().contains(token);
}
void DOMTokenList::add(const AtomicString& token, ExceptionCode& ec)
@@ -139,25 +140,25 @@ void DOMTokenList::removeInternal(const AtomicString& token) const
// Step 5
while (position < inputLength) {
- if (isClassWhitespace(input[position])) { // 6
+ if (isHTMLSpace(input[position])) { // 6
output.append(input[position++]); // 6.1, 6.2
continue; // 6.3
}
// Step 7
Vector<UChar> s;
- while (position < inputLength && !isClassWhitespace(input[position]))
+ while (position < inputLength && isNotHTMLSpace(input[position]))
s.append(input[position++]);
// Step 8
if (s == token) {
// Step 8.1
- while (position < inputLength && isClassWhitespace(input[position]))
+ while (position < inputLength && isHTMLSpace(input[position]))
++position;
// Step 8.2
size_t j = output.size();
- while (j > 0 && isClassWhitespace(output[j - 1]))
+ while (j > 0 && isHTMLSpace(output[j - 1]))
--j;
output.resize(j);
@@ -198,6 +199,7 @@ void DOMTokenList::reset(const String& newClassName)
const SpaceSplitString& DOMTokenList::classNames() const
{
+ ASSERT(m_element->hasClass());
if (!m_classNamesForQuirksMode.isNull())
return m_classNamesForQuirksMode;
return m_element->attributeMap()->classNames();
diff --git a/WebCore/html/DateInputType.cpp b/WebCore/html/DateInputType.cpp
index 0605846..3409d3b 100644
--- a/WebCore/html/DateInputType.cpp
+++ b/WebCore/html/DateInputType.cpp
@@ -31,10 +31,18 @@
#include "config.h"
#include "DateInputType.h"
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
+static const double dateDefaultStep = 1.0;
+static const double dateStepScaleFactor = 86400000.0;
+
PassOwnPtr<InputType> DateInputType::create(HTMLInputElement* element)
{
return adoptPtr(new DateInputType(element));
@@ -45,4 +53,42 @@ const AtomicString& DateInputType::formControlType() const
return InputTypeNames::date();
}
+double DateInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDate());
+}
+
+double DateInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDate());
+}
+
+double DateInputType::defaultStep() const
+{
+ return dateDefaultStep;
+}
+
+double DateInputType::stepScaleFactor() const
+{
+ return dateStepScaleFactor;
+}
+
+bool DateInputType::parsedStepValueShouldBeInteger() const
+{
+ return true;
+}
+
+bool DateInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+{
+ ASSERT(out);
+ unsigned end;
+ return out->parseDate(characters, length, 0, end) && end == length;
+}
+
+bool DateInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+{
+ ASSERT(date);
+ return date->setMillisecondsSinceEpochForDate(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/DateInputType.h b/WebCore/html/DateInputType.h
index e6f60d7..965d9ea 100644
--- a/WebCore/html/DateInputType.h
+++ b/WebCore/html/DateInputType.h
@@ -31,17 +31,24 @@
#ifndef DateInputType_h
#define DateInputType_h
-#include "TextFieldInputType.h"
+#include "BaseDateAndTimeInputType.h"
namespace WebCore {
-class DateInputType : public TextFieldInputType {
+class DateInputType : public BaseDateAndTimeInputType {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- DateInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ DateInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool parsedStepValueShouldBeInteger() const;
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const;
};
} // namespace WebCore
diff --git a/WebCore/html/DateTimeInputType.cpp b/WebCore/html/DateTimeInputType.cpp
index 0bf5e04..c78a540 100644
--- a/WebCore/html/DateTimeInputType.cpp
+++ b/WebCore/html/DateTimeInputType.cpp
@@ -31,10 +31,18 @@
#include "config.h"
#include "DateTimeInputType.h"
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
+static const double dateTimeDefaultStep = 60.0;
+static const double dateTimeStepScaleFactor = 1000.0;
+
PassOwnPtr<InputType> DateTimeInputType::create(HTMLInputElement* element)
{
return adoptPtr(new DateTimeInputType(element));
@@ -45,4 +53,42 @@ const AtomicString& DateTimeInputType::formControlType() const
return InputTypeNames::datetime();
}
+double DateTimeInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDateTime());
+}
+
+double DateTimeInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDateTime());
+}
+
+double DateTimeInputType::defaultStep() const
+{
+ return dateTimeDefaultStep;
+}
+
+double DateTimeInputType::stepScaleFactor() const
+{
+ return dateTimeStepScaleFactor;
+}
+
+bool DateTimeInputType::scaledStepValeuShouldBeInteger() const
+{
+ return true;
+}
+
+bool DateTimeInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+{
+ ASSERT(out);
+ unsigned end;
+ return out->parseDateTime(characters, length, 0, end) && end == length;
+}
+
+bool DateTimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+{
+ ASSERT(date);
+ return date->setMillisecondsSinceEpochForDateTime(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/DateTimeInputType.h b/WebCore/html/DateTimeInputType.h
index f24ebfb..140975b 100644
--- a/WebCore/html/DateTimeInputType.h
+++ b/WebCore/html/DateTimeInputType.h
@@ -31,17 +31,24 @@
#ifndef DateTimeInputType_h
#define DateTimeInputType_h
-#include "TextFieldInputType.h"
+#include "BaseDateAndTimeInputType.h"
namespace WebCore {
-class DateTimeInputType : public TextFieldInputType {
+class DateTimeInputType : public BaseDateAndTimeInputType {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- DateTimeInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ DateTimeInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool scaledStepValeuShouldBeInteger() const;
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const;
};
} // namespace WebCore
diff --git a/WebCore/html/DateTimeLocalInputType.cpp b/WebCore/html/DateTimeLocalInputType.cpp
index 33c6cfa..1ec2a47 100644
--- a/WebCore/html/DateTimeLocalInputType.cpp
+++ b/WebCore/html/DateTimeLocalInputType.cpp
@@ -31,10 +31,18 @@
#include "config.h"
#include "DateTimeLocalInputType.h"
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
+static const double dateTimeLocalDefaultStep = 60.0;
+static const double dateTimeLocalStepScaleFactor = 1000.0;
+
PassOwnPtr<InputType> DateTimeLocalInputType::create(HTMLInputElement* element)
{
return adoptPtr(new DateTimeLocalInputType(element));
@@ -45,4 +53,54 @@ const AtomicString& DateTimeLocalInputType::formControlType() const
return InputTypeNames::datetimelocal();
}
+double DateTimeLocalInputType::valueAsDate() const
+{
+ // valueAsDate doesn't work for the datetime-local type according to the standard.
+ return DateComponents::invalidMilliseconds();
+}
+
+void DateTimeLocalInputType::setValueAsDate(double value, ExceptionCode& ec) const
+{
+ // valueAsDate doesn't work for the datetime-local type according to the standard.
+ InputType::setValueAsDate(value, ec);
+}
+
+double DateTimeLocalInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDateTime());
+}
+
+double DateTimeLocalInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDateTime());
+}
+
+double DateTimeLocalInputType::defaultStep() const
+{
+ return dateTimeLocalDefaultStep;
+}
+
+double DateTimeLocalInputType::stepScaleFactor() const
+{
+ return dateTimeLocalStepScaleFactor;
+}
+
+bool DateTimeLocalInputType::scaledStepValeuShouldBeInteger() const
+{
+ return true;
+}
+
+bool DateTimeLocalInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+{
+ ASSERT(out);
+ unsigned end;
+ return out->parseDateTimeLocal(characters, length, 0, end) && end == length;
+}
+
+bool DateTimeLocalInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+{
+ ASSERT(date);
+ return date->setMillisecondsSinceEpochForDateTimeLocal(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/DateTimeLocalInputType.h b/WebCore/html/DateTimeLocalInputType.h
index 1a3d866..966e294 100644
--- a/WebCore/html/DateTimeLocalInputType.h
+++ b/WebCore/html/DateTimeLocalInputType.h
@@ -31,17 +31,26 @@
#ifndef DateTimeLocalInputType_h
#define DateTimeLocalInputType_h
-#include "TextFieldInputType.h"
+#include "BaseDateAndTimeInputType.h"
namespace WebCore {
-class DateTimeLocalInputType : public TextFieldInputType {
+class DateTimeLocalInputType : public BaseDateAndTimeInputType {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- DateTimeLocalInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ DateTimeLocalInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double valueAsDate() const;
+ virtual void setValueAsDate(double, ExceptionCode&) const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool scaledStepValeuShouldBeInteger() const;
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const;
};
} // namespace WebCore
diff --git a/WebCore/html/EmailInputType.cpp b/WebCore/html/EmailInputType.cpp
index 4472310..78bda9c 100644
--- a/WebCore/html/EmailInputType.cpp
+++ b/WebCore/html/EmailInputType.cpp
@@ -1,40 +1,54 @@
/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2009 Michelangelo De Simone <micdesim@gmail.com>
* Copyright (C) 2010 Google Inc. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
*
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "EmailInputType.h"
+#include "HTMLInputElement.h"
+#include "RegularExpression.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+static const char emailPattern[] =
+ "[a-z0-9!#$%&'*+/=?^_`{|}~.-]+" // local part
+ "@"
+ "[a-z0-9-]+(\\.[a-z0-9-]+)+"; // domain part
+
+static bool isValidEmailAddress(const String& address)
+{
+ int addressLength = address.length();
+ if (!addressLength)
+ return false;
+
+ DEFINE_STATIC_LOCAL(const RegularExpression, regExp, (emailPattern, TextCaseInsensitive));
+
+ int matchLength;
+ int matchOffset = regExp.match(address, 0, &matchLength);
+
+ return !matchOffset && matchLength == addressLength;
+}
+
PassOwnPtr<InputType> EmailInputType::create(HTMLInputElement* element)
{
return adoptPtr(new EmailInputType(element));
@@ -45,4 +59,24 @@ const AtomicString& EmailInputType::formControlType() const
return InputTypeNames::email();
}
+bool EmailInputType::typeMismatchFor(const String& value) const
+{
+ if (value.isEmpty())
+ return false;
+ if (!element()->multiple())
+ return !isValidEmailAddress(value);
+ Vector<String> addresses;
+ value.split(',', addresses);
+ for (unsigned i = 0; i < addresses.size(); ++i) {
+ if (!isValidEmailAddress(addresses[i]))
+ return true;
+ }
+ return false;
+}
+
+bool EmailInputType::typeMismatch() const
+{
+ return typeMismatchFor(element()->value());
+}
+
} // namespace WebCore
diff --git a/WebCore/html/EmailInputType.h b/WebCore/html/EmailInputType.h
index bbf6f73..b77a9ad 100644
--- a/WebCore/html/EmailInputType.h
+++ b/WebCore/html/EmailInputType.h
@@ -42,6 +42,8 @@ public:
private:
EmailInputType(HTMLInputElement* element) : BaseTextInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool typeMismatchFor(const String&) const;
+ virtual bool typeMismatch() const;
};
} // namespace WebCore
diff --git a/WebCore/html/FTPDirectoryDocument.cpp b/WebCore/html/FTPDirectoryDocument.cpp
index 6475ea9..2a08696 100644
--- a/WebCore/html/FTPDirectoryDocument.cpp
+++ b/WebCore/html/FTPDirectoryDocument.cpp
@@ -39,6 +39,7 @@
#include "Text.h"
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
#include <wtf/CurrentTime.h>
#include <wtf/StdLibExtras.h>
@@ -253,9 +254,9 @@ static String processFileDateString(const FTPTime& fileTime)
String dateString;
if (fileTime.tm_year > -1)
- dateString = String::format("%s %i, %i", months[month], fileTime.tm_mday, fileTime.tm_year);
+ dateString = makeString(months[month], ' ', String::number(fileTime.tm_mday), ", ", String::number(fileTime.tm_year));
else
- dateString = String::format("%s %i, %i", months[month], fileTime.tm_mday, now.tm_year);
+ dateString = makeString(months[month], ' ', String::number(fileTime.tm_mday), ", ", String::number(now.tm_year));
return dateString + timeOfDay;
}
diff --git a/WebCore/html/FileInputType.cpp b/WebCore/html/FileInputType.cpp
index 0e08362..6cb17f2 100644
--- a/WebCore/html/FileInputType.cpp
+++ b/WebCore/html/FileInputType.cpp
@@ -32,6 +32,7 @@
#include "FileInputType.h"
#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -45,4 +46,9 @@ const AtomicString& FileInputType::formControlType() const
return InputTypeNames::file();
}
+bool FileInputType::valueMissing(const String& value) const
+{
+ return value.isEmpty();
+}
+
} // namespace WebCore
diff --git a/WebCore/html/FileInputType.h b/WebCore/html/FileInputType.h
index cebfab7..2cbfe67 100644
--- a/WebCore/html/FileInputType.h
+++ b/WebCore/html/FileInputType.h
@@ -42,6 +42,7 @@ public:
private:
FileInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool valueMissing(const String&) const;
};
} // namespace WebCore
diff --git a/WebCore/html/HTMLAnchorElement.cpp b/WebCore/html/HTMLAnchorElement.cpp
index 8beccc2..dcdde28 100644
--- a/WebCore/html/HTMLAnchorElement.cpp
+++ b/WebCore/html/HTMLAnchorElement.cpp
@@ -30,6 +30,7 @@
#include "FrameLoaderTypes.h"
#include "HTMLImageElement.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "Page.h"
@@ -37,6 +38,7 @@
#include "RenderImage.h"
#include "ResourceHandle.h"
#include "Settings.h"
+#include "UserGestureIndicator.h"
namespace WebCore {
@@ -145,7 +147,7 @@ void HTMLAnchorElement::defaultEventHandler(Event* event)
}
if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event))) {
- String url = deprecatedParseURL(getAttribute(hrefAttr));
+ String url = stripLeadingAndTrailingHTMLSpaces(getAttribute(hrefAttr));
appendServerMapMousePosition(url, event);
handleLinkClick(event, document(), url, getAttribute(targetAttr), hasRel(RelationNoReferrer));
sendPings(document()->completeURL(url));
@@ -210,7 +212,7 @@ void HTMLAnchorElement::parseMappedAttribute(Attribute* attr)
if (wasLink != isLink())
setNeedsStyleRecalc();
if (isLink()) {
- String parsedURL = deprecatedParseURL(attr->value());
+ String parsedURL = stripLeadingAndTrailingHTMLSpaces(attr->value());
if (document()->isDNSPrefetchEnabled()) {
if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "https") || parsedURL.startsWith("//"))
ResourceHandle::prepareForURL(document()->completeURL(parsedURL));
@@ -261,7 +263,7 @@ bool HTMLAnchorElement::draggable() const
KURL HTMLAnchorElement::href() const
{
- return document()->completeURL(deprecatedParseURL(getAttribute(hrefAttr)));
+ return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(hrefAttr)));
}
void HTMLAnchorElement::setHref(const AtomicString& value)
@@ -448,6 +450,13 @@ String HTMLAnchorElement::origin() const
return origin->toString();
}
+String HTMLAnchorElement::getParameter(const String& name) const
+{
+ ParsedURLParameters parameters;
+ href().copyParsedQueryTo(parameters);
+ return parameters.get(name);
+}
+
void HTMLAnchorElement::setSearch(const String& value)
{
KURL url = href();
@@ -542,7 +551,9 @@ void handleLinkClick(Event* event, Document* document, const String& url, const
Frame* frame = document->frame();
if (!frame)
return;
- frame->loader()->urlSelected(document->completeURL(url), target, event, false, false, true, hideReferrer ? NoReferrer : SendReferrer);
+ // FIXME: This seems wrong. Why are we manufactuing a user gesture?
+ UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
+ frame->loader()->urlSelected(document->completeURL(url), target, event, false, false, hideReferrer ? NoReferrer : SendReferrer);
}
}
diff --git a/WebCore/html/HTMLAnchorElement.h b/WebCore/html/HTMLAnchorElement.h
index a7e7eec..71837ca 100644
--- a/WebCore/html/HTMLAnchorElement.h
+++ b/WebCore/html/HTMLAnchorElement.h
@@ -84,6 +84,8 @@ public:
String origin() const;
+ String getParameter(const String&) const;
+
String text() const;
String toString() const;
diff --git a/WebCore/html/HTMLAnchorElement.idl b/WebCore/html/HTMLAnchorElement.idl
index c918fde..432df69 100644
--- a/WebCore/html/HTMLAnchorElement.idl
+++ b/WebCore/html/HTMLAnchorElement.idl
@@ -53,6 +53,8 @@ module html {
readonly attribute [ConvertNullToNullString] DOMString origin;
#endif
+ DOMString getParameter(in DOMString name);
+
readonly attribute DOMString text;
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
diff --git a/WebCore/html/HTMLAreaElement.cpp b/WebCore/html/HTMLAreaElement.cpp
index 3547cd9..0155bce 100644
--- a/WebCore/html/HTMLAreaElement.cpp
+++ b/WebCore/html/HTMLAreaElement.cpp
@@ -174,12 +174,17 @@ HTMLImageElement* HTMLAreaElement::imageElement() const
bool HTMLAreaElement::isKeyboardFocusable(KeyboardEvent*) const
{
- return supportsFocus();
+ return isFocusable();
+}
+
+bool HTMLAreaElement::isMouseFocusable() const
+{
+ return isFocusable();
}
bool HTMLAreaElement::isFocusable() const
{
- return supportsFocus();
+ return supportsFocus() && Element::tabIndex() >= 0;
}
void HTMLAreaElement::dispatchBlurEvent()
@@ -192,7 +197,10 @@ void HTMLAreaElement::dispatchBlurEvent()
void HTMLAreaElement::updateFocusAppearance(bool restorePreviousSelection)
{
- Node* parent = parentNode();
+ if (!isFocusable())
+ return;
+
+ ContainerNode* parent = parentNode();
if (!parent || !parent->hasTagName(mapTag))
return;
diff --git a/WebCore/html/HTMLAreaElement.h b/WebCore/html/HTMLAreaElement.h
index 10784c3..42d4198 100644
--- a/WebCore/html/HTMLAreaElement.h
+++ b/WebCore/html/HTMLAreaElement.h
@@ -54,6 +54,7 @@ private:
virtual bool supportsFocus() const;
virtual String target() const;
virtual bool isKeyboardFocusable(KeyboardEvent*) const;
+ virtual bool isMouseFocusable() const;
virtual bool isFocusable() const;
virtual void updateFocusAppearance(bool /*restorePreviousSelection*/);
virtual void dispatchBlurEvent();
diff --git a/WebCore/html/HTMLAttributeNames.in b/WebCore/html/HTMLAttributeNames.in
index 7a80c13..d5c48c4 100644
--- a/WebCore/html/HTMLAttributeNames.in
+++ b/WebCore/html/HTMLAttributeNames.in
@@ -206,6 +206,7 @@ onseeked
onseeking
onselect
onselectstart
+onwebkitspeechchange
onstalled
onstorage
onsuspend
@@ -258,7 +259,7 @@ size
sortable
sortdirection
span
-webkitspeech
+x-webkit-speech
spellcheck
src
standby
diff --git a/WebCore/html/HTMLBodyElement.cpp b/WebCore/html/HTMLBodyElement.cpp
index 60126f7..c394f3d 100644
--- a/WebCore/html/HTMLBodyElement.cpp
+++ b/WebCore/html/HTMLBodyElement.cpp
@@ -33,6 +33,7 @@
#include "FrameView.h"
#include "HTMLFrameElementBase.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "ScriptEventListener.h"
#ifdef ANDROID_META_SUPPORT
@@ -100,7 +101,7 @@ bool HTMLBodyElement::mapToEntry(const QualifiedName& attrName, MappedAttributeE
void HTMLBodyElement::parseMappedAttribute(Attribute* attr)
{
if (attr->name() == backgroundAttr) {
- String url = deprecatedParseURL(attr->value());
+ String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
if (!url.isEmpty())
addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string());
} else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) {
@@ -218,6 +219,9 @@ void HTMLBodyElement::insertedIntoDocument()
// But without it we hang during WebKit tests; need to fix that and remove this.
if (FrameView* view = document()->view())
view->scheduleRelayout();
+
+ if (document() && document()->page())
+ document()->page()->updateViewportArguments();
}
bool HTMLBodyElement::isURLAttribute(Attribute *attr) const
@@ -225,6 +229,11 @@ bool HTMLBodyElement::isURLAttribute(Attribute *attr) const
return attr->name() == backgroundAttr;
}
+bool HTMLBodyElement::supportsFocus() const
+{
+ return isContentEditable() || HTMLElement::supportsFocus();
+}
+
String HTMLBodyElement::aLink() const
{
return getAttribute(alinkAttr);
diff --git a/WebCore/html/HTMLBodyElement.h b/WebCore/html/HTMLBodyElement.h
index d6ef185..df7bfec 100644
--- a/WebCore/html/HTMLBodyElement.h
+++ b/WebCore/html/HTMLBodyElement.h
@@ -77,6 +77,8 @@ private:
void createLinkDecl();
virtual bool isURLAttribute(Attribute*) const;
+
+ virtual bool supportsFocus() const;
virtual int scrollLeft() const;
virtual void setScrollLeft(int scrollLeft);
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index 634fe13..fea70d1 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -260,9 +260,9 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
ImageBuffer* imageBuffer = buffer();
if (imageBuffer) {
if (imageBuffer->drawsUsingCopy())
- context->drawImage(copiedImage(), DeviceColorSpace, r);
+ context->drawImage(copiedImage(), ColorSpaceDeviceRGB, r);
else
- context->drawImageBuffer(imageBuffer, DeviceColorSpace, r);
+ context->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, r);
}
}
}
diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp
index a56efdc..1483fbc 100644
--- a/WebCore/html/HTMLElement.cpp
+++ b/WebCore/html/HTMLElement.cpp
@@ -456,7 +456,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionCode& ec)
return;
}
- Node* parent = parentNode();
+ ContainerNode* parent = parentNode();
if (!parent) {
ec = NO_MODIFICATION_ALLOWED_ERR;
return;
@@ -507,9 +507,8 @@ Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, Exception
// Opera also appears to disallow such usage.
if (equalIgnoringCase(where, "beforeBegin")) {
- if (Node* p = parent())
- return p->insertBefore(newChild, this, ec) ? newChild : 0;
- return 0;
+ ContainerNode* parent = this->parent();
+ return (parent && parent->insertBefore(newChild, this, ec)) ? newChild : 0;
}
if (equalIgnoringCase(where, "afterBegin"))
@@ -519,9 +518,8 @@ Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, Exception
return appendChild(newChild, ec) ? newChild : 0;
if (equalIgnoringCase(where, "afterEnd")) {
- if (Node* p = parent())
- return p->insertBefore(newChild, nextSibling(), ec) ? newChild : 0;
- return 0;
+ ContainerNode* parent = this->parent();
+ return (parent && parent->insertBefore(newChild, nextSibling(), ec)) ? newChild : 0;
}
// IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
@@ -546,7 +544,7 @@ Element* HTMLElement::insertAdjacentElement(const String& where, Element* newChi
static Element* contextElementForInsertion(const String& where, Element* element, ExceptionCode& ec)
{
if (equalIgnoringCase(where, "beforeBegin") || equalIgnoringCase(where, "afterEnd")) {
- Node* parent = element->parentNode();
+ ContainerNode* parent = element->parentNode();
if (parent && parent->isDocumentNode()) {
ec = NO_MODIFICATION_ALLOWED_ERR;
return 0;
@@ -793,9 +791,10 @@ RenderObject* HTMLElement::createRenderer(RenderArena* arena, RenderStyle* style
HTMLFormElement* HTMLElement::findFormAncestor() const
{
- for (Node* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode())
+ for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
if (ancestor->hasTagName(formTag))
return static_cast<HTMLFormElement*>(ancestor);
+ }
return 0;
}
diff --git a/WebCore/html/HTMLEmbedElement.cpp b/WebCore/html/HTMLEmbedElement.cpp
index e88ee81..c4f007c 100644
--- a/WebCore/html/HTMLEmbedElement.cpp
+++ b/WebCore/html/HTMLEmbedElement.cpp
@@ -25,13 +25,16 @@
#include "HTMLEmbedElement.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "CSSPropertyNames.h"
+#include "DocumentLoader.h"
#include "Frame.h"
#include "HTMLDocument.h"
#include "HTMLImageLoader.h"
#include "HTMLNames.h"
#include "HTMLObjectElement.h"
+#include "HTMLParserIdioms.h"
+#include "MainResourceLoader.h"
+#include "PluginDocument.h"
#include "RenderEmbeddedObject.h"
#include "RenderImage.h"
#include "RenderWidget.h"
@@ -94,9 +97,9 @@ void HTMLEmbedElement::parseMappedAttribute(Attribute* attr)
if (!isImageType() && m_imageLoader)
m_imageLoader.clear();
} else if (attr->name() == codeAttr)
- m_url = deprecatedParseURL(value.string());
+ m_url = stripLeadingAndTrailingHTMLSpaces(value.string());
else if (attr->name() == srcAttr) {
- m_url = deprecatedParseURL(value.string());
+ m_url = stripLeadingAndTrailingHTMLSpaces(value.string());
if (renderer() && isImageType()) {
if (!m_imageLoader)
m_imageLoader = adoptPtr(new HTMLImageLoader(this));
@@ -158,8 +161,20 @@ void HTMLEmbedElement::updateWidget(bool onlyCreateNonNetscapePlugins)
Vector<String> paramValues;
parametersForPlugin(paramNames, paramValues);
- if (!dispatchBeforeLoadEvent(m_url))
+ ASSERT(!m_inBeforeLoadEventHandler);
+ m_inBeforeLoadEventHandler = true;
+ bool beforeLoadAllowedLoad = dispatchBeforeLoadEvent(m_url);
+ m_inBeforeLoadEventHandler = false;
+
+ if (!beforeLoadAllowedLoad) {
+ if (document()->isPluginDocument()) {
+ // Plugins inside plugin documents load differently than other plugins. By the time
+ // we are here in a plugin document, the load of the plugin (which is the plugin document's
+ // main resource) has already started. We need to explicitly cancel the main resource load here.
+ toPluginDocument(document())->cancelManualPluginLoad();
+ }
return;
+ }
SubframeLoader* loader = document()->frame()->loader()->subframeLoader();
// FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above.
@@ -177,7 +192,7 @@ bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style)
// If my parent is an <object> and is not set to use fallback content, I
// should be ignored and not get a renderer.
- Node* p = parentNode();
+ ContainerNode* p = parentNode();
if (p && p->hasTagName(objectTag)) {
ASSERT(p->renderer());
if (!static_cast<HTMLObjectElement*>(p)->useFallbackContent()) {
diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp
index 2080d91..51b9e20 100644
--- a/WebCore/html/HTMLFormControlElement.cpp
+++ b/WebCore/html/HTMLFormControlElement.cpp
@@ -255,7 +255,7 @@ bool HTMLFormControlElement::isKeyboardFocusable(KeyboardEvent* event) const
bool HTMLFormControlElement::isMouseFocusable() const
{
-#if PLATFORM(GTK)
+#if PLATFORM(GTK) || PLATFORM(QT)
return HTMLElement::isMouseFocusable();
#else
return false;
@@ -440,7 +440,7 @@ bool HTMLFormControlElementWithState::autoComplete() const
bool HTMLFormControlElementWithState::shouldSaveAndRestoreFormControlState() const
{
// We don't save/restore control state in a form with autocomplete=off.
- return autoComplete();
+ return attached() && autoComplete();
}
void HTMLFormControlElementWithState::finishParsingChildren()
@@ -592,10 +592,10 @@ int HTMLTextFormControlElement::selectionEnd()
return toRenderTextControl(renderer())->selectionEnd();
}
-VisibleSelection HTMLTextFormControlElement::selection() const
+PassRefPtr<Range> HTMLTextFormControlElement::selection() const
{
if (!renderer() || !isTextFormControl() || cachedSelectionStart() < 0 || cachedSelectionEnd() < 0)
- return VisibleSelection();
+ return 0;
return toRenderTextControl(renderer())->selection(cachedSelectionStart(), cachedSelectionEnd());
}
diff --git a/WebCore/html/HTMLFormControlElement.h b/WebCore/html/HTMLFormControlElement.h
index eae7f0a..4792dba 100644
--- a/WebCore/html/HTMLFormControlElement.h
+++ b/WebCore/html/HTMLFormControlElement.h
@@ -177,6 +177,8 @@ public:
virtual ~HTMLTextFormControlElement();
+ // The derived class should return true if placeholder processing is needed.
+ virtual bool supportsPlaceholder() const = 0;
String strippedPlaceholder() const;
int selectionStart();
@@ -185,7 +187,7 @@ public:
void setSelectionEnd(int);
void select();
void setSelectionRange(int start, int end);
- VisibleSelection selection() const;
+ PassRefPtr<Range> selection() const;
protected:
HTMLTextFormControlElement(const QualifiedName&, Document*, HTMLFormElement*);
@@ -204,8 +206,6 @@ private:
virtual int cachedSelectionStart() const = 0;
virtual int cachedSelectionEnd() const = 0;
- // The derived class should return true if placeholder processing is needed.
- virtual bool supportsPlaceholder() const = 0;
// Returns true if user-editable value is empty. Used to check placeholder visibility.
virtual bool isEmptyValue() const = 0;
// Called in dispatchFocusEvent(), after placeholder process, before calling parent's dispatchFocusEvent().
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index db5da66..31a72bd 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -107,7 +107,7 @@ bool HTMLFormElement::rendererIsNeeded(RenderStyle* style)
if (!isDemoted())
return HTMLElement::rendererIsNeeded(style);
- Node* node = parentNode();
+ ContainerNode* node = parentNode();
RenderObject* parentRenderer = node->renderer();
bool parentIsTableElementPart = (parentRenderer->isTable() && node->hasTagName(tableTag))
|| (parentRenderer->isTableRow() && node->hasTagName(trTag))
diff --git a/WebCore/html/HTMLFrameElementBase.cpp b/WebCore/html/HTMLFrameElementBase.cpp
index 8cca465..f8d682c 100644
--- a/WebCore/html/HTMLFrameElementBase.cpp
+++ b/WebCore/html/HTMLFrameElementBase.cpp
@@ -25,7 +25,6 @@
#include "HTMLFrameElementBase.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "Document.h"
#include "EventNames.h"
#include "FocusController.h"
@@ -35,6 +34,7 @@
#include "FrameView.h"
#include "HTMLFrameSetElement.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "KURL.h"
#include "Page.h"
#include "RenderEmbeddedObject.h"
@@ -112,7 +112,7 @@ void HTMLFrameElementBase::openURL(bool lockHistory, bool lockBackForwardList)
void HTMLFrameElementBase::parseMappedAttribute(Attribute* attr)
{
if (attr->name() == srcAttr)
- setLocation(deprecatedParseURL(attr->value()));
+ setLocation(stripLeadingAndTrailingHTMLSpaces(attr->value()));
else if (isIdAttributeName(attr->name())) {
// Important to call through to base for the id attribute so the hasID bit gets set.
HTMLFrameOwnerElement::parseMappedAttribute(attr);
diff --git a/WebCore/html/HTMLFrameSetElement.cpp b/WebCore/html/HTMLFrameSetElement.cpp
index 48c19a1..d7a47d7 100644
--- a/WebCore/html/HTMLFrameSetElement.cpp
+++ b/WebCore/html/HTMLFrameSetElement.cpp
@@ -164,7 +164,7 @@ void HTMLFrameSetElement::attach()
{
// Inherit default settings from parent frameset
// FIXME: This is not dynamic.
- for (Node* node = parentNode(); node; node = node->parentNode()) {
+ for (ContainerNode* node = parentNode(); node; node = node->parentNode()) {
if (node->hasTagName(framesetTag)) {
HTMLFrameSetElement* frameset = static_cast<HTMLFrameSetElement*>(node);
if (!frameBorderSet)
@@ -186,7 +186,7 @@ void HTMLFrameSetElement::attach()
void HTMLFrameSetElement::defaultEventHandler(Event* evt)
{
- if (evt->isMouseEvent() && !noresize && renderer()) {
+ if (evt->isMouseEvent() && !noresize && renderer() && renderer()->isFrameSet()) {
if (toRenderFrameSet(renderer())->userResize(static_cast<MouseEvent*>(evt))) {
evt->setDefaultHandled();
return;
diff --git a/WebCore/html/HTMLHtmlElement.cpp b/WebCore/html/HTMLHtmlElement.cpp
index 6007805..59c0d3e 100644
--- a/WebCore/html/HTMLHtmlElement.cpp
+++ b/WebCore/html/HTMLHtmlElement.cpp
@@ -27,6 +27,7 @@
#include "ApplicationCacheHost.h"
#include "Document.h"
#include "DocumentLoader.h"
+#include "DocumentParser.h"
#include "Frame.h"
#include "HTMLNames.h"
@@ -56,11 +57,10 @@ bool HTMLHtmlElement::isURLAttribute(Attribute* attribute) const
}
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-void HTMLHtmlElement::insertedIntoDocument()
+void HTMLHtmlElement::insertedByParser()
{
- HTMLElement::insertedIntoDocument();
-
- if (!document()->parsing())
+ // When parsing a fragment, its dummy document has a null parser.
+ if (!document()->parser() || !document()->parser()->documentWasLoadedAsPartOfNavigation())
return;
if (!document()->frame())
@@ -70,12 +70,8 @@ void HTMLHtmlElement::insertedIntoDocument()
if (!documentLoader)
return;
- // Check the manifest attribute
- // FIXME: Revisit this when we get a clarification from whatwg on how to handle empty
- // manifest attributes. As spec'd, and coded here, the system will initiate an update
- // passing in the document URL as the manifest URL. That's not a good thing.
const AtomicString& manifest = getAttribute(manifestAttr);
- if (manifest.isNull())
+ if (manifest.isEmpty())
documentLoader->applicationCacheHost()->selectCacheWithoutManifest();
else
documentLoader->applicationCacheHost()->selectCacheWithManifest(document()->completeURL(manifest));
diff --git a/WebCore/html/HTMLHtmlElement.h b/WebCore/html/HTMLHtmlElement.h
index 47503f7..9cad44e 100644
--- a/WebCore/html/HTMLHtmlElement.h
+++ b/WebCore/html/HTMLHtmlElement.h
@@ -33,14 +33,14 @@ public:
static PassRefPtr<HTMLHtmlElement> create(Document*);
static PassRefPtr<HTMLHtmlElement> create(const QualifiedName&, Document*);
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ void insertedByParser();
+#endif
+
private:
HTMLHtmlElement(const QualifiedName&, Document*);
virtual bool isURLAttribute(Attribute*) const;
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- virtual void insertedIntoDocument();
-#endif
};
} // namespace
diff --git a/WebCore/html/HTMLIFrameElement.cpp b/WebCore/html/HTMLIFrameElement.cpp
index b3fffe3..06af093 100644
--- a/WebCore/html/HTMLIFrameElement.cpp
+++ b/WebCore/html/HTMLIFrameElement.cpp
@@ -67,7 +67,6 @@ bool HTMLIFrameElement::mapToEntry(const QualifiedName& attrName, MappedAttribut
return HTMLFrameElementBase::mapToEntry(attrName, result);
}
-#if ENABLE(SANDBOX)
static SandboxFlags parseSandboxAttribute(Attribute* attribute)
{
if (attribute->isNull())
@@ -103,7 +102,6 @@ static SandboxFlags parseSandboxAttribute(Attribute* attribute)
return flags;
}
-#endif
void HTMLIFrameElement::parseMappedAttribute(Attribute* attr)
{
@@ -127,11 +125,8 @@ void HTMLIFrameElement::parseMappedAttribute(Attribute* attr)
if (!attr->isNull() && !attr->value().toInt())
// Add a rule that nulls out our border width.
addCSSLength(attr, CSSPropertyBorderWidth, "0");
- }
-#if ENABLE(SANDBOX)
- else if (attr->name() == sandboxAttr)
+ } else if (attr->name() == sandboxAttr)
setSandboxFlags(parseSandboxAttribute(attr));
-#endif
else
HTMLFrameElementBase::parseMappedAttribute(attr);
}
diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp
index 29ea592..d66075e 100644
--- a/WebCore/html/HTMLImageElement.cpp
+++ b/WebCore/html/HTMLImageElement.cpp
@@ -24,7 +24,6 @@
#include "HTMLImageElement.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "EventNames.h"
@@ -32,6 +31,7 @@
#include "HTMLDocument.h"
#include "HTMLFormElement.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "RenderImage.h"
#include "ScriptEventListener.h"
@@ -131,7 +131,7 @@ void HTMLImageElement::parseMappedAttribute(Attribute* attr)
if (attr->value().string()[0] == '#')
usemap = attr->value();
else
- usemap = document()->completeURL(deprecatedParseURL(attr->value())).string();
+ usemap = document()->completeURL(stripLeadingAndTrailingHTMLSpaces(attr->value())).string();
setIsLink(!attr->isNull());
} else if (attrName == ismapAttr)
ismap = true;
@@ -237,7 +237,7 @@ void HTMLImageElement::insertedIntoTree(bool deep)
{
if (!m_form) {
// m_form can be non-null if it was set in constructor.
- for (Node* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
+ for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
if (ancestor->hasTagName(formTag)) {
m_form = static_cast<HTMLFormElement*>(ancestor);
m_form->registerImgElement(this);
diff --git a/WebCore/html/HTMLImageLoader.cpp b/WebCore/html/HTMLImageLoader.cpp
index 6e31d9b..f620542 100644
--- a/WebCore/html/HTMLImageLoader.cpp
+++ b/WebCore/html/HTMLImageLoader.cpp
@@ -22,13 +22,13 @@
#include "config.h"
#include "HTMLImageLoader.h"
-#include "CSSHelper.h"
#include "CachedImage.h"
#include "Element.h"
#include "Event.h"
#include "EventNames.h"
#include "HTMLNames.h"
#include "HTMLObjectElement.h"
+#include "HTMLParserIdioms.h"
#if USE(JSC)
#include "JSDOMWindowBase.h"
@@ -55,7 +55,7 @@ void HTMLImageLoader::dispatchLoadEvent()
String HTMLImageLoader::sourceURI(const AtomicString& attr) const
{
- return deprecatedParseURL(attr);
+ return stripLeadingAndTrailingHTMLSpaces(attr);
}
void HTMLImageLoader::notifyFinished(CachedResource*)
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index ef7c42f..9807a55 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -56,7 +56,6 @@
#include "LocalizedStrings.h"
#include "MouseEvent.h"
#include "Page.h"
-#include "RegularExpression.h"
#include "RenderButton.h"
#include "RenderFileUploadControl.h"
#include "RenderImage.h"
@@ -65,6 +64,7 @@
#include "RenderTextControlSingleLine.h"
#include "RenderTheme.h"
#include "ScriptEventListener.h"
+#include "Settings.h"
#include "StepRange.h"
#include "TextEvent.h"
#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
@@ -84,72 +84,12 @@ using namespace HTMLNames;
const int maxSavedResults = 256;
-// Constant values for getAllowedValueStep().
-static const double dateDefaultStep = 1.0;
-static const double dateStepScaleFactor = 86400000.0;
-static const double dateTimeDefaultStep = 60.0;
-static const double dateTimeStepScaleFactor = 1000.0;
-static const double monthDefaultStep = 1.0;
-static const double monthStepScaleFactor = 1.0;
-static const double numberDefaultStep = 1.0;
-static const double numberStepScaleFactor = 1.0;
-static const double timeDefaultStep = 60.0;
-static const double timeStepScaleFactor = 1000.0;
-static const double weekDefaultStep = 1.0;
-static const double weekStepScaleFactor = 604800000.0;
-
-// Constant values for minimum().
-static const double numberDefaultMinimum = -DBL_MAX;
-static const double rangeDefaultMinimum = 0.0;
-
-// Constant values for maximum().
-static const double numberDefaultMaximum = DBL_MAX;
-static const double rangeDefaultMaximum = 100.0;
-
-static const double defaultStepBase = 0.0;
-static const double weekDefaultStepBase = -259200000.0; // The first day of 1970-W01.
-
-static const double msecPerMinute = 60 * 1000;
-static const double msecPerSecond = 1000;
-
-static const char emailPattern[] =
- "[a-z0-9!#$%&'*+/=?^_`{|}~.-]+" // local part
- "@"
- "[a-z0-9-]+(\\.[a-z0-9-]+)+"; // domain part
-
static bool isNumberCharacter(UChar ch)
{
return ch == '+' || ch == '-' || ch == '.' || ch == 'e' || ch == 'E'
|| (ch >= '0' && ch <= '9');
}
-static bool isValidColorString(const String& value)
-{
- if (value.isEmpty())
- return false;
- if (value[0] == '#') {
- // We don't accept #rgb and #aarrggbb formats.
- if (value.length() != 7)
- return false;
- }
- Color color(value); // This accepts named colors such as "white".
- return color.isValid() && !color.hasAlpha();
-}
-
-static bool isValidEmailAddress(const String& address)
-{
- int addressLength = address.length();
- if (!addressLength)
- return false;
-
- DEFINE_STATIC_LOCAL(const RegularExpression, regExp, (emailPattern, TextCaseInsensitive));
-
- int matchLength;
- int matchOffset = regExp.match(address, 0, &matchLength);
-
- return !matchOffset && matchLength == addressLength;
-}
-
HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
: HTMLTextFormControlElement(tagName, document, form)
, m_xPos(0)
@@ -199,17 +139,10 @@ bool HTMLInputElement::autoComplete() const
return HTMLTextFormControlElement::autoComplete();
}
-static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement* element)
-{
- if (HTMLFormElement* form = element->form())
- return form->checkedRadioButtons();
- return element->document()->checkedRadioButtons();
-}
-
void HTMLInputElement::updateCheckedRadioButtons()
{
if (attached() && checked())
- checkedRadioButtons(this).addButton(this);
+ checkedRadioButtons().addButton(this);
if (form()) {
const Vector<HTMLFormControlElement*>& controls = form()->associatedElements();
@@ -250,7 +183,7 @@ bool HTMLInputElement::isValidValue(const String& value) const
ASSERT_NOT_REACHED();
return false;
}
- return !typeMismatch(value)
+ return !m_inputType->typeMismatchFor(value)
&& !stepMismatch(value)
&& !rangeUnderflow(value)
&& !rangeOverflow(value)
@@ -259,93 +192,16 @@ bool HTMLInputElement::isValidValue(const String& value) const
&& !valueMissing(value);
}
-bool HTMLInputElement::typeMismatch(const String& value) const
+bool HTMLInputElement::typeMismatch() const
{
- switch (deprecatedInputType()) {
- case COLOR:
- return !isValidColorString(value);
- case NUMBER:
- ASSERT(parseToDoubleForNumberType(value, 0));
- return false;
- case URL:
- return !KURL(KURL(), value).isValid();
- case EMAIL: {
- if (!multiple())
- return !isValidEmailAddress(value);
- Vector<String> addresses;
- value.split(',', addresses);
- for (unsigned i = 0; i < addresses.size(); ++i) {
- if (!isValidEmailAddress(addresses[i]))
- return true;
- }
- return false;
- }
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case TIME:
- case WEEK:
- return !parseToDateComponents(deprecatedInputType(), value, 0);
- case BUTTON:
- case CHECKBOX:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RANGE:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- return false;
- }
- ASSERT_NOT_REACHED();
- return false;
+ return m_inputType->typeMismatch();
}
bool HTMLInputElement::valueMissing(const String& value) const
{
if (!isRequiredFormControl() || readOnly() || disabled())
return false;
-
- switch (deprecatedInputType()) {
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case EMAIL:
- case FILE:
- case MONTH:
- case NUMBER:
- case PASSWORD:
- case SEARCH:
- case TELEPHONE:
- case TEXT:
- case TIME:
- case URL:
- case WEEK:
- return value.isEmpty();
- case CHECKBOX:
- return !checked();
- case RADIO:
- return !checkedRadioButtons(this).checkedButtonForGroup(name());
- case COLOR:
- return false;
- case BUTTON:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case RANGE:
- case RESET:
- case SUBMIT:
- break;
- }
-
- ASSERT_NOT_REACHED();
- return false;
+ return m_inputType->valueMissing(value);
}
bool HTMLInputElement::patternMismatch(const String& value) const
@@ -373,199 +229,22 @@ bool HTMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check)
bool HTMLInputElement::rangeUnderflow(const String& value) const
{
- const double nan = numeric_limits<double>::quiet_NaN();
- switch (deprecatedInputType()) {
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case NUMBER:
- case TIME:
- case WEEK: {
- double doubleValue = parseToDouble(value, nan);
- return isfinite(doubleValue) && doubleValue < minimum();
- }
- case RANGE: // Guaranteed by sanitization.
- ASSERT(parseToDouble(value, nan) >= minimum());
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
- }
- return false;
+ return m_inputType->rangeUnderflow(value);
}
bool HTMLInputElement::rangeOverflow(const String& value) const
{
- const double nan = numeric_limits<double>::quiet_NaN();
- switch (deprecatedInputType()) {
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case NUMBER:
- case TIME:
- case WEEK: {
- double doubleValue = parseToDouble(value, nan);
- return isfinite(doubleValue) && doubleValue > maximum();
- }
- case RANGE: // Guaranteed by sanitization.
- ASSERT(parseToDouble(value, nan) <= maximum());
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
- }
- return false;
+ return m_inputType->rangeOverflow(value);
}
double HTMLInputElement::minimum() const
{
- switch (deprecatedInputType()) {
- case DATE:
- return parseToDouble(getAttribute(minAttr), DateComponents::minimumDate());
- case DATETIME:
- case DATETIMELOCAL:
- return parseToDouble(getAttribute(minAttr), DateComponents::minimumDateTime());
- case MONTH:
- return parseToDouble(getAttribute(minAttr), DateComponents::minimumMonth());
- case NUMBER:
- return parseToDouble(getAttribute(minAttr), numberDefaultMinimum);
- case RANGE:
- return parseToDouble(getAttribute(minAttr), rangeDefaultMinimum);
- case TIME:
- return parseToDouble(getAttribute(minAttr), DateComponents::minimumTime());
- case WEEK:
- return parseToDouble(getAttribute(minAttr), DateComponents::minimumWeek());
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
- }
- ASSERT_NOT_REACHED();
- return 0;
+ return m_inputType->minimum();
}
double HTMLInputElement::maximum() const
{
- switch (deprecatedInputType()) {
- case DATE:
- return parseToDouble(getAttribute(maxAttr), DateComponents::maximumDate());
- case DATETIME:
- case DATETIMELOCAL:
- return parseToDouble(getAttribute(maxAttr), DateComponents::maximumDateTime());
- case MONTH:
- return parseToDouble(getAttribute(maxAttr), DateComponents::maximumMonth());
- case NUMBER:
- return parseToDouble(getAttribute(maxAttr), numberDefaultMaximum);
- case RANGE: {
- double max = parseToDouble(getAttribute(maxAttr), rangeDefaultMaximum);
- // A remedy for the inconsistent min/max values for RANGE.
- // Sets the maximum to the default or the minimum value.
- double min = minimum();
- if (max < min)
- max = std::max(min, rangeDefaultMaximum);
- return max;
- }
- case TIME:
- return parseToDouble(getAttribute(maxAttr), DateComponents::maximumTime());
- case WEEK:
- return parseToDouble(getAttribute(maxAttr), DateComponents::maximumWeek());
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
- }
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-double HTMLInputElement::stepBase() const
-{
- switch (deprecatedInputType()) {
- case RANGE:
- return minimum();
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case NUMBER:
- case TIME:
- return parseToDouble(getAttribute(minAttr), defaultStepBase);
- case WEEK:
- return parseToDouble(getAttribute(minAttr), weekDefaultStepBase);
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
- }
- ASSERT_NOT_REACHED();
- return 0.0;
+ return m_inputType->maximum();
}
bool HTMLInputElement::stepMismatch(const String& value) const
@@ -573,126 +252,15 @@ bool HTMLInputElement::stepMismatch(const String& value) const
double step;
if (!getAllowedValueStep(&step))
return false;
- switch (deprecatedInputType()) {
- case RANGE:
- // stepMismatch doesn't occur for RANGE. RenderSlider guarantees the
- // value matches to step on user input, and sanitation takes care
- // of the general case.
- return false;
- case NUMBER: {
- double doubleValue;
- if (!parseToDoubleForNumberType(value, &doubleValue))
- return false;
- doubleValue = fabs(doubleValue - stepBase());
- if (isinf(doubleValue))
- return false;
- // double's fractional part size is DBL_MAN_DIG-bit. If the current
- // value is greater than step*2^DBL_MANT_DIG, the following fmod() makes
- // no sense.
- if (doubleValue / pow(2.0, DBL_MANT_DIG) > step)
- return false;
- double remainder = fmod(doubleValue, step);
- // Accepts errors in lower 7-bit.
- double acceptableError = step / pow(2.0, DBL_MANT_DIG - 7);
- return acceptableError < remainder && remainder < (step - acceptableError);
- }
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case TIME:
- case WEEK: {
- const double nan = numeric_limits<double>::quiet_NaN();
- double doubleValue = parseToDouble(value, nan);
- doubleValue = fabs(doubleValue - stepBase());
- if (!isfinite(doubleValue))
- return false;
- ASSERT(round(doubleValue) == doubleValue);
- ASSERT(round(step) == step);
- return fmod(doubleValue, step);
- }
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
- }
- // Non-supported types should be rejected by getAllowedValueStep().
- ASSERT_NOT_REACHED();
- return false;
-}
-
-bool HTMLInputElement::getStepParameters(double* defaultStep, double* stepScaleFactor) const
-{
- ASSERT(defaultStep);
- ASSERT(stepScaleFactor);
- switch (deprecatedInputType()) {
- case NUMBER:
- case RANGE:
- *defaultStep = numberDefaultStep;
- *stepScaleFactor = numberStepScaleFactor;
- return true;
- case DATE:
- *defaultStep = dateDefaultStep;
- *stepScaleFactor = dateStepScaleFactor;
- return true;
- case DATETIME:
- case DATETIMELOCAL:
- *defaultStep = dateTimeDefaultStep;
- *stepScaleFactor = dateTimeStepScaleFactor;
- return true;
- case MONTH:
- *defaultStep = monthDefaultStep;
- *stepScaleFactor = monthStepScaleFactor;
- return true;
- case TIME:
- *defaultStep = timeDefaultStep;
- *stepScaleFactor = timeStepScaleFactor;
- return true;
- case WEEK:
- *defaultStep = weekDefaultStep;
- *stepScaleFactor = weekStepScaleFactor;
- return true;
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- return false;
- }
- ASSERT_NOT_REACHED();
- return false;
+ return m_inputType->stepMismatch(value, step);
}
bool HTMLInputElement::getAllowedValueStep(double* step) const
{
ASSERT(step);
- double defaultStep;
- double stepScaleFactor;
- if (!getStepParameters(&defaultStep, &stepScaleFactor))
+ double defaultStep = m_inputType->defaultStep();
+ double stepScaleFactor = m_inputType->stepScaleFactor();
+ if (!isfinite(defaultStep) || !isfinite(stepScaleFactor))
return false;
const AtomicString& stepString = getAttribute(stepAttr);
if (stepString.isEmpty()) {
@@ -706,12 +274,12 @@ bool HTMLInputElement::getAllowedValueStep(double* step) const
*step = defaultStep * stepScaleFactor;
return true;
}
- // For DATE, MONTH, WEEK, the parsed value should be an integer.
- if (deprecatedInputType() == DATE || deprecatedInputType() == MONTH || deprecatedInputType() == WEEK)
+ // For date, month, week, the parsed value should be an integer for some types.
+ if (m_inputType->parsedStepValueShouldBeInteger())
parsed = max(round(parsed), 1.0);
double result = parsed * stepScaleFactor;
- // For DATETIME, DATETIMELOCAL, TIME, the result should be an integer.
- if (deprecatedInputType() == DATETIME || deprecatedInputType() == DATETIMELOCAL || deprecatedInputType() == TIME)
+ // For datetime, datetime-local, time, the result should be an integer.
+ if (m_inputType->scaledStepValeuShouldBeInteger())
result = max(round(result), 1.0);
ASSERT(result > 0);
*step = result;
@@ -726,7 +294,7 @@ void HTMLInputElement::applyStep(double count, ExceptionCode& ec)
return;
}
const double nan = numeric_limits<double>::quiet_NaN();
- double current = parseToDouble(value(), nan);
+ double current = m_inputType->parseToDouble(value(), nan);
if (!isfinite(current)) {
ec = INVALID_STATE_ERR;
return;
@@ -736,13 +304,13 @@ void HTMLInputElement::applyStep(double count, ExceptionCode& ec)
ec = INVALID_STATE_ERR;
return;
}
- if (newValue < minimum()) {
+ if (newValue < m_inputType->minimum()) {
ec = INVALID_STATE_ERR;
return;
}
- double base = stepBase();
+ double base = m_inputType->stepBase();
newValue = base + round((newValue - base) / step) * step;
- if (newValue > maximum()) {
+ if (newValue > m_inputType->maximum()) {
ec = INVALID_STATE_ERR;
return;
}
@@ -770,6 +338,9 @@ bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
return false;
if (deprecatedInputType() == RADIO) {
+ // When using Spatial Navigation, every radio button should be focusable.
+ if (document()->frame() && document()->frame()->settings() && document()->frame()->settings()->isSpatialNavigationEnabled())
+ return true;
// Never allow keyboard tabbing to leave you in the same radio group. Always
// skip any other elements in the group.
@@ -781,7 +352,7 @@ bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
}
// Allow keyboard focus if we're checked or if nothing in the group is checked.
- return checked() || !checkedRadioButtons(this).checkedButtonForGroup(name());
+ return checked() || !checkedRadioButtons().checkedButtonForGroup(name());
}
return true;
@@ -847,33 +418,32 @@ void HTMLInputElement::setType(const String& t)
setAttribute(typeAttr, t);
}
-typedef HashMap<String, HTMLInputElement::DeprecatedInputType, CaseFoldingHash> InputTypeMap;
-static PassOwnPtr<InputTypeMap> createTypeMap()
+PassOwnPtr<HTMLInputElement::InputTypeMap> HTMLInputElement::createTypeMap()
{
OwnPtr<InputTypeMap> map = adoptPtr(new InputTypeMap);
- map->add("button", HTMLInputElement::BUTTON);
- map->add("checkbox", HTMLInputElement::CHECKBOX);
- map->add("color", HTMLInputElement::COLOR);
- map->add("date", HTMLInputElement::DATE);
- map->add("datetime", HTMLInputElement::DATETIME);
- map->add("datetime-local", HTMLInputElement::DATETIMELOCAL);
- map->add("email", HTMLInputElement::EMAIL);
- map->add("file", HTMLInputElement::FILE);
- map->add("hidden", HTMLInputElement::HIDDEN);
- map->add("image", HTMLInputElement::IMAGE);
- map->add("khtml_isindex", HTMLInputElement::ISINDEX);
- map->add("month", HTMLInputElement::MONTH);
- map->add("number", HTMLInputElement::NUMBER);
- map->add("password", HTMLInputElement::PASSWORD);
- map->add("radio", HTMLInputElement::RADIO);
- map->add("range", HTMLInputElement::RANGE);
- map->add("reset", HTMLInputElement::RESET);
- map->add("search", HTMLInputElement::SEARCH);
- map->add("submit", HTMLInputElement::SUBMIT);
- map->add("tel", HTMLInputElement::TELEPHONE);
- map->add("time", HTMLInputElement::TIME);
- map->add("url", HTMLInputElement::URL);
- map->add("week", HTMLInputElement::WEEK);
+ map->add("button", BUTTON);
+ map->add("checkbox", CHECKBOX);
+ map->add("color", COLOR);
+ map->add("date", DATE);
+ map->add("datetime", DATETIME);
+ map->add("datetime-local", DATETIMELOCAL);
+ map->add("email", EMAIL);
+ map->add("file", FILE);
+ map->add("hidden", HIDDEN);
+ map->add("image", IMAGE);
+ map->add("khtml_isindex", ISINDEX);
+ map->add("month", MONTH);
+ map->add("number", NUMBER);
+ map->add("password", PASSWORD);
+ map->add("radio", RADIO);
+ map->add("range", RANGE);
+ map->add("reset", RESET);
+ map->add("search", SEARCH);
+ map->add("submit", SUBMIT);
+ map->add("tel", TELEPHONE);
+ map->add("time", TIME);
+ map->add("url", URL);
+ map->add("week", WEEK);
// No need to register "text" because it is the default type.
return map.release();
}
@@ -897,7 +467,7 @@ void HTMLInputElement::updateType()
// Useful in case we were called from inside parseMappedAttribute.
setAttribute(typeAttr, type());
else {
- checkedRadioButtons(this).removeButton(this);
+ checkedRadioButtons().removeButton(this);
if (newType == FILE && !m_fileList)
m_fileList = FileList::create();
@@ -947,7 +517,7 @@ void HTMLInputElement::updateType()
updateFocusAppearance(true);
}
- checkedRadioButtons(this).addButton(this);
+ checkedRadioButtons().addButton(this);
}
setNeedsValidityCheck();
@@ -1115,9 +685,9 @@ bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttribute
void HTMLInputElement::parseMappedAttribute(Attribute* attr)
{
if (attr->name() == nameAttr) {
- checkedRadioButtons(this).removeButton(this);
+ checkedRadioButtons().removeButton(this);
m_data.setName(attr->value());
- checkedRadioButtons(this).addButton(this);
+ checkedRadioButtons().addButton(this);
HTMLFormControlElementWithState::parseMappedAttribute(attr);
} else if (attr->name() == autocompleteAttr) {
if (equalIgnoringCase(attr->value(), "off")) {
@@ -1219,7 +789,8 @@ void HTMLInputElement::parseMappedAttribute(Attribute* attr)
if (renderer())
renderer()->updateFromElement();
setNeedsStyleRecalc();
- }
+ } else if (attr->name() == onwebkitspeechchangeAttr)
+ setAttributeEventListener(eventNames().webkitspeechchangeEvent, createAttributeEventListener(this, attr));
#endif
else
HTMLTextFormControlElement::parseMappedAttribute(attr);
@@ -1461,7 +1032,7 @@ void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
if (checked() == nowChecked)
return;
- checkedRadioButtons(this).removeButton(this);
+ checkedRadioButtons().removeButton(this);
m_useDefaultChecked = false;
m_checked = nowChecked;
@@ -1584,6 +1155,7 @@ String HTMLInputElement::valueWithDefault() const
v = submitButtonDefaultLabel();
break;
}
+<<<<<<< HEAD
}
return v;
}
@@ -1825,144 +1397,97 @@ double HTMLInputElement::valueAsNumber() const
case TEXT:
case URL:
return nan;
+=======
+>>>>>>> webkit.org at r70209
}
- ASSERT_NOT_REACHED();
- return nan;
+ return v;
}
-void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
+void HTMLInputElement::setValueForUser(const String& value)
{
- if (!isfinite(newValue)) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
- switch (deprecatedInputType()) {
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case NUMBER:
- case RANGE:
- case TIME:
- case WEEK:
- setValue(serialize(newValue));
+ // Call setValue and make it send a change event.
+ setValue(value, true);
+}
+
+const String& HTMLInputElement::suggestedValue() const
+{
+ return m_data.suggestedValue();
+}
+
+void HTMLInputElement::setSuggestedValue(const String& value)
+{
+ if (deprecatedInputType() != TEXT)
return;
+ setFormControlValueMatchesRenderer(false);
+ m_data.setSuggestedValue(sanitizeValue(value));
+ updatePlaceholderVisibility(false);
+ if (renderer())
+ renderer()->updateFromElement();
+ setNeedsStyleRecalc();
+}
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- ec = INVALID_STATE_ERR;
+void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
+{
+ // For security reasons, we don't allow setting the filename, but we do allow clearing it.
+ // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
+ // but we don't want to break existing websites, who may be relying on this method to clear things.
+ if (deprecatedInputType() == FILE && !value.isEmpty())
return;
+
+ setFormControlValueMatchesRenderer(false);
+ if (storesValueSeparateFromAttribute()) {
+ if (deprecatedInputType() == FILE)
+ m_fileList->clear();
+ else {
+ m_data.setValue(sanitizeValue(value));
+ if (isTextField())
+ updatePlaceholderVisibility(false);
+ }
+ setNeedsStyleRecalc();
+ } else
+ setAttribute(valueAttr, sanitizeValue(value));
+
+ setNeedsValidityCheck();
+
+ if (isTextField()) {
+ unsigned max = m_data.value().length();
+ if (document()->focusedNode() == this)
+ InputElement::updateSelectionRange(this, this, max, max);
+ else
+ cacheSelection(max, max);
+ m_data.setSuggestedValue(String());
}
- ASSERT_NOT_REACHED();
+
+ // Don't dispatch the change event when focused, it will be dispatched
+ // when the control loses focus.
+ if (sendChangeEvent && document()->focusedNode() != this)
+ dispatchFormControlChangeEvent();
+
+ InputElement::notifyFormStateChanged(this);
}
-String HTMLInputElement::serializeForDateTimeTypes(double value) const
+double HTMLInputElement::valueAsDate() const
{
- bool success = false;
- DateComponents date;
- switch (deprecatedInputType()) {
- case DATE:
- success = date.setMillisecondsSinceEpochForDate(value);
- break;
- case DATETIME:
- success = date.setMillisecondsSinceEpochForDateTime(value);
- break;
- case DATETIMELOCAL:
- success = date.setMillisecondsSinceEpochForDateTimeLocal(value);
- break;
- case MONTH:
- success = date.setMonthsSinceEpoch(value);
- break;
- case TIME:
- success = date.setMillisecondsSinceMidnight(value);
- break;
- case WEEK:
- success = date.setMillisecondsSinceEpochForWeek(value);
- break;
- case NUMBER:
- case RANGE:
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- ASSERT_NOT_REACHED();
- return String();
- }
- if (!success)
- return String();
+ return m_inputType->valueAsDate();
+}
- double step;
- if (!getAllowedValueStep(&step))
- return date.toString();
- if (!fmod(step, msecPerMinute))
- return date.toString(DateComponents::None);
- if (!fmod(step, msecPerSecond))
- return date.toString(DateComponents::Second);
- return date.toString(DateComponents::Millisecond);
+void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec)
+{
+ m_inputType->setValueAsDate(value, ec);
}
-String HTMLInputElement::serialize(double value) const
+double HTMLInputElement::valueAsNumber() const
{
- if (!isfinite(value))
- return String();
- switch (deprecatedInputType()) {
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case MONTH:
- case TIME:
- case WEEK:
- return serializeForDateTimeTypes(value);
- case NUMBER:
- case RANGE:
- return serializeForNumberType(value);
+ return m_inputType->valueAsNumber();
+}
- case BUTTON:
- case CHECKBOX:
- case COLOR:
- case EMAIL:
- case FILE:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case PASSWORD:
- case RADIO:
- case RESET:
- case SEARCH:
- case SUBMIT:
- case TELEPHONE:
- case TEXT:
- case URL:
- break;
+void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
+{
+ if (!isfinite(newValue)) {
+ ec = NOT_SUPPORTED_ERR;
+ return;
}
- ASSERT_NOT_REACHED();
- return String();
+ m_inputType->setValueAsNumber(newValue, ec);
}
String HTMLInputElement::placeholder() const
@@ -2090,7 +1615,7 @@ void* HTMLInputElement::preDispatchEventHandler(Event* evt)
// We really want radio groups to end up in sane states, i.e., to have something checked.
// Therefore if nothing is currently selected, we won't allow this action to be "undone", since
// we want some object in the radio group to actually get selected.
- HTMLInputElement* currRadio = checkedRadioButtons(this).checkedButtonForGroup(name());
+ HTMLInputElement* currRadio = checkedRadioButtons().checkedButtonForGroup(name());
if (currRadio) {
// We have a radio button selected that is not us. Cache it in our result field and ref it so
// that it can't be destroyed.
@@ -2326,29 +1851,32 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
// Right and down mean "next radio button".
// Tested in WinIE, and even for RTL, left still means previous radio button (and so moves
// to the right). Seems strange, but we'll match it.
- bool forward = (key == "Down" || key == "Right");
-
- // We can only stay within the form's children if the form hasn't been demoted to a leaf because
- // of malformed HTML.
- Node* n = this;
- while ((n = (forward ? n->traverseNextNode() : n->traversePreviousNode()))) {
- // Once we encounter a form element, we know we're through.
- if (n->hasTagName(formTag))
- break;
-
- // Look for more radio buttons.
- if (n->hasTagName(inputTag)) {
- HTMLInputElement* elt = static_cast<HTMLInputElement*>(n);
- if (elt->form() != form())
+ // However, when using Spatial Navigation, we need to be able to navigate without changing the selection.
+ if (!document()->frame() || !document()->frame()->settings() || !document()->frame()->settings()->isSpatialNavigationEnabled()) {
+ bool forward = (key == "Down" || key == "Right");
+
+ // We can only stay within the form's children if the form hasn't been demoted to a leaf because
+ // of malformed HTML.
+ Node* n = this;
+ while ((n = (forward ? n->traverseNextNode() : n->traversePreviousNode()))) {
+ // Once we encounter a form element, we know we're through.
+ if (n->hasTagName(formTag))
break;
+
+ // Look for more radio buttons.
if (n->hasTagName(inputTag)) {
- HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n);
- if (inputElt->deprecatedInputType() == RADIO && inputElt->name() == name() && inputElt->isFocusable()) {
- inputElt->setChecked(true);
- document()->setFocusedNode(inputElt);
- inputElt->dispatchSimulatedClick(evt, false, false);
- evt->setDefaultHandled();
+ HTMLInputElement* elt = static_cast<HTMLInputElement*>(n);
+ if (elt->form() != form())
break;
+ if (n->hasTagName(inputTag)) {
+ HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n);
+ if (inputElt->deprecatedInputType() == RADIO && inputElt->name() == name() && inputElt->isFocusable()) {
+ inputElt->setChecked(true);
+ document()->setFocusedNode(inputElt);
+ inputElt->dispatchSimulatedClick(evt, false, false);
+ evt->setDefaultHandled();
+ break;
+ }
}
}
}
@@ -2500,11 +2028,11 @@ void HTMLInputElement::handleKeyEventForRange(KeyboardEvent* event)
ExceptionCode ec;
if (equalIgnoringCase(getAttribute(stepAttr), "any")) {
- double min = minimum();
- double max = maximum();
+ double min = m_inputType->minimum();
+ double max = m_inputType->maximum();
// FIXME: Is 1/100 reasonable?
double step = (max - min) / 100;
- double current = parseToDouble(value(), numeric_limits<double>::quiet_NaN());
+ double current = m_inputType->parseToDouble(value(), numeric_limits<double>::quiet_NaN());
ASSERT(isfinite(current));
double newValue;
if (key == "Up" || key == "Right") {
@@ -2678,40 +2206,7 @@ void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
bool HTMLInputElement::isRequiredFormControl() const
{
- if (!required())
- return false;
-
- switch (deprecatedInputType()) {
- case CHECKBOX:
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case EMAIL:
- case FILE:
- case MONTH:
- case NUMBER:
- case PASSWORD:
- case RADIO:
- case SEARCH:
- case TELEPHONE:
- case TEXT:
- case TIME:
- case URL:
- case WEEK:
- return true;
- case BUTTON:
- case COLOR:
- case HIDDEN:
- case IMAGE:
- case ISINDEX:
- case RANGE:
- case RESET:
- case SUBMIT:
- return false;
- }
-
- ASSERT_NOT_REACHED();
- return false;
+ return m_inputType->supportsRequired() && required();
}
void HTMLInputElement::cacheSelection(int start, int end)
@@ -2771,66 +2266,7 @@ void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) cons
bool HTMLInputElement::recalcWillValidate() const
{
- switch (deprecatedInputType()) {
- case CHECKBOX:
- case COLOR:
- case DATE:
- case DATETIME:
- case DATETIMELOCAL:
- case EMAIL:
- case FILE:
- case ISINDEX:
- case MONTH:
- case NUMBER:
- case PASSWORD:
- case RADIO:
- case RANGE:
- case SEARCH:
- case TELEPHONE:
- case TEXT:
- case TIME:
- case URL:
- case WEEK:
- return HTMLFormControlElementWithState::recalcWillValidate();
- case BUTTON:
- case HIDDEN:
- case IMAGE:
- case RESET:
- case SUBMIT:
- return false;
- }
- ASSERT_NOT_REACHED();
- return false;
-}
-
-bool HTMLInputElement::parseToDateComponents(DeprecatedInputType type, const String& formString, DateComponents* out)
-{
- if (formString.isEmpty())
- return false;
- DateComponents ignoredResult;
- if (!out)
- out = &ignoredResult;
- const UChar* characters = formString.characters();
- unsigned length = formString.length();
- unsigned end;
-
- switch (type) {
- case DATE:
- return out->parseDate(characters, length, 0, end) && end == length;
- case DATETIME:
- return out->parseDateTime(characters, length, 0, end) && end == length;
- case DATETIMELOCAL:
- return out->parseDateTimeLocal(characters, length, 0, end) && end == length;
- case MONTH:
- return out->parseMonth(characters, length, 0, end) && end == length;
- case WEEK:
- return out->parseWeek(characters, length, 0, end) && end == length;
- case TIME:
- return out->parseTime(characters, length, 0, end) && end == length;
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ return m_inputType->supportsValidation() && HTMLFormControlElementWithState::recalcWillValidate();
}
#if ENABLE(DATALIST)
@@ -2924,9 +2360,9 @@ void HTMLInputElement::stepUpFromRenderer(int n)
const double nan = numeric_limits<double>::quiet_NaN();
String currentStringValue = value();
- double current = parseToDouble(currentStringValue, nan);
- if (!isfinite(current) || (n > 0 && current < minimum()) || (n < 0 && current > maximum()))
- setValue(serialize(n > 0 ? minimum() : maximum()));
+ double current = m_inputType->parseToDouble(currentStringValue, nan);
+ if (!isfinite(current) || (n > 0 && current < m_inputType->minimum()) || (n < 0 && current > m_inputType->maximum()))
+ setValue(m_inputType->serialize(n > 0 ? m_inputType->minimum() : m_inputType->maximum()));
else {
ExceptionCode ec;
stepUp(n, ec);
@@ -2982,6 +2418,12 @@ bool HTMLInputElement::isSpeechEnabled() const
}
return false;
}
+
+void HTMLInputElement::dispatchWebkitSpeechChangeEvent()
+{
+ ASSERT(isSpeechEnabled());
+ dispatchEvent(Event::create(eventNames().webkitspeechchangeEvent, true, false));
+}
#endif
} // namespace
diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h
index 88e2bf7..e584a78 100644
--- a/WebCore/html/HTMLInputElement.h
+++ b/WebCore/html/HTMLInputElement.h
@@ -25,6 +25,7 @@
#define HTMLInputElement_h
#include "HTMLFormControlElement.h"
+#include "HTMLFormElement.h"
#include "InputElement.h"
#include <wtf/OwnPtr.h>
@@ -41,40 +42,15 @@ class VisibleSelection;
class HTMLInputElement : public HTMLTextFormControlElement, public InputElement {
public:
- enum DeprecatedInputType {
- TEXT = 0, // TEXT must be 0.
- PASSWORD,
- ISINDEX,
- CHECKBOX,
- RADIO,
- SUBMIT,
- RESET,
- FILE,
- HIDDEN,
- IMAGE,
- BUTTON,
- SEARCH,
- RANGE,
- EMAIL,
- NUMBER,
- TELEPHONE,
- URL,
- COLOR,
- DATE,
- DATETIME,
- DATETIMELOCAL,
- MONTH,
- TIME,
- WEEK,
- };
-
static PassRefPtr<HTMLInputElement> create(const QualifiedName&, Document*, HTMLFormElement*);
virtual ~HTMLInputElement();
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitspeechchange);
+
bool autoComplete() const;
// For ValidityState
- bool typeMismatch(const String&) const;
+ bool typeMismatch() const;
// valueMissing() ignores the specified string value for CHECKBOX and RADIO.
bool valueMissing(const String&) const;
bool patternMismatch(const String&) const;
@@ -125,7 +101,8 @@ public:
#if ENABLE(INPUT_SPEECH)
virtual bool isSpeechEnabled() const;
-#endif
+ void dispatchWebkitSpeechChangeEvent();
+#endif
bool checked() const { return m_checked; }
void setChecked(bool, bool sendChangeEvent = false);
@@ -175,8 +152,6 @@ public:
virtual bool isActivatedSubmit() const;
virtual void setActivatedSubmit(bool flag);
- DeprecatedInputType deprecatedInputType() const { return static_cast<DeprecatedInputType>(m_deprecatedTypeNumber); }
-
String altText() const;
int maxResults() const { return m_maxResults; }
@@ -212,11 +187,6 @@ public:
void addSearchResult();
void onSearch();
- // Parses the specified string as the DeprecatedInputType, and returns true if it is successfully parsed.
- // An instance pointed by the DateComponents* parameter will have parsed values and be
- // modified even if the parsing fails. The DateComponents* parameter may be 0.
- static bool parseToDateComponents(DeprecatedInputType, const String&, DateComponents*);
-
#if ENABLE(DATALIST)
HTMLElement* list() const;
HTMLOptionElement* selectedOption() const;
@@ -226,14 +196,52 @@ public:
void setWapInputFormat(String& mask);
#endif
+ inline CheckedRadioButtons& checkedRadioButtons() const
+ {
+ if (HTMLFormElement* formElement = form())
+ return formElement->checkedRadioButtons();
+ return document()->checkedRadioButtons();
+ }
+
protected:
HTMLInputElement(const QualifiedName&, Document*, HTMLFormElement* = 0);
virtual void defaultEventHandler(Event*);
private:
+ enum DeprecatedInputType {
+ TEXT = 0, // TEXT must be 0.
+ PASSWORD,
+ ISINDEX,
+ CHECKBOX,
+ RADIO,
+ SUBMIT,
+ RESET,
+ FILE,
+ HIDDEN,
+ IMAGE,
+ BUTTON,
+ SEARCH,
+ RANGE,
+ EMAIL,
+ NUMBER,
+ TELEPHONE,
+ URL,
+ COLOR,
+ DATE,
+ DATETIME,
+ DATETIMELOCAL,
+ MONTH,
+ TIME,
+ WEEK,
+ };
+
enum AutoCompleteSetting { Uninitialized, On, Off };
+ typedef HashMap<String, HTMLInputElement::DeprecatedInputType, CaseFoldingHash> InputTypeMap;
+ static PassOwnPtr<InputTypeMap> createTypeMap();
+ DeprecatedInputType deprecatedInputType() const { return static_cast<DeprecatedInputType>(m_deprecatedTypeNumber); }
+
virtual void willMoveToNewOwnerDocument();
virtual void didMoveToNewOwnerDocument();
@@ -326,26 +334,8 @@ private:
void handleBeforeTextInsertedEvent(Event*);
void handleKeyEventForRange(KeyboardEvent*);
PassRefPtr<HTMLFormElement> createTemporaryFormForIsIndex();
- // Helper for getAllowedValueStep();
- bool getStepParameters(double* defaultStep, double* stepScaleFactor) const;
// Helper for stepUp()/stepDown(). Adds step value * count to the current value.
void applyStep(double count, ExceptionCode&);
- // Helper for applyStepForNumberOrRange().
- double stepBase() const;
-
- // Parses the specified string for the current type, and return
- // the double value for the parsing result if the parsing
- // succeeds; Returns defaultValue otherwise. This function can
- // return NaN or Infinity only if defaultValue is NaN or Infinity.
- double parseToDouble(const String&, double defaultValue) const;
- // Create a string representation of the specified double value for the
- // current input type. If NaN or Infinity is specified, this returns an
- // emtpy string. This should not be called for types without valueAsNumber.
- String serialize(double) const;
- // Create a string representation of the specified double value for the
- // current input type. The type must be one of DATE, DATETIME,
- // DATETIMELOCAL, MONTH, TIME, and WEEK.
- String serializeForDateTimeTypes(double) const;
#if ENABLE(DATALIST)
HTMLDataListElement* dataList() const;
diff --git a/WebCore/html/HTMLInputElement.idl b/WebCore/html/HTMLInputElement.idl
index 19dfa5a..1ca7d6c 100644
--- a/WebCore/html/HTMLInputElement.idl
+++ b/WebCore/html/HTMLInputElement.idl
@@ -56,7 +56,7 @@ module html {
#endif
attribute [Reflect, URL] DOMString src;
attribute [Reflect] DOMString step;
- attribute [ConvertNullToNullString, JSCCustomGetter] DOMString type; // readonly dropped as part of DOM level 2
+ attribute [ConvertNullToNullString] DOMString type; // readonly dropped as part of DOM level 2
attribute [Reflect] DOMString useMap;
attribute [ConvertNullToNullString] DOMString value;
#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
@@ -100,7 +100,8 @@ module html {
readonly attribute NodeList labels;
#if defined(ENABLE_INPUT_SPEECH) && ENABLE_INPUT_SPEECH
- attribute [Reflect, EnabledAtRuntime] boolean webkitspeech;
+ attribute [Reflect, EnabledAtRuntime] boolean webkitSpeech;
+ attribute [DontEnum] EventListener onwebkitspeechchange;
#endif
};
diff --git a/WebCore/html/HTMLLegendElement.cpp b/WebCore/html/HTMLLegendElement.cpp
index acc4a59..f998118 100644
--- a/WebCore/html/HTMLLegendElement.cpp
+++ b/WebCore/html/HTMLLegendElement.cpp
@@ -57,7 +57,7 @@ const AtomicString& HTMLLegendElement::formControlType() const
HTMLFormControlElement* HTMLLegendElement::associatedControl()
{
// Check if there's a fieldset belonging to this legend.
- Node* fieldset = parentNode();
+ ContainerNode* fieldset = parentNode();
while (fieldset && !fieldset->hasTagName(fieldsetTag))
fieldset = fieldset->parentNode();
if (!fieldset)
diff --git a/WebCore/html/HTMLLinkElement.cpp b/WebCore/html/HTMLLinkElement.cpp
index 939b375..6a5c2f6 100644
--- a/WebCore/html/HTMLLinkElement.cpp
+++ b/WebCore/html/HTMLLinkElement.cpp
@@ -25,7 +25,6 @@
#include "HTMLLinkElement.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "CachedCSSStyleSheet.h"
#include "CachedResourceLoader.h"
#include "Document.h"
@@ -34,6 +33,7 @@
#include "FrameLoaderClient.h"
#include "FrameTree.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "MediaList.h"
#include "MediaQueryEvaluator.h"
#include "Page.h"
@@ -118,7 +118,7 @@ void HTMLLinkElement::parseMappedAttribute(Attribute* attr)
tokenizeRelAttribute(attr->value(), m_relAttribute);
process();
} else if (attr->name() == hrefAttr) {
- m_url = document()->completeURL(deprecatedParseURL(attr->value()));
+ m_url = document()->completeURL(stripLeadingAndTrailingHTMLSpaces(attr->value()));
process();
} else if (attr->name() == typeAttr) {
m_type = attr->value();
diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp
index 6399f60..3f6c286 100644
--- a/WebCore/html/HTMLMediaElement.cpp
+++ b/WebCore/html/HTMLMediaElement.cpp
@@ -34,7 +34,6 @@
#include "ClientRect.h"
#include "ClientRectList.h"
#include "ContentType.h"
-#include "CSSHelper.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "Event.h"
@@ -126,6 +125,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
, m_lastTimeUpdateEventMovieTime(numeric_limits<float>::max())
, m_loadState(WaitingForSource)
, m_currentSourceNode(0)
+ , m_nextChildNodeToConsider(0)
, m_player(0)
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
, m_proxyWidget(0)
@@ -137,7 +137,6 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
, m_playing(false)
, m_isWaitingUntilMediaCanStart(false)
, m_shouldDelayLoadEvent(false)
- , m_isWaitingToDecrementLoadEventDelayCount(false)
, m_haveFiredLoadedData(false)
, m_inActiveDocument(true)
, m_autoplaying(true)
@@ -157,12 +156,14 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
, m_loadInitiatedByUserGesture(false)
, m_completelyLoaded(false)
{
+ LOG(Media, "HTMLMediaElement::HTMLMediaElement");
document->registerForDocumentActivationCallbacks(this);
document->registerForMediaVolumeCallbacks(this);
}
HTMLMediaElement::~HTMLMediaElement()
{
+ LOG(Media, "HTMLMediaElement::~HTMLMediaElement");
if (m_isWaitingUntilMediaCanStart)
document()->removeMediaCanStartListener(this);
setShouldDelayLoadEvent(false);
@@ -326,6 +327,7 @@ RenderObject* HTMLMediaElement::createRenderer(RenderArena* arena, RenderStyle*)
void HTMLMediaElement::insertedIntoDocument()
{
+ LOG(Media, "HTMLMediaElement::removedFromDocument");
HTMLElement::insertedIntoDocument();
if (!getAttribute(srcAttr).isEmpty() && m_networkState == NETWORK_EMPTY)
scheduleLoad();
@@ -333,6 +335,7 @@ void HTMLMediaElement::insertedIntoDocument()
void HTMLMediaElement::removedFromDocument()
{
+ LOG(Media, "HTMLMediaElement::removedFromDocument");
if (m_networkState > NETWORK_EMPTY)
pause(processingUserGesture());
if (m_isFullscreen)
@@ -372,6 +375,7 @@ void HTMLMediaElement::recalcStyle(StyleChange change)
void HTMLMediaElement::scheduleLoad()
{
+ LOG(Media, "HTMLMediaElement::scheduleLoad");
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
createMediaPlayerProxy();
#endif
@@ -400,15 +404,6 @@ void HTMLMediaElement::scheduleEvent(const AtomicString& eventName)
void HTMLMediaElement::asyncEventTimerFired(Timer<HTMLMediaElement>*)
{
- // If we are waiting to release our delay on the load event, do that first and post
- // the pending events on the next go around.
- if (m_isWaitingToDecrementLoadEventDelayCount) {
- setShouldDelayLoadEvent(false);
- if (!m_asyncEventTimer.isActive())
- m_asyncEventTimer.startOneShot(0);
- return;
- }
-
Vector<RefPtr<Event> > pendingEvents;
ExceptionCode ec = 0;
@@ -541,6 +536,7 @@ void HTMLMediaElement::prepareForLoad()
m_displayMode = Unknown;
// 1 - Abort any already-running instance of the resource selection algorithm for this element.
+ m_loadState = WaitingForSource;
m_currentSourceNode = 0;
// 2 - If there are any tasks from the media element's media element event task source in
@@ -879,7 +875,7 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
LOG(Media, "HTMLMediaElement::setNetworkState(%d) - current state is %d", static_cast<int>(state), static_cast<int>(m_networkState));
if (state == MediaPlayer::Empty) {
- // just update the cached state and leave, we can't do anything
+ // Just update the cached state and leave, we can't do anything.
m_networkState = NETWORK_EMPTY;
return;
}
@@ -890,12 +886,17 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
// If we failed while trying to load a <source> element, the movie was never parsed, and there are more
// <source> children, schedule the next one
if (m_readyState < HAVE_METADATA && m_loadState == LoadingFromSourceElement) {
- m_currentSourceNode->scheduleErrorEvent();
+
+ if (m_currentSourceNode)
+ m_currentSourceNode->scheduleErrorEvent();
+ else
+ LOG(Media, "HTMLMediaElement::setNetworkState - error event not sent, <source> was removed");
+
if (havePotentialSourceChild()) {
- LOG(Media, "HTMLMediaElement::setNetworkState scheduling next <source>");
+ LOG(Media, "HTMLMediaElement::setNetworkState - scheduling next <source>");
scheduleNextSourceChild();
} else {
- LOG(Media, "HTMLMediaElement::setNetworkState no more <source> elements, waiting");
+ LOG(Media, "HTMLMediaElement::setNetworkState - no more <source> elements, waiting");
waitForSourceChange();
}
@@ -1431,7 +1432,7 @@ float HTMLMediaElement::volume() const
void HTMLMediaElement::setVolume(float vol, ExceptionCode& ec)
{
- LOG(Media, "HTMLMediaElement::setControls(%f)", vol);
+ LOG(Media, "HTMLMediaElement::setVolume(%f)", vol);
if (vol < 0.0f || vol > 1.0f) {
ec = INDEX_SIZE_ERR;
@@ -1579,11 +1580,15 @@ float HTMLMediaElement::percentLoaded() const
bool HTMLMediaElement::havePotentialSourceChild()
{
- // Stash the current <source> node so we can restore it after checking
- // to see there is another potential
+ // Stash the current <source> node and next nodes so we can restore them after checking
+ // to see there is another potential.
HTMLSourceElement* currentSourceNode = m_currentSourceNode;
+ Node* nextNode = m_nextChildNodeToConsider;
+
KURL nextURL = selectNextSourceChild(0, DoNothing);
+
m_currentSourceNode = currentSourceNode;
+ m_nextChildNodeToConsider = nextNode;
return nextURL.isValid();
}
@@ -1597,22 +1602,29 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType *contentType, InvalidSo
LOG(Media, "HTMLMediaElement::selectNextSourceChild(contentType : \"%s\")", contentType ? contentType->raw().utf8().data() : "");
#endif
+ if (m_nextChildNodeToConsider == sourceChildEndOfListValue()) {
+#if !LOG_DISABLED
+ if (shouldLog)
+ LOG(Media, "HTMLMediaElement::selectNextSourceChild -> 0x0000, \"\"");
+#endif
+ return KURL();
+ }
+
KURL mediaURL;
Node* node;
- bool lookingForPreviousNode = m_currentSourceNode;
+ HTMLSourceElement* source = 0;
+ bool lookingForStartNode = m_nextChildNodeToConsider;
bool canUse = false;
for (node = firstChild(); !canUse && node; node = node->nextSibling()) {
- if (!node->hasTagName(sourceTag))
+ if (lookingForStartNode && m_nextChildNodeToConsider != node)
continue;
-
- if (lookingForPreviousNode) {
- if (m_currentSourceNode == static_cast<HTMLSourceElement*>(node))
- lookingForPreviousNode = false;
+ lookingForStartNode = false;
+
+ if (!node->hasTagName(sourceTag))
continue;
- }
- HTMLSourceElement* source = static_cast<HTMLSourceElement*>(node);
+ source = static_cast<HTMLSourceElement*>(node);
// If candidate does not have a src attribute, or if its src attribute's value is the empty string ... jump down to the failed step below
mediaURL = source->getNonEmptyURLAttribute(srcAttr);
@@ -1647,26 +1659,108 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType *contentType, InvalidSo
if (!isSafeToLoadURL(mediaURL, actionIfInvalid) || !dispatchBeforeLoadEvent(mediaURL.string()))
goto check_again;
- // Making it this far means the <source> looks reasonable
+ // Making it this far means the <source> looks reasonable.
canUse = true;
- if (contentType)
- *contentType = ContentType(source->type());
check_again:
if (!canUse && actionIfInvalid == Complain)
source->scheduleErrorEvent();
- m_currentSourceNode = static_cast<HTMLSourceElement*>(node);
}
- if (!canUse)
+ if (canUse) {
+ if (contentType)
+ *contentType = ContentType(source->type());
+ m_currentSourceNode = source;
+ m_nextChildNodeToConsider = source->nextSibling();
+ if (!m_nextChildNodeToConsider)
+ m_nextChildNodeToConsider = sourceChildEndOfListValue();
+ } else {
m_currentSourceNode = 0;
+ m_nextChildNodeToConsider = sourceChildEndOfListValue();
+ }
+
#if !LOG_DISABLED
if (shouldLog)
- LOG(Media, "HTMLMediaElement::selectNextSourceChild -> %s", canUse ? urlForLogging(mediaURL.string()).utf8().data() : "");
+ LOG(Media, "HTMLMediaElement::selectNextSourceChild -> %p, %s", m_currentSourceNode, canUse ? urlForLogging(mediaURL.string()).utf8().data() : "");
#endif
return canUse ? mediaURL : KURL();
}
+void HTMLMediaElement::sourceWasAdded(HTMLSourceElement* source)
+{
+ LOG(Media, "HTMLMediaElement::sourceWasAdded(%p)", source);
+
+#if !LOG_DISABLED
+ if (source->hasTagName(sourceTag)) {
+ KURL url = source->getNonEmptyURLAttribute(srcAttr);
+ LOG(Media, "HTMLMediaElement::sourceWasAdded - 'src' is %s", urlForLogging(url).utf8().data());
+ }
+#endif
+
+ // We should only consider a <source> element when there is not src attribute at all.
+ if (hasAttribute(srcAttr))
+ return;
+
+ // 4.8.8 - If a source element is inserted as a child of a media element that has no src
+ // attribute and whose networkState has the value NETWORK_EMPTY, the user agent must invoke
+ // the media element's resource selection algorithm.
+ if (networkState() == HTMLMediaElement::NETWORK_EMPTY) {
+ scheduleLoad();
+ return;
+ }
+
+ if (m_currentSourceNode && source == m_currentSourceNode->nextSibling()) {
+ LOG(Media, "HTMLMediaElement::sourceWasAdded - <source> inserted immediately after current source");
+ m_nextChildNodeToConsider = source;
+ return;
+ }
+
+ if (m_nextChildNodeToConsider != sourceChildEndOfListValue())
+ return;
+
+ // 4.8.9.5, resource selection algorithm, source elements section:
+ // 20 - Wait until the node after pointer is a node other than the end of the list. (This step might wait forever.)
+ // 21 - Asynchronously await a stable state...
+ // 22 - Set the element's delaying-the-load-event flag back to true (this delays the load event again, in case
+ // it hasn't been fired yet).
+ setShouldDelayLoadEvent(true);
+
+ // 23 - Set the networkState back to NETWORK_LOADING.
+ m_networkState = NETWORK_LOADING;
+
+ // 24 - Jump back to the find next candidate step above.
+ m_nextChildNodeToConsider = source;
+ scheduleNextSourceChild();
+}
+
+void HTMLMediaElement::sourceWillBeRemoved(HTMLSourceElement* source)
+{
+ LOG(Media, "HTMLMediaElement::sourceWillBeRemoved(%p)", source);
+
+#if !LOG_DISABLED
+ if (source->hasTagName(sourceTag)) {
+ KURL url = source->getNonEmptyURLAttribute(srcAttr);
+ LOG(Media, "HTMLMediaElement::sourceWillBeRemoved - 'src' is %s", urlForLogging(url).utf8().data());
+ }
+#endif
+
+ if (source != m_currentSourceNode && source != m_nextChildNodeToConsider)
+ return;
+
+ if (source == m_nextChildNodeToConsider) {
+ m_nextChildNodeToConsider = m_nextChildNodeToConsider->nextSibling();
+ if (!m_nextChildNodeToConsider)
+ m_nextChildNodeToConsider = sourceChildEndOfListValue();
+ LOG(Media, "HTMLMediaElement::sourceRemoved - m_nextChildNodeToConsider set to %p", m_nextChildNodeToConsider);
+ } else if (source == m_currentSourceNode) {
+ // Clear the current source node pointer, but don't change the movie as the spec says:
+ // 4.8.8 - Dynamically modifying a source element and its attribute when the element is already
+ // inserted in a video or audio element will have no effect.
+ m_currentSourceNode = 0;
+ LOG(Media, "HTMLMediaElement::sourceRemoved - m_currentSourceNode set to 0");
+ }
+}
+
void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*)
{
LOG(Media, "HTMLMediaElement::mediaPlayerTimeChanged");
@@ -2003,6 +2097,7 @@ void HTMLMediaElement::userCancelledLoad()
m_player.clear();
#endif
stopPeriodicTimers();
+ m_loadState = WaitingForSource;
// 2 - Set the error attribute to a new MediaError object whose code attribute is set to MEDIA_ERR_ABORTED.
m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED);
@@ -2338,24 +2433,9 @@ void HTMLMediaElement::setShouldDelayLoadEvent(bool shouldDelay)
if (m_shouldDelayLoadEvent == shouldDelay)
return;
- // Don't decrement the load event delay if we are in the middle of a callback from
- // the media engine. The load event is sent synchronously and may trigger a script that
- // causes the document to be come inactive and that will clear the media engine, causing
- // the return to be a rough one.
- if (!shouldDelay && processingMediaPlayerCallback()) {
- m_isWaitingToDecrementLoadEventDelayCount = true;
-
- // Instead of creating yet-another-timer, reuse the async event timer which is always
- // used as a one-shot.
- if (!m_asyncEventTimer.isActive())
- m_asyncEventTimer.startOneShot(0);
- return;
- }
-
LOG(Media, "HTMLMediaElement::setShouldDelayLoadEvent(%s)", boolString(shouldDelay));
m_shouldDelayLoadEvent = shouldDelay;
- m_isWaitingToDecrementLoadEventDelayCount = false;
if (shouldDelay)
document()->incrementLoadEventDelayCount();
else
diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h
index db75a9c..e5e7ae0 100644
--- a/WebCore/html/HTMLMediaElement.h
+++ b/WebCore/html/HTMLMediaElement.h
@@ -169,6 +169,9 @@ public:
bool processingUserGesture() const;
+ void sourceWillBeRemoved(HTMLSourceElement*);
+ void sourceWasAdded(HTMLSourceElement*);
+
protected:
HTMLMediaElement(const QualifiedName&, Document*);
virtual ~HTMLMediaElement();
@@ -331,7 +334,9 @@ private:
enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
LoadState m_loadState;
HTMLSourceElement* m_currentSourceNode;
-
+ Node* m_nextChildNodeToConsider;
+ Node* sourceChildEndOfListValue() { return static_cast<Node*>(this); }
+
OwnPtr<MediaPlayer> m_player;
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
RefPtr<Widget> m_proxyWidget;
@@ -350,7 +355,6 @@ private:
bool m_playing : 1;
bool m_isWaitingUntilMediaCanStart : 1;
bool m_shouldDelayLoadEvent : 1;
- bool m_isWaitingToDecrementLoadEventDelayCount : 1;
bool m_haveFiredLoadedData : 1;
bool m_inActiveDocument : 1;
bool m_autoplaying : 1;
diff --git a/WebCore/html/HTMLObjectElement.cpp b/WebCore/html/HTMLObjectElement.cpp
index e9c6f60..2b51286 100644
--- a/WebCore/html/HTMLObjectElement.cpp
+++ b/WebCore/html/HTMLObjectElement.cpp
@@ -25,7 +25,6 @@
#include "HTMLObjectElement.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "EventNames.h"
#include "ExceptionCode.h"
#include "Frame.h"
@@ -34,6 +33,7 @@
#include "HTMLImageLoader.h"
#include "HTMLNames.h"
#include "HTMLParamElement.h"
+#include "HTMLParserIdioms.h"
#include "MIMETypeRegistry.h"
#include "RenderEmbeddedObject.h"
#include "RenderImage.h"
@@ -77,7 +77,7 @@ void HTMLObjectElement::parseMappedAttribute(Attribute* attr)
if (!isImageType() && m_imageLoader)
m_imageLoader.clear();
} else if (attr->name() == dataAttr) {
- m_url = deprecatedParseURL(attr->value());
+ m_url = stripLeadingAndTrailingHTMLSpaces(attr->value());
if (renderer()) {
setNeedsWidgetUpdate(true);
if (isImageType()) {
@@ -182,7 +182,7 @@ void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<S
// FIXME: url adjustment does not belong in this function.
if (url.isEmpty() && urlParameter.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
- urlParameter = deprecatedParseURL(p->value());
+ urlParameter = stripLeadingAndTrailingHTMLSpaces(p->value());
// FIXME: serviceType calculation does not belong in this function.
if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
serviceType = p->value();
@@ -279,7 +279,10 @@ void HTMLObjectElement::updateWidget(bool onlyCreateNonNetscapePlugins)
if (onlyCreateNonNetscapePlugins && wouldLoadAsNetscapePlugin(url, serviceType))
return;
+ ASSERT(!m_inBeforeLoadEventHandler);
+ m_inBeforeLoadEventHandler = true;
bool beforeLoadAllowedLoad = dispatchBeforeLoadEvent(url);
+ m_inBeforeLoadEventHandler = false;
// beforeload events can modify the DOM, potentially causing
// RenderWidget::destroy() to be called. Ensure we haven't been
diff --git a/WebCore/html/HTMLOptGroupElement.cpp b/WebCore/html/HTMLOptGroupElement.cpp
index 091e0f2..987eb51 100644
--- a/WebCore/html/HTMLOptGroupElement.cpp
+++ b/WebCore/html/HTMLOptGroupElement.cpp
@@ -79,7 +79,7 @@ void HTMLOptGroupElement::parseMappedAttribute(Attribute* attr)
void HTMLOptGroupElement::recalcSelectOptions()
{
- Node* select = parentNode();
+ ContainerNode* select = parentNode();
while (select && !select->hasTagName(selectTag))
select = select->parentNode();
if (select)
@@ -123,7 +123,7 @@ String HTMLOptGroupElement::groupLabelText() const
HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const
{
- Node* select = parentNode();
+ ContainerNode* select = parentNode();
while (select && !select->hasTagName(selectTag))
select = select->parentNode();
diff --git a/WebCore/html/HTMLOptionElement.cpp b/WebCore/html/HTMLOptionElement.cpp
index 3bf522c..67c3567 100644
--- a/WebCore/html/HTMLOptionElement.cpp
+++ b/WebCore/html/HTMLOptionElement.cpp
@@ -193,7 +193,7 @@ void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange
HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const
{
- Node* select = parentNode();
+ ContainerNode* select = parentNode();
while (select && !(select->hasTagName(selectTag) || select->hasTagName(keygenTag)))
select = select->parentNode();
diff --git a/WebCore/html/HTMLPlugInElement.cpp b/WebCore/html/HTMLPlugInElement.cpp
index 25ef751..bf2722b 100644
--- a/WebCore/html/HTMLPlugInElement.cpp
+++ b/WebCore/html/HTMLPlugInElement.cpp
@@ -49,10 +49,11 @@ using namespace HTMLNames;
HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document* doc)
: HTMLFrameOwnerElement(tagName, doc)
+ , m_inBeforeLoadEventHandler(false)
#if ENABLE(NETSCAPE_PLUGIN_API)
, m_NPObject(0)
- , m_isCapturingMouseEvents(false)
#endif
+ , m_isCapturingMouseEvents(false)
{
}
@@ -100,6 +101,12 @@ PassScriptInstance HTMLPlugInElement::getInstance() const
Widget* HTMLPlugInElement::pluginWidget() const
{
+ if (m_inBeforeLoadEventHandler) {
+ // The plug-in hasn't loaded yet, and it makes no sense to try to load if beforeload handler happened to touch the plug-in element.
+ // That would recursively call beforeload for the same element.
+ return 0;
+ }
+
RenderWidget* renderWidget = renderWidgetForJSBindings();
if (!renderWidget)
return 0;
diff --git a/WebCore/html/HTMLPlugInElement.h b/WebCore/html/HTMLPlugInElement.h
index 5467177..44c6149 100644
--- a/WebCore/html/HTMLPlugInElement.h
+++ b/WebCore/html/HTMLPlugInElement.h
@@ -59,11 +59,15 @@ protected:
virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const;
virtual void parseMappedAttribute(Attribute*);
+<<<<<<< HEAD
#if PLATFORM(ANDROID)
// in Android, plugin has a focused mode where it accepts all the touch events.
// so need to claim that plugin element supports focus instead of using the default.
virtual bool supportsFocus() const;
#endif
+=======
+ bool m_inBeforeLoadEventHandler;
+>>>>>>> webkit.org at r70209
private:
virtual void defaultEventHandler(Event*);
diff --git a/WebCore/html/HTMLSourceElement.cpp b/WebCore/html/HTMLSourceElement.cpp
index 96c9829..59b3882 100644
--- a/WebCore/html/HTMLSourceElement.cpp
+++ b/WebCore/html/HTMLSourceElement.cpp
@@ -33,6 +33,7 @@
#include "HTMLDocument.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
+#include "Logging.h"
using namespace std;
@@ -44,6 +45,7 @@ inline HTMLSourceElement::HTMLSourceElement(const QualifiedName& tagName, Docume
: HTMLElement(tagName, document)
, m_errorEventTimer(this, &HTMLSourceElement::errorEventTimerFired)
{
+ LOG(Media, "HTMLSourceElement::HTMLSourceElement - %p", this);
ASSERT(hasTagName(sourceTag));
}
@@ -55,13 +57,17 @@ PassRefPtr<HTMLSourceElement> HTMLSourceElement::create(const QualifiedName& tag
void HTMLSourceElement::insertedIntoTree(bool deep)
{
HTMLElement::insertedIntoTree(deep);
- if (parentNode() && (parentNode()->hasTagName(audioTag) || parentNode()->hasTagName(videoTag))) {
- HTMLMediaElement* media = static_cast<HTMLMediaElement*>(parentNode());
- if (media->networkState() == HTMLMediaElement::NETWORK_EMPTY)
- media->scheduleLoad();
- }
+ if (parentNode() && (parentNode()->hasTagName(audioTag) || parentNode()->hasTagName(videoTag)))
+ static_cast<HTMLMediaElement*>(parentNode())->sourceWasAdded(this);
}
+void HTMLSourceElement::willRemove()
+{
+ if (parentNode() && (parentNode()->hasTagName(audioTag) || parentNode()->hasTagName(videoTag)))
+ static_cast<HTMLMediaElement*>(parentNode())->sourceWillBeRemoved(this);
+ HTMLElement::willRemove();
+}
+
void HTMLSourceElement::setSrc(const String& url)
{
setAttribute(srcAttr, url);
@@ -89,6 +95,7 @@ void HTMLSourceElement::setType(const String& type)
void HTMLSourceElement::scheduleErrorEvent()
{
+ LOG(Media, "HTMLSourceElement::scheduleErrorEvent - %p", this);
if (m_errorEventTimer.isActive())
return;
@@ -97,11 +104,13 @@ void HTMLSourceElement::scheduleErrorEvent()
void HTMLSourceElement::cancelPendingErrorEvent()
{
+ LOG(Media, "HTMLSourceElement::cancelPendingErrorEvent - %p", this);
m_errorEventTimer.stop();
}
void HTMLSourceElement::errorEventTimerFired(Timer<HTMLSourceElement>*)
{
+ LOG(Media, "HTMLSourceElement::errorEventTimerFired - %p", this);
dispatchEvent(Event::create(eventNames().errorEvent, false, true));
}
diff --git a/WebCore/html/HTMLSourceElement.h b/WebCore/html/HTMLSourceElement.h
index 8aa1d06..cc1e5d7 100644
--- a/WebCore/html/HTMLSourceElement.h
+++ b/WebCore/html/HTMLSourceElement.h
@@ -50,6 +50,7 @@ private:
HTMLSourceElement(const QualifiedName&, Document*);
virtual void insertedIntoTree(bool);
+ virtual void willRemove();
virtual bool isURLAttribute(Attribute*) const;
void errorEventTimerFired(Timer<HTMLSourceElement>*);
diff --git a/WebCore/html/HTMLTableCellElement.cpp b/WebCore/html/HTMLTableCellElement.cpp
index d90b125..0bd3cf5 100644
--- a/WebCore/html/HTMLTableCellElement.cpp
+++ b/WebCore/html/HTMLTableCellElement.cpp
@@ -123,7 +123,7 @@ void HTMLTableCellElement::parseMappedAttribute(Attribute* attr)
// used by table cells to share style decls created by the enclosing table.
void HTMLTableCellElement::additionalAttributeStyleDecls(Vector<CSSMutableStyleDeclaration*>& results)
{
- Node* p = parentNode();
+ ContainerNode* p = parentNode();
while (p && !p->hasTagName(tableTag))
p = p->parentNode();
if (!p)
@@ -173,4 +173,20 @@ void HTMLTableCellElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls)
addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr)));
}
+HTMLTableCellElement* HTMLTableCellElement::cellAbove() const
+{
+ RenderObject* cellRenderer = renderer();
+ if (!cellRenderer)
+ return 0;
+ if (!cellRenderer->isTableCell())
+ return 0;
+
+ RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer);
+ RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer);
+ if (!cellAboveRenderer)
+ return 0;
+
+ return static_cast<HTMLTableCellElement*>(cellAboveRenderer->node());
}
+
+} // namespace WebCore
diff --git a/WebCore/html/HTMLTableCellElement.h b/WebCore/html/HTMLTableCellElement.h
index 0c97413..f6d202b 100644
--- a/WebCore/html/HTMLTableCellElement.h
+++ b/WebCore/html/HTMLTableCellElement.h
@@ -53,6 +53,8 @@ public:
void setRowSpan(int);
String scope() const;
+ HTMLTableCellElement* cellAbove() const;
+
private:
HTMLTableCellElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLTableColElement.cpp b/WebCore/html/HTMLTableColElement.cpp
index 20b0f36..96af708 100644
--- a/WebCore/html/HTMLTableColElement.cpp
+++ b/WebCore/html/HTMLTableColElement.cpp
@@ -82,7 +82,7 @@ void HTMLTableColElement::additionalAttributeStyleDecls(Vector<CSSMutableStyleDe
{
if (!hasLocalName(colgroupTag))
return;
- Node* p = parentNode();
+ ContainerNode* p = parentNode();
while (p && !p->hasTagName(tableTag))
p = p->parentNode();
if (!p)
diff --git a/WebCore/html/HTMLTableElement.cpp b/WebCore/html/HTMLTableElement.cpp
index ef29bf6..fe823ea 100644
--- a/WebCore/html/HTMLTableElement.cpp
+++ b/WebCore/html/HTMLTableElement.cpp
@@ -31,6 +31,7 @@
#include "CSSValueKeywords.h"
#include "ExceptionCode.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
#include "HTMLTableCaptionElement.h"
#include "HTMLTableRowElement.h"
#include "HTMLTableRowsCollection.h"
@@ -202,7 +203,7 @@ PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionCode& ec
}
}
- Node* parent;
+ ContainerNode* parent;
if (lastRow)
parent = row ? row->parent() : lastRow->parent();
else {
@@ -336,7 +337,7 @@ void HTMLTableElement::parseMappedAttribute(Attribute* attr)
m_borderColorAttr = true;
}
} else if (attr->name() == backgroundAttr) {
- String url = deprecatedParseURL(attr->value());
+ String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
if (!url.isEmpty())
addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string());
} else if (attr->name() == frameAttr) {
diff --git a/WebCore/html/HTMLTablePartElement.cpp b/WebCore/html/HTMLTablePartElement.cpp
index 316ace4..dfaecca 100644
--- a/WebCore/html/HTMLTablePartElement.cpp
+++ b/WebCore/html/HTMLTablePartElement.cpp
@@ -26,11 +26,11 @@
#include "HTMLTablePartElement.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "Document.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
namespace WebCore {
@@ -64,7 +64,7 @@ void HTMLTablePartElement::parseMappedAttribute(Attribute* attr)
if (attr->name() == bgcolorAttr)
addCSSColor(attr, CSSPropertyBackgroundColor, attr->value());
else if (attr->name() == backgroundAttr) {
- String url = deprecatedParseURL(attr->value());
+ String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
if (!url.isEmpty())
addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string());
} else if (attr->name() == bordercolorAttr) {
diff --git a/WebCore/html/HTMLTableRowElement.cpp b/WebCore/html/HTMLTableRowElement.cpp
index e9b5cec..fbc253d 100644
--- a/WebCore/html/HTMLTableRowElement.cpp
+++ b/WebCore/html/HTMLTableRowElement.cpp
@@ -56,7 +56,7 @@ PassRefPtr<HTMLTableRowElement> HTMLTableRowElement::create(const QualifiedName&
int HTMLTableRowElement::rowIndex() const
{
- Node *table = parentNode();
+ ContainerNode* table = parentNode();
if (!table)
return -1;
table = table->parentNode();
diff --git a/WebCore/html/HTMLTableSectionElement.cpp b/WebCore/html/HTMLTableSectionElement.cpp
index 982e035..5ef25f1 100644
--- a/WebCore/html/HTMLTableSectionElement.cpp
+++ b/WebCore/html/HTMLTableSectionElement.cpp
@@ -50,7 +50,7 @@ PassRefPtr<HTMLTableSectionElement> HTMLTableSectionElement::create(const Qualif
// used by table row groups to share style decls created by the enclosing table.
void HTMLTableSectionElement::additionalAttributeStyleDecls(Vector<CSSMutableStyleDeclaration*>& results)
{
- Node* p = parentNode();
+ ContainerNode* p = parentNode();
while (p && !p->hasTagName(tableTag))
p = p->parentNode();
if (!p)
diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp
index 219bb85..bbda53a 100644
--- a/WebCore/html/HTMLVideoElement.cpp
+++ b/WebCore/html/HTMLVideoElement.cpp
@@ -29,7 +29,6 @@
#include "HTMLVideoElement.h"
#include "Attribute.h"
-#include "CSSHelper.h"
#include "CSSPropertyNames.h"
#include "Chrome.h"
#include "ChromeClient.h"
diff --git a/WebCore/html/HiddenInputType.cpp b/WebCore/html/HiddenInputType.cpp
index d97fe3a..76742ae 100644
--- a/WebCore/html/HiddenInputType.cpp
+++ b/WebCore/html/HiddenInputType.cpp
@@ -44,4 +44,9 @@ const AtomicString& HiddenInputType::formControlType() const {
return InputTypeNames::hidden();
}
+bool HiddenInputType::supportsValidation() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/HiddenInputType.h b/WebCore/html/HiddenInputType.h
index 564f99e..cc49f98 100644
--- a/WebCore/html/HiddenInputType.h
+++ b/WebCore/html/HiddenInputType.h
@@ -42,6 +42,7 @@ public:
private:
HiddenInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool supportsValidation() const;
};
} // namespace WebCore
diff --git a/WebCore/html/ImageDocument.cpp b/WebCore/html/ImageDocument.cpp
index db53837..6361f43 100644
--- a/WebCore/html/ImageDocument.cpp
+++ b/WebCore/html/ImageDocument.cpp
@@ -32,6 +32,7 @@
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "FrameView.h"
+#include "HTMLHtmlElement.h"
#include "HTMLImageElement.h"
#include "HTMLNames.h"
#include "LocalizedStrings.h"
@@ -194,6 +195,9 @@ void ImageDocument::createDocumentStructure()
RefPtr<Element> rootElement = Document::createElement(htmlTag, false);
appendChild(rootElement, ec);
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ static_cast<HTMLHtmlElement*>(rootElement.get())->insertedByParser();
+#endif
if (frame() && frame()->loader())
frame()->loader()->dispatchDocumentElementAvailable();
diff --git a/WebCore/html/ImageInputType.cpp b/WebCore/html/ImageInputType.cpp
index 78b3981..604b052 100644
--- a/WebCore/html/ImageInputType.cpp
+++ b/WebCore/html/ImageInputType.cpp
@@ -45,4 +45,9 @@ const AtomicString& ImageInputType::formControlType() const
return InputTypeNames::image();
}
+bool ImageInputType::supportsValidation() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/ImageInputType.h b/WebCore/html/ImageInputType.h
index 00ac77b..be308b3 100644
--- a/WebCore/html/ImageInputType.h
+++ b/WebCore/html/ImageInputType.h
@@ -42,6 +42,7 @@ public:
private:
ImageInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool supportsValidation() const;
};
} // namespace WebCore
diff --git a/WebCore/html/InputType.cpp b/WebCore/html/InputType.cpp
index c3435f7..1b2303a 100644
--- a/WebCore/html/InputType.cpp
+++ b/WebCore/html/InputType.cpp
@@ -30,6 +30,7 @@
#include "ButtonInputType.h"
#include "CheckboxInputType.h"
#include "ColorInputType.h"
+#include "DateComponents.h"
#include "DateInputType.h"
#include "DateTimeInputType.h"
#include "DateTimeLocalInputType.h"
@@ -53,11 +54,15 @@
#include "TimeInputType.h"
#include "URLInputType.h"
#include "WeekInputType.h"
+#include <limits>
+#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
+using namespace std;
+
typedef HashMap<String, PassOwnPtr<InputType> (*)(HTMLInputElement*), CaseFoldingHash> InputTypeFactoryMap;
static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
{
@@ -117,11 +122,130 @@ bool InputType::isTextType() const
return false;
}
+double InputType::valueAsDate() const
+{
+ return DateComponents::invalidMilliseconds();
+}
+
+void InputType::setValueAsDate(double, ExceptionCode& ec) const
+{
+ ec = INVALID_STATE_ERR;
+}
+
+double InputType::valueAsNumber() const
+{
+ return numeric_limits<double>::quiet_NaN();
+}
+
+void InputType::setValueAsNumber(double, ExceptionCode& ec) const
+{
+ ec = INVALID_STATE_ERR;
+}
+
+bool InputType::supportsValidation() const
+{
+ return true;
+}
+
+bool InputType::typeMismatchFor(const String&) const
+{
+ return false;
+}
+
+bool InputType::typeMismatch() const
+{
+ return false;
+}
+
+bool InputType::supportsRequired() const
+{
+ // Almost all validatable types support @required.
+ return supportsValidation();
+}
+
+bool InputType::valueMissing(const String&) const
+{
+ return false;
+}
+
bool InputType::patternMismatch(const String&) const
{
return false;
}
+bool InputType::rangeUnderflow(const String&) const
+{
+ return false;
+}
+
+bool InputType::rangeOverflow(const String&) const
+{
+ return false;
+}
+
+double InputType::minimum() const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+double InputType::maximum() const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+bool InputType::stepMismatch(const String&, double) const
+{
+ // Non-supported types should be rejected by HTMLInputElement::getAllowedValueStep().
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double InputType::stepBase() const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+double InputType::defaultStep() const
+{
+ return numeric_limits<double>::quiet_NaN();
+}
+
+double InputType::stepScaleFactor() const
+{
+ return numeric_limits<double>::quiet_NaN();
+}
+
+bool InputType::parsedStepValueShouldBeInteger() const
+{
+ return false;
+}
+
+bool InputType::scaledStepValeuShouldBeInteger() const
+{
+ return false;
+}
+
+double InputType::parseToDouble(const String&, double defaultValue) const
+{
+ return defaultValue;
+}
+
+bool InputType::parseToDateComponents(const String&, DateComponents*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+String InputType::serialize(double) const
+{
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+
namespace InputTypeNames {
// The type names must be lowercased because they will be the return values of
diff --git a/WebCore/html/InputType.h b/WebCore/html/InputType.h
index 3141f34..953b123 100644
--- a/WebCore/html/InputType.h
+++ b/WebCore/html/InputType.h
@@ -31,11 +31,13 @@
#ifndef InputType_h
#define InputType_h
+#include "ExceptionCode.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
namespace WebCore {
+class DateComponents;
class HTMLInputElement;
class InputType : public Noncopyable {
@@ -48,11 +50,53 @@ public:
virtual bool isTextType() const;
virtual const AtomicString& formControlType() const = 0;
+ virtual double valueAsDate() const;
+ virtual void setValueAsDate(double, ExceptionCode&) const;
+ virtual double valueAsNumber() const;
+ virtual void setValueAsNumber(double, ExceptionCode&) const;
+
+ // Validation-related functions
+
+ virtual bool supportsValidation() const;
+ virtual bool typeMismatchFor(const String&) const;
+ // Type check for the current input value. We do nothing for some types
+ // though typeMismatchFor() does something for them because of value
+ // sanitization.
+ virtual bool typeMismatch() const;
+ virtual bool supportsRequired() const;
+ virtual bool valueMissing(const String&) const;
virtual bool patternMismatch(const String&) const;
+ virtual bool rangeUnderflow(const String&) const;
+ virtual bool rangeOverflow(const String&) const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual bool stepMismatch(const String&, double) const;
+ virtual double stepBase() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool parsedStepValueShouldBeInteger() const;
+ virtual bool scaledStepValeuShouldBeInteger() const;
+
+ // Parses the specified string for the type, and return
+ // the double value for the parsing result if the parsing
+ // succeeds; Returns defaultValue otherwise. This function can
+ // return NaN or Infinity only if defaultValue is NaN or Infinity.
+ virtual double parseToDouble(const String&, double defaultValue) const;
+ // Parses the specified string for this InputType, and returns true if it
+ // is successfully parsed. An instance pointed by the DateComponents*
+ // parameter will have parsed values and be modified even if the parsing
+ // fails. The DateComponents* parameter may be 0.
+ virtual bool parseToDateComponents(const String&, DateComponents*) const;
+ // Create a string representation of the specified double value for the
+ // input type. If NaN or Infinity is specified, this returns an empty
+ // string. This should not be called for types without valueAsNumber.
+ virtual String serialize(double) const;
protected:
InputType(HTMLInputElement* element) : m_element(element) { }
HTMLInputElement* element() const { return m_element; }
+ // We can't make this a static const data member because VC++ doesn't like it.
+ static double defaultStepBase() { return 0.0; }
private:
// Raw pointer because the HTMLInputElement object owns this InputType object.
diff --git a/WebCore/html/IsIndexInputType.cpp b/WebCore/html/IsIndexInputType.cpp
index 80e0617..c3cff41 100644
--- a/WebCore/html/IsIndexInputType.cpp
+++ b/WebCore/html/IsIndexInputType.cpp
@@ -45,4 +45,9 @@ const AtomicString& IsIndexInputType::formControlType() const
return emptyAtom;
}
+bool IsIndexInputType::supportsRequired() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/IsIndexInputType.h b/WebCore/html/IsIndexInputType.h
index 93a1c08..2d4e193 100644
--- a/WebCore/html/IsIndexInputType.h
+++ b/WebCore/html/IsIndexInputType.h
@@ -43,6 +43,7 @@ public:
private:
IsIndexInputType(HTMLInputElement* element) : TextFieldInputType(element) { };
virtual const AtomicString& formControlType() const;
+ virtual bool supportsRequired() const;
};
} // namespace WebCore
diff --git a/WebCore/html/MediaDocument.cpp b/WebCore/html/MediaDocument.cpp
index 875141b..c4f0b14 100644
--- a/WebCore/html/MediaDocument.cpp
+++ b/WebCore/html/MediaDocument.cpp
@@ -33,6 +33,7 @@
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "HTMLEmbedElement.h"
+#include "HTMLHtmlElement.h"
#include "HTMLNames.h"
#include "HTMLVideoElement.h"
#include "KeyboardEvent.h"
@@ -71,6 +72,9 @@ void MediaDocumentParser::createDocumentStructure()
ExceptionCode ec;
RefPtr<Element> rootElement = document()->createElement(htmlTag, false);
document()->appendChild(rootElement, ec);
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ static_cast<HTMLHtmlElement*>(rootElement.get())->insertedByParser();
+#endif
if (document()->frame())
document()->frame()->loader()->dispatchDocumentElementAvailable();
diff --git a/WebCore/html/MonthInputType.cpp b/WebCore/html/MonthInputType.cpp
index 54f78c6..cbde5cb 100644
--- a/WebCore/html/MonthInputType.cpp
+++ b/WebCore/html/MonthInputType.cpp
@@ -31,10 +31,19 @@
#include "config.h"
#include "MonthInputType.h"
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
+static const double monthDefaultStep = 1.0;
+static const double monthStepScaleFactor = 1.0;
+
PassOwnPtr<InputType> MonthInputType::create(HTMLInputElement* element)
{
return adoptPtr(new MonthInputType(element));
@@ -45,4 +54,72 @@ const AtomicString& MonthInputType::formControlType() const
return InputTypeNames::month();
}
+double MonthInputType::valueAsDate() const
+{
+ DateComponents date;
+ if (!parseToDateComponents(element()->value(), &date))
+ return DateComponents::invalidMilliseconds();
+ double msec = date.millisecondsSinceEpoch();
+ ASSERT(isfinite(msec));
+ return msec;
+}
+
+void MonthInputType::setValueAsDate(double value, ExceptionCode&) const
+{
+ DateComponents date;
+ if (!date.setMillisecondsSinceEpochForMonth(value)) {
+ element()->setValue(String());
+ return;
+ }
+ element()->setValue(date.toString());
+}
+
+double MonthInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumMonth());
+}
+
+double MonthInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumMonth());
+}
+
+double MonthInputType::defaultStep() const
+{
+ return monthDefaultStep;
+}
+
+double MonthInputType::stepScaleFactor() const
+{
+ return monthStepScaleFactor;
+}
+
+bool MonthInputType::parsedStepValueShouldBeInteger() const
+{
+ return true;
+}
+
+double MonthInputType::parseToDouble(const String& src, double defaultValue) const
+{
+ DateComponents date;
+ if (!parseToDateComponents(src, &date))
+ return defaultValue;
+ double months = date.monthsSinceEpoch();
+ ASSERT(isfinite(months));
+ return months;
+}
+
+bool MonthInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+{
+ ASSERT(out);
+ unsigned end;
+ return out->parseMonth(characters, length, 0, end) && end == length;
+}
+
+bool MonthInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+{
+ ASSERT(date);
+ return date->setMonthsSinceEpoch(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/MonthInputType.h b/WebCore/html/MonthInputType.h
index d605ffa..50cf7d5 100644
--- a/WebCore/html/MonthInputType.h
+++ b/WebCore/html/MonthInputType.h
@@ -31,17 +31,27 @@
#ifndef MonthInputType_h
#define MonthInputType_h
-#include "TextFieldInputType.h"
+#include "BaseDateAndTimeInputType.h"
namespace WebCore {
-class MonthInputType : public TextFieldInputType {
+class MonthInputType : public BaseDateAndTimeInputType {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- MonthInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ MonthInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double valueAsDate() const;
+ virtual void setValueAsDate(double, ExceptionCode&) const;
+ virtual double parseToDouble(const String&, double) const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool parsedStepValueShouldBeInteger() const;
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const;
};
} // namespace WebCore
diff --git a/WebCore/html/NumberInputType.cpp b/WebCore/html/NumberInputType.cpp
index 9aba5c3..a4e118c 100644
--- a/WebCore/html/NumberInputType.cpp
+++ b/WebCore/html/NumberInputType.cpp
@@ -31,10 +31,27 @@
#include "config.h"
#include "NumberInputType.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
+#include <limits>
+#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+using namespace std;
+
+// FIXME: Number values should be in the range of IEEE 754 single-precision
+// floating point number.
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#real-numbers
+static const double numberDefaultMinimum = -DBL_MAX;
+static const double numberDefaultMaximum = DBL_MAX;
+
+static const double numberDefaultStep = 1.0;
+static const double numberStepScaleFactor = 1.0;
+
PassOwnPtr<InputType> NumberInputType::create(HTMLInputElement* element)
{
return adoptPtr(new NumberInputType(element));
@@ -45,4 +62,98 @@ const AtomicString& NumberInputType::formControlType() const
return InputTypeNames::number();
}
+double NumberInputType::valueAsNumber() const
+{
+ return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN());
+}
+
+void NumberInputType::setValueAsNumber(double newValue, ExceptionCode&) const
+{
+ element()->setValue(serialize(newValue));
+}
+
+bool NumberInputType::typeMismatchFor(const String& value) const
+{
+ return !value.isEmpty() && !parseToDoubleForNumberType(value, 0);
+}
+
+bool NumberInputType::typeMismatch() const
+{
+ ASSERT(!typeMismatchFor(element()->value()));
+ return false;
+}
+
+bool NumberInputType::rangeUnderflow(const String& value) const
+{
+ const double nan = numeric_limits<double>::quiet_NaN();
+ double doubleValue = parseToDouble(value, nan);
+ return isfinite(doubleValue) && doubleValue < minimum();
+}
+
+bool NumberInputType::rangeOverflow(const String& value) const
+{
+ const double nan = numeric_limits<double>::quiet_NaN();
+ double doubleValue = parseToDouble(value, nan);
+ return isfinite(doubleValue) && doubleValue > maximum();
+}
+
+double NumberInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), numberDefaultMinimum);
+}
+
+double NumberInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), numberDefaultMaximum);
+}
+
+bool NumberInputType::stepMismatch(const String& value, double step) const
+{
+ double doubleValue;
+ if (!parseToDoubleForNumberType(value, &doubleValue))
+ return false;
+ doubleValue = fabs(doubleValue - stepBase());
+ if (isinf(doubleValue))
+ return false;
+ // double's fractional part size is DBL_MAN_DIG-bit. If the current value
+ // is greater than step*2^DBL_MANT_DIG, the following fmod() makes no sense.
+ if (doubleValue / pow(2.0, DBL_MANT_DIG) > step)
+ return false;
+ double remainder = fmod(doubleValue, step);
+ // Accepts errors in lower 7-bit.
+ double acceptableError = step / pow(2.0, DBL_MANT_DIG - 7);
+ return acceptableError < remainder && remainder < (step - acceptableError);
+}
+
+double NumberInputType::stepBase() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), defaultStepBase());
+}
+
+double NumberInputType::defaultStep() const
+{
+ return numberDefaultStep;
+}
+
+double NumberInputType::stepScaleFactor() const
+{
+ return numberStepScaleFactor;
+}
+
+double NumberInputType::parseToDouble(const String& src, double defaultValue) const
+{
+ double numberValue;
+ if (!parseToDoubleForNumberType(src, &numberValue))
+ return defaultValue;
+ ASSERT(isfinite(numberValue));
+ return numberValue;
+}
+
+String NumberInputType::serialize(double value) const
+{
+ if (!isfinite(value))
+ return String();
+ return serializeForNumberType(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/NumberInputType.h b/WebCore/html/NumberInputType.h
index 5347249..262955e 100644
--- a/WebCore/html/NumberInputType.h
+++ b/WebCore/html/NumberInputType.h
@@ -42,6 +42,20 @@ public:
private:
NumberInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double valueAsNumber() const;
+ virtual void setValueAsNumber(double, ExceptionCode&) const;
+ virtual bool typeMismatchFor(const String&) const;
+ virtual bool typeMismatch() const;
+ virtual bool rangeUnderflow(const String&) const;
+ virtual bool rangeOverflow(const String&) const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual bool stepMismatch(const String&, double) const;
+ virtual double stepBase() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual double parseToDouble(const String&, double) const;
+ virtual String serialize(double) const;
};
} // namespace WebCore
diff --git a/WebCore/html/PluginDocument.cpp b/WebCore/html/PluginDocument.cpp
index ad11dfb..cebb949 100644
--- a/WebCore/html/PluginDocument.cpp
+++ b/WebCore/html/PluginDocument.cpp
@@ -29,8 +29,10 @@
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "HTMLEmbedElement.h"
+#include "HTMLHtmlElement.h"
#include "HTMLNames.h"
#include "MainResourceLoader.h"
+#include "NodeList.h"
#include "Page.h"
#include "RawDataDocumentParser.h"
#include "RenderEmbeddedObject.h"
@@ -48,8 +50,6 @@ public:
return adoptRef(new PluginDocumentParser(document));
}
- static Widget* pluginWidgetFromDocument(Document*);
-
private:
PluginDocumentParser(Document* document)
: RawDataDocumentParser(document)
@@ -64,25 +64,14 @@ private:
HTMLEmbedElement* m_embedElement;
};
-Widget* PluginDocumentParser::pluginWidgetFromDocument(Document* doc)
-{
- ASSERT(doc);
- RefPtr<Element> body = doc->body();
- if (body) {
- RefPtr<Node> node = body->firstChild();
- if (node && node->renderer()) {
- ASSERT(node->renderer()->isEmbeddedObject());
- return toRenderEmbeddedObject(node->renderer())->widget();
- }
- }
- return 0;
-}
-
void PluginDocumentParser::createDocumentStructure()
{
ExceptionCode ec;
RefPtr<Element> rootElement = document()->createElement(htmlTag, false);
document()->appendChild(rootElement, ec);
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ static_cast<HTMLHtmlElement*>(rootElement.get())->insertedByParser();
+#endif
if (document()->frame() && document()->frame()->loader())
document()->frame()->loader()->dispatchDocumentElementAvailable();
@@ -103,7 +92,9 @@ void PluginDocumentParser::createDocumentStructure()
m_embedElement->setAttribute(nameAttr, "plugin");
m_embedElement->setAttribute(srcAttr, document()->url().string());
m_embedElement->setAttribute(typeAttr, document()->frame()->loader()->writer()->mimeType());
-
+
+ static_cast<PluginDocument*>(document())->setPluginNode(m_embedElement);
+
body->appendChild(embedElement, ec);
}
@@ -125,8 +116,13 @@ void PluginDocumentParser::appendBytes(DocumentWriter*, const char*, int, bool)
document()->updateLayout();
if (RenderPart* renderer = m_embedElement->renderPart()) {
- frame->loader()->client()->redirectDataToPlugin(renderer->widget());
- frame->loader()->activeDocumentLoader()->mainResourceLoader()->setShouldBufferData(false);
+ if (Widget* widget = renderer->widget()) {
+ frame->loader()->client()->redirectDataToPlugin(widget);
+ // In a plugin document, the main resource is the plugin. If we have a null widget, that means
+ // the loading of the plugin was cancelled, which gives us a null mainResourceLoader(), so we
+ // need to have this call in a null check of the widget or of mainResourceLoader().
+ frame->loader()->activeDocumentLoader()->mainResourceLoader()->setShouldBufferData(false);
+ }
}
finish();
@@ -134,11 +130,12 @@ void PluginDocumentParser::appendBytes(DocumentWriter*, const char*, int, bool)
PluginDocument::PluginDocument(Frame* frame, const KURL& url)
: HTMLDocument(frame, url)
+ , m_shouldLoadPluginManually(true)
{
setCompatibilityMode(QuirksMode);
lockCompatibilityMode();
}
-
+
PassRefPtr<DocumentParser> PluginDocument::createParser()
{
return PluginDocumentParser::create(this);
@@ -146,16 +143,34 @@ PassRefPtr<DocumentParser> PluginDocument::createParser()
Widget* PluginDocument::pluginWidget()
{
- return PluginDocumentParser::pluginWidgetFromDocument(this);
+ if (m_pluginNode && m_pluginNode->renderer()) {
+ ASSERT(m_pluginNode->renderer()->isEmbeddedObject());
+ return toRenderEmbeddedObject(m_pluginNode->renderer())->widget();
+ }
+ return 0;
}
Node* PluginDocument::pluginNode()
{
- RefPtr<Element> body_element = body();
- if (body_element)
- return body_element->firstChild();
+ return m_pluginNode.get();
+}
- return 0;
+void PluginDocument::detach()
+{
+ // Release the plugin node so that we don't have a circular reference.
+ m_pluginNode = 0;
+ HTMLDocument::detach();
+}
+
+void PluginDocument::cancelManualPluginLoad()
+{
+ // PluginDocument::cancelManualPluginLoad should only be called once, but there are issues
+ // with how many times we call beforeload on object elements. <rdar://problem/8441094>.
+ if (!shouldLoadPluginManually())
+ return;
+
+ frame()->loader()->activeDocumentLoader()->mainResourceLoader()->cancel();
+ setShouldLoadPluginManually(false);
}
}
diff --git a/WebCore/html/PluginDocument.h b/WebCore/html/PluginDocument.h
index 3bb5d99..da0bb75 100644
--- a/WebCore/html/PluginDocument.h
+++ b/WebCore/html/PluginDocument.h
@@ -38,16 +38,44 @@ public:
return adoptRef(new PluginDocument(frame, url));
}
+ void setPluginNode(Node* pluginNode) { m_pluginNode = pluginNode; }
+
Widget* pluginWidget();
Node* pluginNode();
virtual bool isPluginDocument() const { return true; }
+ virtual void detach();
+
+ void cancelManualPluginLoad();
+
+ bool shouldLoadPluginManually() { return m_shouldLoadPluginManually; }
+
private:
PluginDocument(Frame*, const KURL&);
virtual PassRefPtr<DocumentParser> createParser();
+
+ void setShouldLoadPluginManually(bool loadManually) { m_shouldLoadPluginManually = loadManually; }
+
+ bool m_shouldLoadPluginManually;
+ RefPtr<Node> m_pluginNode;
};
+
+inline PluginDocument* toPluginDocument(Document* document)
+{
+ ASSERT(!document || document->isPluginDocument());
+ return static_cast<PluginDocument*>(document);
+}
+
+inline const PluginDocument* toPluginDocument(const Document* document)
+{
+ ASSERT(!document || document->isPluginDocument());
+ return static_cast<const PluginDocument*>(document);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toPluginDocument(const PluginDocument*);
}
diff --git a/WebCore/html/RadioInputType.cpp b/WebCore/html/RadioInputType.cpp
index a1c8d04..5df4bbc 100644
--- a/WebCore/html/RadioInputType.cpp
+++ b/WebCore/html/RadioInputType.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "RadioInputType.h"
+#include "HTMLInputElement.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -45,4 +46,9 @@ const AtomicString& RadioInputType::formControlType() const
return InputTypeNames::radio();
}
+bool RadioInputType::valueMissing(const String&) const
+{
+ return !element()->checkedRadioButtons().checkedButtonForGroup(element()->name());
+}
+
} // namespace WebCore
diff --git a/WebCore/html/RadioInputType.h b/WebCore/html/RadioInputType.h
index 180c6dd..2ff2c41 100644
--- a/WebCore/html/RadioInputType.h
+++ b/WebCore/html/RadioInputType.h
@@ -42,6 +42,7 @@ public:
private:
RadioInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool valueMissing(const String&) const;
};
} // namespace WebCore
diff --git a/WebCore/html/RangeInputType.cpp b/WebCore/html/RangeInputType.cpp
index f5f7322..7448071 100644
--- a/WebCore/html/RangeInputType.cpp
+++ b/WebCore/html/RangeInputType.cpp
@@ -31,10 +31,23 @@
#include "config.h"
#include "RangeInputType.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
+#include <limits>
+#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+using namespace std;
+
+static const double rangeDefaultMinimum = 0.0;
+static const double rangeDefaultMaximum = 100.0;
+static const double rangeDefaultStep = 1.0;
+static const double rangeStepScaleFactor = 1.0;
+
PassOwnPtr<InputType> RangeInputType::create(HTMLInputElement* element)
{
return adoptPtr(new RangeInputType(element));
@@ -45,4 +58,88 @@ const AtomicString& RangeInputType::formControlType() const
return InputTypeNames::range();
}
+double RangeInputType::valueAsNumber() const
+{
+ return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN());
+}
+
+void RangeInputType::setValueAsNumber(double newValue, ExceptionCode&) const
+{
+ element()->setValue(serialize(newValue));
+}
+
+bool RangeInputType::supportsRequired() const
+{
+ return false;
+}
+
+bool RangeInputType::rangeUnderflow(const String& value) const
+{
+ // Guaranteed by sanitization.
+ ASSERT_UNUSED(value, parseToDouble(value, numeric_limits<double>::quiet_NaN()) >= minimum());
+ return false;
+}
+
+bool RangeInputType::rangeOverflow(const String& value) const
+{
+ // Guaranteed by sanitization.
+ ASSERT_UNUSED(value, parseToDouble(value, numeric_limits<double>::quiet_NaN()) <= maximum());
+ return false;
+}
+
+double RangeInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), rangeDefaultMinimum);
+}
+
+double RangeInputType::maximum() const
+{
+ double max = parseToDouble(element()->fastGetAttribute(maxAttr), rangeDefaultMaximum);
+ // A remedy for the inconsistent min/max values.
+ // Sets the maximum to the default or the minimum value.
+ double min = minimum();
+ if (max < min)
+ max = std::max(min, rangeDefaultMaximum);
+ return max;
+}
+
+bool RangeInputType::stepMismatch(const String&, double) const
+{
+ // stepMismatch doesn't occur for type=range. RenderSlider guarantees the
+ // value matches to step on user input, and sanitization takes care
+ // of the general case.
+ return false;
+}
+
+double RangeInputType::stepBase() const
+{
+ return minimum();
+}
+
+double RangeInputType::defaultStep() const
+{
+ return rangeDefaultStep;
+}
+
+double RangeInputType::stepScaleFactor() const
+{
+ return rangeStepScaleFactor;
+}
+
+double RangeInputType::parseToDouble(const String& src, double defaultValue) const
+{
+ double numberValue;
+ if (!parseToDoubleForNumberType(src, &numberValue))
+ return defaultValue;
+ ASSERT(isfinite(numberValue));
+ return numberValue;
+}
+
+String RangeInputType::serialize(double value) const
+{
+ if (!isfinite(value))
+ return String();
+ return serializeForNumberType(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/RangeInputType.h b/WebCore/html/RangeInputType.h
index d42c617..0ff6f60 100644
--- a/WebCore/html/RangeInputType.h
+++ b/WebCore/html/RangeInputType.h
@@ -42,6 +42,19 @@ public:
private:
RangeInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double valueAsNumber() const;
+ virtual void setValueAsNumber(double, ExceptionCode&) const;
+ virtual bool supportsRequired() const;
+ virtual bool rangeUnderflow(const String&) const;
+ virtual bool rangeOverflow(const String&) const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual bool stepMismatch(const String&, double) const;
+ virtual double stepBase() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual double parseToDouble(const String&, double) const;
+ virtual String serialize(double) const;
};
} // namespace WebCore
diff --git a/WebCore/html/ResetInputType.cpp b/WebCore/html/ResetInputType.cpp
index 8b18a8d..1db7592 100644
--- a/WebCore/html/ResetInputType.cpp
+++ b/WebCore/html/ResetInputType.cpp
@@ -45,4 +45,9 @@ const AtomicString& ResetInputType::formControlType() const
return InputTypeNames::reset();
}
+bool ResetInputType::supportsValidation() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/ResetInputType.h b/WebCore/html/ResetInputType.h
index e0d8997..3f883a3 100644
--- a/WebCore/html/ResetInputType.h
+++ b/WebCore/html/ResetInputType.h
@@ -42,6 +42,7 @@ public:
private:
ResetInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool supportsValidation() const;
};
} // namespace WebCore
diff --git a/WebCore/html/SubmitInputType.cpp b/WebCore/html/SubmitInputType.cpp
index dd13e6b..65934f9 100644
--- a/WebCore/html/SubmitInputType.cpp
+++ b/WebCore/html/SubmitInputType.cpp
@@ -45,4 +45,9 @@ const AtomicString& SubmitInputType::formControlType() const
return InputTypeNames::submit();
}
+bool SubmitInputType::supportsValidation() const
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/html/SubmitInputType.h b/WebCore/html/SubmitInputType.h
index 7ea448e..83fa5e5 100644
--- a/WebCore/html/SubmitInputType.h
+++ b/WebCore/html/SubmitInputType.h
@@ -42,6 +42,7 @@ public:
private:
SubmitInputType(HTMLInputElement* element) : InputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool supportsValidation() const;
};
} // namespace WebCore
diff --git a/WebCore/html/TextFieldInputType.cpp b/WebCore/html/TextFieldInputType.cpp
index e681b40..82382ef 100644
--- a/WebCore/html/TextFieldInputType.cpp
+++ b/WebCore/html/TextFieldInputType.cpp
@@ -31,6 +31,8 @@
#include "config.h"
#include "TextFieldInputType.h"
+#include <wtf/text/WTFString.h>
+
namespace WebCore {
bool TextFieldInputType::isTextField() const
@@ -38,4 +40,9 @@ bool TextFieldInputType::isTextField() const
return true;
}
+bool TextFieldInputType::valueMissing(const String& value) const
+{
+ return value.isEmpty();
+}
+
} // namespace WebCore
diff --git a/WebCore/html/TextFieldInputType.h b/WebCore/html/TextFieldInputType.h
index fb33a01..9108c42 100644
--- a/WebCore/html/TextFieldInputType.h
+++ b/WebCore/html/TextFieldInputType.h
@@ -41,6 +41,7 @@ class TextFieldInputType : public InputType {
protected:
TextFieldInputType(HTMLInputElement* element) : InputType(element) { }
virtual bool isTextField() const;
+ virtual bool valueMissing(const String&) const;
};
} // namespace WebCore
diff --git a/WebCore/html/TimeInputType.cpp b/WebCore/html/TimeInputType.cpp
index 1564bc5..27dce90 100644
--- a/WebCore/html/TimeInputType.cpp
+++ b/WebCore/html/TimeInputType.cpp
@@ -31,10 +31,18 @@
#include "config.h"
#include "TimeInputType.h"
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
+static const double timeDefaultStep = 60.0;
+static const double timeStepScaleFactor = 1000.0;
+
PassOwnPtr<InputType> TimeInputType::create(HTMLInputElement* element)
{
return adoptPtr(new TimeInputType(element));
@@ -45,4 +53,42 @@ const AtomicString& TimeInputType::formControlType() const
return InputTypeNames::time();
}
+double TimeInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumTime());
+}
+
+double TimeInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumTime());
+}
+
+double TimeInputType::defaultStep() const
+{
+ return timeDefaultStep;
+}
+
+double TimeInputType::stepScaleFactor() const
+{
+ return timeStepScaleFactor;
+}
+
+bool TimeInputType::scaledStepValeuShouldBeInteger() const
+{
+ return true;
+}
+
+bool TimeInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+{
+ ASSERT(out);
+ unsigned end;
+ return out->parseTime(characters, length, 0, end) && end == length;
+}
+
+bool TimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+{
+ ASSERT(date);
+ return date->setMillisecondsSinceMidnight(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/TimeInputType.h b/WebCore/html/TimeInputType.h
index 9530f7d..6070fa0 100644
--- a/WebCore/html/TimeInputType.h
+++ b/WebCore/html/TimeInputType.h
@@ -31,17 +31,24 @@
#ifndef TimeInputType_h
#define TimeInputType_h
-#include "TextFieldInputType.h"
+#include "BaseDateAndTimeInputType.h"
namespace WebCore {
-class TimeInputType : public TextFieldInputType {
+class TimeInputType : public BaseDateAndTimeInputType {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- TimeInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ TimeInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool scaledStepValeuShouldBeInteger() const;
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const;
};
} // namespace WebCore
diff --git a/WebCore/html/URLInputType.cpp b/WebCore/html/URLInputType.cpp
index 2afdcde..517ffad 100644
--- a/WebCore/html/URLInputType.cpp
+++ b/WebCore/html/URLInputType.cpp
@@ -31,6 +31,8 @@
#include "config.h"
#include "URLInputType.h"
+#include "HTMLInputElement.h"
+#include "KURL.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
@@ -45,4 +47,14 @@ const AtomicString& URLInputType::formControlType() const
return InputTypeNames::url();
}
+bool URLInputType::typeMismatchFor(const String& value) const
+{
+ return !value.isEmpty() && !KURL(KURL(), value).isValid();
+}
+
+bool URLInputType::typeMismatch() const
+{
+ return typeMismatchFor(element()->value());
+}
+
} // namespace WebCore
diff --git a/WebCore/html/URLInputType.h b/WebCore/html/URLInputType.h
index 85d4f9f..82ab1b7 100644
--- a/WebCore/html/URLInputType.h
+++ b/WebCore/html/URLInputType.h
@@ -42,6 +42,8 @@ public:
private:
URLInputType(HTMLInputElement* element) : BaseTextInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual bool typeMismatchFor(const String&) const;
+ virtual bool typeMismatch() const;
};
} // namespace WebCore
diff --git a/WebCore/html/ValidityState.cpp b/WebCore/html/ValidityState.cpp
index f18469e..57fb438 100644
--- a/WebCore/html/ValidityState.cpp
+++ b/WebCore/html/ValidityState.cpp
@@ -83,12 +83,7 @@ bool ValidityState::typeMismatch() const
{
if (!m_control->hasTagName(inputTag))
return false;
-
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_control);
- String value = input->value();
- if (value.isEmpty())
- return false;
- return input->typeMismatch(value);
+ return static_cast<HTMLInputElement*>(m_control)->typeMismatch();
}
bool ValidityState::patternMismatch() const
diff --git a/WebCore/html/WeekInputType.cpp b/WebCore/html/WeekInputType.cpp
index 0b4ab30..a5836dc 100644
--- a/WebCore/html/WeekInputType.cpp
+++ b/WebCore/html/WeekInputType.cpp
@@ -31,10 +31,19 @@
#include "config.h"
#include "WeekInputType.h"
+#include "DateComponents.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
+static const double weekDefaultStepBase = -259200000.0; // The first day of 1970-W01.
+static const double weekDefaultStep = 1.0;
+static const double weekStepScaleFactor = 604800000.0;
+
PassOwnPtr<InputType> WeekInputType::create(HTMLInputElement* element)
{
return adoptPtr(new WeekInputType(element));
@@ -45,4 +54,47 @@ const AtomicString& WeekInputType::formControlType() const
return InputTypeNames::week();
}
+double WeekInputType::minimum() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumWeek());
+}
+
+double WeekInputType::maximum() const
+{
+ return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumWeek());
+}
+
+double WeekInputType::stepBase() const
+{
+ return parseToDouble(element()->fastGetAttribute(minAttr), weekDefaultStepBase);
+}
+
+double WeekInputType::defaultStep() const
+{
+ return weekDefaultStep;
+}
+
+double WeekInputType::stepScaleFactor() const
+{
+ return weekStepScaleFactor;
+}
+
+bool WeekInputType::parsedStepValueShouldBeInteger() const
+{
+ return true;
+}
+
+bool WeekInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+{
+ ASSERT(out);
+ unsigned end;
+ return out->parseWeek(characters, length, 0, end) && end == length;
+}
+
+bool WeekInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+{
+ ASSERT(date);
+ return date->setMillisecondsSinceEpochForWeek(value);
+}
+
} // namespace WebCore
diff --git a/WebCore/html/WeekInputType.h b/WebCore/html/WeekInputType.h
index 7b6ee23..437164b 100644
--- a/WebCore/html/WeekInputType.h
+++ b/WebCore/html/WeekInputType.h
@@ -31,17 +31,25 @@
#ifndef WeekInputType_h
#define WeekInputType_h
-#include "TextFieldInputType.h"
+#include "BaseDateAndTimeInputType.h"
namespace WebCore {
-class WeekInputType : public TextFieldInputType {
+class WeekInputType : public BaseDateAndTimeInputType {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
private:
- WeekInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
+ WeekInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
virtual const AtomicString& formControlType() const;
+ virtual double minimum() const;
+ virtual double maximum() const;
+ virtual double stepBase() const;
+ virtual double defaultStep() const;
+ virtual double stepScaleFactor() const;
+ virtual bool parsedStepValueShouldBeInteger() const;
+ virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const;
+ virtual bool setMillisecondToDateComponents(double, DateComponents*) const;
};
} // namespace WebCore
diff --git a/WebCore/html/canvas/ArrayBuffer.cpp b/WebCore/html/canvas/ArrayBuffer.cpp
index 3b204ff..014cc1e 100644
--- a/WebCore/html/canvas/ArrayBuffer.cpp
+++ b/WebCore/html/canvas/ArrayBuffer.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "ArrayBuffer.h"
@@ -93,4 +93,4 @@ void* ArrayBuffer::tryAllocate(unsigned numElements, unsigned elementByteSize)
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/ArrayBuffer.idl b/WebCore/html/canvas/ArrayBuffer.idl
index 92098e5..79a4685 100644
--- a/WebCore/html/canvas/ArrayBuffer.idl
+++ b/WebCore/html/canvas/ArrayBuffer.idl
@@ -26,10 +26,11 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
- V8CustomConstructor
+ NoStaticTables,
+ V8CustomConstructor,
] ArrayBuffer {
readonly attribute int byteLength;
};
diff --git a/WebCore/html/canvas/ArrayBufferView.cpp b/WebCore/html/canvas/ArrayBufferView.cpp
index 485d18b..7f41bda 100644
--- a/WebCore/html/canvas/ArrayBufferView.cpp
+++ b/WebCore/html/canvas/ArrayBufferView.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "ArrayBufferView.h"
@@ -106,4 +106,4 @@ void ArrayBufferView::calculateOffsetAndLength(int start, int end, unsigned arra
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/ArrayBufferView.idl b/WebCore/html/canvas/ArrayBufferView.idl
index 450345e..74a3fe3 100644
--- a/WebCore/html/canvas/ArrayBufferView.idl
+++ b/WebCore/html/canvas/ArrayBufferView.idl
@@ -24,7 +24,7 @@
*/
module html {
- interface [Conditional=3D_CANVAS, CustomToJS, OmitConstructor] ArrayBufferView {
+ interface [Conditional=3D_CANVAS|BLOB, CustomToJS, NoStaticTables, OmitConstructor] ArrayBufferView {
readonly attribute ArrayBuffer buffer;
readonly attribute unsigned long byteOffset;
readonly attribute unsigned long byteLength;
diff --git a/WebCore/html/canvas/CanvasGradient.cpp b/WebCore/html/canvas/CanvasGradient.cpp
index fd48194..7c98a82 100644
--- a/WebCore/html/canvas/CanvasGradient.cpp
+++ b/WebCore/html/canvas/CanvasGradient.cpp
@@ -27,6 +27,8 @@
#include "config.h"
#include "CanvasGradient.h"
+#include "CanvasPattern.h"
+#include "CanvasStyle.h"
#include "CSSParser.h"
#include "ExceptionCode.h"
@@ -52,7 +54,7 @@ void CanvasGradient::addColorStop(float value, const String& color, ExceptionCod
}
RGBA32 rgba = 0;
- if (!CSSParser::parseColor(rgba, color)) {
+ if (!parseColorOrCurrentColor(rgba, color, 0 /*canvas*/)) {
if (!m_dashbardCompatibilityMode)
ec = SYNTAX_ERR;
return;
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 161a891..b1d7b23 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -128,10 +128,10 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, bo
return;
if (!p->settings()->accelerated2dCanvasEnabled())
return;
- m_context3D = p->chrome()->client()->getSharedGraphicsContext3D();
- if (m_context3D) {
- if (GraphicsContext* c = drawingContext()) {
- m_drawingBuffer = DrawingBuffer::create(m_context3D.get(), IntSize(canvas->width(), canvas->height()));
+ if (GraphicsContext* c = drawingContext()) {
+ m_context3D = p->sharedGraphicsContext3D();
+ if (m_context3D) {
+ m_drawingBuffer = m_context3D->graphicsContext3D()->createDrawingBuffer(IntSize(canvas->width(), canvas->height()));
c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas->width(), canvas->height()));
}
}
@@ -167,8 +167,8 @@ void CanvasRenderingContext2D::reset()
m_stateStack.first() = State();
m_path.clear();
#if ENABLE(ACCELERATED_2D_CANVAS)
- if (m_context3D) {
- if (GraphicsContext* c = drawingContext()) {
+ if (GraphicsContext* c = drawingContext()) {
+ if (m_context3D) {
m_drawingBuffer->reset(IntSize(canvas()->width(), canvas()->height()));
c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas()->width(), canvas()->height()));
}
@@ -231,7 +231,7 @@ void CanvasRenderingContext2D::setAllAttributesToDefault()
if (!context)
return;
- context->setShadow(FloatSize(), 0, Color::transparent, DeviceColorSpace);
+ context->setShadow(FloatSize(), 0, Color::transparent, ColorSpaceDeviceRGB);
context->setAlpha(1);
context->setCompositeOperation(CompositeSourceOver);
}
@@ -249,7 +249,13 @@ void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> style)
if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style))
return;
- checkOrigin(style->canvasPattern());
+ if (style->isCurrentColor()) {
+ if (style->hasOverrideAlpha())
+ style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha()));
+ else
+ style = CanvasStyle::createFromRGBA(currentColor(canvas()));
+ } else
+ checkOrigin(style->canvasPattern());
state().m_strokeStyle = style;
GraphicsContext* c = drawingContext();
@@ -272,7 +278,13 @@ void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> style)
if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style))
return;
- checkOrigin(style->canvasPattern());
+ if (style->isCurrentColor()) {
+ if (style->hasOverrideAlpha())
+ style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha()));
+ else
+ style = CanvasStyle::createFromRGBA(currentColor(canvas()));
+ } else
+ checkOrigin(style->canvasPattern());
state().m_fillStyle = style;
GraphicsContext* c = drawingContext();
@@ -394,7 +406,7 @@ String CanvasRenderingContext2D::shadowColor() const
void CanvasRenderingContext2D::setShadowColor(const String& color)
{
- if (!CSSParser::parseColor(state().m_shadowColor, color))
+ if (!parseColorOrCurrentColor(state().m_shadowColor, color, canvas()))
return;
applyShadow();
@@ -982,7 +994,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur)
void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color)
{
- if (!CSSParser::parseColor(state().m_shadowColor, color))
+ if (!parseColorOrCurrentColor(state().m_shadowColor, color, canvas()))
return;
state().m_shadowOffset = FloatSize(width, height);
@@ -1000,14 +1012,14 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
if (!c)
return;
- c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, DeviceColorSpace);
+ c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, ColorSpaceDeviceRGB);
}
void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color, float alpha)
{
RGBA32 rgba;
- if (!CSSParser::parseColor(rgba, color))
+ if (!parseColorOrCurrentColor(rgba, color, canvas()))
return;
state().m_shadowColor = colorWithOverrideAlpha(rgba, alpha);
@@ -1018,7 +1030,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
if (!c)
return;
- c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, DeviceColorSpace);
+ c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, ColorSpaceDeviceRGB);
}
void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha)
@@ -1031,7 +1043,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
if (!c)
return;
- c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, DeviceColorSpace);
+ c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, ColorSpaceDeviceRGB);
}
void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float r, float g, float b, float a)
@@ -1044,7 +1056,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
if (!c)
return;
- c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, DeviceColorSpace);
+ c->setShadow(IntSize(width, -height), state().m_shadowBlur, state().m_shadowColor, ColorSpaceDeviceRGB);
}
void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float c, float m, float y, float k, float a)
@@ -1064,7 +1076,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
CGContextSetShadowWithColor(dc->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor);
CGColorRelease(shadowColor);
#else
- dc->setShadow(IntSize(width, -height), blur, state().m_shadowColor, DeviceColorSpace);
+ dc->setShadow(IntSize(width, -height), blur, state().m_shadowColor, ColorSpaceDeviceRGB);
#endif
}
@@ -1084,7 +1096,7 @@ void CanvasRenderingContext2D::applyShadow()
float width = state().m_shadowOffset.width();
float height = state().m_shadowOffset.height();
- c->setShadow(FloatSize(width, -height), state().m_shadowBlur, state().m_shadowColor, DeviceColorSpace);
+ c->setShadow(FloatSize(width, -height), state().m_shadowBlur, state().m_shadowColor, ColorSpaceDeviceRGB);
}
static IntSize size(HTMLImageElement* image)
@@ -1186,7 +1198,7 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec
FloatRect sourceRect = c->roundToDevicePixels(normalizedSrcRect);
FloatRect destRect = c->roundToDevicePixels(normalizedDstRect);
- c->drawImage(cachedImage->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
+ c->drawImage(cachedImage->image(), ColorSpaceDeviceRGB, destRect, sourceRect, state().m_globalComposite);
didDraw(destRect);
}
@@ -1268,7 +1280,7 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
sourceCanvas->makeRenderingResultsAvailable();
#endif
- c->drawImageBuffer(buffer, DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
+ c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, destRect, sourceRect, state().m_globalComposite);
didDraw(destRect);
}
@@ -1371,7 +1383,7 @@ void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image,
op = CompositeSourceOver;
FloatRect destRect = FloatRect(dx, dy, dw, dh);
- c->drawImage(cachedImage->image(), DeviceColorSpace, destRect, FloatRect(sx, sy, sw, sh), op);
+ c->drawImage(cachedImage->image(), ColorSpaceDeviceRGB, destRect, FloatRect(sx, sy, sw, sh), op);
didDraw(destRect);
}
@@ -1402,9 +1414,9 @@ PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float
return 0;
}
- PassRefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
+ RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
prepareGradientForDashboard(gradient.get());
- return gradient;
+ return gradient.release();
}
PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode& ec)
@@ -1413,9 +1425,15 @@ PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float
ec = NOT_SUPPORTED_ERR;
return 0;
}
- PassRefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
+
+ if (r0 < 0 || r1 < 0) {
+ ec = INDEX_SIZE_ERR;
+ return 0;
+ }
+
+ RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
prepareGradientForDashboard(gradient.get());
- return gradient;
+ return gradient.release();
}
PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image,
@@ -1513,7 +1531,7 @@ static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size)
{
RefPtr<ImageData> data = ImageData::create(size.width(), size.height());
memset(data->data()->data()->data(), 0, data->data()->data()->length());
- return data.get();
+ return data.release();
}
PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<ImageData> imageData, ExceptionCode& ec) const
@@ -1614,16 +1632,16 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy,
FloatRect clipRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
clipRect.intersect(IntRect(0, 0, data->width(), data->height()));
IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy));
- IntRect sourceRect = enclosingIntRect(clipRect);
- sourceRect.move(destOffset);
- sourceRect.intersect(IntRect(IntPoint(), buffer->size()));
- if (sourceRect.isEmpty())
+ IntRect destRect = enclosingIntRect(clipRect);
+ destRect.move(destOffset);
+ destRect.intersect(IntRect(IntPoint(), buffer->size()));
+ if (destRect.isEmpty())
return;
+ IntRect sourceRect(destRect);
sourceRect.move(-destOffset);
- IntPoint destPoint(destOffset.width(), destOffset.height());
- buffer->putUnmultipliedImageData(data, sourceRect, destPoint);
- didDraw(sourceRect, CanvasDidDrawApplyNone); // ignore transform, shadow and clip
+ buffer->putUnmultipliedImageData(data, sourceRect, IntPoint(destOffset));
+ didDraw(destRect, CanvasDidDrawApplyNone); // ignore transform, shadow and clip
}
String CanvasRenderingContext2D::font() const
@@ -1732,7 +1750,7 @@ PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text
Font::setCodePath(oldCodePath);
#endif
- return metrics;
+ return metrics.release();
}
void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float /*maxWidth*/, bool /*useMaxWidth*/)
@@ -1749,7 +1767,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
// FIXME: Need to turn off font smoothing.
RenderStyle* computedStyle = canvas()->computedStyle();
- bool rtl = computedStyle ? computedStyle->direction() == RTL : false;
+ bool rtl = computedStyle ? !computedStyle->isLeftToRightDirection() : false;
bool override = computedStyle ? computedStyle->unicodeBidi() == Override : false;
unsigned length = text.length();
@@ -1812,9 +1830,9 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
GraphicsContext* maskImageContext = maskImage->context();
if (fill)
- maskImageContext->setFillColor(Color::black, DeviceColorSpace);
+ maskImageContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
else {
- maskImageContext->setStrokeColor(Color::black, DeviceColorSpace);
+ maskImageContext->setStrokeColor(Color::black, ColorSpaceDeviceRGB);
maskImageContext->setStrokeThickness(c->strokeThickness());
}
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.h b/WebCore/html/canvas/CanvasRenderingContext2D.h
index 2c88a31..f51c5e9 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.h
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.h
@@ -294,7 +294,7 @@ private:
#endif
#if ENABLE(ACCELERATED_2D_CANVAS)
- OwnPtr<DrawingBuffer> m_drawingBuffer;
+ RefPtr<DrawingBuffer> m_drawingBuffer;
RefPtr<SharedGraphicsContext3D> m_context3D;
#endif
};
diff --git a/WebCore/html/canvas/CanvasStyle.cpp b/WebCore/html/canvas/CanvasStyle.cpp
index fd3c6e5..a4e87e3 100644
--- a/WebCore/html/canvas/CanvasStyle.cpp
+++ b/WebCore/html/canvas/CanvasStyle.cpp
@@ -30,9 +30,11 @@
#include "CanvasStyle.h"
#include "CSSParser.h"
+#include "CSSPropertyNames.h"
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "GraphicsContext.h"
+#include "HTMLCanvasElement.h"
#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h>
@@ -49,6 +51,49 @@
namespace WebCore {
+enum ColorParseResult { ParsedRGBA, ParsedCurrentColor, ParseFailed };
+
+static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString)
+{
+ if (equalIgnoringCase(colorString, "currentcolor"))
+ return ParsedCurrentColor;
+ if (CSSParser::parseColor(parsedColor, colorString))
+ return ParsedRGBA;
+ return ParseFailed;
+}
+
+RGBA32 currentColor(HTMLCanvasElement* canvas)
+{
+ if (!canvas || !canvas->inDocument())
+ return Color::black;
+ RGBA32 rgba = Color::black;
+ CSSParser::parseColor(rgba, canvas->style()->getPropertyValue(CSSPropertyColor));
+ return rgba;
+}
+
+bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement* canvas)
+{
+ ColorParseResult parseResult = parseColor(parsedColor, colorString);
+ switch (parseResult) {
+ case ParsedRGBA:
+ return true;
+ case ParsedCurrentColor:
+ parsedColor = currentColor(canvas);
+ return true;
+ case ParseFailed:
+ return false;
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+}
+
+CanvasStyle::CanvasStyle(Type type, float overrideAlpha)
+ : m_type(type)
+ , m_overrideAlpha(overrideAlpha)
+{
+}
+
CanvasStyle::CanvasStyle(RGBA32 rgba)
: m_type(RGBA)
, m_rgba(rgba)
@@ -89,17 +134,35 @@ CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern)
PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color)
{
RGBA32 rgba;
- if (!CSSParser::parseColor(rgba, color))
+ ColorParseResult parseResult = parseColor(rgba, color);
+ switch (parseResult) {
+ case ParsedRGBA:
+ return adoptRef(new CanvasStyle(rgba));
+ case ParsedCurrentColor:
+ return adoptRef(new CanvasStyle(CurrentColor));
+ case ParseFailed:
return 0;
- return adoptRef(new CanvasStyle(rgba));
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
}
PassRefPtr<CanvasStyle> CanvasStyle::createFromStringWithOverrideAlpha(const String& color, float alpha)
{
RGBA32 rgba;
- if (!CSSParser::parseColor(rgba, color))
+ ColorParseResult parseResult = parseColor(rgba, color);
+ switch (parseResult) {
+ case ParsedRGBA:
+ return adoptRef(new CanvasStyle(colorWithOverrideAlpha(rgba, alpha)));
+ case ParsedCurrentColor:
+ return adoptRef(new CanvasStyle(CurrentColorWithOverrideAlpha, alpha));
+ case ParseFailed:
+ return 0;
+ default:
+ ASSERT_NOT_REACHED();
return 0;
- return adoptRef(new CanvasStyle(colorWithOverrideAlpha(rgba, alpha)));
+ }
}
PassRefPtr<CanvasStyle> CanvasStyle::createFromGradient(PassRefPtr<CanvasGradient> gradient)
@@ -121,16 +184,18 @@ bool CanvasStyle::isEquivalentColor(const CanvasStyle& other) const
return false;
switch (m_type) {
- case CanvasStyle::RGBA:
+ case RGBA:
return m_rgba == other.m_rgba;
- case CanvasStyle::CMYKA:
+ case CMYKA:
return m_cmyka.c == other.m_cmyka.c
&& m_cmyka.m == other.m_cmyka.m
&& m_cmyka.y == other.m_cmyka.y
&& m_cmyka.k == other.m_cmyka.k
&& m_cmyka.a == other.m_cmyka.a;
- case CanvasStyle::Gradient:
- case CanvasStyle::ImagePattern:
+ case Gradient:
+ case ImagePattern:
+ case CurrentColor:
+ case CurrentColorWithOverrideAlpha:
return false;
}
@@ -164,7 +229,7 @@ void CanvasStyle::applyStrokeColor(GraphicsContext* context)
return;
switch (m_type) {
case RGBA:
- context->setStrokeColor(m_rgba, DeviceColorSpace);
+ context->setStrokeColor(m_rgba, ColorSpaceDeviceRGB);
break;
case CMYKA: {
// FIXME: Do this through platform-independent GraphicsContext API.
@@ -178,7 +243,7 @@ void CanvasStyle::applyStrokeColor(GraphicsContext* context)
currentPen.setColor(clr);
context->platformContext()->setPen(currentPen);
#else
- context->setStrokeColor(m_rgba, DeviceColorSpace);
+ context->setStrokeColor(m_rgba, ColorSpaceDeviceRGB);
#endif
break;
}
@@ -188,6 +253,10 @@ void CanvasStyle::applyStrokeColor(GraphicsContext* context)
case ImagePattern:
context->setStrokePattern(canvasPattern()->pattern());
break;
+ case CurrentColor:
+ case CurrentColorWithOverrideAlpha:
+ ASSERT_NOT_REACHED();
+ break;
}
}
@@ -197,7 +266,7 @@ void CanvasStyle::applyFillColor(GraphicsContext* context)
return;
switch (m_type) {
case RGBA:
- context->setFillColor(m_rgba, DeviceColorSpace);
+ context->setFillColor(m_rgba, ColorSpaceDeviceRGB);
break;
case CMYKA: {
// FIXME: Do this through platform-independent GraphicsContext API.
@@ -211,7 +280,7 @@ void CanvasStyle::applyFillColor(GraphicsContext* context)
currentBrush.setColor(clr);
context->platformContext()->setBrush(currentBrush);
#else
- context->setFillColor(m_rgba, DeviceColorSpace);
+ context->setFillColor(m_rgba, ColorSpaceDeviceRGB);
#endif
break;
}
@@ -221,6 +290,10 @@ void CanvasStyle::applyFillColor(GraphicsContext* context)
case ImagePattern:
context->setFillPattern(canvasPattern()->pattern());
break;
+ case CurrentColor:
+ case CurrentColorWithOverrideAlpha:
+ ASSERT_NOT_REACHED();
+ break;
}
}
diff --git a/WebCore/html/canvas/CanvasStyle.h b/WebCore/html/canvas/CanvasStyle.h
index 3ca760a..91dc923 100644
--- a/WebCore/html/canvas/CanvasStyle.h
+++ b/WebCore/html/canvas/CanvasStyle.h
@@ -29,12 +29,14 @@
#include "Color.h"
#include "PlatformString.h"
+#include <wtf/Assertions.h>
namespace WebCore {
class CanvasGradient;
class CanvasPattern;
class GraphicsContext;
+ class HTMLCanvasElement;
class CanvasStyle : public RefCounted<CanvasStyle> {
public:
@@ -47,7 +49,11 @@ namespace WebCore {
static PassRefPtr<CanvasStyle> createFromGradient(PassRefPtr<CanvasGradient>);
static PassRefPtr<CanvasStyle> createFromPattern(PassRefPtr<CanvasPattern>);
- String color() const { return Color(m_rgba).serialized(); }
+ bool isCurrentColor() const { return m_type == CurrentColor || m_type == CurrentColorWithOverrideAlpha; }
+ bool hasOverrideAlpha() const { return m_type == CurrentColorWithOverrideAlpha; }
+ float overrideAlpha() const { ASSERT(m_type == CurrentColorWithOverrideAlpha); return m_overrideAlpha; }
+
+ String color() const { ASSERT(m_type == RGBA || m_type == CMYKA); return Color(m_rgba).serialized(); }
CanvasGradient* canvasGradient() const { return m_gradient.get(); }
CanvasPattern* canvasPattern() const { return m_pattern.get(); }
@@ -59,6 +65,9 @@ namespace WebCore {
bool isEquivalentCMYKA(float c, float m, float y, float k, float a) const;
private:
+ enum Type { RGBA, CMYKA, Gradient, ImagePattern, CurrentColor, CurrentColorWithOverrideAlpha };
+
+ CanvasStyle(Type, float overrideAlpha = 0);
CanvasStyle(RGBA32 rgba);
CanvasStyle(float grayLevel, float alpha);
CanvasStyle(float r, float g, float b, float a);
@@ -66,11 +75,12 @@ namespace WebCore {
CanvasStyle(PassRefPtr<CanvasGradient>);
CanvasStyle(PassRefPtr<CanvasPattern>);
- enum Type { RGBA, CMYKA, Gradient, ImagePattern };
-
Type m_type;
- RGBA32 m_rgba;
+ union {
+ RGBA32 m_rgba;
+ float m_overrideAlpha;
+ };
RefPtr<CanvasGradient> m_gradient;
RefPtr<CanvasPattern> m_pattern;
@@ -86,6 +96,9 @@ namespace WebCore {
} m_cmyka;
};
+ RGBA32 currentColor(HTMLCanvasElement*);
+ bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement*);
+
} // namespace WebCore
#endif
diff --git a/WebCore/html/canvas/Float32Array.cpp b/WebCore/html/canvas/Float32Array.cpp
index e6e8439..e918d8f 100644
--- a/WebCore/html/canvas/Float32Array.cpp
+++ b/WebCore/html/canvas/Float32Array.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Float32Array.h"
@@ -59,4 +59,4 @@ PassRefPtr<ArrayBufferView> Float32Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Float32Array.idl b/WebCore/html/canvas/Float32Array.idl
index 5a939ca..c3c0a2d 100644
--- a/WebCore/html/canvas/Float32Array.idl
+++ b/WebCore/html/canvas/Float32Array.idl
@@ -26,13 +26,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Float32Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/Int16Array.cpp b/WebCore/html/canvas/Int16Array.cpp
index f3f9742..635ea5e 100644
--- a/WebCore/html/canvas/Int16Array.cpp
+++ b/WebCore/html/canvas/Int16Array.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Int16Array.h"
@@ -58,4 +58,4 @@ PassRefPtr<ArrayBufferView> Int16Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Int16Array.idl b/WebCore/html/canvas/Int16Array.idl
index 02417f8..7980a69 100644
--- a/WebCore/html/canvas/Int16Array.idl
+++ b/WebCore/html/canvas/Int16Array.idl
@@ -25,13 +25,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Int16Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/Int32Array.cpp b/WebCore/html/canvas/Int32Array.cpp
index 423c36b..cc926a3 100644
--- a/WebCore/html/canvas/Int32Array.cpp
+++ b/WebCore/html/canvas/Int32Array.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Int32Array.h"
@@ -59,4 +59,4 @@ PassRefPtr<ArrayBufferView> Int32Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Int32Array.h b/WebCore/html/canvas/Int32Array.h
index 72fb579..bd05450 100644
--- a/WebCore/html/canvas/Int32Array.h
+++ b/WebCore/html/canvas/Int32Array.h
@@ -37,8 +37,10 @@ class Int32Array : public IntegralTypedArrayBase<int> {
static PassRefPtr<Int32Array> create(int* array, unsigned length);
static PassRefPtr<Int32Array> create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length);
+#if !COMPILER(RVCT)
using TypedArrayBase<int>::set;
using IntegralTypedArrayBase<int>::set;
+#endif
private:
Int32Array(PassRefPtr<ArrayBuffer> buffer,
diff --git a/WebCore/html/canvas/Int32Array.idl b/WebCore/html/canvas/Int32Array.idl
index 6977d00..bd1554d 100644
--- a/WebCore/html/canvas/Int32Array.idl
+++ b/WebCore/html/canvas/Int32Array.idl
@@ -26,13 +26,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Int32Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/Int8Array.cpp b/WebCore/html/canvas/Int8Array.cpp
index 20ff32a..c2dd2fa 100644
--- a/WebCore/html/canvas/Int8Array.cpp
+++ b/WebCore/html/canvas/Int8Array.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Int8Array.h"
@@ -59,4 +59,4 @@ PassRefPtr<ArrayBufferView> Int8Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Int8Array.idl b/WebCore/html/canvas/Int8Array.idl
index 4dba9e4..ec0bdb7 100644
--- a/WebCore/html/canvas/Int8Array.idl
+++ b/WebCore/html/canvas/Int8Array.idl
@@ -26,13 +26,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Int8Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/Uint16Array.cpp b/WebCore/html/canvas/Uint16Array.cpp
index 4656173..a0f891c 100644
--- a/WebCore/html/canvas/Uint16Array.cpp
+++ b/WebCore/html/canvas/Uint16Array.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Uint16Array.h"
@@ -59,4 +59,4 @@ PassRefPtr<ArrayBufferView> Uint16Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Uint16Array.idl b/WebCore/html/canvas/Uint16Array.idl
index de1e5e0..75a7499 100644
--- a/WebCore/html/canvas/Uint16Array.idl
+++ b/WebCore/html/canvas/Uint16Array.idl
@@ -26,13 +26,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Uint16Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/Uint32Array.cpp b/WebCore/html/canvas/Uint32Array.cpp
index 3f43bef..f49a83a 100644
--- a/WebCore/html/canvas/Uint32Array.cpp
+++ b/WebCore/html/canvas/Uint32Array.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Uint32Array.h"
@@ -59,4 +59,4 @@ PassRefPtr<ArrayBufferView> Uint32Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Uint32Array.idl b/WebCore/html/canvas/Uint32Array.idl
index ce632dd..06e17c6 100644
--- a/WebCore/html/canvas/Uint32Array.idl
+++ b/WebCore/html/canvas/Uint32Array.idl
@@ -26,13 +26,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Uint32Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/Uint8Array.cpp b/WebCore/html/canvas/Uint8Array.cpp
index 13b7022..6c785f9 100644
--- a/WebCore/html/canvas/Uint8Array.cpp
+++ b/WebCore/html/canvas/Uint8Array.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(3D_CANVAS) || ENABLE(BLOB)
#include "Uint8Array.h"
@@ -59,4 +59,4 @@ PassRefPtr<ArrayBufferView> Uint8Array::slice(int start, int end) const
}
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(3D_CANVAS) || ENABLE(BLOB)
diff --git a/WebCore/html/canvas/Uint8Array.h b/WebCore/html/canvas/Uint8Array.h
index 6e20b42..fce63da 100644
--- a/WebCore/html/canvas/Uint8Array.h
+++ b/WebCore/html/canvas/Uint8Array.h
@@ -39,8 +39,10 @@ class Uint8Array : public IntegralTypedArrayBase<unsigned char> {
static PassRefPtr<Uint8Array> create(unsigned char* array, unsigned length);
static PassRefPtr<Uint8Array> create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length);
+#if !COMPILER(RVCT)
using TypedArrayBase<unsigned char>::set;
using IntegralTypedArrayBase<unsigned char>::set;
+#endif
private:
Uint8Array(PassRefPtr<ArrayBuffer> buffer,
diff --git a/WebCore/html/canvas/Uint8Array.idl b/WebCore/html/canvas/Uint8Array.idl
index c520844..bd28023 100644
--- a/WebCore/html/canvas/Uint8Array.idl
+++ b/WebCore/html/canvas/Uint8Array.idl
@@ -26,13 +26,14 @@
module html {
interface [
- Conditional=3D_CANVAS,
+ Conditional=3D_CANVAS|BLOB,
CanBeConstructed,
CustomConstructFunction,
V8CustomConstructor,
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
+ NoStaticTables,
CustomToJS,
DontCheckEnums
] Uint8Array : ArrayBufferView {
diff --git a/WebCore/html/canvas/WebGLProgram.cpp b/WebCore/html/canvas/WebGLProgram.cpp
index 0853b67..e4ffa80 100644
--- a/WebCore/html/canvas/WebGLProgram.cpp
+++ b/WebCore/html/canvas/WebGLProgram.cpp
@@ -40,7 +40,7 @@ PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx)
WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
: WebGLObject(ctx)
- , m_linkFailure(false)
+ , m_linkStatus(false)
{
setObject(context()->graphicsContext3D()->createProgram());
}
diff --git a/WebCore/html/canvas/WebGLProgram.h b/WebCore/html/canvas/WebGLProgram.h
index e5548eb..3b88fdd 100644
--- a/WebCore/html/canvas/WebGLProgram.h
+++ b/WebCore/html/canvas/WebGLProgram.h
@@ -50,11 +50,8 @@ public:
bool isUsingVertexAttrib0() const;
- // Return true means getProgramParameter(LINK_STATUS) should return
- // false; return false means we should actually call
- // getProgramParameter(LINK_STATUS) to find out.
- bool isLinkFailureFlagSet() const { return m_linkFailure; }
- void setLinkFailureFlag(bool failed) { m_linkFailure = failed; }
+ bool getLinkStatus() const { return m_linkStatus; }
+ void setLinkStatus(bool status) { m_linkStatus = status; }
WebGLShader* getAttachedShader(GraphicsContext3D::WebGLEnumType);
bool attachShader(WebGLShader*);
@@ -70,7 +67,7 @@ private:
Vector<int> m_activeAttribLocations;
- bool m_linkFailure;
+ bool m_linkStatus;
RefPtr<WebGLShader> m_vertexShader;
RefPtr<WebGLShader> m_fragmentShader;
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index d1bb0cd..a8751da 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -88,15 +88,15 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
{
HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow();
GraphicsContext3D::Attributes emptyAttributes;
- OwnPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs ? attrs->attributes() : emptyAttributes, hostWindow));
+ RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs ? attrs->attributes() : emptyAttributes, hostWindow));
if (!context)
return 0;
- return new WebGLRenderingContext(canvas, context.release());
+ return new WebGLRenderingContext(canvas, context);
}
-WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<GraphicsContext3D> context)
+WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context)
: CanvasRenderingContext(passedCanvas)
, m_context(context)
, m_needsUpdate(true)
@@ -1484,10 +1484,7 @@ WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, u
m_context->getProgramiv(objectOrZero(program), pname, &value);
return WebGLGetInfo(static_cast<bool>(value));
case GraphicsContext3D::LINK_STATUS:
- if (program->isLinkFailureFlagSet())
- return WebGLGetInfo(false);
- m_context->getProgramiv(objectOrZero(program), pname, &value);
- return WebGLGetInfo(static_cast<bool>(value));
+ return WebGLGetInfo(program->getLinkStatus());
case GraphicsContext3D::INFO_LOG_LENGTH:
case GraphicsContext3D::ATTACHED_SHADERS:
case GraphicsContext3D::ACTIVE_ATTRIBUTES:
@@ -1897,14 +1894,17 @@ void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec
return;
if (!isGLES2Compliant()) {
if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) {
- program->setLinkFailureFlag(true);
+ program->setLinkStatus(false);
return;
}
- program->setLinkFailureFlag(false);
}
m_context->linkProgram(objectOrZero(program));
program->cacheActiveAttribLocations();
+ // cache link status
+ int value = 0;
+ m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::LINK_STATUS, &value);
+ program->setLinkStatus(static_cast<bool>(value));
cleanupAfterGraphicsCall(false);
}
@@ -2714,11 +2714,12 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
{
+ UNUSED_PARAM(ec);
if (program && program->context() != this) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
- if (program && program->object() && !getProgramParameter(program, GraphicsContext3D::LINK_STATUS, ec).getBool()) {
+ if (program && program->object() && !program->getLinkStatus()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
cleanupAfterGraphicsCall(false);
return;
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index f507054..c4c856c 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -291,7 +291,7 @@ public:
private:
friend class WebGLObject;
- WebGLRenderingContext(HTMLCanvasElement*, PassOwnPtr<GraphicsContext3D>);
+ WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>);
void addObject(WebGLObject*);
void detachAndRemoveAllObjects();
@@ -329,7 +329,7 @@ public:
PassRefPtr<Image> videoFrameToImage(HTMLVideoElement* video);
- OwnPtr<GraphicsContext3D> m_context;
+ RefPtr<GraphicsContext3D> m_context;
bool m_needsUpdate;
bool m_markedCanvasDirty;
// FIXME: I think this is broken -- it does not increment any
diff --git a/WebCore/html/parser/CSSPreloadScanner.cpp b/WebCore/html/parser/CSSPreloadScanner.cpp
index 6ac923d..23364f9 100644
--- a/WebCore/html/parser/CSSPreloadScanner.cpp
+++ b/WebCore/html/parser/CSSPreloadScanner.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved.
* Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
* Copyright (C) 2010 Google Inc. All Rights Reserved.
*
@@ -28,23 +28,18 @@
#include "config.h"
#include "CSSPreloadScanner.h"
-#include "CSSHelper.h"
#include "CachedCSSStyleSheet.h"
#include "CachedResourceLoader.h"
#include "Document.h"
+#include "HTMLParserIdioms.h"
#include "HTMLToken.h"
namespace WebCore {
-static inline bool isWhitespace(UChar c)
-{
- return c == ' ' || c == '\n' || c == '\r' || c == '\t';
-}
-
CSSPreloadScanner::CSSPreloadScanner(Document* document)
- : m_document(document)
+ : m_state(Initial)
+ , m_document(document)
{
- reset();
}
void CSSPreloadScanner::reset()
@@ -59,10 +54,8 @@ void CSSPreloadScanner::scan(const HTMLToken& token, bool scanningBody)
m_scanningBody = scanningBody;
const HTMLToken::DataVector& characters = token.characters();
- for (HTMLToken::DataVector::const_iterator iter = characters.begin();
- iter != characters.end(); ++iter) {
+ for (HTMLToken::DataVector::const_iterator iter = characters.begin(); iter != characters.end(); ++iter)
tokenize(*iter);
- }
}
inline void CSSPreloadScanner::tokenize(UChar c)
@@ -104,7 +97,7 @@ inline void CSSPreloadScanner::tokenize(UChar c)
m_state = Initial;
break;
case Rule:
- if (isWhitespace(c))
+ if (isHTMLSpace(c))
m_state = AfterRule;
else if (c == ';')
m_state = Initial;
@@ -112,7 +105,7 @@ inline void CSSPreloadScanner::tokenize(UChar c)
m_rule.append(c);
break;
case AfterRule:
- if (isWhitespace(c))
+ if (isHTMLSpace(c))
;
else if (c == ';')
m_state = Initial;
@@ -122,7 +115,7 @@ inline void CSSPreloadScanner::tokenize(UChar c)
}
break;
case RuleValue:
- if (isWhitespace(c))
+ if (isHTMLSpace(c))
m_state = AfterRuleValue;
else if (c == ';') {
emitRule();
@@ -131,7 +124,7 @@ inline void CSSPreloadScanner::tokenize(UChar c)
m_ruleValue.append(c);
break;
case AfterRuleValue:
- if (isWhitespace(c))
+ if (isHTMLSpace(c))
;
else if (c == ';') {
emitRule();
@@ -144,14 +137,56 @@ inline void CSSPreloadScanner::tokenize(UChar c)
}
}
+static String parseCSSStringOrURL(const UChar* characters, size_t length)
+{
+ size_t offset = 0;
+ size_t reducedLength = length;
+
+ while (reducedLength && isHTMLSpace(characters[offset])) {
+ ++offset;
+ --reducedLength;
+ }
+ while (reducedLength && isHTMLSpace(characters[offset + reducedLength - 1]))
+ --reducedLength;
+
+ if (reducedLength >= 5
+ && (characters[offset] == 'u' || characters[offset] == 'U')
+ && (characters[offset + 1] == 'r' || characters[offset + 1] == 'R')
+ && (characters[offset + 2] == 'l' || characters[offset + 2] == 'L')
+ && characters[offset + 3] == '('
+ && characters[offset + reducedLength - 1] == ')') {
+ offset += 4;
+ reducedLength -= 5;
+ }
+
+ while (reducedLength && isHTMLSpace(characters[offset])) {
+ ++offset;
+ --reducedLength;
+ }
+ while (reducedLength && isHTMLSpace(characters[offset + reducedLength - 1]))
+ --reducedLength;
+
+ if (reducedLength < 2 || characters[offset] != characters[offset + reducedLength - 1] || !(characters[offset] == '\'' || characters[offset] == '"'))
+ return String();
+ offset++;
+ reducedLength -= 2;
+
+ while (reducedLength && isHTMLSpace(characters[offset])) {
+ ++offset;
+ --reducedLength;
+ }
+ while (reducedLength && isHTMLSpace(characters[offset + reducedLength - 1]))
+ --reducedLength;
+
+ return String(characters + offset, reducedLength);
+}
+
void CSSPreloadScanner::emitRule()
{
- String rule(m_rule.data(), m_rule.size());
- if (equalIgnoringCase(rule, "import") && !m_ruleValue.isEmpty()) {
- String value(m_ruleValue.data(), m_ruleValue.size());
- String url = deprecatedParseURL(value);
- if (!url.isEmpty())
- m_document->cachedResourceLoader()->preload(CachedResource::CSSStyleSheet, url, String(), m_scanningBody);
+ if (equalIgnoringCase("import", m_rule.data(), m_rule.size())) {
+ String value = parseCSSStringOrURL(m_ruleValue.data(), m_ruleValue.size());
+ if (!value.isEmpty())
+ m_document->cachedResourceLoader()->preload(CachedResource::CSSStyleSheet, value, String(), m_scanningBody);
}
m_rule.clear();
m_ruleValue.clear();
diff --git a/WebCore/html/parser/HTMLConstructionSite.cpp b/WebCore/html/parser/HTMLConstructionSite.cpp
index 6215bba..7201ac7 100644
--- a/WebCore/html/parser/HTMLConstructionSite.cpp
+++ b/WebCore/html/parser/HTMLConstructionSite.cpp
@@ -168,9 +168,12 @@ void HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded()
void HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken& token)
{
- RefPtr<Element> element = HTMLHtmlElement::create(m_document);
+ RefPtr<HTMLHtmlElement> element = HTMLHtmlElement::create(m_document);
element->setAttributeMap(token.takeAtributes(), m_fragmentScriptingPermission);
- m_openElements.pushHTMLHtmlElement(attach(m_document, element.release()));
+ m_openElements.pushHTMLHtmlElement(attach<Element>(m_document, element.get()));
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ element->insertedByParser();
+#endif
dispatchDocumentElementAvailableIfNeeded();
}
@@ -234,13 +237,6 @@ PassRefPtr<Element> HTMLConstructionSite::attachToCurrent(PassRefPtr<Element> ch
return attach(currentElement(), child);
}
-void HTMLConstructionSite::insertHTMLHtmlElement(AtomicHTMLToken& token)
-{
- ASSERT(!shouldFosterParent());
- m_openElements.pushHTMLHtmlElement(attachToCurrent(createHTMLElement(token)));
- dispatchDocumentElementAvailableIfNeeded();
-}
-
void HTMLConstructionSite::insertHTMLHeadElement(AtomicHTMLToken& token)
{
ASSERT(!shouldFosterParent());
diff --git a/WebCore/html/parser/HTMLConstructionSite.h b/WebCore/html/parser/HTMLConstructionSite.h
index 6bed6a7..8b09bf5 100644
--- a/WebCore/html/parser/HTMLConstructionSite.h
+++ b/WebCore/html/parser/HTMLConstructionSite.h
@@ -54,7 +54,6 @@ public:
void insertHTMLElement(AtomicHTMLToken&);
void insertSelfClosingHTMLElement(AtomicHTMLToken&);
void insertFormattingElement(AtomicHTMLToken&);
- void insertHTMLHtmlElement(AtomicHTMLToken&);
void insertHTMLHeadElement(AtomicHTMLToken&);
void insertHTMLBodyElement(AtomicHTMLToken&);
void insertHTMLFormElement(AtomicHTMLToken&, bool isDemoted = false);
diff --git a/WebCore/html/parser/HTMLDocumentParser.cpp b/WebCore/html/parser/HTMLDocumentParser.cpp
index dc19c96..743e5d5 100644
--- a/WebCore/html/parser/HTMLDocumentParser.cpp
+++ b/WebCore/html/parser/HTMLDocumentParser.cpp
@@ -36,11 +36,13 @@
#include "HTMLScriptRunner.h"
#include "HTMLTreeBuilder.h"
#include "HTMLDocument.h"
+#include "InspectorInstrumentation.h"
#include "NestingLevelIncrementer.h"
#include "Settings.h"
#include "XSSAuditor.h"
#include <wtf/CurrentTime.h>
+<<<<<<< HEAD
#ifdef ANDROID_INSTRUMENT
#include "TimeCounter.h"
#endif
@@ -49,6 +51,8 @@
#include "InspectorTimelineAgent.h"
#endif
+=======
+>>>>>>> webkit.org at r70209
namespace WebCore {
using namespace HTMLNames;
@@ -214,9 +218,12 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
// ASSERT that this object is both attached to the Document and protected.
ASSERT(refCount() >= 2);
- // We tell the InspectorTimelineAgent about every pump, even if we
+ // We tell the InspectorInstrumentation about every pump, even if we
// end up pumping nothing. It can filter out empty pumps itself.
- willPumpLexer();
+ // FIXME: m_input.current().length() is only accurate if we
+ // end up parsing the whole buffer in this pump. We should pass how
+ // much we parsed as part of didWriteHTML instead of willWriteHTML.
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willWriteHTML(document(), m_input.current().length(), m_tokenizer->lineNumber());
HTMLParserScheduler::PumpSession session;
// FIXME: This loop body has is now too long and needs cleanup.
@@ -260,26 +267,7 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
m_preloadScanner->scan();
}
- didPumpLexer();
-}
-
-void HTMLDocumentParser::willPumpLexer()
-{
-#if ENABLE(INSPECTOR)
- // FIXME: m_input.current().length() is only accurate if we
- // end up parsing the whole buffer in this pump. We should pass how
- // much we parsed as part of didWriteHTML instead of willWriteHTML.
- if (InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent())
- timelineAgent->willWriteHTML(m_input.current().length(), m_tokenizer->lineNumber());
-#endif
-}
-
-void HTMLDocumentParser::didPumpLexer()
-{
-#if ENABLE(INSPECTOR)
- if (InspectorTimelineAgent* timelineAgent = document()->inspectorTimelineAgent())
- timelineAgent->didWriteHTML(m_tokenizer->lineNumber());
-#endif
+ InspectorInstrumentation::didWriteHTML(cookie, m_tokenizer->lineNumber());
}
bool HTMLDocumentParser::hasInsertionPoint()
diff --git a/WebCore/html/parser/HTMLDocumentParser.h b/WebCore/html/parser/HTMLDocumentParser.h
index e65a582..d9625f1 100644
--- a/WebCore/html/parser/HTMLDocumentParser.h
+++ b/WebCore/html/parser/HTMLDocumentParser.h
@@ -103,9 +103,6 @@ private:
// CachedResourceClient
virtual void notifyFinished(CachedResource*);
- void willPumpLexer();
- void didPumpLexer();
-
enum SynchronousMode {
AllowYield,
ForceSynchronous,
diff --git a/WebCore/html/parser/HTMLElementStack.cpp b/WebCore/html/parser/HTMLElementStack.cpp
index 123778d..6b96291 100644
--- a/WebCore/html/parser/HTMLElementStack.cpp
+++ b/WebCore/html/parser/HTMLElementStack.cpp
@@ -113,6 +113,12 @@ inline bool isButtonScopeMarker(Element* element)
|| element->hasTagName(buttonTag);
}
+inline bool isSelectScopeMarker(Element* element)
+{
+ return !element->hasTagName(optgroupTag)
+ && !element->hasTagName(optionTag);
+}
+
}
HTMLElementStack::ElementRecord::ElementRecord(PassRefPtr<Element> element, PassOwnPtr<ElementRecord> next)
@@ -486,6 +492,17 @@ bool HTMLElementStack::inButtonScope(const QualifiedName& tagName) const
return inButtonScope(tagName.localName());
}
+bool HTMLElementStack::inSelectScope(const AtomicString& targetTag) const
+{
+ return inScopeCommon<isSelectScopeMarker>(m_top.get(), targetTag);
+}
+
+bool HTMLElementStack::inSelectScope(const QualifiedName& tagName) const
+{
+ // FIXME: Is localName() right for non-html elements?
+ return inSelectScope(tagName.localName());
+}
+
Element* HTMLElementStack::htmlElement() const
{
ASSERT(m_htmlElement);
diff --git a/WebCore/html/parser/HTMLElementStack.h b/WebCore/html/parser/HTMLElementStack.h
index 47fa603..8a8e160 100644
--- a/WebCore/html/parser/HTMLElementStack.h
+++ b/WebCore/html/parser/HTMLElementStack.h
@@ -117,6 +117,8 @@ public:
bool inTableScope(const QualifiedName&) const;
bool inButtonScope(const AtomicString& tagName) const;
bool inButtonScope(const QualifiedName&) const;
+ bool inSelectScope(const AtomicString& tagName) const;
+ bool inSelectScope(const QualifiedName&) const;
bool hasOnlyHTMLElementsInScope() const;
bool hasNumberedHeaderElementInScope() const;
diff --git a/WebCore/html/parser/HTMLParserIdioms.cpp b/WebCore/html/parser/HTMLParserIdioms.cpp
index a558cf5..f093eb2 100644
--- a/WebCore/html/parser/HTMLParserIdioms.cpp
+++ b/WebCore/html/parser/HTMLParserIdioms.cpp
@@ -43,7 +43,7 @@ String stripLeadingAndTrailingHTMLSpaces(const String& string)
}
if (numLeadingSpaces == length)
- return emptyAtom;
+ return string.isNull() ? string : emptyAtom.string();
unsigned numTrailingSpaces;
for (numTrailingSpaces = 0; numTrailingSpaces < length; ++numTrailingSpaces) {
@@ -53,7 +53,7 @@ String stripLeadingAndTrailingHTMLSpaces(const String& string)
ASSERT(numLeadingSpaces + numTrailingSpaces < length);
- return string.substring(numLeadingSpaces, length - numTrailingSpaces);
+ return string.substring(numLeadingSpaces, length - (numLeadingSpaces + numTrailingSpaces));
}
String serializeForNumberType(double number)
diff --git a/WebCore/html/parser/HTMLParserIdioms.h b/WebCore/html/parser/HTMLParserIdioms.h
index f4704f7..4839138 100644
--- a/WebCore/html/parser/HTMLParserIdioms.h
+++ b/WebCore/html/parser/HTMLParserIdioms.h
@@ -52,8 +52,17 @@ bool parseHTMLInteger(const String&, int&);
inline bool isHTMLSpace(UChar character)
{
- // FIXME: Consider branch permutations as we did in isASCIISpace.
- return character == '\t' || character == '\x0A' || character == '\x0C' || character == '\x0D' || character == ' ';
+ // Histogram from Apple's page load test combined with some ad hoc browsing some other test suites.
+ //
+ // 82%: 216330 non-space characters, all > U+0020
+ // 11%: 30017 plain space characters, U+0020
+ // 5%: 12099 newline characters, U+000A
+ // 2%: 5346 tab characters, U+0009
+ //
+ // No other characters seen. No U+000C or U+000D, and no other control characters.
+ // Accordingly, we check for non-spaces first, then space, then newline, then tab, then the other characters.
+
+ return character <= ' ' && (character == ' ' || character == '\n' || character == '\t' || character == '\r' || character == '\f');
}
inline bool isNotHTMLSpace(UChar character)
diff --git a/WebCore/html/parser/HTMLPreloadScanner.cpp b/WebCore/html/parser/HTMLPreloadScanner.cpp
index 7859dd8..5c86579 100644
--- a/WebCore/html/parser/HTMLPreloadScanner.cpp
+++ b/WebCore/html/parser/HTMLPreloadScanner.cpp
@@ -28,13 +28,13 @@
#include "config.h"
#include "HTMLPreloadScanner.h"
-#include "CSSHelper.h"
#include "CachedResourceLoader.h"
#include "Document.h"
#include "HTMLDocumentParser.h"
#include "HTMLTokenizer.h"
#include "HTMLLinkElement.h"
#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
namespace WebCore {
@@ -90,7 +90,7 @@ public:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#attribute-name-state
if (!m_urlToLoad.isEmpty())
return;
- m_urlToLoad = deprecatedParseURL(attributeValue);
+ m_urlToLoad = stripLeadingAndTrailingHTMLSpaces(attributeValue);
}
void preload(Document* document, bool scanningBody)
diff --git a/WebCore/html/parser/HTMLTreeBuilder.cpp b/WebCore/html/parser/HTMLTreeBuilder.cpp
index 355dc8d..5f90285 100644
--- a/WebCore/html/parser/HTMLTreeBuilder.cpp
+++ b/WebCore/html/parser/HTMLTreeBuilder.cpp
@@ -1422,7 +1422,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
|| token.name() == keygenTag
|| token.name() == textareaTag) {
parseError(token);
- if (!m_tree.openElements()->inTableScope(selectTag)) {
+ if (!m_tree.openElements()->inSelectScope(selectTag)) {
ASSERT(isParsingFragment());
return;
}
@@ -1849,7 +1849,7 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
|| token.name() == trTag
|| isTableBodyContextTag(token.name())) {
if (!m_tree.openElements()->inTableScope(token.name())) {
- ASSERT(isParsingFragment());
+ ASSERT(isTableBodyContextTag(token.name()) || isParsingFragment());
parseError(token);
return;
}
@@ -2279,7 +2279,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
return;
}
if (token.name() == selectTag) {
- if (!m_tree.openElements()->inTableScope(token.name())) {
+ if (!m_tree.openElements()->inSelectScope(token.name())) {
ASSERT(isParsingFragment());
parseError(token);
return;