summaryrefslogtreecommitdiffstats
path: root/WebCore/html
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:31:00 +0100
committerSteve Block <steveblock@google.com>2010-05-11 14:42:12 +0100
commitdcc8cf2e65d1aa555cce12431a16547e66b469ee (patch)
tree92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/html
parentccac38a6b48843126402088a309597e682f40fe6 (diff)
downloadexternal_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/html')
-rw-r--r--WebCore/html/Blob.cpp65
-rw-r--r--WebCore/html/Blob.h39
-rw-r--r--WebCore/html/Blob.idl4
-rw-r--r--WebCore/html/DOMFormData.cpp57
-rw-r--r--WebCore/html/DOMFormData.h58
-rw-r--r--WebCore/html/DOMFormData.idl42
-rw-r--r--WebCore/html/DateComponents.cpp4
-rw-r--r--WebCore/html/File.cpp5
-rw-r--r--WebCore/html/File.h4
-rw-r--r--WebCore/html/File.idl1
-rw-r--r--WebCore/html/FileStream.cpp105
-rw-r--r--WebCore/html/FileStream.h76
-rw-r--r--WebCore/html/FileStreamClient.h64
-rw-r--r--WebCore/html/FileStreamProxy.cpp193
-rw-r--r--WebCore/html/FileStreamProxy.h95
-rw-r--r--WebCore/html/FileThread.cpp119
-rw-r--r--WebCore/html/FileThread.h83
-rw-r--r--WebCore/html/FileThreadTask.h238
-rw-r--r--WebCore/html/FormDataList.h43
-rw-r--r--WebCore/html/HTMLAnchorElement.cpp4
-rw-r--r--WebCore/html/HTMLAppletElement.idl3
-rw-r--r--WebCore/html/HTMLAttributeNames.in5
-rw-r--r--WebCore/html/HTMLAudioElement.cpp2
-rw-r--r--WebCore/html/HTMLBodyElement.idl38
-rw-r--r--WebCore/html/HTMLButtonElement.cpp4
-rw-r--r--WebCore/html/HTMLButtonElement.h3
-rw-r--r--WebCore/html/HTMLCanvasElement.cpp86
-rw-r--r--WebCore/html/HTMLCanvasElement.h49
-rw-r--r--WebCore/html/HTMLDocument.cpp2
-rw-r--r--WebCore/html/HTMLElement.cpp75
-rw-r--r--WebCore/html/HTMLElementsAllInOne.cpp1
-rw-r--r--WebCore/html/HTMLEmbedElement.idl3
-rw-r--r--WebCore/html/HTMLFieldSetElement.h4
-rw-r--r--WebCore/html/HTMLFormControlElement.cpp134
-rw-r--r--WebCore/html/HTMLFormControlElement.h18
-rw-r--r--WebCore/html/HTMLFormElement.cpp178
-rw-r--r--WebCore/html/HTMLFormElement.h7
-rw-r--r--WebCore/html/HTMLFrameElementBase.cpp6
-rw-r--r--WebCore/html/HTMLFrameElementBase.h2
-rw-r--r--WebCore/html/HTMLFrameSetElement.cpp4
-rw-r--r--WebCore/html/HTMLFrameSetElement.idl36
-rw-r--r--WebCore/html/HTMLIFrameElement.cpp15
-rw-r--r--WebCore/html/HTMLImageElement.cpp6
-rw-r--r--WebCore/html/HTMLImageElement.h3
-rw-r--r--WebCore/html/HTMLInputElement.cpp186
-rw-r--r--WebCore/html/HTMLInputElement.h7
-rw-r--r--WebCore/html/HTMLLabelElement.cpp2
-rw-r--r--WebCore/html/HTMLLinkElement.cpp9
-rw-r--r--WebCore/html/HTMLMapElement.cpp2
-rw-r--r--WebCore/html/HTMLMediaElement.cpp247
-rw-r--r--WebCore/html/HTMLMediaElement.h91
-rw-r--r--WebCore/html/HTMLMediaElement.idl2
-rw-r--r--WebCore/html/HTMLMetaElement.cpp11
-rw-r--r--WebCore/html/HTMLObjectElement.idl3
-rw-r--r--WebCore/html/HTMLParser.cpp30
-rw-r--r--WebCore/html/HTMLPlugInImageElement.cpp11
-rw-r--r--WebCore/html/HTMLPlugInImageElement.h5
-rw-r--r--WebCore/html/HTMLProgressElement.cpp108
-rw-r--r--WebCore/html/HTMLProgressElement.h56
-rw-r--r--WebCore/html/HTMLProgressElement.idl30
-rw-r--r--WebCore/html/HTMLScriptElement.cpp5
-rw-r--r--WebCore/html/HTMLScriptElement.h1
-rw-r--r--WebCore/html/HTMLSelectElement.cpp46
-rw-r--r--WebCore/html/HTMLSelectElement.h3
-rw-r--r--WebCore/html/HTMLTagNames.in2
-rw-r--r--WebCore/html/HTMLTextAreaElement.cpp24
-rw-r--r--WebCore/html/HTMLTitleElement.cpp9
-rw-r--r--WebCore/html/HTMLTokenizer.cpp18
-rw-r--r--WebCore/html/HTMLVideoElement.cpp44
-rw-r--r--WebCore/html/HTMLVideoElement.h44
-rw-r--r--WebCore/html/HTMLVideoElement.idl4
-rw-r--r--WebCore/html/HTMLViewSourceDocument.cpp2
-rw-r--r--WebCore/html/PreloadScanner.cpp2
-rw-r--r--WebCore/html/StepRange.cpp84
-rw-r--r--WebCore/html/StepRange.h68
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.cpp129
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.h15
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.idl67
-rw-r--r--WebCore/html/canvas/CanvasStyle.cpp10
-rw-r--r--WebCore/html/canvas/WebGLArray.cpp24
-rw-r--r--WebCore/html/canvas/WebGLArray.h46
-rw-r--r--WebCore/html/canvas/WebGLArray.idl2
-rw-r--r--WebCore/html/canvas/WebGLArrayBuffer.cpp31
-rw-r--r--WebCore/html/canvas/WebGLArrayBuffer.h6
-rw-r--r--WebCore/html/canvas/WebGLByteArray.cpp32
-rw-r--r--WebCore/html/canvas/WebGLByteArray.h6
-rw-r--r--WebCore/html/canvas/WebGLFloatArray.cpp35
-rw-r--r--WebCore/html/canvas/WebGLFloatArray.h6
-rw-r--r--WebCore/html/canvas/WebGLFramebuffer.cpp18
-rw-r--r--WebCore/html/canvas/WebGLFramebuffer.h11
-rw-r--r--WebCore/html/canvas/WebGLIntArray.cpp36
-rw-r--r--WebCore/html/canvas/WebGLIntArray.h6
-rw-r--r--WebCore/html/canvas/WebGLProgram.cpp35
-rw-r--r--WebCore/html/canvas/WebGLProgram.h10
-rw-r--r--WebCore/html/canvas/WebGLRenderbuffer.cpp2
-rw-r--r--WebCore/html/canvas/WebGLRenderbuffer.h6
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.cpp499
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.h7
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.idl4
-rw-r--r--WebCore/html/canvas/WebGLShortArray.cpp36
-rw-r--r--WebCore/html/canvas/WebGLShortArray.h6
-rw-r--r--WebCore/html/canvas/WebGLUnsignedByteArray.cpp32
-rw-r--r--WebCore/html/canvas/WebGLUnsignedByteArray.h6
-rw-r--r--WebCore/html/canvas/WebGLUnsignedIntArray.cpp37
-rw-r--r--WebCore/html/canvas/WebGLUnsignedIntArray.h6
-rw-r--r--WebCore/html/canvas/WebGLUnsignedShortArray.cpp37
-rw-r--r--WebCore/html/canvas/WebGLUnsignedShortArray.h6
107 files changed, 3348 insertions, 1000 deletions
diff --git a/WebCore/html/Blob.cpp b/WebCore/html/Blob.cpp
index 0b677ea..83bbdc0 100644
--- a/WebCore/html/Blob.cpp
+++ b/WebCore/html/Blob.cpp
@@ -35,19 +35,84 @@
namespace WebCore {
+#if ENABLE(BLOB_SLICE)
+const int Blob::toEndOfFile = -1;
+const double Blob::doNotCheckFileChange = 0;
+#endif
+
Blob::Blob(const String& path)
: m_path(path)
+#if ENABLE(BLOB_SLICE)
+ , m_start(0)
+ , m_length(toEndOfFile)
+ , m_snapshotCaptured(false)
+ , m_snapshotSize(0)
+ , m_snapshotModificationTime(doNotCheckFileChange)
+#endif
+{
+}
+
+#if ENABLE(BLOB_SLICE)
+Blob::Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime)
+ : m_path(path)
+ , m_start(start)
+ , m_length(length)
+ , m_snapshotCaptured(true)
+ , m_snapshotSize(snapshotSize)
+ , m_snapshotModificationTime(snapshotModificationTime)
{
+ ASSERT(start >= 0 && length >= 0 && start + length <= snapshotSize && snapshotModificationTime);
}
+#endif
unsigned long long Blob::size() const
{
// FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
// come up with an exception to throw if file size is not represetable.
+#if ENABLE(BLOB_SLICE)
+ if (m_snapshotCaptured)
+ return m_length;
+#endif
long long size;
if (!getFileSize(m_path, size))
return 0;
return static_cast<unsigned long long>(size);
}
+#if ENABLE(BLOB_SLICE)
+PassRefPtr<Blob> Blob::slice(long long start, long long length) const
+{
+ // When we slice a file for the first time, we obtain a snapshot of the file by capturing its current size and modification time.
+ // The modification time will be used to verify if the file has been changed or not, when the underlying data are accessed.
+ long long snapshotSize;
+ double snapshotModificationTime;
+ if (m_snapshotCaptured) {
+ snapshotSize = m_snapshotSize;
+ snapshotModificationTime = m_snapshotModificationTime;
+ } else {
+ // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, an empty blob will be returned.
+ time_t modificationTime;
+ if (!getFileSize(m_path, snapshotSize) || !getFileModificationTime(m_path, modificationTime)) {
+ snapshotSize = 0;
+ snapshotModificationTime = 0;
+ } else
+ snapshotModificationTime = modificationTime;
+ }
+
+ // Clamp the range if it exceeds the size limit.
+ if (start < 0)
+ start = 0;
+ if (length < 0)
+ length = 0;
+
+ if (start > snapshotSize) {
+ start = 0;
+ length = 0;
+ } else if (start + length > snapshotSize)
+ length = snapshotSize - start;
+
+ return adoptRef(new Blob(m_path, m_start + start, length, snapshotSize, snapshotModificationTime));
+}
+#endif
+
} // namespace WebCore
diff --git a/WebCore/html/Blob.h b/WebCore/html/Blob.h
index b910e8f..e8b5f3f 100644
--- a/WebCore/html/Blob.h
+++ b/WebCore/html/Blob.h
@@ -33,6 +33,7 @@
#include "ExceptionCode.h"
#include "PlatformString.h"
+#include <time.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -40,6 +41,11 @@ namespace WebCore {
class Blob : public RefCounted<Blob> {
public:
+#if ENABLE(BLOB_SLICE)
+ static const int toEndOfFile;
+ static const double doNotCheckFileChange;
+#endif
+
static PassRefPtr<Blob> create(const String& path)
{
return adoptRef(new Blob(path));
@@ -47,14 +53,47 @@ public:
virtual ~Blob() { }
+ virtual bool isFile() const { return false; }
+
+#if ENABLE(BLOB_SLICE)
+ PassRefPtr<Blob> slice(long long start, long long length) const;
+#endif
+
const String& path() const { return m_path; }
unsigned long long size() const;
+#if ENABLE(BLOB_SLICE)
+ long long start() const { return m_start; }
+ long long length() const { return m_length; }
+ double modificationTime() const { return m_snapshotModificationTime; }
+#endif
protected:
Blob(const String& path);
private:
+#if ENABLE(BLOB_SLICE)
+ Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime);
+#endif
+
+ // The underlying path of the file-based blob.
String m_path;
+
+#if ENABLE(BLOB_SLICE)
+ // The starting position of the file-based blob.
+ long long m_start;
+
+ // The length of the file-based blob. The value of -1 means to the end of the file.
+ long long m_length;
+
+ // A flag to tell if a snapshot has been captured.
+ bool m_snapshotCaptured;
+
+ // The size of the file when a snapshot is captured. It can be 0 if the file is empty.
+ long long m_snapshotSize;
+
+ // The last modification time of the file when a snapshot is captured. The value of 0 also means that the snapshot is not captured.
+ double m_snapshotModificationTime;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/html/Blob.idl b/WebCore/html/Blob.idl
index 573be35..8db6064 100644
--- a/WebCore/html/Blob.idl
+++ b/WebCore/html/Blob.idl
@@ -32,6 +32,10 @@ module html {
interface Blob {
readonly attribute unsigned long long size;
+
+#if defined(ENABLE_BLOB_SLICE) && ENABLE_BLOB_SLICE
+ Blob slice(in long long start, in long long length);
+#endif
};
}
diff --git a/WebCore/html/DOMFormData.cpp b/WebCore/html/DOMFormData.cpp
new file mode 100644
index 0000000..f848898
--- /dev/null
+++ b/WebCore/html/DOMFormData.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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 "DOMFormData.h"
+
+#include "Blob.h"
+#include "PlatformString.h"
+#include "TextEncoding.h"
+
+namespace WebCore {
+
+DOMFormData::DOMFormData(const TextEncoding& encoding)
+ : FormDataList(encoding)
+{
+}
+
+void DOMFormData::append(const String& name, const String& value)
+{
+ if (!name.isEmpty())
+ appendData(name, value);
+}
+
+void DOMFormData::append(const String& name, Blob* blob)
+{
+ if (!name.isEmpty())
+ appendBlob(name, blob);
+}
+
+} // namespace WebCore
diff --git a/WebCore/html/DOMFormData.h b/WebCore/html/DOMFormData.h
new file mode 100644
index 0000000..f071d4a
--- /dev/null
+++ b/WebCore/html/DOMFormData.h
@@ -0,0 +1,58 @@
+/*
+ * 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 DOMFormData_h
+#define DOMFormData_h
+
+#include "FormDataList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Blob;
+class String;
+class TextEncoding;
+
+class DOMFormData : public FormDataList, public RefCounted<DOMFormData> {
+public:
+ static PassRefPtr<DOMFormData> create() { return adoptRef(new DOMFormData(UTF8Encoding())); }
+ 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&);
+};
+
+} // namespace WebCore
+
+#endif // DOMFormData_h
diff --git a/WebCore/html/DOMFormData.idl b/WebCore/html/DOMFormData.idl
new file mode 100644
index 0000000..c339381
--- /dev/null
+++ b/WebCore/html/DOMFormData.idl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+module html {
+
+ interface [
+ CanBeConstructed,
+ GenerateNativeConverter,
+ GenerateToJS
+ ] DOMFormData {
+ // void append(DOMString name, Blob value);
+ [Custom] void append(in DOMString name, in DOMString value);
+ };
+
+}
diff --git a/WebCore/html/DateComponents.cpp b/WebCore/html/DateComponents.cpp
index 9c62d30..39dd733 100644
--- a/WebCore/html/DateComponents.cpp
+++ b/WebCore/html/DateComponents.cpp
@@ -145,8 +145,8 @@ bool DateComponents::parseYear(const UChar* src, unsigned length, unsigned start
static bool beforeGregorianStartDate(int year, int month, int monthDay)
{
return year < gregorianStartYear
- || year == gregorianStartYear && month < gregorianStartMonth
- || year == gregorianStartYear && month == gregorianStartMonth && monthDay < gregorianStartDay;
+ || (year == gregorianStartYear && month < gregorianStartMonth)
+ || (year == gregorianStartYear && month == gregorianStartMonth && monthDay < gregorianStartDay);
}
bool DateComponents::addDay(int dayDiff)
diff --git a/WebCore/html/File.cpp b/WebCore/html/File.cpp
index 25e28e4..97fdc45 100644
--- a/WebCore/html/File.cpp
+++ b/WebCore/html/File.cpp
@@ -27,6 +27,7 @@
#include "File.h"
#include "FileSystem.h"
+#include "MIMETypeRegistry.h"
namespace WebCore {
@@ -34,6 +35,10 @@ File::File(const String& path)
: Blob(path)
, m_name(pathGetFileName(path))
{
+ // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure.
+ int index = m_name.reverseFind('.');
+ if (index != -1)
+ m_type = MIMETypeRegistry::getMIMETypeForExtension(m_name.substring(index + 1));
}
} // namespace WebCore
diff --git a/WebCore/html/File.h b/WebCore/html/File.h
index be53e30..065dd86 100644
--- a/WebCore/html/File.h
+++ b/WebCore/html/File.h
@@ -39,7 +39,10 @@ public:
return adoptRef(new File(path));
}
+ virtual bool isFile() const { return true; }
+
const String& name() const { return m_name; }
+ const String& type() const { return m_type; }
// FIXME: obsolete attributes. To be removed.
const String& fileName() const { return m_name; }
@@ -49,6 +52,7 @@ private:
File(const String& path);
String m_name;
+ String m_type;
};
} // namespace WebCore
diff --git a/WebCore/html/File.idl b/WebCore/html/File.idl
index 2632a4d..94287ff 100644
--- a/WebCore/html/File.idl
+++ b/WebCore/html/File.idl
@@ -30,6 +30,7 @@ module html {
GenerateToJS
] File : Blob {
readonly attribute DOMString name;
+ readonly attribute DOMString type;
// FIXME: obsolete attributes. To be removed.
readonly attribute DOMString fileName;
diff --git a/WebCore/html/FileStream.cpp b/WebCore/html/FileStream.cpp
new file mode 100644
index 0000000..84a28d6
--- /dev/null
+++ b/WebCore/html/FileStream.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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"
+
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#include "FileStream.h"
+
+#include "Blob.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+FileStream::FileStream(FileStreamClient* client)
+ : m_client(client)
+ , m_handle(invalidPlatformFileHandle)
+{
+}
+
+FileStream::~FileStream()
+{
+ ASSERT(!isHandleValid(m_handle));
+}
+
+void FileStream::start()
+{
+ ASSERT(!isMainThread());
+ m_client->didStart();
+}
+
+void FileStream::stop()
+{
+ ASSERT(!isMainThread());
+ close();
+ m_client->didStop();
+}
+
+void FileStream::openForRead(Blob*)
+{
+ ASSERT(!isMainThread());
+ // FIXME: to be implemented.
+}
+
+void FileStream::openForWrite(const String&)
+{
+ ASSERT(!isMainThread());
+ // FIXME: to be implemented.
+}
+
+void FileStream::close()
+{
+ ASSERT(!isMainThread());
+ if (isHandleValid(m_handle))
+ closeFile(m_handle);
+}
+
+void FileStream::read(char*, int)
+{
+ ASSERT(!isMainThread());
+ // FIXME: to be implemented.
+}
+
+void FileStream::write(Blob*, long long, int)
+{
+ ASSERT(!isMainThread());
+ // FIXME: to be implemented.
+}
+
+void FileStream::truncate(long long)
+{
+ ASSERT(!isMainThread());
+ // FIXME: to be implemented.
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_WRITER) || ENABLE_FILE_READER)
diff --git a/WebCore/html/FileStream.h b/WebCore/html/FileStream.h
new file mode 100644
index 0000000..bda8fc7
--- /dev/null
+++ b/WebCore/html/FileStream.h
@@ -0,0 +1,76 @@
+/*
+ * 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 FileStream_h
+#define FileStream_h
+
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#include "FileStreamClient.h"
+#include "FileSystem.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Blob;
+class String;
+
+// All methods are synchronous and should be called on File or Worker thread.
+class FileStream : public RefCounted<FileStream> {
+public:
+ static PassRefPtr<FileStream> create(FileStreamClient* client)
+ {
+ return adoptRef(new FileStream(client));
+ }
+ virtual ~FileStream();
+
+ void start();
+ void stop();
+
+ void openForRead(Blob*);
+ void openForWrite(const String& path);
+ void close();
+ void read(char* buffer, int length);
+ void write(Blob* blob, long long position, int length);
+ void truncate(long long position);
+
+private:
+ FileStream(FileStreamClient*);
+
+ FileStreamClient* m_client;
+ PlatformFileHandle m_handle;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#endif // FileStream_h
diff --git a/WebCore/html/FileStreamClient.h b/WebCore/html/FileStreamClient.h
new file mode 100644
index 0000000..e1aec53
--- /dev/null
+++ b/WebCore/html/FileStreamClient.h
@@ -0,0 +1,64 @@
+/*
+ * 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 FileStreamClient_h
+#define FileStreamClient_h
+
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#include "ExceptionCode.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class FileStreamClient {
+public:
+ // For reading.
+ virtual void didRead(const char*, int) { }
+
+ // For writing.
+ virtual void didWrite(int) { }
+
+ // For both reading and writing.
+ virtual void didStart() { }
+ virtual void didStop() { }
+ virtual void didFinish() { }
+ virtual void didFail(ExceptionCode) { }
+ virtual void didGetSize(long long) { }
+
+protected:
+ virtual ~FileStreamClient() { }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#endif // FileStreamClient_h
diff --git a/WebCore/html/FileStreamProxy.cpp b/WebCore/html/FileStreamProxy.cpp
new file mode 100644
index 0000000..6b41f32
--- /dev/null
+++ b/WebCore/html/FileStreamProxy.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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"
+
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#include "FileStreamProxy.h"
+
+#include "Blob.h"
+#include "FileStream.h"
+#include "FileThread.h"
+#include "FileThreadTask.h"
+#include "GenericWorkerTask.h"
+#include "PlatformString.h"
+#include "ScriptExecutionContext.h"
+
+namespace WebCore {
+
+FileStreamProxy::FileStreamProxy(ScriptExecutionContext* context, FileStreamClient* client)
+ : m_context(context)
+ , m_client(client)
+ , m_stream(FileStream::create(this))
+{
+ // Holds an extra ref so that the instance will not get deleted while there can be any tasks on the file thread.
+ ref();
+
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::start));
+}
+
+FileStreamProxy::~FileStreamProxy()
+{
+}
+
+void FileStreamProxy::openForRead(Blob* blob)
+{
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::openForRead, blob));
+}
+
+void FileStreamProxy::openForWrite(const String& path)
+{
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::openForWrite, path));
+}
+
+void FileStreamProxy::close()
+{
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::close));
+}
+
+void FileStreamProxy::read(char* buffer, int length)
+{
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::read, buffer, length));
+}
+
+void FileStreamProxy::write(Blob* blob, long long position, int length)
+{
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::write, blob, position, length));
+}
+
+void FileStreamProxy::truncate(long long position)
+{
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::truncate, position));
+}
+
+FileThread* FileStreamProxy::fileThread()
+{
+ ASSERT(m_context->isContextThread());
+ ASSERT(m_context->fileThread());
+ return m_context->fileThread();
+}
+
+void FileStreamProxy::stop()
+{
+ // Clear the client so that we won't be calling callbacks on the client.
+ m_client = 0;
+
+ fileThread()->unscheduleTasks(m_stream.get());
+ fileThread()->postTask(createFileThreadTask(m_stream.get(), &FileStream::stop));
+}
+
+static void notifyGetSizeOnContext(ScriptExecutionContext*, FileStreamProxy* proxy, long long size)
+{
+ if (proxy->client())
+ proxy->client()->didGetSize(size);
+}
+
+void FileStreamProxy::didGetSize(long long size)
+{
+ ASSERT(!m_context->isContextThread());
+ m_context->postTask(createCallbackTask(&notifyGetSizeOnContext, this, size));
+}
+
+static void notifyReadOnContext(ScriptExecutionContext*, FileStreamProxy* proxy, const char* data, int bytesRead)
+{
+ if (proxy->client())
+ proxy->client()->didRead(data, bytesRead);
+}
+
+void FileStreamProxy::didRead(const char* data, int bytesRead)
+{
+ ASSERT(!m_context->isContextThread());
+ m_context->postTask(createCallbackTask(&notifyReadOnContext, this, data, bytesRead));
+}
+
+static void notifyWriteOnContext(ScriptExecutionContext*, FileStreamProxy* proxy, int bytesWritten)
+{
+ if (proxy->client())
+ proxy->client()->didWrite(bytesWritten);
+}
+
+void FileStreamProxy::didWrite(int bytesWritten)
+{
+ ASSERT(!m_context->isContextThread());
+ m_context->postTask(createCallbackTask(&notifyWriteOnContext, this, bytesWritten));
+}
+
+static void notifyStartOnContext(ScriptExecutionContext*, FileStreamProxy* proxy)
+{
+ if (proxy->client())
+ proxy->client()->didStart();
+}
+
+void FileStreamProxy::didStart()
+{
+ ASSERT(!m_context->isContextThread());
+ m_context->postTask(createCallbackTask(&notifyStartOnContext, this));
+}
+
+static void notifyFinishOnContext(ScriptExecutionContext*, FileStreamProxy* proxy)
+{
+ if (proxy->client())
+ proxy->client()->didFinish();
+}
+
+void FileStreamProxy::didFinish()
+{
+ ASSERT(!m_context->isContextThread());
+ m_context->postTask(createCallbackTask(&notifyFinishOnContext, this));
+}
+
+static void notifyFailOnContext(ScriptExecutionContext*, FileStreamProxy* proxy, ExceptionCode ec)
+{
+ if (proxy->client())
+ proxy->client()->didFail(ec);
+}
+
+void FileStreamProxy::didFail(ExceptionCode ec)
+{
+ ASSERT(!m_context->isContextThread());
+ m_context->postTask(createCallbackTask(&notifyFailOnContext, this, ec));
+}
+
+static void derefProxyOnContext(ScriptExecutionContext*, FileStreamProxy* proxy)
+{
+ ASSERT(proxy->hasOneRef());
+ proxy->deref();
+}
+
+void FileStreamProxy::didStop()
+{
+ m_context->postTask(createCallbackTask(&derefProxyOnContext, this));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_WRITER)
diff --git a/WebCore/html/FileStreamProxy.h b/WebCore/html/FileStreamProxy.h
new file mode 100644
index 0000000..308da15
--- /dev/null
+++ b/WebCore/html/FileStreamProxy.h
@@ -0,0 +1,95 @@
+/*
+ * 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 FileStreamProxy_h
+#define FileStreamProxy_h
+
+#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#include "ExceptionCode.h"
+#include "FileStreamClient.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Blob;
+class FileStream;
+class FileThread;
+class ScriptExecutionContext;
+class String;
+
+// A proxy module that calls corresponding FileStream methods on the file thread. Note: you must call stop() first and then release the reference to destruct the FileStreamProxy instance.
+class FileStreamProxy : public RefCounted<FileStreamProxy>, public FileStreamClient {
+public:
+ static PassRefPtr<FileStreamProxy> create(ScriptExecutionContext* context, FileStreamClient* client)
+ {
+ return adoptRef(new FileStreamProxy(context, client));
+ }
+ virtual ~FileStreamProxy();
+
+ void openForRead(Blob* blob);
+ void openForWrite(const String& path);
+ void close();
+ void read(char* buffer, int length);
+ void write(Blob* blob, long long position, int length);
+ void truncate(long long position);
+
+ // Stops the proxy and scedules it to be destructed. All the pending tasks will be aborted and the file stream will be closed.
+ // Note: the caller should deref the instance immediately after calling stop().
+ void stop();
+
+ FileStreamClient* client() const { return m_client; }
+
+private:
+ FileStreamProxy(ScriptExecutionContext*, FileStreamClient*);
+
+ // FileStreamClient methods.
+ virtual void didGetSize(long long);
+ virtual void didRead(const char*, int);
+ virtual void didWrite(int);
+ virtual void didFinish();
+ virtual void didFail(ExceptionCode);
+ virtual void didStart();
+ virtual void didStop();
+
+ FileThread* fileThread();
+
+ RefPtr<ScriptExecutionContext> m_context;
+ FileStreamClient* m_client;
+ RefPtr<FileStream> m_stream;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_READER) || ENABLE(FILE_WRITER)
+
+#endif // FileStreamProxy_h
diff --git a/WebCore/html/FileThread.cpp b/WebCore/html/FileThread.cpp
new file mode 100644
index 0000000..02b1718
--- /dev/null
+++ b/WebCore/html/FileThread.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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"
+
+#if ENABLE(FILE_WRITER) || ENABLE(FILE_READER)
+
+#include "FileThread.h"
+
+#include "AutodrainedPool.h"
+#include "Logging.h"
+
+namespace WebCore {
+
+FileThread::FileThread()
+ : m_threadID(0)
+{
+ m_selfRef = this;
+}
+
+FileThread::~FileThread()
+{
+ ASSERT(m_queue.killed());
+}
+
+bool FileThread::start()
+{
+ MutexLocker lock(m_threadCreationMutex);
+ if (m_threadID)
+ return true;
+ m_threadID = createThread(FileThread::fileThreadStart, this, "WebCore: File");
+ return m_threadID;
+}
+
+void FileThread::stop()
+{
+ return m_queue.kill();
+}
+
+void FileThread::postTask(PassOwnPtr<Task> task)
+{
+ m_queue.append(task);
+}
+
+class SameFilePredicate {
+public:
+ SameFilePredicate(const FileStream* stream) : m_stream(stream) { }
+ bool operator()(FileThread::Task* task) const { return task->stream() == m_stream; }
+private:
+ const FileStream* m_stream;
+};
+
+void FileThread::unscheduleTasks(const FileStream* stream)
+{
+ SameFilePredicate predicate(stream);
+ m_queue.removeIf(predicate);
+}
+
+void* FileThread::fileThreadStart(void* arg)
+{
+ FileThread* fileThread = static_cast<FileThread*>(arg);
+ return fileThread->runLoop();
+}
+
+void* FileThread::runLoop()
+{
+ {
+ // Wait for FileThread::start() to complete to have m_threadID
+ // established before starting the main loop.
+ MutexLocker lock(m_threadCreationMutex);
+ LOG(FileAPI, "Started FileThread %p", this);
+ }
+
+ AutodrainedPool pool;
+ while (OwnPtr<Task> task = m_queue.waitForMessage()) {
+ task->performTask();
+ pool.cycle();
+ }
+
+ LOG(FileAPI, "About to detach thread %i and clear the ref to FileThread %p, which currently has %i ref(s)", m_threadID, this, refCount());
+
+ detachThread(m_threadID);
+
+ // Clear the self refptr, possibly resulting in deletion
+ m_selfRef = 0;
+
+ return 0;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_WRITER) || ENABLE(FILE_READER)
diff --git a/WebCore/html/FileThread.h b/WebCore/html/FileThread.h
new file mode 100644
index 0000000..d27273a
--- /dev/null
+++ b/WebCore/html/FileThread.h
@@ -0,0 +1,83 @@
+/*
+ * 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 FileThread_h
+#define FileThread_h
+
+#if ENABLE(FILE_WRITER) || ENABLE(FILE_READER)
+
+#include <wtf/MessageQueue.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+class FileStream;
+
+class FileThread : public ThreadSafeShared<FileThread> {
+public:
+ static PassRefPtr<FileThread> create() { return adoptRef(new FileThread()); }
+ ~FileThread();
+
+ bool start();
+ void stop();
+
+ class Task : public Noncopyable {
+ public:
+ virtual ~Task() { }
+ virtual void performTask() = 0;
+ FileStream* stream() const { return m_stream; }
+ protected:
+ Task(FileStream* stream) : m_stream(stream) { }
+ FileStream* m_stream;
+ };
+
+ void postTask(PassOwnPtr<Task> task);
+ void unscheduleTasks(const FileStream*);
+
+private:
+ FileThread();
+
+ static void* fileThreadStart(void*);
+ void* runLoop();
+
+ ThreadIdentifier m_threadID;
+ RefPtr<FileThread> m_selfRef;
+ MessageQueue<Task> m_queue;
+
+ Mutex m_threadCreationMutex;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_WRITER) || ENABLE(FILE_READER)
+
+#endif // FileThread_h
diff --git a/WebCore/html/FileThreadTask.h b/WebCore/html/FileThreadTask.h
new file mode 100644
index 0000000..f4c59d8
--- /dev/null
+++ b/WebCore/html/FileThreadTask.h
@@ -0,0 +1,238 @@
+/*
+ * 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 FileThreadTask_h
+#define FileThreadTask_h
+
+#include "CrossThreadCopier.h"
+#include "FileThread.h"
+#include <memory>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/TypeTraits.h>
+
+namespace WebCore {
+
+// Traits for the Task.
+template<typename T> struct FileThreadTaskTraits {
+ typedef const T& ParamType;
+};
+
+template<typename T> struct FileThreadTaskTraits<T*> {
+ typedef T* ParamType;
+};
+
+template<typename T> struct FileThreadTaskTraits<PassRefPtr<T> > {
+ typedef PassRefPtr<T> ParamType;
+};
+
+template<typename T> struct FileThreadTaskTraits<PassOwnPtr<T> > {
+ typedef PassOwnPtr<T> ParamType;
+};
+
+class FileThreadTask0 : public FileThread::Task {
+public:
+ typedef void (FileStream::*Method)();
+ typedef FileThreadTask0 FileThreadTask;
+
+ static PassOwnPtr<FileThreadTask> create(FileStream* stream, Method method)
+ {
+ return new FileThreadTask(stream, method);
+ }
+
+private:
+ FileThreadTask0(FileStream* stream, Method method)
+ : FileThread::Task(stream)
+ , m_method(method)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*stream().*m_method)();
+ }
+
+private:
+ Method m_method;
+};
+
+template<typename P1, typename MP1>
+class FileThreadTask1 : public FileThread::Task {
+public:
+ typedef void (FileStream::*Method)(MP1);
+ typedef FileThreadTask1<P1, MP1> FileThreadTask;
+ typedef typename FileThreadTaskTraits<P1>::ParamType Param1;
+
+ static PassOwnPtr<FileThreadTask> create(FileStream* stream, Method method, Param1 parameter1)
+ {
+ return new FileThreadTask(stream, method, parameter1);
+ }
+
+private:
+ FileThreadTask1(FileStream* stream, Method method, Param1 parameter1)
+ : FileThread::Task(stream)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*stream().*m_method)(m_parameter1);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2>
+class FileThreadTask2 : public FileThread::Task {
+public:
+ typedef void (FileStream::*Method)(MP1, MP2);
+ typedef FileThreadTask2<P1, MP1, P2, MP2> FileThreadTask;
+ typedef typename FileThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename FileThreadTaskTraits<P2>::ParamType Param2;
+
+ static PassOwnPtr<FileThreadTask> create(FileStream* stream, Method method, Param1 parameter1, Param2 parameter2)
+ {
+ return new FileThreadTask(stream, method, parameter1, parameter2);
+ }
+
+private:
+ FileThreadTask2(FileStream* stream, Method method, Param1 parameter1, Param2 parameter2)
+ : FileThread::Task(stream)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*stream().*m_method)(m_parameter1, m_parameter2);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+};
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+class FileThreadTask3 : public FileThread::Task {
+public:
+ typedef void (FileStream::*Method)(MP1, MP2, MP3);
+ typedef FileThreadTask3<P1, MP1, P2, MP2, P3, MP3> FileThreadTask;
+ typedef typename FileThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename FileThreadTaskTraits<P2>::ParamType Param2;
+ typedef typename FileThreadTaskTraits<P3>::ParamType Param3;
+
+ static PassOwnPtr<FileThreadTask> create(FileStream* stream, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ {
+ return new FileThreadTask(stream, method, parameter1, parameter2, parameter3);
+ }
+
+private:
+ FileThreadTask3(FileStream* stream, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ : FileThread::Task(stream)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*stream().*m_method)(m_parameter1, m_parameter2, m_parameter3);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+};
+
+PassOwnPtr<FileThread::Task> createFileThreadTask(
+ FileStream* const callee,
+ void (FileStream::*method)())
+{
+ return FileThreadTask0::create(
+ callee,
+ method);
+}
+
+template<typename P1, typename MP1>
+PassOwnPtr<FileThread::Task> createFileThreadTask(
+ FileStream* const callee,
+ void (FileStream::*method)(MP1),
+ const P1& parameter1)
+{
+ return FileThreadTask1<typename CrossThreadCopier<P1>::Type, MP1>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2>
+PassOwnPtr<FileThread::Task> createFileThreadTask(
+ FileStream* const callee,
+ void (FileStream::*method)(MP1, MP2),
+ const P1& parameter1,
+ const P2& parameter2)
+{
+ return FileThreadTask2<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2));
+}
+
+template<typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+PassOwnPtr<FileThread::Task> createFileThreadTask(
+ FileStream* const callee,
+ void (FileStream::*method)(MP1, MP2, MP3),
+ const P1& parameter1,
+ const P2& parameter2,
+ const P3& parameter3)
+{
+ return FileThreadTask3<typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3));
+}
+
+} // namespace WebCore
+
+#endif // FileThreadTask_h
diff --git a/WebCore/html/FormDataList.h b/WebCore/html/FormDataList.h
index aec1a52..8ecf64e 100644
--- a/WebCore/html/FormDataList.h
+++ b/WebCore/html/FormDataList.h
@@ -21,9 +21,9 @@
#ifndef FormDataList_h
#define FormDataList_h
-#include "CString.h"
-#include "File.h"
+#include "Blob.h"
#include "TextEncoding.h"
+#include <wtf/text/CString.h>
namespace WebCore {
@@ -32,32 +32,45 @@ public:
FormDataList(const TextEncoding&);
void appendData(const String& key, const String& value)
- { appendString(key); appendString(value); }
- void appendData(const String& key, const CString& value)
- { appendString(key); appendString(value); }
+ {
+ appendString(key);
+ appendString(value);
+ }
+ void appendData(const String& key, const WTF::CString& value)
+ {
+ appendString(key);
+ appendString(value);
+ }
void appendData(const String& key, int value)
- { appendString(key); appendString(String::number(value)); }
- void appendFile(const String& key, PassRefPtr<File> file)
- { appendString(key); m_list.append(file); }
+ {
+ appendString(key);
+ appendString(String::number(value));
+ }
+ void appendBlob(const String& key, PassRefPtr<Blob> blob)
+ {
+ appendString(key);
+ m_list.append(blob);
+ }
class Item {
public:
Item() { }
- Item(const CString& data) : m_data(data) { }
- Item(PassRefPtr<File> file) : m_file(file) { }
+ Item(const WTF::CString& data) : m_data(data) { }
+ Item(PassRefPtr<Blob> blob) : m_blob(blob) { }
- const CString& data() const { return m_data; }
- File* file() const { return m_file.get(); }
+ const WTF::CString& data() const { return m_data; }
+ Blob* blob() const { return m_blob.get(); }
private:
- CString m_data;
- RefPtr<File> m_file;
+ WTF::CString m_data;
+ RefPtr<Blob> m_blob;
};
const Vector<Item>& list() const { return m_list; }
+ const TextEncoding& encoding() const { return m_encoding; }
private:
- void appendString(const CString&);
+ void appendString(const WTF::CString&);
void appendString(const String&);
TextEncoding m_encoding;
diff --git a/WebCore/html/HTMLAnchorElement.cpp b/WebCore/html/HTMLAnchorElement.cpp
index f3b6ddd..f636020 100644
--- a/WebCore/html/HTMLAnchorElement.cpp
+++ b/WebCore/html/HTMLAnchorElement.cpp
@@ -24,7 +24,6 @@
#include "config.h"
#include "HTMLAnchorElement.h"
-#include "DNS.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameLoaderTypes.h"
@@ -35,6 +34,7 @@
#include "MouseEvent.h"
#include "Page.h"
#include "RenderImage.h"
+#include "ResourceHandle.h"
#include "Settings.h"
namespace WebCore {
@@ -279,7 +279,7 @@ void HTMLAnchorElement::parseMappedAttribute(MappedAttribute *attr)
String parsedURL = deprecatedParseURL(attr->value());
if (document()->isDNSPrefetchEnabled()) {
if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "https") || parsedURL.startsWith("//"))
- prefetchDNS(document()->completeURL(parsedURL).host());
+ ResourceHandle::prepareForURL(document()->completeURL(parsedURL));
}
if (document()->page() && !document()->page()->javaScriptURLsAreAllowed() && protocolIsJavaScript(parsedURL)) {
setIsLink(false);
diff --git a/WebCore/html/HTMLAppletElement.idl b/WebCore/html/HTMLAppletElement.idl
index 8d6803e..f5984f0 100644
--- a/WebCore/html/HTMLAppletElement.idl
+++ b/WebCore/html/HTMLAppletElement.idl
@@ -23,8 +23,7 @@ module html {
interface [
DelegatingPutFunction,
DelegatingGetOwnPropertySlot,
- CustomCall,
- HasOverridingNameGetter
+ CustomCall
] HTMLAppletElement : HTMLElement {
attribute [ConvertNullToNullString, Reflect] DOMString align;
attribute [ConvertNullToNullString, Reflect] DOMString alt;
diff --git a/WebCore/html/HTMLAttributeNames.in b/WebCore/html/HTMLAttributeNames.in
index ad13070..7a353b2 100644
--- a/WebCore/html/HTMLAttributeNames.in
+++ b/WebCore/html/HTMLAttributeNames.in
@@ -42,7 +42,6 @@ aria-valuemax
aria-valuemin
aria-valuenow
aria-valuetext
-autobuffer
autocomplete
autofocus
autoplay
@@ -88,6 +87,7 @@ disabled
draggable
enctype
end
+event
expanded
face
focused
@@ -163,6 +163,8 @@ onemptied
onended
onerror
onfocus
+onfocusin
+onfocusout
onhashchange
oninput
oninvalid
@@ -222,6 +224,7 @@ placeholder
pluginurl
poster
precision
+preload
primary
profile
progress
diff --git a/WebCore/html/HTMLAudioElement.cpp b/WebCore/html/HTMLAudioElement.cpp
index 347b8c4..6018b52 100644
--- a/WebCore/html/HTMLAudioElement.cpp
+++ b/WebCore/html/HTMLAudioElement.cpp
@@ -44,7 +44,7 @@ HTMLAudioElement::HTMLAudioElement(const QualifiedName& tagName, Document* docum
PassRefPtr<HTMLAudioElement> HTMLAudioElement::createForJSConstructor(Document* document, const String& src)
{
RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(audioTag, document);
- audio->setAutobuffer(true);
+ audio->setPreload("auto");
if (!src.isNull()) {
audio->setSrc(src);
audio->scheduleLoad();
diff --git a/WebCore/html/HTMLBodyElement.idl b/WebCore/html/HTMLBodyElement.idl
index 95140c7..c92dcd3 100644
--- a/WebCore/html/HTMLBodyElement.idl
+++ b/WebCore/html/HTMLBodyElement.idl
@@ -30,31 +30,31 @@ module html {
#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
// Event handler attributes
- attribute [DontEnum] EventListener onbeforeunload;
- attribute [DontEnum] EventListener onhashchange;
- attribute [DontEnum] EventListener onmessage;
- attribute [DontEnum] EventListener onoffline;
- attribute [DontEnum] EventListener ononline;
- attribute [DontEnum] EventListener onpopstate;
- attribute [DontEnum] EventListener onresize;
- attribute [DontEnum] EventListener onstorage;
- attribute [DontEnum] EventListener onunload;
+ attribute [DontEnum, WindowEventListener] EventListener onbeforeunload;
+ attribute [DontEnum, WindowEventListener] EventListener onhashchange;
+ attribute [DontEnum, WindowEventListener] EventListener onmessage;
+ attribute [DontEnum, WindowEventListener] EventListener onoffline;
+ attribute [DontEnum, WindowEventListener] EventListener ononline;
+ attribute [DontEnum, WindowEventListener] EventListener onpopstate;
+ attribute [DontEnum, WindowEventListener] EventListener onresize;
+ attribute [DontEnum, WindowEventListener] EventListener onstorage;
+ attribute [DontEnum, WindowEventListener] EventListener onunload;
#if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS
- attribute [DontEnum] EventListener onorientationchange;
+ attribute [DontEnum, WindowEventListener] EventListener onorientationchange;
#endif
- // Overrides of Element attributes (left in for completeness).
- // attribute [DontEnum] EventListener onblur;
- // attribute [DontEnum] EventListener onerror;
- // attribute [DontEnum] EventListener onfocus;
- // attribute [DontEnum] EventListener onload;
+ // Overrides of Element attributes (with different implementation in bindings).
+ attribute [DontEnum, WindowEventListener] EventListener onblur;
+ attribute [DontEnum, WindowEventListener] EventListener onerror;
+ attribute [DontEnum, WindowEventListener] EventListener onfocus;
+ attribute [DontEnum, WindowEventListener] EventListener onload;
// Not implemented yet.
- // attribute [DontEnum] EventListener onafterprint;
- // attribute [DontEnum] EventListener onbeforeprint;
- // attribute [DontEnum] EventListener onredo;
- // attribute [DontEnum] EventListener onundo;
+ // attribute [DontEnum, WindowEventListener] EventListener onafterprint;
+ // attribute [DontEnum, WindowEventListener] EventListener onbeforeprint;
+ // attribute [DontEnum, WindowEventListener] EventListener onredo;
+ // attribute [DontEnum, WindowEventListener] EventListener onundo;
#endif
};
diff --git a/WebCore/html/HTMLButtonElement.cpp b/WebCore/html/HTMLButtonElement.cpp
index 3987859..b3d358d 100644
--- a/WebCore/html/HTMLButtonElement.cpp
+++ b/WebCore/html/HTMLButtonElement.cpp
@@ -90,10 +90,6 @@ void HTMLButtonElement::parseMappedAttribute(MappedAttribute* attr)
} else if (attr->name() == alignAttr) {
// Don't map 'align' attribute. This matches what Firefox and IE do, but not Opera.
// See http://bugs.webkit.org/show_bug.cgi?id=12071
- } else if (attr->name() == onfocusAttr) {
- setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
- } else if (attr->name() == onblurAttr) {
- setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
} else
HTMLFormControlElement::parseMappedAttribute(attr);
}
diff --git a/WebCore/html/HTMLButtonElement.h b/WebCore/html/HTMLButtonElement.h
index f5b9b62..f4df571 100644
--- a/WebCore/html/HTMLButtonElement.h
+++ b/WebCore/html/HTMLButtonElement.h
@@ -57,11 +57,10 @@ public:
String value() const;
void setValue(const String&);
- virtual bool willValidate() const { return false; }
-
private:
enum Type { SUBMIT, RESET, BUTTON };
virtual bool isOptionalFormControl() const { return true; }
+ virtual bool recalcWillValidate() const { return false; }
Type m_type;
bool m_activeSubmit;
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index fa03dbf..0b60949 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -28,22 +28,20 @@
#include "HTMLCanvasElement.h"
#include "CanvasContextAttributes.h"
-#include "CanvasGradient.h"
-#include "CanvasPattern.h"
#include "CanvasRenderingContext2D.h"
#if ENABLE(3D_CANVAS)
#include "WebGLContextAttributes.h"
#include "WebGLRenderingContext.h"
#endif
+#include "CanvasGradient.h"
+#include "CanvasPattern.h"
#include "CanvasStyle.h"
#include "Chrome.h"
#include "Document.h"
-#include "ExceptionCode.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "ImageBuffer.h"
-#include "MIMETypeRegistry.h"
#include "MappedAttribute.h"
#include "Page.h"
#include "RenderHTMLCanvas.h"
@@ -55,22 +53,11 @@ namespace WebCore {
using namespace HTMLNames;
-// These values come from the WhatWG spec.
-static const int defaultWidth = 300;
-static const int defaultHeight = 150;
-
-// Firefox limits width/height to 32767 pixels, but slows down dramatically before it
-// reaches that limit. We limit by area instead, giving us larger maximum dimensions,
-// in exchange for a smaller maximum canvas size.
-const float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
-
HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc)
: HTMLElement(tagName, doc)
- , m_size(defaultWidth, defaultHeight)
+ , CanvasSurface(doc->frame() ? doc->frame()->page()->chrome()->scaleFactor() : 1)
, m_observer(0)
- , m_originClean(true)
, m_ignoreReset(false)
- , m_createdImageBuffer(false)
{
ASSERT(hasTagName(canvasTag));
}
@@ -113,8 +100,8 @@ void HTMLCanvasElement::parseMappedAttribute(MappedAttribute* attr)
RenderObject* HTMLCanvasElement::createRenderer(RenderArena* arena, RenderStyle* style)
{
- Settings* settings = document()->settings();
- if (settings && settings->isJavaScriptEnabled()) {
+ Frame* frame = document()->frame();
+ if (frame && frame->script()->canExecuteScripts(NotAboutToExecuteScript)) {
m_rendererIsCanvas = true;
return new (arena) RenderHTMLCanvas(this);
}
@@ -133,22 +120,6 @@ void HTMLCanvasElement::setWidth(int value)
setAttribute(widthAttr, String::number(value));
}
-String HTMLCanvasElement::toDataURL(const String& mimeType, ExceptionCode& ec)
-{
- if (!m_originClean) {
- ec = SECURITY_ERR;
- return String();
- }
-
- if (m_size.isEmpty() || !buffer())
- return String("data:,");
-
- if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
- return buffer()->toDataURL("image/png");
-
- return buffer()->toDataURL(mimeType);
-}
-
CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, CanvasContextAttributes* attrs)
{
// A Canvas can either be "2D" or "webgl" but never both. If you request a 2D canvas and the existing
@@ -162,13 +133,19 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
if (type == "2d") {
if (m_context && !m_context->is2d())
return 0;
- if (!m_context)
- m_context = new CanvasRenderingContext2D(this);
+ if (!m_context) {
+ bool usesDashbardCompatibilityMode = false;
+#if ENABLE(DASHBOARD_SUPPORT)
+ if (Settings* settings = document()->settings())
+ usesDashbardCompatibilityMode = settings->usesDashboardBackwardCompatibilityMode();
+#endif
+ m_context = new CanvasRenderingContext2D(this, document()->inCompatMode(), usesDashbardCompatibilityMode);
+ }
return m_context.get();
}
#if ENABLE(3D_CANVAS)
Settings* settings = document()->settings();
- if (settings && settings->webGLEnabled()) {
+ if (settings && settings->webGLEnabled() && settings->acceleratedCompositingEnabled()) {
// Accept the legacy "webkit-3d" name as well as the provisional "experimental-webgl" name.
// Once ratified, we will also accept "webgl" as the context name.
if ((type == "webkit-3d") ||
@@ -193,12 +170,11 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
void HTMLCanvasElement::willDraw(const FloatRect& rect)
{
- if (m_imageBuffer)
- m_imageBuffer->clearImage();
-
+ CanvasSurface::willDraw(rect);
+
if (RenderBox* ro = renderBox()) {
FloatRect destRect = ro->contentBoxRect();
- FloatRect r = mapRect(rect, FloatRect(0, 0, m_size.width(), m_size.height()), destRect);
+ FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect);
r.intersect(destRect);
if (m_dirtyRect.contains(r))
return;
@@ -219,28 +195,26 @@ void HTMLCanvasElement::reset()
bool ok;
int w = getAttribute(widthAttr).toInt(&ok);
if (!ok)
- w = defaultWidth;
+ w = DefaultWidth;
int h = getAttribute(heightAttr).toInt(&ok);
if (!ok)
- h = defaultHeight;
+ h = DefaultHeight;
- IntSize oldSize = m_size;
- m_size = IntSize(w, h);
+ IntSize oldSize = size();
+ setSurfaceSize(IntSize(w, h));
#if ENABLE(3D_CANVAS)
if (m_context && m_context->is3d())
static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height());
#endif
- bool hadImageBuffer = m_createdImageBuffer;
- m_createdImageBuffer = false;
- m_imageBuffer.clear();
+ bool hadImageBuffer = hasCreatedImageBuffer();
if (m_context && m_context->is2d())
static_cast<CanvasRenderingContext2D*>(m_context.get())->reset();
if (RenderObject* renderer = this->renderer()) {
if (m_rendererIsCanvas) {
- if (oldSize != m_size)
+ if (oldSize != size())
toRenderHTMLCanvas(renderer)->canvasSizeChanged();
if (hadImageBuffer)
renderer->repaint();
@@ -267,10 +241,13 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
}
#endif
- if (m_imageBuffer) {
- Image* image = m_imageBuffer->image();
- if (image)
- context->drawImage(image, DeviceColorSpace, r);
+ if (hasCreatedImageBuffer()) {
+ ImageBuffer* imageBuffer = buffer();
+ if (imageBuffer) {
+ Image* image = imageBuffer->image();
+ if (image)
+ context->drawImage(image, DeviceColorSpace, r);
+ }
}
#if ENABLE(3D_CANVAS)
@@ -279,6 +256,7 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
#endif
}
+<<<<<<< HEAD
IntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const
{
return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size()));
@@ -373,6 +351,8 @@ AffineTransform HTMLCanvasElement::baseTransform() const
return transform;
}
+=======
+>>>>>>> webkit.org at r58033
#if ENABLE(3D_CANVAS)
bool HTMLCanvasElement::is3D() const
{
diff --git a/WebCore/html/HTMLCanvasElement.h b/WebCore/html/HTMLCanvasElement.h
index d70a7e6..b2a76a1 100644
--- a/WebCore/html/HTMLCanvasElement.h
+++ b/WebCore/html/HTMLCanvasElement.h
@@ -27,7 +27,7 @@
#ifndef HTMLCanvasElement_h
#define HTMLCanvasElement_h
-#include "AffineTransform.h"
+#include "CanvasSurface.h"
#include "FloatRect.h"
#include "HTMLElement.h"
#if ENABLE(3D_CANVAS)
@@ -39,13 +39,8 @@ namespace WebCore {
class CanvasContextAttributes;
class CanvasRenderingContext;
-class FloatPoint;
-class FloatRect;
-class FloatSize;
class GraphicsContext;
class HTMLCanvasElement;
-class ImageBuffer;
-class IntPoint;
class IntSize;
class CanvasObserver {
@@ -57,53 +52,38 @@ public:
virtual void canvasDestroyed(HTMLCanvasElement*) = 0;
};
-class HTMLCanvasElement : public HTMLElement {
+class HTMLCanvasElement : public HTMLElement, public CanvasSurface {
public:
HTMLCanvasElement(const QualifiedName&, Document*);
virtual ~HTMLCanvasElement();
- int width() const { return m_size.width(); }
- int height() const { return m_size.height(); }
void setWidth(int);
void setHeight(int);
- String toDataURL(const String& mimeType, ExceptionCode&);
-
CanvasRenderingContext* getContext(const String&, CanvasContextAttributes* attributes = 0);
- const IntSize& size() const { return m_size; }
- void setSize(const IntSize& size)
+ void setSize(const IntSize& newSize)
{
- if (size == m_size)
+ if (newSize == size())
return;
m_ignoreReset = true;
- setWidth(size.width());
- setHeight(size.height());
+ setWidth(newSize.width());
+ setHeight(newSize.height());
m_ignoreReset = false;
reset();
}
- void willDraw(const FloatRect&);
+ virtual void willDraw(const FloatRect&);
void paint(GraphicsContext*, const IntRect&);
- GraphicsContext* drawingContext() const;
-
- ImageBuffer* buffer() const;
-
- IntRect convertLogicalToDevice(const FloatRect&) const;
- IntSize convertLogicalToDevice(const FloatSize&) const;
- IntPoint convertLogicalToDevice(const FloatPoint&) const;
-
- void setOriginTainted() { m_originClean = false; }
- bool originClean() const { return m_originClean; }
-
void setObserver(CanvasObserver* observer) { m_observer = observer; }
- AffineTransform baseTransform() const;
-
CanvasRenderingContext* renderingContext() const { return m_context.get(); }
+ RenderBox* renderBox() const { return HTMLElement::renderBox(); }
+ RenderStyle* computedStyle() { return HTMLElement::computedStyle(); }
+
#if ENABLE(3D_CANVAS)
bool is3D() const;
#endif
@@ -117,24 +97,15 @@ private:
virtual void parseMappedAttribute(MappedAttribute*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
- void createImageBuffer() const;
void reset();
- static const float MaxCanvasArea;
-
bool m_rendererIsCanvas;
OwnPtr<CanvasRenderingContext> m_context;
- IntSize m_size;
CanvasObserver* m_observer;
- bool m_originClean;
bool m_ignoreReset;
FloatRect m_dirtyRect;
-
- // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
- mutable bool m_createdImageBuffer;
- mutable OwnPtr<ImageBuffer> m_imageBuffer;
};
} //namespace
diff --git a/WebCore/html/HTMLDocument.cpp b/WebCore/html/HTMLDocument.cpp
index cf98755..c0e9eb7 100644
--- a/WebCore/html/HTMLDocument.cpp
+++ b/WebCore/html/HTMLDocument.cpp
@@ -55,7 +55,6 @@
#include "CSSPropertyNames.h"
#include "CSSStyleSelector.h"
-#include "CString.h"
#include "CookieJar.h"
#include "DocumentLoader.h"
#include "DocumentType.h"
@@ -72,6 +71,7 @@
#include "InspectorController.h"
#include "KURL.h"
#include "Page.h"
+#include <wtf/text/CString.h>
#include "DocTypeStrings.cpp"
diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp
index d3a7f22..816bb60 100644
--- a/WebCore/html/HTMLElement.cpp
+++ b/WebCore/html/HTMLElement.cpp
@@ -107,6 +107,7 @@ static const TagPriorityMap* createTagPriorityMap()
map->add(centerTag.localName().impl(), 5);
map->add(footerTag.localName().impl(), 5);
map->add(headerTag.localName().impl(), 5);
+ map->add(hgroupTag.localName().impl(), 5);
map->add(nobrTag.localName().impl(), 5);
map->add(rubyTag.localName().impl(), 5);
map->add(navTag.localName().impl(), 5);
@@ -197,6 +198,10 @@ void HTMLElement::parseMappedAttribute(MappedAttribute *attr)
setAttributeEventListener(eventNames().mousewheelEvent, createAttributeEventListener(this, attr));
} else if (attr->name() == onfocusAttr) {
setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
+ } else if (attr->name() == onfocusinAttr) {
+ setAttributeEventListener(eventNames().focusinEvent, createAttributeEventListener(this, attr));
+ } else if (attr->name() == onfocusoutAttr) {
+ setAttributeEventListener(eventNames().focusoutEvent, createAttributeEventListener(this, attr));
} else if (attr->name() == onblurAttr) {
setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
} else if (attr->name() == onkeydownAttr) {
@@ -272,9 +277,9 @@ String HTMLElement::outerHTML() const
return createMarkup(this);
}
-PassRefPtr<DocumentFragment> HTMLElement::createContextualFragment(const String &html, FragmentScriptingPermission scriptingPermission)
+PassRefPtr<DocumentFragment> HTMLElement::createContextualFragment(const String& markup, FragmentScriptingPermission scriptingPermission)
{
- // the following is in accordance with the definition as used by IE
+ // The following is in accordance with the definition as used by IE.
if (endTagRequirement() == TagStatusForbidden)
return 0;
@@ -282,47 +287,7 @@ PassRefPtr<DocumentFragment> HTMLElement::createContextualFragment(const String
hasLocalName(headTag) || hasLocalName(styleTag) || hasLocalName(titleTag))
return 0;
- RefPtr<DocumentFragment> fragment = DocumentFragment::create(document());
-
- if (document()->isHTMLDocument())
- parseHTMLDocumentFragment(html, fragment.get(), scriptingPermission);
- else {
- if (!parseXMLDocumentFragment(html, fragment.get(), this, scriptingPermission))
- // FIXME: We should propagate a syntax error exception out here.
- return 0;
- }
-
- // Exceptions are ignored because none ought to happen here.
- int ignoredExceptionCode;
-
- // we need to pop <html> and <body> elements and remove <head> to
- // accommodate folks passing complete HTML documents to make the
- // child of an element.
-
- RefPtr<Node> nextNode;
- for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) {
- nextNode = node->nextSibling();
- if (node->hasTagName(htmlTag) || node->hasTagName(bodyTag)) {
- Node *firstChild = node->firstChild();
- if (firstChild)
- nextNode = firstChild;
- RefPtr<Node> nextChild;
- for (RefPtr<Node> child = firstChild; child; child = nextChild) {
- nextChild = child->nextSibling();
- node->removeChild(child.get(), ignoredExceptionCode);
- ASSERT(!ignoredExceptionCode);
- fragment->insertBefore(child, node.get(), ignoredExceptionCode);
- ASSERT(!ignoredExceptionCode);
- }
- fragment->removeChild(node.get(), ignoredExceptionCode);
- ASSERT(!ignoredExceptionCode);
- } else if (node->hasTagName(headTag)) {
- fragment->removeChild(node.get(), ignoredExceptionCode);
- ASSERT(!ignoredExceptionCode);
- }
- }
-
- return fragment.release();
+ return Element::createContextualFragment(markup, scriptingPermission);
}
static inline bool hasOneChild(ContainerNode* node)
@@ -415,7 +380,7 @@ void HTMLElement::setOuterHTML(const String& html, ExceptionCode& ec)
void HTMLElement::setInnerText(const String& text, ExceptionCode& ec)
{
- // follow the IE specs about when this is allowed
+ // Follow the IE specs about when this is allowed.
if (endTagRequirement() == TagStatusForbidden) {
ec = NO_MODIFICATION_ALLOWED_ERR;
return;
@@ -485,7 +450,7 @@ void HTMLElement::setInnerText(const String& text, ExceptionCode& ec)
void HTMLElement::setOuterText(const String &text, ExceptionCode& ec)
{
- // follow the IE specs about when this is allowed
+ // Follow the IE specs about when this is allowed.
if (endTagRequirement() == TagStatusForbidden) {
ec = NO_MODIFICATION_ALLOWED_ERR;
return;
@@ -513,7 +478,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionCode& ec)
if (ec)
return;
- // is previous node a text node? if so, merge into it
+ // Is previous node a text node? If so, merge into it.
Node* prev = t->previousSibling();
if (prev && prev->isTextNode()) {
Text* textPrev = static_cast<Text*>(prev);
@@ -526,7 +491,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionCode& ec)
t = textPrev;
}
- // is next node a text node? if so, merge it in
+ // Is next node a text node? If so, merge it in.
Node* next = t->nextSibling();
if (next && next->isTextNode()) {
Text* textNext = static_cast<Text*>(next);
@@ -566,7 +531,7 @@ Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, Exception
return 0;
}
- // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
+ // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
ec = NOT_SUPPORTED_ERR;
return 0;
}
@@ -574,7 +539,7 @@ Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, Exception
Element* HTMLElement::insertAdjacentElement(const String& where, Element* newChild, ExceptionCode& ec)
{
if (!newChild) {
- // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
+ // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
ec = TYPE_MISMATCH_ERR;
return 0;
}
@@ -611,8 +576,8 @@ void HTMLElement::addHTMLAlignment(MappedAttribute* attr)
void HTMLElement::addHTMLAlignmentToStyledElement(StyledElement* element, MappedAttribute* attr)
{
- // vertical alignment with respect to the current baseline of the text
- // right or left means floating images
+ // Vertical alignment with respect to the current baseline of the text
+ // right or left means floating images.
int floatValue = CSSValueInvalid;
int verticalAlignValue = CSSValueInvalid;
@@ -893,6 +858,9 @@ static HashSet<AtomicStringImpl*>* inlineTagList()
tagList.add(rpTag.localName().impl());
tagList.add(rtTag.localName().impl());
tagList.add(rubyTag.localName().impl());
+#if ENABLE(PROGRESS_TAG)
+ tagList.add(progressTag.localName().impl());
+#endif
}
return &tagList;
}
@@ -921,6 +889,7 @@ static HashSet<AtomicStringImpl*>* blockTagList()
tagList.add(h5Tag.localName().impl());
tagList.add(h6Tag.localName().impl());
tagList.add(headerTag.localName().impl());
+ tagList.add(hgroupTag.localName().impl());
tagList.add(hrTag.localName().impl());
tagList.add(isindexTag.localName().impl());
tagList.add(layerTag.localName().impl());
@@ -1011,8 +980,8 @@ bool HTMLElement::rendererIsNeeded(RenderStyle *style)
{
#if !ENABLE(XHTMLMP)
if (hasLocalName(noscriptTag)) {
- Settings* settings = document()->settings();
- if (settings && settings->isJavaScriptEnabled())
+ Frame* frame = document()->frame();
+ if (frame && frame->script()->canExecuteScripts(NotAboutToExecuteScript))
return false;
}
#endif
diff --git a/WebCore/html/HTMLElementsAllInOne.cpp b/WebCore/html/HTMLElementsAllInOne.cpp
index f9c970a..4cee927 100644
--- a/WebCore/html/HTMLElementsAllInOne.cpp
+++ b/WebCore/html/HTMLElementsAllInOne.cpp
@@ -87,6 +87,7 @@
#include "HTMLPlugInElement.cpp"
#include "HTMLPlugInImageElement.cpp"
#include "HTMLPreElement.cpp"
+#include "HTMLProgressElement.cpp"
#include "HTMLQuoteElement.cpp"
#include "HTMLScriptElement.cpp"
#include "HTMLSelectElement.cpp"
diff --git a/WebCore/html/HTMLEmbedElement.idl b/WebCore/html/HTMLEmbedElement.idl
index d491a0d..576bca9 100644
--- a/WebCore/html/HTMLEmbedElement.idl
+++ b/WebCore/html/HTMLEmbedElement.idl
@@ -23,8 +23,7 @@ module html {
interface [
DelegatingPutFunction,
DelegatingGetOwnPropertySlot,
- CustomCall,
- HasOverridingNameGetter
+ CustomCall
] HTMLEmbedElement : HTMLElement {
attribute [ConvertNullToNullString, Reflect] DOMString align;
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
diff --git a/WebCore/html/HTMLFieldSetElement.h b/WebCore/html/HTMLFieldSetElement.h
index 0900317..457fe93 100644
--- a/WebCore/html/HTMLFieldSetElement.h
+++ b/WebCore/html/HTMLFieldSetElement.h
@@ -47,8 +47,8 @@ public:
virtual bool supportsFocus() const;
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual const AtomicString& formControlType() const;
-
- virtual bool willValidate() const { return false; }
+private:
+ virtual bool recalcWillValidate() const { return false; }
};
} //namespace
diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp
index 6f24e0c..bcdf40d 100644
--- a/WebCore/html/HTMLFormControlElement.cpp
+++ b/WebCore/html/HTMLFormControlElement.cpp
@@ -49,14 +49,16 @@ namespace WebCore {
using namespace HTMLNames;
-HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
- : HTMLElement(tagName, doc)
+HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f, ConstructionType constructionType)
+ : HTMLElement(tagName, doc, constructionType)
, m_form(f)
- , m_hasName(false)
, m_disabled(false)
, m_readOnly(false)
, m_required(false)
, m_valueMatchesRenderer(false)
+ , m_willValidateInitialized(false)
+ , m_willValidate(true)
+ , m_isValid(true)
{
if (!m_form)
m_form = findFormAncestor();
@@ -90,10 +92,7 @@ ValidityState* HTMLFormControlElement::validity()
void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
{
- bool oldWillValidate = willValidate();
- if (attr->name() == nameAttr)
- m_hasName = !attr->isEmpty();
- else if (attr->name() == disabledAttr) {
+ if (attr->name() == disabledAttr) {
bool oldDisabled = m_disabled;
m_disabled = !attr->isNull();
if (oldDisabled != m_disabled) {
@@ -112,12 +111,13 @@ void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
} else if (attr->name() == requiredAttr) {
bool oldRequired = m_required;
m_required = !attr->isNull();
- if (oldRequired != m_required)
- setNeedsStyleRecalc();
+ if (oldRequired != m_required) {
+ setNeedsValidityCheck();
+ setNeedsStyleRecalc(); // Updates for :required :optional classes.
+ }
} else
HTMLElement::parseMappedAttribute(attr);
- if (oldWillValidate != willValidate())
- setNeedsWillValidateCheck();
+ setNeedsWillValidateCheck();
}
void HTMLFormControlElement::attach()
@@ -153,10 +153,9 @@ void HTMLFormControlElement::insertedIntoTree(bool deep)
// setting a form, we will already have a non-null value for m_form,
// and so we don't need to do anything.
m_form = findFormAncestor();
- if (m_form) {
+ if (m_form)
m_form->registerFormElement(this);
- setNeedsWillValidateCheck();
- } else
+ else
document()->checkedRadioButtons().addButton(this);
}
@@ -183,19 +182,11 @@ void HTMLFormControlElement::removedFromTree(bool deep)
if (m_form && !(parser && parser->isHandlingResidualStyleAcrossBlocks()) && findRoot(this) != findRoot(m_form)) {
m_form->removeFormElement(this);
m_form = 0;
- setNeedsWillValidateCheck();
}
HTMLElement::removedFromTree(deep);
}
-void HTMLFormControlElement::formDestroyed()
-{
- if (m_form)
- setNeedsWillValidateCheck();
- m_form = 0;
-}
-
const AtomicString& HTMLFormControlElement::formControlName() const
{
const AtomicString& n = getAttribute(nameAttr);
@@ -299,42 +290,74 @@ short HTMLFormControlElement::tabIndex() const
return Element::tabIndex();
}
-bool HTMLFormControlElement::willValidate() const
+bool HTMLFormControlElement::recalcWillValidate() const
{
- // FIXME: Implementation shall be completed with these checks:
- // The control does not have a repetition template as an ancestor.
- // The control does not have a datalist element as an ancestor.
- // The control is not an output element.
- return m_form && m_hasName && !m_disabled && !m_readOnly;
+ // FIXME: Should return false if this element has a datalist element as an
+ // ancestor. See HTML5 4.10.10 'The datalist element.'
+ return !m_disabled && !m_readOnly;
}
-String HTMLFormControlElement::validationMessage()
+bool HTMLFormControlElement::willValidate() const
{
- return validity()->validationMessage();
+ if (!m_willValidateInitialized) {
+ m_willValidateInitialized = true;
+ m_willValidate = recalcWillValidate();
+ } else {
+ // If the following assertion fails, setNeedsWillValidateCheck() is not
+ // called correctly when something which changes recalcWillValidate() result
+ // is updated.
+ ASSERT(m_willValidate == recalcWillValidate());
+ }
+ return m_willValidate;
}
void HTMLFormControlElement::setNeedsWillValidateCheck()
{
+ // We need to recalculate willValidte immediately because willValidate
+ // change can causes style change.
+ bool newWillValidate = recalcWillValidate();
+ if (m_willValidateInitialized && m_willValidate == newWillValidate)
+ return;
+ m_willValidateInitialized = true;
+ m_willValidate = newWillValidate;
setNeedsStyleRecalc();
// FIXME: Show/hide a validation message.
}
-bool HTMLFormControlElement::checkValidity()
+String HTMLFormControlElement::validationMessage()
{
- if (willValidate() && !isValidFormControlElement()) {
- dispatchEvent(Event::create(eventNames().invalidEvent, false, true));
- return false;
- }
+ return validity()->validationMessage();
+}
- return true;
+bool HTMLFormControlElement::checkValidity(Vector<RefPtr<HTMLFormControlElement> >* unhandledInvalidControls)
+{
+ if (!willValidate() || isValidFormControlElement())
+ return true;
+ // An event handler can deref this object.
+ RefPtr<HTMLFormControlElement> protector(this);
+ RefPtr<Document> originalDocument(document());
+ bool needsDefaultAction = dispatchEvent(Event::create(eventNames().invalidEvent, false, true));
+ if (needsDefaultAction && unhandledInvalidControls && inDocument() && originalDocument == document())
+ unhandledInvalidControls->append(this);
+ return false;
+}
+
+bool HTMLFormControlElement::isValidFormControlElement()
+{
+ // If the following assertion fails, setNeedsValidityCheck() is not called
+ // correctly when something which changes validity is updated.
+ ASSERT(m_isValid == validity()->valid());
+ return m_isValid;
}
void HTMLFormControlElement::setNeedsValidityCheck()
{
- if (willValidate()) {
+ bool newIsValid = validity()->valid();
+ if (willValidate() && newIsValid != m_isValid) {
// Update style for pseudo classes such as :valid :invalid.
setNeedsStyleRecalc();
}
+ m_isValid = newIsValid;
// FIXME: show/hide a validation message.
}
@@ -345,16 +368,16 @@ void HTMLFormControlElement::setCustomValidity(const String& error)
void HTMLFormControlElement::dispatchFocusEvent()
{
- if (document()->frame() && document()->frame()->page())
- document()->frame()->page()->chrome()->client()->formDidFocus(this);
+ if (document()->page())
+ document()->page()->chrome()->client()->formDidFocus(this);
HTMLElement::dispatchFocusEvent();
}
void HTMLFormControlElement::dispatchBlurEvent()
{
- if (document()->frame() && document()->frame()->page())
- document()->frame()->page()->chrome()->client()->formDidBlur(this);
+ if (document()->page())
+ document()->page()->chrome()->client()->formDidBlur(this);
HTMLElement::dispatchBlurEvent();
}
@@ -369,11 +392,6 @@ bool HTMLFormControlElement::isDefaultButtonForForm() const
return isSuccessfulSubmitButton() && m_form && m_form->defaultButton() == this;
}
-bool HTMLFormControlElement::isValidFormControlElement()
-{
- return validity()->valid();
-}
-
void HTMLFormControlElement::removeFromForm()
{
if (!m_form)
@@ -405,9 +423,29 @@ void HTMLFormControlElementWithState::didMoveToNewOwnerDocument()
HTMLFormControlElement::didMoveToNewOwnerDocument();
}
+bool HTMLFormControlElementWithState::autoComplete() const
+{
+ if (!form())
+ return true;
+ return form()->autoComplete();
+}
+
+bool HTMLFormControlElementWithState::shouldSaveAndRestoreFormControlState() const
+{
+ // We don't save/restore control state in a form with autocomplete=off.
+ return autoComplete();
+}
+
void HTMLFormControlElementWithState::finishParsingChildren()
{
HTMLFormControlElement::finishParsingChildren();
+
+ // We don't save state of a control with shouldSaveAndRestoreFormControlState()=false.
+ // But we need to skip restoring process too because a control in another
+ // form might have the same pair of name and type and saved its state.
+ if (!shouldSaveAndRestoreFormControlState())
+ return;
+
Document* doc = document();
if (doc->hasStateForNewFormElements()) {
String state;
@@ -520,10 +558,6 @@ void HTMLTextFormControlElement::parseMappedAttribute(MappedAttribute* attr)
{
if (attr->name() == placeholderAttr)
updatePlaceholderVisibility(true);
- else if (attr->name() == onfocusAttr)
- setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
- else if (attr->name() == onblurAttr)
- setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
else if (attr->name() == onselectAttr)
setAttributeEventListener(eventNames().selectEvent, createAttributeEventListener(this, attr));
else if (attr->name() == onchangeAttr)
diff --git a/WebCore/html/HTMLFormControlElement.h b/WebCore/html/HTMLFormControlElement.h
index 117087b..0045fbe 100644
--- a/WebCore/html/HTMLFormControlElement.h
+++ b/WebCore/html/HTMLFormControlElement.h
@@ -36,7 +36,7 @@ class VisibleSelection;
class HTMLFormControlElement : public HTMLElement {
public:
- HTMLFormControlElement(const QualifiedName& tagName, Document*, HTMLFormElement*);
+ HTMLFormControlElement(const QualifiedName& tagName, Document*, HTMLFormElement*, ConstructionType = CreateElementZeroRefCount);
virtual ~HTMLFormControlElement();
virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; }
@@ -108,7 +108,7 @@ public:
virtual bool willValidate() const;
String validationMessage();
- bool checkValidity();
+ bool checkValidity(Vector<RefPtr<HTMLFormControlElement> >* unhandledInvalidControls = 0);
// This must be called when a validation constraint or control value is changed.
void setNeedsValidityCheck();
void setCustomValidity(const String&);
@@ -116,7 +116,7 @@ public:
virtual bool patternMismatch() const { return false; }
virtual bool tooLong() const { return false; }
- void formDestroyed();
+ void formDestroyed() { m_form = 0; }
virtual void dispatchFocusEvent();
virtual void dispatchBlurEvent();
@@ -125,6 +125,7 @@ protected:
void removeFromForm();
// This must be called any time the result of willValidate() has changed.
void setNeedsWillValidateCheck();
+ virtual bool recalcWillValidate() const;
private:
virtual HTMLFormElement* virtualForm() const;
@@ -133,11 +134,18 @@ private:
HTMLFormElement* m_form;
OwnPtr<ValidityState> m_validityState;
- bool m_hasName : 1;
bool m_disabled : 1;
bool m_readOnly : 1;
bool m_required : 1;
bool m_valueMatchesRenderer : 1;
+ // The initial value of m_willValidate depends on a subclass, and we can't
+ // initialize it with a virtual function in the constructor. m_willValidate
+ // is not deterministic during m_willValidateInitialized=false.
+ mutable bool m_willValidateInitialized: 1;
+ mutable bool m_willValidate : 1;
+ // Cache of validity()->valid().
+ // "candidate for constraint validation" doesn't affect to m_isValid.
+ bool m_isValid : 1;
};
class HTMLFormControlElementWithState : public HTMLFormControlElement {
@@ -145,6 +153,8 @@ public:
HTMLFormControlElementWithState(const QualifiedName& tagName, Document*, HTMLFormElement*);
virtual ~HTMLFormControlElementWithState();
+ virtual bool autoComplete() const;
+ virtual bool shouldSaveAndRestoreFormControlState() const;
virtual void finishParsingChildren();
protected:
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index 2f88894..cafa3c9 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -26,8 +26,8 @@
#include "HTMLFormElement.h"
#include "CSSHelper.h"
-#include "Chrome.h"
-#include "ChromeClient.h"
+#include "DOMFormData.h"
+#include "DOMWindow.h"
#include "Document.h"
#include "Event.h"
#include "EventNames.h"
@@ -46,7 +46,6 @@
#include "ScriptEventListener.h"
#include "MIMETypeRegistry.h"
#include "MappedAttribute.h"
-#include "Page.h"
#include "RenderTextControl.h"
#include "ValidityState.h"
#include <limits>
@@ -201,83 +200,16 @@ TextEncoding HTMLFormElement::dataEncoding() const
return m_formDataBuilder.dataEncoding(document());
}
-PassRefPtr<FormData> HTMLFormElement::createFormData(const CString& boundary)
+PassRefPtr<FormData> HTMLFormElement::createFormData()
{
- Vector<char> encodedData;
- TextEncoding encoding = dataEncoding().encodingForFormSubmission();
-
- RefPtr<FormData> result = FormData::create();
-
+ RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding().encodingForFormSubmission());
for (unsigned i = 0; i < formElements.size(); ++i) {
HTMLFormControlElement* control = formElements[i];
- FormDataList list(encoding);
-
- if (!control->disabled() && control->appendFormData(list, m_formDataBuilder.isMultiPartForm())) {
- size_t formDataListSize = list.list().size();
- ASSERT(formDataListSize % 2 == 0);
- for (size_t j = 0; j < formDataListSize; j += 2) {
- const FormDataList::Item& key = list.list()[j];
- const FormDataList::Item& value = list.list()[j + 1];
- if (!m_formDataBuilder.isMultiPartForm()) {
- // Omit the name "isindex" if it's the first form data element.
- // FIXME: Why is this a good rule? Is this obsolete now?
- if (encodedData.isEmpty() && key.data() == "isindex")
- FormDataBuilder::encodeStringAsFormData(encodedData, value.data());
- else
- m_formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data());
- } else {
- Vector<char> header;
- m_formDataBuilder.beginMultiPartHeader(header, boundary, key.data());
-
- bool shouldGenerateFile = false;
- // if the current type is FILE, then we also need to include the filename
- if (value.file()) {
- const String& path = value.file()->path();
- String fileName = value.file()->fileName();
-
- // Let the application specify a filename if it's going to generate a replacement file for the upload.
- if (!path.isEmpty()) {
- if (Page* page = document()->page()) {
- String generatedFileName;
- shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
- if (shouldGenerateFile)
- fileName = generatedFileName;
- }
- }
-
- // We have to include the filename=".." part in the header, even if the filename is empty
- m_formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName);
-
- if (!fileName.isEmpty()) {
- // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path,
- // not just a basename. But filename is not the path. But note that it's not safe to
- // just use path instead since in the generated-file case it will not reflect the
- // MIME type of the generated file.
- String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName);
- if (!mimeType.isEmpty())
- m_formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1());
- }
- }
-
- m_formDataBuilder.finishMultiPartHeader(header);
-
- // Append body
- result->appendData(header.data(), header.size());
- if (size_t dataSize = value.data().length())
- result->appendData(value.data().data(), dataSize);
- else if (value.file() && !value.file()->path().isEmpty())
- result->appendFile(value.file()->path(), shouldGenerateFile);
-
- result->appendData("\r\n", 2);
- }
- }
- }
+ if (!control->disabled())
+ control->appendFormData(*domFormData, m_formDataBuilder.isMultiPartForm());
}
- if (m_formDataBuilder.isMultiPartForm())
- m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true);
-
- result->appendData(encodedData.data(), encodedData.size());
+ RefPtr<FormData> result = (m_formDataBuilder.isMultiPartForm()) ? FormData::createMultiPart(*domFormData, document()) : FormData::create(*domFormData);
result->setIdentifier(generateFormDataIdentifier());
return result;
@@ -288,6 +220,64 @@ bool HTMLFormElement::isMailtoForm() const
return protocolIs(m_url, "mailto");
}
+static inline HTMLFormControlElement* submitElementFromEvent(const Event* event)
+{
+ Node* targetNode = event->target()->toNode();
+ if (!targetNode || !targetNode->isElementNode())
+ return 0;
+ Element* targetElement = static_cast<Element*>(targetNode);
+ if (!targetElement->isFormControlElement())
+ return 0;
+ return static_cast<HTMLFormControlElement*>(targetElement);
+}
+
+bool HTMLFormElement::validateInteractively(Event* event)
+{
+ ASSERT(event);
+ if (noValidate())
+ return true;
+
+ HTMLFormControlElement* submitElement = submitElementFromEvent(event);
+ if (submitElement && submitElement->formNoValidate())
+ return true;
+
+ Vector<RefPtr<HTMLFormControlElement> > unhandledInvalidControls;
+ collectUnhandledInvalidControls(unhandledInvalidControls);
+ if (unhandledInvalidControls.isEmpty())
+ return true;
+ // If the form has invalid controls, abort submission.
+
+ RefPtr<HTMLFormElement> protector(this);
+ // Focus on the first focusable control.
+ for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) {
+ HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get();
+ if (unhandled->isFocusable() && unhandled->inDocument()) {
+ RefPtr<Document> originalDocument(unhandled->document());
+ unhandled->scrollIntoViewIfNeeded(false);
+ // scrollIntoViewIfNeeded() dispatches events, so the state
+ // of 'unhandled' might be changed so it's no longer focusable or
+ // moved to another document.
+ if (unhandled->isFocusable() && unhandled->inDocument() && originalDocument == unhandled->document()) {
+ unhandled->focus();
+ break;
+ }
+ }
+ }
+ // Warn about all of unfocusable controls.
+ if (Frame* frame = document()->frame()) {
+ for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) {
+ HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get();
+ if (unhandled->isFocusable() && unhandled->inDocument())
+ continue;
+ String message("An invalid form control with name='%name' is not focusable.");
+ message.replace("%name", unhandled->name());
+ frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, ErrorMessageLevel, message, 0, document()->url().string());
+ }
+ }
+ m_insubmit = false;
+ return false;
+}
+
bool HTMLFormElement::prepareSubmit(Event* event)
{
Frame* frame = document()->frame();
@@ -297,6 +287,10 @@ bool HTMLFormElement::prepareSubmit(Event* event)
m_insubmit = true;
m_doingsubmit = false;
+ // Interactive validation must be done before dispatching the submit event.
+ if (!validateInteractively(event))
+ return false;
+
if (dispatchEvent(Event::create(eventNames().submitEvent, true, true)) && !m_doingsubmit)
m_doingsubmit = true;
@@ -389,8 +383,8 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockH
ASSERT(!m_formDataBuilder.isMultiPartForm());
}
+ RefPtr<FormData> data = createFormData();
if (!m_formDataBuilder.isMultiPartForm()) {
- RefPtr<FormData> data = createFormData(CString());
if (isMailtoForm()) {
// Convert the form data into a string that we put into the URL.
@@ -400,13 +394,11 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockH
}
frame->loader()->submitForm("POST", m_url, data.release(), m_target, m_formDataBuilder.encodingType(), String(), lockHistory, event, formState.release());
- } else {
- Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString();
- frame->loader()->submitForm("POST", m_url, createFormData(boundary.data()), m_target, m_formDataBuilder.encodingType(), boundary.data(), lockHistory, event, formState.release());
- }
+ } else
+ frame->loader()->submitForm("POST", m_url, data.get(), m_target, m_formDataBuilder.encodingType(), data->boundary().data(), lockHistory, event, formState.release());
} else {
m_formDataBuilder.setIsMultiPartForm(false);
- frame->loader()->submitForm("GET", m_url, createFormData(CString()), m_target, String(), String(), lockHistory, event, formState.release());
+ frame->loader()->submitForm("GET", m_url, createFormData(), m_target, String(), String(), lockHistory, event, formState.release());
}
if (needButtonActivation && firstSuccessfulSubmitButton)
@@ -612,16 +604,24 @@ HTMLFormControlElement* HTMLFormElement::defaultButton() const
bool HTMLFormElement::checkValidity()
{
- // TODO: Check for unhandled invalid controls, see #27452 for tips.
+ Vector<RefPtr<HTMLFormControlElement> > controls;
+ collectUnhandledInvalidControls(controls);
+ return controls.isEmpty();
+}
- bool hasOnlyValidControls = true;
- for (unsigned i = 0; i < formElements.size(); ++i) {
- HTMLFormControlElement* control = formElements[i];
- if (!control->checkValidity())
- hasOnlyValidControls = false;
+void HTMLFormElement::collectUnhandledInvalidControls(Vector<RefPtr<HTMLFormControlElement> >& unhandledInvalidControls)
+{
+ RefPtr<HTMLFormElement> protector(this);
+ // Copy formElements because event handlers called from
+ // HTMLFormControlElement::checkValidity() might change formElements.
+ Vector<RefPtr<HTMLFormControlElement> > elements;
+ elements.reserveCapacity(formElements.size());
+ for (unsigned i = 0; i < formElements.size(); ++i)
+ elements.append(formElements[i]);
+ for (unsigned i = 0; i < elements.size(); ++i) {
+ if (elements[i]->form() == this)
+ elements[i]->checkValidity(&unhandledInvalidControls);
}
-
- return hasOnlyValidControls;
}
PassRefPtr<HTMLFormControlElement> HTMLFormElement::elementForAlias(const AtomicString& alias)
diff --git a/WebCore/html/HTMLFormElement.h b/WebCore/html/HTMLFormElement.h
index c0ce3e3..923c734 100644
--- a/WebCore/html/HTMLFormElement.h
+++ b/WebCore/html/HTMLFormElement.h
@@ -135,8 +135,13 @@ private:
bool isMailtoForm() const;
TextEncoding dataEncoding() const;
- PassRefPtr<FormData> createFormData(const CString& boundary);
+ PassRefPtr<FormData> createFormData();
unsigned formElementIndex(HTMLFormControlElement*);
+ // Returns true if the submission should be proceeded.
+ bool validateInteractively(Event*);
+ // Validates each of the controls, and stores controls of which 'invalid'
+ // event was not canceled to the specified vector.
+ void collectUnhandledInvalidControls(Vector<RefPtr<HTMLFormControlElement> >&);
friend class HTMLFormCollection;
diff --git a/WebCore/html/HTMLFrameElementBase.cpp b/WebCore/html/HTMLFrameElementBase.cpp
index 9d84b62..76f3ed4 100644
--- a/WebCore/html/HTMLFrameElementBase.cpp
+++ b/WebCore/html/HTMLFrameElementBase.cpp
@@ -90,7 +90,7 @@ bool HTMLFrameElementBase::isURLAllowed() const
return true;
}
-void HTMLFrameElementBase::openURL()
+void HTMLFrameElementBase::openURL(bool lockHistory, bool lockBackForwardList)
{
ASSERT(!m_frameName.isEmpty());
@@ -104,7 +104,7 @@ void HTMLFrameElementBase::openURL()
if (!parentFrame)
return;
- parentFrame->loader()->requestFrame(this, m_URL, m_frameName);
+ parentFrame->loader()->requestFrame(this, m_URL, m_frameName, lockHistory, lockBackForwardList);
if (contentFrame())
contentFrame()->setInViewSourceMode(viewSourceMode());
}
@@ -231,7 +231,7 @@ void HTMLFrameElementBase::setLocation(const String& str)
m_URL = AtomicString(str);
if (inDocument())
- openURL();
+ openURL(false, false);
}
bool HTMLFrameElementBase::supportsFocus() const
diff --git a/WebCore/html/HTMLFrameElementBase.h b/WebCore/html/HTMLFrameElementBase.h
index 7717df0..6424ba7 100644
--- a/WebCore/html/HTMLFrameElementBase.h
+++ b/WebCore/html/HTMLFrameElementBase.h
@@ -73,7 +73,7 @@ private:
bool viewSourceMode() const { return m_viewSource; }
void setNameAndOpenURL();
- void openURL();
+ void openURL(bool lockHistory = true, bool lockBackForwardList = true);
static void setNameAndOpenURLCallback(Node*);
diff --git a/WebCore/html/HTMLFrameSetElement.cpp b/WebCore/html/HTMLFrameSetElement.cpp
index f4d1558..9cc4975 100644
--- a/WebCore/html/HTMLFrameSetElement.cpp
+++ b/WebCore/html/HTMLFrameSetElement.cpp
@@ -135,6 +135,10 @@ void HTMLFrameSetElement::parseMappedAttribute(MappedAttribute *attr)
document()->setWindowAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(document()->frame(), attr));
else if (attr->name() == onfocusAttr)
document()->setWindowAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(document()->frame(), attr));
+ else if (attr->name() == onfocusinAttr)
+ document()->setWindowAttributeEventListener(eventNames().focusinEvent, createAttributeEventListener(document()->frame(), attr));
+ else if (attr->name() == onfocusoutAttr)
+ document()->setWindowAttributeEventListener(eventNames().focusoutEvent, createAttributeEventListener(document()->frame(), attr));
#if ENABLE(ORIENTATION_EVENTS)
else if (attr->name() == onorientationchangeAttr)
document()->setWindowAttributeEventListener(eventNames().orientationchangeEvent, createAttributeEventListener(document()->frame(), attr));
diff --git a/WebCore/html/HTMLFrameSetElement.idl b/WebCore/html/HTMLFrameSetElement.idl
index 3a761ae..9763460 100644
--- a/WebCore/html/HTMLFrameSetElement.idl
+++ b/WebCore/html/HTMLFrameSetElement.idl
@@ -28,31 +28,31 @@ module html {
#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
// Event handler attributes
- attribute [DontEnum] EventListener onbeforeunload;
- attribute [DontEnum] EventListener onhashchange;
- attribute [DontEnum] EventListener onmessage;
- attribute [DontEnum] EventListener onoffline;
- attribute [DontEnum] EventListener ononline;
- attribute [DontEnum] EventListener onpopstate;
- attribute [DontEnum] EventListener onresize;
- attribute [DontEnum] EventListener onstorage;
- attribute [DontEnum] EventListener onunload;
+ attribute [DontEnum, WindowEventListener] EventListener onbeforeunload;
+ attribute [DontEnum, WindowEventListener] EventListener onhashchange;
+ attribute [DontEnum, WindowEventListener] EventListener onmessage;
+ attribute [DontEnum, WindowEventListener] EventListener onoffline;
+ attribute [DontEnum, WindowEventListener] EventListener ononline;
+ attribute [DontEnum, WindowEventListener] EventListener onpopstate;
+ attribute [DontEnum, WindowEventListener] EventListener onresize;
+ attribute [DontEnum, WindowEventListener] EventListener onstorage;
+ attribute [DontEnum, WindowEventListener] EventListener onunload;
#if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS
attribute [DontEnum] EventListener onorientationchange;
#endif
- // Overrides of Element attributes (left in for completeness).
- // attribute [DontEnum] EventListener onblur;
- // attribute [DontEnum] EventListener onerror;
- // attribute [DontEnum] EventListener onfocus;
- // attribute [DontEnum] EventListener onload;
+ // Overrides of Element attributes (with different implementation in bindings).
+ attribute [DontEnum, WindowEventListener] EventListener onblur;
+ attribute [DontEnum, WindowEventListener] EventListener onerror;
+ attribute [DontEnum, WindowEventListener] EventListener onfocus;
+ attribute [DontEnum, WindowEventListener] EventListener onload;
// Not implemented yet.
- // attribute [DontEnum] EventListener onafterprint;
- // attribute [DontEnum] EventListener onbeforeprint;
- // attribute [DontEnum] EventListener onredo;
- // attribute [DontEnum] EventListener onundo;
+ // attribute [DontEnum, WindowEventListener] EventListener onafterprint;
+ // attribute [DontEnum, WindowEventListener] EventListener onbeforeprint;
+ // attribute [DontEnum, WindowEventListener] EventListener onredo;
+ // attribute [DontEnum, WindowEventListener] EventListener onundo;
#endif
};
diff --git a/WebCore/html/HTMLIFrameElement.cpp b/WebCore/html/HTMLIFrameElement.cpp
index 359bdb7..cce39df 100644
--- a/WebCore/html/HTMLIFrameElement.cpp
+++ b/WebCore/html/HTMLIFrameElement.cpp
@@ -30,7 +30,7 @@
#include "HTMLDocument.h"
#include "HTMLNames.h"
#include "MappedAttribute.h"
-#include "RenderPartObject.h"
+#include "RenderIFrame.h"
namespace WebCore {
@@ -67,6 +67,7 @@ bool HTMLIFrameElement::mapToEntry(const QualifiedName& attrName, MappedAttribut
return HTMLFrameElementBase::mapToEntry(attrName, result);
}
+#if ENABLE(SANDBOX)
static SandboxFlags parseSandboxAttribute(MappedAttribute* attribute)
{
if (attribute->isNull())
@@ -94,12 +95,15 @@ static SandboxFlags parseSandboxAttribute(MappedAttribute* attribute)
flags &= ~SandboxForms;
else if (equalIgnoringCase(sandboxToken, "allow-scripts"))
flags &= ~SandboxScripts;
+ else if (equalIgnoringCase(sandboxToken, "allow-top-navigation"))
+ flags &= ~SandboxTopNavigation;
start = end + 1;
}
-
+
return flags;
}
+#endif
void HTMLIFrameElement::parseMappedAttribute(MappedAttribute* attr)
{
@@ -123,8 +127,11 @@ void HTMLIFrameElement::parseMappedAttribute(MappedAttribute* attr)
if (!attr->isNull() && !attr->value().toInt())
// Add a rule that nulls out our border width.
addCSSLength(attr, CSSPropertyBorderWidth, "0");
- } else if (attr->name() == sandboxAttr)
+ }
+#if ENABLE(SANDBOX)
+ else if (attr->name() == sandboxAttr)
setSandboxFlags(parseSandboxAttribute(attr));
+#endif
else
HTMLFrameElementBase::parseMappedAttribute(attr);
}
@@ -136,7 +143,7 @@ bool HTMLIFrameElement::rendererIsNeeded(RenderStyle* style)
RenderObject* HTMLIFrameElement::createRenderer(RenderArena* arena, RenderStyle*)
{
- return new (arena) RenderPartObject(this);
+ return new (arena) RenderIFrame(this);
}
void HTMLIFrameElement::insertedIntoDocument()
diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp
index d3cea92..db66533 100644
--- a/WebCore/html/HTMLImageElement.cpp
+++ b/WebCore/html/HTMLImageElement.cpp
@@ -435,4 +435,10 @@ void HTMLImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) cons
addSubresourceURL(urls, document()->completeURL(getAttribute(usemapAttr)));
}
+void HTMLImageElement::willMoveToNewOwnerDocument()
+{
+ m_imageLoader.elementWillMoveToNewOwnerDocument();
+ HTMLElement::willMoveToNewOwnerDocument();
+}
+
}
diff --git a/WebCore/html/HTMLImageElement.h b/WebCore/html/HTMLImageElement.h
index d7df1dc..e9b813c 100644
--- a/WebCore/html/HTMLImageElement.h
+++ b/WebCore/html/HTMLImageElement.h
@@ -105,6 +105,9 @@ public:
virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
+protected:
+ virtual void willMoveToNewOwnerDocument();
+
private:
virtual void insertedIntoDocument();
virtual void removedFromDocument();
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index c3f6703..60669ef 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
* Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
*
@@ -60,6 +60,7 @@
#include "RenderText.h"
#include "RenderTextControlSingleLine.h"
#include "RenderTheme.h"
+#include "StepRange.h"
#include "StringHash.h"
#include "TextEvent.h"
#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
@@ -157,13 +158,14 @@ bool HTMLInputElement::autoComplete() const
{
if (m_autocomplete != Uninitialized)
return m_autocomplete == On;
-
- // Assuming we're still in a Form, respect the Form's setting
- if (HTMLFormElement* form = this->form())
- return form->autoComplete();
-
- // The default is true
- return true;
+ return HTMLTextFormControlElement::autoComplete();
+}
+
+static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement* element)
+{
+ if (HTMLFormElement* form = element->form())
+ return form->checkedRadioButtons();
+ return element->document()->checkedRadioButtons();
}
bool HTMLInputElement::valueMissing() const
@@ -190,7 +192,7 @@ bool HTMLInputElement::valueMissing() const
case CHECKBOX:
return !checked();
case RADIO:
- return !document()->checkedRadioButtons().checkedButtonForGroup(name());
+ return !checkedRadioButtons(this).checkedButtonForGroup(name());
case COLOR:
return false;
case BUTTON:
@@ -270,7 +272,7 @@ bool HTMLInputElement::tooLong() const
bool userEdited = !m_data.value().isNull();
if (!userEdited)
return false;
- return value().numGraphemeClusters() > static_cast<unsigned>(max);
+ return numGraphemeClusters(value()) > static_cast<unsigned>(max);
}
case BUTTON:
case CHECKBOX:
@@ -305,12 +307,13 @@ bool HTMLInputElement::rangeUnderflow() const
case DATETIMELOCAL:
case MONTH:
case NUMBER:
- case RANGE:
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:
@@ -341,12 +344,13 @@ bool HTMLInputElement::rangeOverflow() const
case DATETIMELOCAL:
case MONTH:
case NUMBER:
- case RANGE:
case TIME:
case WEEK: {
double doubleValue = parseToDouble(value(), nan);
- return isfinite(doubleValue) && doubleValue > maximum();
+ return isfinite(doubleValue) && doubleValue > maximum();
}
+ case RANGE: // Guaranteed by sanitization.
+ ASSERT(parseToDouble(value(), nan) <= maximum());
case BUTTON:
case CHECKBOX:
case COLOR:
@@ -499,7 +503,8 @@ bool HTMLInputElement::stepMismatch() const
switch (inputType()) {
case RANGE:
// stepMismatch doesn't occur for RANGE. RenderSlider guarantees the
- // value matches to step.
+ // value matches to step on user input, and sanitation takes care
+ // of the general case.
return false;
case NUMBER: {
double doubleValue;
@@ -681,14 +686,6 @@ void HTMLInputElement::stepDown(int n, ExceptionCode& ec)
applyStep(-n, ec);
}
-static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement *element)
-{
- if (HTMLFormElement* form = element->form())
- return form->checkedRadioButtons();
-
- return element->document()->checkedRadioButtons();
-}
-
bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
{
// If text fields can be focused, then they should always be keyboard focusable
@@ -809,7 +806,6 @@ void HTMLInputElement::setInputType(const String& t)
// type change, otherwise a JavaScript programmer would be able to set a text
// field's value to something like /etc/passwd and then change it to a file field.
if (inputType() != newType) {
- bool oldWillValidate = willValidate();
if (newType == FILE && m_haveType)
// Set the attribute back to the old value.
// Useful in case we were called from inside parseMappedAttribute.
@@ -828,6 +824,7 @@ void HTMLInputElement::setInputType(const String& t)
bool wasPasswordField = inputType() == PASSWORD;
bool didRespectHeightAndWidth = respectHeightAndWidthAttrs();
m_type = newType;
+ setNeedsWillValidateCheck();
bool willStoreValue = storesValueSeparateFromAttribute();
bool isPasswordField = inputType() == PASSWORD;
bool willRespectHeightAndWidth = respectHeightAndWidthAttrs();
@@ -867,8 +864,6 @@ void HTMLInputElement::setInputType(const String& t)
}
setNeedsValidityCheck();
- if (oldWillValidate != willValidate())
- setNeedsWillValidateCheck();
InputElement::notifyFormStateChanged(this);
}
m_haveType = true;
@@ -917,9 +912,6 @@ const AtomicString& HTMLInputElement::formControlType() const
bool HTMLInputElement::saveFormControlState(String& result) const
{
- if (!autoComplete())
- return false;
-
switch (inputType()) {
case BUTTON:
case COLOR:
@@ -941,9 +933,13 @@ bool HTMLInputElement::saveFormControlState(String& result) const
case TEXT:
case TIME:
case URL:
- case WEEK:
- result = value();
+ case WEEK: {
+ String currentValue = value();
+ if (currentValue == defaultValue())
+ return false;
+ result = currentValue;
return true;
+ }
case CHECKBOX:
case RADIO:
result = checked() ? "on" : "off";
@@ -1150,8 +1146,14 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
|| attr->name() == incrementalAttr)
setNeedsStyleRecalc();
else if (attr->name() == minAttr
- || attr->name() == maxAttr
- || attr->name() == multipleAttr
+ || attr->name() == maxAttr) {
+ if (inputType() == RANGE) {
+ // Sanitize the value.
+ setValue(value());
+ setNeedsStyleRecalc();
+ }
+ setNeedsValidityCheck();
+ } else if (attr->name() == multipleAttr
|| attr->name() == patternAttr
|| attr->name() == precisionAttr
|| attr->name() == stepAttr)
@@ -1359,12 +1361,12 @@ bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
// If no filename at all is entered, return successful but empty.
// Null would be more logical, but Netscape posts an empty file. Argh.
if (!numFiles) {
- encoding.appendFile(name(), File::create(""));
+ encoding.appendBlob(name(), File::create(""));
return true;
}
for (unsigned i = 0; i < numFiles; ++i)
- encoding.appendFile(name(), m_fileList->item(i));
+ encoding.appendBlob(name(), m_fileList->item(i));
return true;
}
}
@@ -1447,8 +1449,8 @@ void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
void HTMLInputElement::setIndeterminate(bool _indeterminate)
{
- // Only checkboxes honor indeterminate.
- if (inputType() != CHECKBOX || indeterminate() == _indeterminate)
+ // Only checkboxes and radio buttons honor indeterminate.
+ if (!allowsIndeterminate() || indeterminate() == _indeterminate)
return;
m_indeterminate = _indeterminate;
@@ -1490,10 +1492,16 @@ String HTMLInputElement::value() const
String value = m_data.value();
if (value.isNull()) {
value = sanitizeValue(getAttribute(valueAttr));
-
- // If no attribute exists, then just use "on" or "" based off the checked() state of the control.
- if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO))
- return checked() ? "on" : "";
+
+ // If no attribute exists, extra handling may be necessary.
+ // For Checkbox Types just use "on" or "" based off the checked() state of the control.
+ // For a Range Input use the calculated default value.
+ if (value.isNull()) {
+ if (inputType() == CHECKBOX || inputType() == RADIO)
+ return checked() ? "on" : "";
+ else if (inputType() == RANGE)
+ return serializeForNumberType(StepRange(this).defaultValue());
+ }
}
return value;
@@ -1575,18 +1583,15 @@ void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
m_fileList->clear();
else {
m_data.setValue(sanitizeValue(value));
- if (isTextField()) {
+ if (isTextField())
updatePlaceholderVisibility(false);
- if (inDocument())
- document()->updateStyleIfNeeded();
- }
}
- if (renderer())
- renderer()->updateFromElement();
setNeedsStyleRecalc();
} else
setAttribute(valueAttr, sanitizeValue(value));
+ setNeedsValidityCheck();
+
if (isTextField()) {
unsigned max = m_data.value().length();
#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
@@ -1606,7 +1611,6 @@ void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
dispatchFormControlChangeEvent();
InputElement::notifyFormStateChanged(this);
- setNeedsValidityCheck();
}
double HTMLInputElement::parseToDouble(const String& src, double defaultValue) const
@@ -1989,6 +1993,16 @@ bool HTMLInputElement::storesValueSeparateFromAttribute() const
return false;
}
+struct EventHandlingState {
+ RefPtr<HTMLInputElement> m_currRadio;
+ bool m_indeterminate;
+ bool m_checked;
+
+ EventHandlingState(bool indeterminate, bool checked)
+ : m_indeterminate(indeterminate)
+ , m_checked(checked) { }
+};
+
void* HTMLInputElement::preDispatchEventHandler(Event *evt)
{
// preventDefault or "return false" are used to reverse the automatic checking/selection we do here.
@@ -1996,17 +2010,14 @@ void* HTMLInputElement::preDispatchEventHandler(Event *evt)
void* result = 0;
if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
&& evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
+
+ EventHandlingState* state = new EventHandlingState(indeterminate(), checked());
+
if (inputType() == CHECKBOX) {
- // As a way to store the state, we return 0 if we were unchecked, 1 if we were checked, and 2 for
- // indeterminate.
- if (indeterminate()) {
- result = (void*)0x2;
+ if (indeterminate())
setIndeterminate(false);
- } else {
- if (checked())
- result = (void*)0x1;
+ else
setChecked(!checked(), true);
- }
} else {
// For radio buttons, store the current selected radio object.
// We really want radio groups to end up in sane states, i.e., to have something checked.
@@ -2016,11 +2027,13 @@ void* HTMLInputElement::preDispatchEventHandler(Event *evt)
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.
- currRadio->ref();
- result = currRadio;
+ state->m_currRadio = currRadio;
}
+ if (indeterminate())
+ setIndeterminate(false);
setChecked(true, true);
}
+ result = state;
}
return result;
}
@@ -2029,28 +2042,30 @@ void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data)
{
if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
&& evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
- if (inputType() == CHECKBOX) {
- // Reverse the checking we did in preDispatch.
- if (evt->defaultPrevented() || evt->defaultHandled()) {
- if (data == (void*)0x2)
- setIndeterminate(true);
- else
- setChecked(data);
- }
- } else if (data) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(data);
- if (evt->defaultPrevented() || evt->defaultHandled()) {
- // Restore the original selected radio button if possible.
- // Make sure it is still a radio button and only do the restoration if it still
- // belongs to our group.
-
- if (input->form() == form() && input->inputType() == RADIO && input->name() == name()) {
- // Ok, the old radio button is still in our form and in our group and is still a
- // radio button, so it's safe to restore selection to it.
- input->setChecked(true);
+
+ if (EventHandlingState* state = reinterpret_cast<EventHandlingState*>(data)) {
+ if (inputType() == CHECKBOX) {
+ // Reverse the checking we did in preDispatch.
+ if (evt->defaultPrevented() || evt->defaultHandled()) {
+ setIndeterminate(state->m_indeterminate);
+ setChecked(state->m_checked);
+ }
+ } else {
+ HTMLInputElement* input = state->m_currRadio.get();
+ if (evt->defaultPrevented() || evt->defaultHandled()) {
+ // Restore the original selected radio button if possible.
+ // Make sure it is still a radio button and only do the restoration if it still
+ // belongs to our group.
+
+ if (input && input->form() == form() && input->inputType() == RADIO && input->name() == name()) {
+ // Ok, the old radio button is still in our form and in our group and is still a
+ // radio button, so it's safe to restore selection to it.
+ input->setChecked(true);
+ }
+ setIndeterminate(state->m_indeterminate);
}
}
- input->deref();
+ delete state;
}
// Left clicks on radio buttons and check boxes already performed default actions in preDispatchEventHandler().
@@ -2505,6 +2520,13 @@ String HTMLInputElement::sanitizeValue(const String& proposedValue) const
{
if (isTextField())
return InputElement::sanitizeValue(this, proposedValue);
+
+ // If the proposedValue is null than this is a reset scenario and we
+ // want the range input's value attribute to take priority over the
+ // calculated default (middle) value.
+ if (inputType() == RANGE && !proposedValue.isNull())
+ return serializeForNumberType(StepRange(this).clampValue(proposedValue));
+
return proposedValue;
}
@@ -2592,6 +2614,9 @@ void HTMLInputElement::documentDidBecomeActive()
void HTMLInputElement::willMoveToNewOwnerDocument()
{
+ if (m_imageLoader)
+ m_imageLoader->elementWillMoveToNewOwnerDocument();
+
// Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
if (needsActivationCallback())
document()->unregisterForDocumentActivationCallbacks(this);
@@ -2615,11 +2640,10 @@ void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) cons
addSubresourceURL(urls, src());
}
-bool HTMLInputElement::willValidate() const
+bool HTMLInputElement::recalcWillValidate() const
{
- // FIXME: This shall check for new WF2 input types too
- return HTMLFormControlElementWithState::willValidate() && inputType() != HIDDEN &&
- inputType() != BUTTON && inputType() != RESET;
+ return HTMLFormControlElementWithState::recalcWillValidate()
+ && inputType() != HIDDEN && inputType() != BUTTON && inputType() != RESET;
}
String HTMLInputElement::serializeForNumberType(double number)
diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h
index 40930ac..c3b0a73 100644
--- a/WebCore/html/HTMLInputElement.h
+++ b/WebCore/html/HTMLInputElement.h
@@ -131,8 +131,12 @@ public:
bool checked() const { return m_checked; }
void setChecked(bool, bool sendChangeEvent = false);
+
+ // 'indeterminate' is a state independent of the checked state that causes the control to draw in a way that hides the actual state.
+ bool allowsIndeterminate() const { return inputType() == CHECKBOX || inputType() == RADIO; }
bool indeterminate() const { return m_indeterminate; }
void setIndeterminate(bool);
+
virtual int size() const;
virtual const AtomicString& formControlType() const;
void setType(const String&);
@@ -257,8 +261,6 @@ public:
virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
- virtual bool willValidate() const;
-
// Converts the specified string to a floating number.
// If the conversion fails, the return value is false. Take care that leading or trailing unnecessary characters make failures. This returns false for an empty string input.
// The double* parameter may be 0.
@@ -291,6 +293,7 @@ private:
virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
virtual bool isRequiredFormControl() const;
+ virtual bool recalcWillValidate() const;
PassRefPtr<HTMLFormElement> createTemporaryFormForIsIndex();
// Helper for getAllowedValueStep();
diff --git a/WebCore/html/HTMLLabelElement.cpp b/WebCore/html/HTMLLabelElement.cpp
index 06b3b2f..645017d 100644
--- a/WebCore/html/HTMLLabelElement.cpp
+++ b/WebCore/html/HTMLLabelElement.cpp
@@ -139,6 +139,8 @@ void HTMLLabelElement::accessKeyAction(bool sendToAnyElement)
{
if (HTMLElement* element = correspondingControl())
element->accessKeyAction(sendToAnyElement);
+ else
+ HTMLElement::accessKeyAction(sendToAnyElement);
}
String HTMLLabelElement::accessKey() const
diff --git a/WebCore/html/HTMLLinkElement.cpp b/WebCore/html/HTMLLinkElement.cpp
index daa1702..7942e67 100644
--- a/WebCore/html/HTMLLinkElement.cpp
+++ b/WebCore/html/HTMLLinkElement.cpp
@@ -26,7 +26,6 @@
#include "CSSHelper.h"
#include "CachedCSSStyleSheet.h"
-#include "DNS.h"
#include "DocLoader.h"
#include "Document.h"
#include "Frame.h"
@@ -38,6 +37,7 @@
#include "MediaList.h"
#include "MediaQueryEvaluator.h"
#include "Page.h"
+#include "ResourceHandle.h"
#include "ScriptEventListener.h"
#include "Settings.h"
#include <wtf/StdLibExtras.h>
@@ -201,6 +201,7 @@ void HTMLLinkElement::process()
if (m_rel.m_isIcon && m_url.isValid() && !m_url.isEmpty())
document()->setIconURL(m_url.string(), type);
+<<<<<<< HEAD
#ifdef ANDROID_APPLE_TOUCH_ICON
if ((m_rel.m_isTouchIcon || m_rel.m_isPrecomposedTouchIcon) && m_url.isValid()
&& !m_url.isEmpty())
@@ -211,6 +212,10 @@ void HTMLLinkElement::process()
if (m_rel.m_isDNSPrefetch && m_url.isValid() && !m_url.isEmpty())
prefetchDNS(m_url.host());
+=======
+ if (m_isDNSPrefetch && m_url.isValid() && !m_url.isEmpty())
+ ResourceHandle::prepareForURL(m_url);
+>>>>>>> webkit.org at r58033
#if ENABLE(LINK_PREFETCH)
if (m_rel.m_isLinkPrefetch && m_url.isValid()) {
@@ -231,7 +236,7 @@ void HTMLLinkElement::process()
String charset = getAttribute(charsetAttr);
if (charset.isEmpty() && document()->frame())
- charset = document()->frame()->loader()->encoding();
+ charset = document()->frame()->loader()->writer()->encoding();
if (m_cachedSheet) {
if (m_loading)
diff --git a/WebCore/html/HTMLMapElement.cpp b/WebCore/html/HTMLMapElement.cpp
index 9617afc..10a05d6 100644
--- a/WebCore/html/HTMLMapElement.cpp
+++ b/WebCore/html/HTMLMapElement.cpp
@@ -79,7 +79,7 @@ bool HTMLMapElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestRes
HTMLImageElement* HTMLMapElement::imageElement() const
{
- RefPtr<HTMLCollection> coll = renderer()->document()->images();
+ RefPtr<HTMLCollection> coll = document()->images();
for (Node* curr = coll->firstItem(); curr; curr = coll->nextItem()) {
if (!curr->hasTagName(imgTag))
continue;
diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp
index e5594ae..20fa7f8 100644
--- a/WebCore/html/HTMLMediaElement.cpp
+++ b/WebCore/html/HTMLMediaElement.cpp
@@ -70,7 +70,7 @@
#endif
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-#include "RenderPartObject.h"
+#include "RenderEmbeddedObject.h"
#include "Widget.h"
#endif
@@ -101,9 +101,14 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc)
, m_loadState(WaitingForSource)
, m_currentSourceNode(0)
, m_player(0)
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ , m_proxyWidget(0)
+#endif
, m_restrictions(NoRestrictions)
+ , m_preload(MediaPlayer::Auto)
, m_playing(false)
, m_processingMediaPlayerCallback(0)
+ , m_isWaitingUntilMediaCanStart(false)
, m_processingLoad(false)
, m_delayingTheLoadEvent(false)
, m_haveFiredLoadedData(false)
@@ -128,6 +133,11 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc)
HTMLMediaElement::~HTMLMediaElement()
{
+ if (m_isWaitingUntilMediaCanStart) {
+ if (Page* page = document()->page())
+ page->removeMediaCanStartListener(this);
+ }
+
document()->unregisterForDocumentActivationCallbacks(this);
document()->unregisterForMediaVolumeCallbacks(this);
}
@@ -158,10 +168,10 @@ void HTMLMediaElement::attributeChanged(Attribute* attr, bool preserveDecls)
const QualifiedName& attrName = attr->name();
if (attrName == srcAttr) {
- // don't have a src or any <source> children, trigger load
- if (inDocument() && m_loadState == WaitingForSource)
+ // Trigger a reload, as long as the 'src' attribute is present.
+ if (!getAttribute(srcAttr).isEmpty())
scheduleLoad();
- }
+ }
#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
else if (attrName == controlsAttr) {
if (!isVideo() && attached() && (controls() != (renderer() != 0))) {
@@ -178,9 +188,23 @@ void HTMLMediaElement::parseMappedAttribute(MappedAttribute* attr)
{
const QualifiedName& attrName = attr->name();
- if (attrName == autobufferAttr) {
- if (m_player)
- m_player->setAutobuffer(!attr->isNull());
+ if (attrName == preloadAttr) {
+ String value = attr->value();
+
+ if (equalIgnoringCase(value, "none"))
+ m_preload = MediaPlayer::None;
+ else if (equalIgnoringCase(value, "metadata"))
+ m_preload = MediaPlayer::MetaData;
+ else {
+ // The spec does not define an "invalid value default" but "auto" is suggested as the
+ // "missing value default", so use it for everything except "none" and "metadata"
+ m_preload = MediaPlayer::Auto;
+ }
+
+ // The attribute must be ignored if the autoplay attribute is present
+ if (!autoplay() && m_player)
+ m_player->setPreload(m_preload);
+
} else if (attrName == onabortAttr)
setAttributeEventListener(eventNames().abortEvent, createAttributeEventListener(this, attr));
else if (attrName == onbeforeloadAttr)
@@ -254,7 +278,11 @@ bool HTMLMediaElement::rendererIsNeeded(RenderStyle* style)
RenderObject* HTMLMediaElement::createRenderer(RenderArena* arena, RenderStyle*)
{
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- return new (arena) RenderEmbeddedObject(this);
+ // Setup the renderer if we already have a proxy widget.
+ RenderEmbeddedObject* mediaRenderer = new (arena) RenderEmbeddedObject(this);
+ if (m_proxyWidget)
+ mediaRenderer->setWidget(m_proxyWidget);
+ return mediaRenderer;
#else
return new (arena) RenderMedia(this);
#endif
@@ -300,6 +328,10 @@ void HTMLMediaElement::recalcStyle(StyleChange change)
void HTMLMediaElement::scheduleLoad()
{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ createMediaPlayerProxy();
+#endif
+
if (m_loadTimer.isActive())
return;
prepareForLoad();
@@ -439,39 +471,30 @@ void HTMLMediaElement::prepareForLoad()
m_sentStalledEvent = false;
m_haveFiredLoadedData = false;
- // 2 - Abort any already-running instance of the resource selection algorithm for this element.
+ // 1 - Abort any already-running instance of the resource selection algorithm for this element.
m_currentSourceNode = 0;
- // 3 - If there are any tasks from the media element's media element event task source in
+ // 2 - If there are any tasks from the media element's media element event task source in
// one of the task queues, then remove those tasks.
cancelPendingEventsAndCallbacks();
-}
-
-void HTMLMediaElement::loadInternal()
-{
- // If the load() method for this element is already being invoked, then abort these steps.
- if (m_processingLoad)
- return;
- m_processingLoad = true;
-
- // Steps 1 and 2 were done in prepareForLoad()
// 3 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, queue
// a task to fire a simple event named abort at the media element.
if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE)
scheduleEvent(eventNames().abortEvent);
- // 4
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ m_player = MediaPlayer::create(this);
+#else
+ createMediaPlayerProxy();
+#endif
+
+ // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps
if (m_networkState != NETWORK_EMPTY) {
m_networkState = NETWORK_EMPTY;
m_readyState = HAVE_NOTHING;
m_paused = true;
m_seeking = false;
- if (m_player) {
- m_player->pause();
- m_playing = false;
- m_player->seek(0);
- }
scheduleEvent(eventNames().emptiedEvent);
}
@@ -486,6 +509,22 @@ void HTMLMediaElement::loadInternal()
m_lastSeekTime = 0;
m_closedCaptionsVisible = false;
+}
+
+void HTMLMediaElement::loadInternal()
+{
+ // If we can't start a load right away, start it later.
+ Page* page = document()->page();
+ if (page && !page->canStartMedia()) {
+ if (m_isWaitingUntilMediaCanStart)
+ return;
+ page->addMediaCanStartListener(this);
+ m_isWaitingUntilMediaCanStart = true;
+ return;
+ }
+
+ // Steps 1 - 6 were done in prepareForLoad
+
// 7 - Invoke the media element's resource selection algorithm.
selectMediaResource();
m_processingLoad = false;
@@ -552,6 +591,11 @@ void HTMLMediaElement::loadNextSourceChild()
return;
}
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ // Recreate the media player for the new url
+ m_player = MediaPlayer::create(this);
+#endif
+
m_loadState = LoadingFromSourceElement;
loadResource(mediaURL, contentType);
}
@@ -579,14 +623,8 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content
if (m_sendProgressEvents)
startProgressEventTimer();
-#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- m_player = MediaPlayer::create(this);
-#else
- if (!m_player)
- m_player = MediaPlayer::create(this);
-#endif
-
- m_player->setAutobuffer(autobuffer());
+ if (!autoplay())
+ m_player->setPreload(m_preload);
m_player->setPreservesPitch(m_webkitPreservesPitch);
updateVolume();
@@ -599,7 +637,7 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content
#endif
if (isVideo() && m_player->canLoadPoster()) {
- KURL posterUrl = static_cast<HTMLVideoElement*>(this)->poster();
+ KURL posterUrl = poster();
if (!posterUrl.isEmpty())
m_player->setPoster(posterUrl);
}
@@ -712,6 +750,16 @@ void HTMLMediaElement::cancelPendingEventsAndCallbacks()
}
}
+Document* HTMLMediaElement::mediaPlayerOwningDocument()
+{
+ Document* d = document();
+
+ if (!d)
+ d = ownerDocument();
+
+ return d;
+}
+
void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*)
{
beginProcessingMediaPlayerCallback();
@@ -755,7 +803,7 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
if (state == MediaPlayer::Idle) {
if (m_networkState > NETWORK_IDLE) {
- stopPeriodicTimers();
+ m_progressEventTimer.stop();
scheduleEvent(eventNames().suspendEvent);
}
m_networkState = NETWORK_IDLE;
@@ -1042,7 +1090,7 @@ float HTMLMediaElement::startTime() const
float HTMLMediaElement::duration() const
{
- if (m_readyState >= HAVE_METADATA)
+ if (m_player && m_readyState >= HAVE_METADATA)
return m_player->duration();
return numeric_limits<float>::quiet_NaN();
@@ -1114,14 +1162,27 @@ void HTMLMediaElement::setAutoplay(bool b)
setBooleanAttribute(autoplayAttr, b);
}
-bool HTMLMediaElement::autobuffer() const
+String HTMLMediaElement::preload() const
{
- return hasAttribute(autobufferAttr);
+ switch (m_preload) {
+ case MediaPlayer::None:
+ return "none";
+ break;
+ case MediaPlayer::MetaData:
+ return "metadata";
+ break;
+ case MediaPlayer::Auto:
+ return "auto";
+ break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return String();
}
-void HTMLMediaElement::setAutobuffer(bool b)
+void HTMLMediaElement::setPreload(const String& preload)
{
- setBooleanAttribute(autobufferAttr, b);
+ setAttribute(preloadAttr, preload);
}
void HTMLMediaElement::play(bool isUserGesture)
@@ -1200,7 +1261,7 @@ bool HTMLMediaElement::controls() const
Frame* frame = document()->frame();
// always show controls when scripting is disabled
- if (frame && !frame->script()->canExecuteScripts())
+ if (frame && !frame->script()->canExecuteScripts(NotAboutToExecuteScript))
return true;
return hasAttribute(controlsAttr);
@@ -1241,7 +1302,7 @@ void HTMLMediaElement::setMuted(bool muted)
m_muted = muted;
// Avoid recursion when the player reports volume changes.
if (!processingMediaPlayerCallback()) {
- if (m_player && m_player->supportsMuting()) {
+ if (m_player) {
m_player->setMuted(m_muted);
if (renderer())
renderer()->updateFromElement();
@@ -1645,7 +1706,8 @@ void HTMLMediaElement::updateVolume()
Page* page = document()->page();
float volumeMultiplier = page ? page->mediaVolume() : 1;
- m_player->setVolume(m_muted ? 0 : m_volume * volumeMultiplier);
+ m_player->setMuted(m_muted);
+ m_player->setVolume(m_volume * volumeMultiplier);
}
if (renderer())
@@ -1735,6 +1797,9 @@ void HTMLMediaElement::userCancelledLoad()
// 7 - Abort the overall resource selection algorithm.
m_currentSourceNode = 0;
+
+ // Reset m_readyState since m_player is gone.
+ m_readyState = HAVE_NOTHING;
}
void HTMLMediaElement::documentWillBecomeInactive()
@@ -1778,12 +1843,11 @@ void HTMLMediaElement::mediaVolumeDidChange()
updateVolume();
}
-const IntRect HTMLMediaElement::screenRect()
+IntRect HTMLMediaElement::screenRect()
{
- IntRect elementRect;
- if (renderer())
- elementRect = renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRect());
- return elementRect;
+ if (!renderer())
+ return IntRect();
+ return renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRect());
}
void HTMLMediaElement::defaultEventHandler(Event* event)
@@ -1816,6 +1880,12 @@ bool HTMLMediaElement::processingUserGesture() const
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+void HTMLMediaElement::ensureMediaPlayer()
+{
+ if (!m_player)
+ m_player = MediaPlayer::create(this);
+}
+
void HTMLMediaElement::deliverNotification(MediaPlayerProxyNotificationType notification)
{
if (notification == MediaPlayerNotificationPlayPauseButtonPressed) {
@@ -1829,34 +1899,76 @@ void HTMLMediaElement::deliverNotification(MediaPlayerProxyNotificationType noti
void HTMLMediaElement::setMediaPlayerProxy(WebMediaPlayerProxy* proxy)
{
- if (m_player)
- m_player->setMediaPlayerProxy(proxy);
+ ensureMediaPlayer();
+ m_player->setMediaPlayerProxy(proxy);
}
-String HTMLMediaElement::initialURL()
+void HTMLMediaElement::getPluginProxyParams(KURL& url, Vector<String>& names, Vector<String>& values)
{
- KURL initialSrc = document()->completeURL(getAttribute(srcAttr));
-
- if (!initialSrc.isValid())
- initialSrc = selectNextSourceChild(0, DoNothing);
+ Frame* frame = document()->frame();
+ FrameLoader* loader = frame ? frame->loader() : 0;
- m_currentSrc = initialSrc.string();
+ if (isVideo()) {
+ String poster = poster();
+ if (!poster.isEmpty() && loader) {
+ KURL posterURL = loader->completeURL(poster);
+ if (posterURL.isValid() && loader->willLoadMediaElementURL(posterURL)) {
+ names.append("_media_element_poster_");
+ values.append(posterURL.string());
+ }
+ }
+ }
+
+ if (controls()) {
+ names.append("_media_element_controls_");
+ values.append("true");
+ }
- return initialSrc;
+ url = src();
+ if (!url.isValid() || !isSafeToLoadURL(url, Complain))
+ url = selectNextSourceChild(0, DoNothing);
+
+ m_currentSrc = url.string();
+ if (url.isValid() && loader && loader->willLoadMediaElementURL(url)) {
+ names.append("_media_element_src_");
+ values.append(m_currentSrc);
+ }
}
void HTMLMediaElement::finishParsingChildren()
{
HTMLElement::finishParsingChildren();
- if (!m_player)
- m_player = MediaPlayer::create(this);
-
document()->updateStyleIfNeeded();
- if (m_needWidgetUpdate && renderer())
- toRenderEmbeddedObject(renderer())->updateWidget(true);
+ createMediaPlayerProxy();
}
-#endif
+void HTMLMediaElement::createMediaPlayerProxy()
+{
+ ensureMediaPlayer();
+
+ if (!inDocument() && m_proxyWidget)
+ return;
+ if (inDocument() && !m_needWidgetUpdate)
+ return;
+
+ Frame* frame = document()->frame();
+ FrameLoader* loader = frame ? frame->loader() : 0;
+ if (!loader)
+ return;
+
+ KURL url;
+ Vector<String> paramNames;
+ Vector<String> paramValues;
+
+ getPluginProxyParams(url, paramNames, paramValues);
+
+ // Hang onto the proxy widget so it won't be destroyed if the plug-in is set to
+ // display:none
+ m_proxyWidget = loader->loadMediaPlayerProxyPlugin(this, url, paramNames, paramValues);
+ if (m_proxyWidget)
+ m_needWidgetUpdate = false;
+}
+#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
void HTMLMediaElement::enterFullscreen()
{
@@ -1927,6 +2039,13 @@ bool HTMLMediaElement::webkitHasClosedCaptions() const
return hasClosedCaptions();
}
+void HTMLMediaElement::mediaCanStart()
+{
+ ASSERT(m_isWaitingUntilMediaCanStart);
+ m_isWaitingUntilMediaCanStart = false;
+ loadInternal();
+}
+
}
#endif
diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h
index 07801da..83e1f2c 100644
--- a/WebCore/html/HTMLMediaElement.h
+++ b/WebCore/html/HTMLMediaElement.h
@@ -29,8 +29,8 @@
#if ENABLE(VIDEO)
#include "HTMLElement.h"
+#include "MediaCanStartListener.h"
#include "MediaPlayer.h"
-#include "Timer.h"
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
#include "MediaPlayerProxy.h"
@@ -43,23 +43,16 @@ class HTMLSourceElement;
class MediaError;
class KURL;
class TimeRanges;
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+class Widget;
+#endif
-class HTMLMediaElement : public HTMLElement, public MediaPlayerClient {
-public:
- virtual ~HTMLMediaElement();
-
- bool checkDTD(const Node* newChild);
-
- void attributeChanged(Attribute*, bool preserveDecls);
- void parseMappedAttribute(MappedAttribute *);
+// FIXME: The inheritance from MediaPlayerClient here should be private inheritance.
+// But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it
+// no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement.
- virtual bool rendererIsNeeded(RenderStyle*);
- virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
- virtual void insertedIntoDocument();
- virtual void removedFromDocument();
- virtual void attach();
- virtual void recalcStyle(StyleChange);
-
+class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener {
+public:
MediaPlayer* player() const { return m_player.get(); }
virtual bool isVideo() const = 0;
@@ -71,6 +64,8 @@ public:
// Eventually overloaded in HTMLVideoElement
virtual bool supportsFullscreen() const { return false; };
+ virtual const KURL poster() const { return KURL(); }
+
virtual bool supportsSave() const;
PlatformMedia platformMedia() const;
@@ -80,11 +75,6 @@ public:
void scheduleLoad();
- virtual void defaultEventHandler(Event*);
-
- // Pauses playback without changing any states or generating events
- void setPausedInternal(bool);
-
MediaPlayer::MovieLoadType movieLoadType() const;
bool inActiveDocument() const { return m_inActiveDocument; }
@@ -100,8 +90,9 @@ public:
enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_LOADED, NETWORK_NO_SOURCE };
NetworkState networkState() const;
- bool autobuffer() const;
- void setAutobuffer(bool);
+
+ String preload() const;
+ void setPreload(const String&);
PassRefPtr<TimeRanges> buffered() const;
void load(bool isUserGesture, ExceptionCode&);
@@ -150,22 +141,25 @@ public:
void beginScrubbing();
void endScrubbing();
- const IntRect screenRect();
+ IntRect screenRect();
bool canPlay() const;
float percentLoaded() const;
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ void allocateMediaPlayerIfNecessary();
void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
void deliverNotification(MediaPlayerProxyNotificationType notification);
void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
- String initialURL();
+ void getPluginProxyParams(KURL& url, Vector<String>& names, Vector<String>& values);
virtual void finishParsingChildren();
+ void createMediaPlayerProxy();
#endif
bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
+ bool isFullscreen() const { return m_isFullscreen; }
void enterFullscreen();
void exitFullscreen();
@@ -177,7 +171,25 @@ public:
protected:
HTMLMediaElement(const QualifiedName&, Document*);
+ virtual ~HTMLMediaElement();
+ virtual void parseMappedAttribute(MappedAttribute*);
+ virtual void attach();
+
+ virtual void willMoveToNewOwnerDocument();
+ virtual void didMoveToNewOwnerDocument();
+
+private:
+ virtual bool checkDTD(const Node* newChild);
+ virtual void attributeChanged(Attribute*, bool preserveDecls);
+ virtual bool rendererIsNeeded(RenderStyle*);
+ virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void recalcStyle(StyleChange);
+
+ virtual void defaultEventHandler(Event*);
+
float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const;
void setTimeOffsetAttribute(const QualifiedName&, float value);
@@ -189,10 +201,7 @@ protected:
void setReadyState(MediaPlayer::ReadyState);
void setNetworkState(MediaPlayer::NetworkState);
- virtual void willMoveToNewOwnerDocument();
- virtual void didMoveToNewOwnerDocument();
-
-private: // MediaPlayerClient
+ virtual Document* mediaPlayerOwningDocument();
virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
virtual void mediaPlayerTimeChanged(MediaPlayer*);
@@ -208,7 +217,6 @@ private: // MediaPlayerClient
virtual void mediaPlayerRenderingModeChanged(MediaPlayer*);
#endif
-private:
void loadTimerFired(Timer<HTMLMediaElement>*);
void asyncEventTimerFired(Timer<HTMLMediaElement>*);
void progressEventTimerFired(Timer<HTMLMediaElement>*);
@@ -263,15 +271,19 @@ private:
float minTimeSeekable() const;
float maxTimeSeekable() const;
- // Restrictions to change default behaviors. This is a effectively a compile time choice at the moment
- // because there are no accessor methods.
+ // Pauses playback without changing any states or generating events
+ void setPausedInternal(bool);
+
+ virtual void mediaCanStart();
+
+ // Restrictions to change default behaviors. This is effectively a compile time choice at the moment
+ // because there are no accessor functions.
enum BehaviorRestrictions {
NoRestrictions = 0,
RequireUserGestureForLoadRestriction = 1 << 0,
RequireUserGestureForRateChangeRestriction = 1 << 1,
};
-protected:
Timer<HTMLMediaElement> m_loadTimer;
Timer<HTMLMediaElement> m_asyncEventTimer;
Timer<HTMLMediaElement> m_progressEventTimer;
@@ -303,18 +315,25 @@ protected:
// loading state
enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
LoadState m_loadState;
- HTMLSourceElement *m_currentSourceNode;
+ HTMLSourceElement* m_currentSourceNode;
OwnPtr<MediaPlayer> m_player;
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ RefPtr<Widget> m_proxyWidget;
+#endif
BehaviorRestrictions m_restrictions;
+
+ MediaPlayer::Preload m_preload;
bool m_playing;
- // counter incremented while processing a callback from the media player, so we can avoid
- // calling the media engine recursively
+ // Counter incremented while processing a callback from the media player, so we can avoid
+ // calling the media engine recursively.
int m_processingMediaPlayerCallback;
+ bool m_isWaitingUntilMediaCanStart;
+
bool m_processingLoad : 1;
bool m_delayingTheLoadEvent : 1;
bool m_haveFiredLoadedData : 1;
diff --git a/WebCore/html/HTMLMediaElement.idl b/WebCore/html/HTMLMediaElement.idl
index 46a2b86..5cd3293 100644
--- a/WebCore/html/HTMLMediaElement.idl
+++ b/WebCore/html/HTMLMediaElement.idl
@@ -39,7 +39,7 @@ interface [Conditional=VIDEO] HTMLMediaElement : HTMLElement {
const unsigned short NETWORK_LOADED = 3;
const unsigned short NETWORK_NO_SOURCE = 4;
readonly attribute unsigned short networkState;
- attribute boolean autobuffer;
+ attribute DOMString preload;
readonly attribute TimeRanges buffered;
[NeedsUserGestureCheck] void load()
diff --git a/WebCore/html/HTMLMetaElement.cpp b/WebCore/html/HTMLMetaElement.cpp
index f90ad0e..35fd299 100644
--- a/WebCore/html/HTMLMetaElement.cpp
+++ b/WebCore/html/HTMLMetaElement.cpp
@@ -68,6 +68,7 @@ void HTMLMetaElement::insertedIntoDocument()
void HTMLMetaElement::process()
{
+<<<<<<< HEAD
#ifdef ANDROID_META_SUPPORT
if (!inDocument() || m_content.isNull())
return;
@@ -92,9 +93,17 @@ void HTMLMetaElement::process()
android::WebViewCore::getWebViewCore(view)->updateViewport();
}
#endif
+=======
+ if (!inDocument() || m_content.isNull())
+ return;
+
+ if (equalIgnoringCase(name(), "viewport"))
+ document()->processViewport(m_content);
+
+>>>>>>> webkit.org at r58033
// Get the document to process the tag, but only if we're actually part of DOM tree (changing a meta tag while
// it's not in the tree shouldn't have any effect on the document)
- if (inDocument() && !m_equiv.isNull() && !m_content.isNull())
+ if (!m_equiv.isNull())
document()->processHttpEquiv(m_equiv, m_content);
}
diff --git a/WebCore/html/HTMLObjectElement.idl b/WebCore/html/HTMLObjectElement.idl
index 8d975ba..be91dc4 100644
--- a/WebCore/html/HTMLObjectElement.idl
+++ b/WebCore/html/HTMLObjectElement.idl
@@ -23,8 +23,7 @@ module html {
interface [
DelegatingPutFunction,
DelegatingGetOwnPropertySlot,
- CustomCall,
- HasOverridingNameGetter
+ CustomCall
] HTMLObjectElement : HTMLElement {
readonly attribute HTMLFormElement form;
attribute [ConvertNullToNullString, Reflect] DOMString code;
diff --git a/WebCore/html/HTMLParser.cpp b/WebCore/html/HTMLParser.cpp
index 644f63e..c5839a8 100644
--- a/WebCore/html/HTMLParser.cpp
+++ b/WebCore/html/HTMLParser.cpp
@@ -400,7 +400,7 @@ bool HTMLParser::insertNode(Node* n, bool flat)
n->finishParsingChildren();
}
- if (localName == htmlTag && m_document->frame())
+ if (localName == htmlTag && m_document->frame() && !m_isParsingFragment)
m_document->frame()->loader()->dispatchDocumentElementAvailable();
return true;
@@ -446,7 +446,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
}
} else if (h->hasLocalName(htmlTag)) {
if (!m_current->isDocumentNode() ) {
- if (m_document->documentElement() && m_document->documentElement()->hasTagName(htmlTag)) {
+ if (m_document->documentElement() && m_document->documentElement()->hasTagName(htmlTag) && !m_isParsingFragment) {
reportError(RedundantHTMLBodyError, &localName);
// we have another <HTML> element.... apply attributes to existing one
// make sure we don't overwrite already existing attributes
@@ -489,7 +489,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
return false;
}
} else if (h->hasLocalName(bodyTag)) {
- if (m_inBody && m_document->body()) {
+ if (m_inBody && m_document->body() && !m_isParsingFragment) {
// we have another <BODY> element.... apply attributes to existing one
// make sure we don't overwrite already existing attributes
// some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor>
@@ -503,8 +503,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
existingBody->setAttribute(it->name(), it->value());
}
return false;
- }
- else if (!m_current->isDocumentNode())
+ } else if (!m_current->isDocumentNode())
return false;
} else if (h->hasLocalName(areaTag)) {
if (m_currentMapElement) {
@@ -551,7 +550,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
if (!m_haveFrameSet) {
// Ensure that head exists.
// But not for older versions of Mail, where the implicit <head> isn't expected - <rdar://problem/6863795>
- if (shouldCreateImplicitHead(m_document))
+ if (!m_isParsingFragment && shouldCreateImplicitHead(m_document))
createHead();
popBlock(headTag);
@@ -758,7 +757,7 @@ bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&)
// we can't implement that behaviour now because it could cause too many
// regressions and the headaches are not worth the work as long as there is
// no site actually relying on that detail (Dirk)
- if (m_document->body())
+ if (m_document->body() && !m_isParsingFragment)
m_document->body()->setAttribute(styleAttr, "display:none");
m_inBody = false;
}
@@ -876,8 +875,8 @@ bool HTMLParser::noframesCreateErrorCheck(Token*, RefPtr<Node>&)
bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&)
{
if (!m_isParsingFragment) {
- Settings* settings = m_document->settings();
- if (settings && settings->isJavaScriptEnabled())
+ Frame* frame = m_document->frame();
+ if (frame && frame->script()->canExecuteScripts(NotAboutToExecuteScript))
setSkipMode(noscriptTag);
}
return true;
@@ -939,6 +938,7 @@ PassRefPtr<Node> HTMLParser::getNode(Token* t)
gFunctionMap.set(h6Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
gFunctionMap.set(headTag.localName().impl(), &HTMLParser::headCreateErrorCheck);
gFunctionMap.set(headerTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
+ gFunctionMap.set(hgroupTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
gFunctionMap.set(hrTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
gFunctionMap.set(iTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck);
gFunctionMap.set(isindexTag.localName().impl(), &HTMLParser::isindexCreateErrorCheck);
@@ -1061,8 +1061,8 @@ bool HTMLParser::isInline(Node* node) const
return true;
#if !ENABLE(XHTMLMP)
if (e->hasLocalName(noscriptTag) && !m_isParsingFragment) {
- Settings* settings = m_document->settings();
- if (settings && settings->isJavaScriptEnabled())
+ Frame* frame = m_document->frame();
+ if (frame && frame->script()->canExecuteScripts(NotAboutToExecuteScript))
return true;
}
#endif
@@ -1590,12 +1590,16 @@ void HTMLParser::createHead()
if (m_head)
return;
- if (!m_document->documentElement()) {
+ if (!m_document->documentElement() && !m_isParsingFragment) {
insertNode(new HTMLHtmlElement(htmlTag, m_document));
- ASSERT(m_document->documentElement());
+ ASSERT(m_document->documentElement() || m_isParsingFragment);
}
m_head = new HTMLHeadElement(headTag, m_document);
+
+ if (m_isParsingFragment)
+ return;
+
HTMLElement* body = m_document->body();
ExceptionCode ec = 0;
m_document->documentElement()->insertBefore(m_head.get(), body, ec);
diff --git a/WebCore/html/HTMLPlugInImageElement.cpp b/WebCore/html/HTMLPlugInImageElement.cpp
index 6dcd5fb..e2898a2 100644
--- a/WebCore/html/HTMLPlugInImageElement.cpp
+++ b/WebCore/html/HTMLPlugInImageElement.cpp
@@ -34,10 +34,6 @@ HTMLPlugInImageElement::HTMLPlugInImageElement(const QualifiedName& tagName, Doc
{
}
-HTMLPlugInImageElement::~HTMLPlugInImageElement()
-{
-}
-
bool HTMLPlugInImageElement::isImageType()
{
if (m_serviceType.isEmpty() && protocolIs(m_url, "data"))
@@ -51,4 +47,11 @@ bool HTMLPlugInImageElement::isImageType()
return Image::supportsType(m_serviceType);
}
+void HTMLPlugInImageElement::willMoveToNewOwnerDocument()
+{
+ if (m_imageLoader)
+ m_imageLoader->elementWillMoveToNewOwnerDocument();
+ HTMLPlugInElement::willMoveToNewOwnerDocument();
+}
+
} // namespace WebCore
diff --git a/WebCore/html/HTMLPlugInImageElement.h b/WebCore/html/HTMLPlugInImageElement.h
index 7725a5a..6f8d305 100644
--- a/WebCore/html/HTMLPlugInImageElement.h
+++ b/WebCore/html/HTMLPlugInImageElement.h
@@ -30,8 +30,6 @@ class HTMLImageLoader;
class HTMLPlugInImageElement : public HTMLPlugInElement {
public:
- virtual ~HTMLPlugInImageElement();
-
const String& serviceType() const { return m_serviceType; }
const String& url() const { return m_url; }
@@ -43,6 +41,9 @@ protected:
OwnPtr<HTMLImageLoader> m_imageLoader;
String m_serviceType;
String m_url;
+
+private:
+ virtual void willMoveToNewOwnerDocument();
};
} // namespace WebCore
diff --git a/WebCore/html/HTMLProgressElement.cpp b/WebCore/html/HTMLProgressElement.cpp
new file mode 100644
index 0000000..6fa8043
--- /dev/null
+++ b/WebCore/html/HTMLProgressElement.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#if ENABLE(PROGRESS_TAG)
+#include "HTMLProgressElement.h"
+
+#include "EventNames.h"
+#include "FormDataList.h"
+#include "HTMLFormElement.h"
+#include "HTMLNames.h"
+#include "MappedAttribute.h"
+#include "RenderProgress.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+HTMLProgressElement::HTMLProgressElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
+ : HTMLFormControlElement(tagName, document, form, CreateElement)
+{
+ ASSERT(hasTagName(progressTag));
+}
+
+PassRefPtr<HTMLProgressElement> HTMLProgressElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
+{
+ return adoptRef(new HTMLProgressElement(tagName, document, form));
+}
+
+RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyle*)
+{
+ return new (arena) RenderProgress(this);
+}
+
+const AtomicString& HTMLProgressElement::formControlType() const
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, progress, ("progress"));
+ return progress;
+}
+
+void HTMLProgressElement::parseMappedAttribute(MappedAttribute* attribute)
+{
+ if (attribute->name() == valueAttr) {
+ if (renderer())
+ renderer()->updateFromElement();
+ } else if (attribute->name() == maxAttr) {
+ if (renderer())
+ renderer()->updateFromElement();
+ } else
+ HTMLFormControlElement::parseMappedAttribute(attribute);
+}
+
+double HTMLProgressElement::value() const
+{
+ const AtomicString& valueString = getAttribute(valueAttr);
+ bool ok;
+ double value = valueString.toDouble(&ok);
+ if (!ok || value < 0)
+ return valueString.isNull() ? 1 : 0;
+ return (value > max()) ? max() : value;
+}
+
+void HTMLProgressElement::setValue(double value)
+{
+ setAttribute(valueAttr, String::number(value >= 0 ? value : 0));
+}
+
+double HTMLProgressElement::max() const
+{
+ bool ok;
+ double max = getAttribute(maxAttr).toDouble(&ok);
+ if (!ok || max <= 0)
+ return 1;
+ return max;
+}
+
+void HTMLProgressElement::setMax(double max)
+{
+ setAttribute(maxAttr, String::number(max > 0 ? max : 1));
+}
+
+double HTMLProgressElement::position() const
+{
+ if (!hasAttribute(valueAttr))
+ return -1;
+ return value() / max();
+}
+
+} // namespace
+#endif
diff --git a/WebCore/html/HTMLProgressElement.h b/WebCore/html/HTMLProgressElement.h
new file mode 100644
index 0000000..a925fc5
--- /dev/null
+++ b/WebCore/html/HTMLProgressElement.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef HTMLProgressElement_h
+#define HTMLProgressElement_h
+
+#if ENABLE(PROGRESS_TAG)
+#include "HTMLFormControlElement.h"
+
+namespace WebCore {
+
+class HTMLProgressElement : public HTMLFormControlElement {
+public:
+ static PassRefPtr<HTMLProgressElement> create(const QualifiedName&, Document*, HTMLFormElement* = 0);
+
+ double value() const;
+ void setValue(double);
+
+ double max() const;
+ void setMax(double);
+
+ double position() const;
+
+private:
+ HTMLProgressElement(const QualifiedName&, Document*, HTMLFormElement*);
+
+ virtual bool isOptionalFormControl() const { return true; }
+
+ virtual const AtomicString& formControlType() const;
+
+ virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+
+ virtual void parseMappedAttribute(MappedAttribute*);
+};
+
+} // namespace
+
+#endif
+#endif
diff --git a/WebCore/html/HTMLProgressElement.idl b/WebCore/html/HTMLProgressElement.idl
new file mode 100644
index 0000000..8da62aa
--- /dev/null
+++ b/WebCore/html/HTMLProgressElement.idl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+module html {
+ interface [
+ Conditional=PROGRESS_TAG
+ ] HTMLProgressElement : HTMLElement {
+ attribute double value;
+ attribute double max;
+ readonly attribute double position;
+ readonly attribute HTMLFormElement form;
+ };
+
+}
diff --git a/WebCore/html/HTMLScriptElement.cpp b/WebCore/html/HTMLScriptElement.cpp
index 636c579..58c3b03 100644
--- a/WebCore/html/HTMLScriptElement.cpp
+++ b/WebCore/html/HTMLScriptElement.cpp
@@ -220,6 +220,11 @@ String HTMLScriptElement::forAttributeValue() const
return getAttribute(forAttr).string();
}
+String HTMLScriptElement::eventAttributeValue() const
+{
+ return getAttribute(eventAttr).string();
+}
+
void HTMLScriptElement::dispatchLoadEvent()
{
ASSERT(!m_data.haveFiredLoadEvent());
diff --git a/WebCore/html/HTMLScriptElement.h b/WebCore/html/HTMLScriptElement.h
index 4d18beb..b6d683f 100644
--- a/WebCore/html/HTMLScriptElement.h
+++ b/WebCore/html/HTMLScriptElement.h
@@ -83,6 +83,7 @@ protected:
virtual String typeAttributeValue() const;
virtual String languageAttributeValue() const;
virtual String forAttributeValue() const;
+ virtual String eventAttributeValue() const;
virtual void dispatchLoadEvent();
virtual void dispatchErrorEvent();
diff --git a/WebCore/html/HTMLSelectElement.cpp b/WebCore/html/HTMLSelectElement.cpp
index 5f5c855..de40ff7 100644
--- a/WebCore/html/HTMLSelectElement.cpp
+++ b/WebCore/html/HTMLSelectElement.cpp
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
@@ -87,9 +88,27 @@ void HTMLSelectElement::setSelectedIndex(int optionIndex, bool deselect)
void HTMLSelectElement::setSelectedIndexByUser(int optionIndex, bool deselect, bool fireOnChangeNow)
{
+ // Bail out if this index is already the selected one, to avoid running unnecessary JavaScript that can mess up
+ // autofill, when there is no actual change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and rdar://7467917 ).
+ // Perhaps this logic could be moved into SelectElement, but some callers of SelectElement::setSelectedIndex()
+ // seem to expect it to fire its change event even when the index was already selected.
+ if (optionIndex == selectedIndex())
+ return;
+
SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, fireOnChangeNow, true);
}
+void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow)
+{
+ if (!multiple())
+ setSelectedIndexByUser(listIndex, true, fireOnChangeNow);
+ else {
+ updateSelectedState(m_data, this, listIndex, allowMultiplySelections, shift);
+ if (fireOnChangeNow)
+ listBoxOnChange();
+ }
+}
+
int HTMLSelectElement::activeSelectionStartListIndex() const
{
if (m_data.activeSelectionAnchorIndex() >= 0)
@@ -181,8 +200,13 @@ void HTMLSelectElement::parseMappedAttribute(MappedAttribute* attr)
String attrSize = String::number(size);
if (attrSize != attr->value())
attr->setValue(attrSize);
+ size = max(size, 1);
+
+ // Ensure that we've determined selectedness of the items at least once prior to changing the size.
+ if (oldSize != size)
+ recalcListItemsIfNeeded();
- m_data.setSize(max(size, 1));
+ m_data.setSize(size);
if ((oldUsesMenuList != m_data.usesMenuList() || (!oldUsesMenuList && m_data.size() != oldSize)) && attached()) {
detach();
attach();
@@ -195,10 +219,6 @@ void HTMLSelectElement::parseMappedAttribute(MappedAttribute* attr)
} else if (attr->name() == alignAttr) {
// Don't map 'align' attribute. This matches what Firefox, Opera and IE do.
// See http://bugs.webkit.org/show_bug.cgi?id=12072
- } else if (attr->name() == onfocusAttr) {
- setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
- } else if (attr->name() == onblurAttr) {
- setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
} else if (attr->name() == onchangeAttr) {
setAttributeEventListener(eventNames().changeEvent, createAttributeEventListener(this, attr));
} else
@@ -411,11 +431,21 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionCode& ec)
} else {
const Vector<Element*>& items = listItems();
+ // Removing children fires mutation events, which might mutate the DOM further, so we first copy out a list
+ // of elements that we intend to remove then attempt to remove them one at a time.
+ Vector<RefPtr<Element> > itemsToRemove;
size_t optionIndex = 0;
- for (size_t listIndex = 0; listIndex < items.size(); listIndex++) {
- if (items[listIndex]->hasLocalName(optionTag) && optionIndex++ >= newLen) {
- Element *item = items[listIndex];
+ for (size_t i = 0; i < items.size(); ++i) {
+ Element* item = items[i];
+ if (item->hasLocalName(optionTag) && optionIndex++ >= newLen) {
ASSERT(item->parentNode());
+ itemsToRemove.append(item);
+ }
+ }
+
+ for (size_t i = 0; i < itemsToRemove.size(); ++i) {
+ Element* item = itemsToRemove[i].get();
+ if (item->parentNode()) {
item->parentNode()->removeChild(item, ec);
}
}
diff --git a/WebCore/html/HTMLSelectElement.h b/WebCore/html/HTMLSelectElement.h
index 0a2050e..8a31efc 100644
--- a/WebCore/html/HTMLSelectElement.h
+++ b/WebCore/html/HTMLSelectElement.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
@@ -80,6 +81,8 @@ public:
void scrollToSelection();
+ void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
+
private:
virtual int tagPriority() const { return 6; }
virtual bool checkDTD(const Node* newChild);
diff --git a/WebCore/html/HTMLTagNames.in b/WebCore/html/HTMLTagNames.in
index 430b8ea..9f4900c 100644
--- a/WebCore/html/HTMLTagNames.in
+++ b/WebCore/html/HTMLTagNames.in
@@ -55,6 +55,7 @@ h5 interfaceName=HTMLHeadingElement, createWithNew
h6 interfaceName=HTMLHeadingElement, createWithNew
head createWithNew
header interfaceName=HTMLElement
+hgroup interfaceName=HTMLElement
hr interfaceName=HTMLHRElement, createWithNew
html createWithNew
i interfaceName=HTMLElement
@@ -89,6 +90,7 @@ p interfaceName=HTMLParagraphElement, createWithNew
param createWithNew
plaintext interfaceName=HTMLElement
pre createWithNew
+progress interfaceName=HTMLProgressElement, conditional=PROGRESS_TAG
q interfaceName=HTMLQuoteElement, createWithNew
rp interfaceName=HTMLElement, conditional=RUBY
rt interfaceName=HTMLElement, conditional=RUBY
diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp
index 633e5ec..2bfde03 100644
--- a/WebCore/html/HTMLTextAreaElement.cpp
+++ b/WebCore/html/HTMLTextAreaElement.cpp
@@ -90,7 +90,10 @@ const AtomicString& HTMLTextAreaElement::formControlType() const
bool HTMLTextAreaElement::saveFormControlState(String& result) const
{
- result = value();
+ String currentValue = value();
+ if (currentValue == defaultValue())
+ return false;
+ result = currentValue;
return true;
}
@@ -170,6 +173,8 @@ bool HTMLTextAreaElement::appendFormData(FormDataList& encoding, bool)
if (name().isEmpty())
return false;
+ document()->updateLayout();
+
// FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
// While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
RenderTextControl* control = toRenderTextControl(renderer());
@@ -239,8 +244,8 @@ void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
return;
unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength);
- unsigned currentLength = toRenderTextControl(renderer())->text().numGraphemeClusters();
- unsigned selectionLength = plainText(document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
+ unsigned currentLength = numGraphemeClusters(toRenderTextControl(renderer())->text());
+ unsigned selectionLength = numGraphemeClusters(plainText(document()->frame()->selection()->selection().toNormalizedRange().get()));
ASSERT(currentLength >= selectionLength);
unsigned baseLength = currentLength - selectionLength;
unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLength - baseLength : 0;
@@ -249,7 +254,7 @@ void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, unsigned maxLength)
{
- return proposedValue.left(proposedValue.numCharactersInGraphemeClusters(maxLength));
+ return proposedValue.left(numCharactersInGraphemeClusters(proposedValue, maxLength));
}
void HTMLTextAreaElement::rendererWillBeDestroyed()
@@ -295,13 +300,11 @@ void HTMLTextAreaElement::setNonDirtyValue(const String& value)
return;
m_value = normalizedValue;
+ updatePlaceholderVisibility(false);
+ setNeedsStyleRecalc();
+ setNeedsValidityCheck();
m_isDirty = false;
setFormControlValueMatchesRenderer(true);
- updatePlaceholderVisibility(false);
- if (inDocument())
- document()->updateStyleIfNeeded();
- if (renderer())
- renderer()->updateFromElement();
// Set the caret to the end of the text value.
if (document()->focusedNode() == this) {
@@ -313,7 +316,6 @@ void HTMLTextAreaElement::setNonDirtyValue(const String& value)
setSelectionRange(endOfString, endOfString);
}
- setNeedsValidityCheck();
notifyFormStateChanged(this);
}
@@ -388,7 +390,7 @@ bool HTMLTextAreaElement::tooLong() const
int max = maxLength();
if (max < 0)
return false;
- return value().numGraphemeClusters() > static_cast<unsigned>(max);
+ return numGraphemeClusters(value()) > static_cast<unsigned>(max);
}
void HTMLTextAreaElement::accessKeyAction(bool)
diff --git a/WebCore/html/HTMLTitleElement.cpp b/WebCore/html/HTMLTitleElement.cpp
index b9a8de7..81ecd10 100644
--- a/WebCore/html/HTMLTitleElement.cpp
+++ b/WebCore/html/HTMLTitleElement.cpp
@@ -84,10 +84,15 @@ void HTMLTitleElement::setText(const String &value)
if (numChildren == 1 && firstChild()->isTextNode())
static_cast<Text*>(firstChild())->setData(value, ec);
else {
+ // We make a copy here because entity of "value" argument can be Document::m_title,
+ // which goes empty during removeChildren() invocation below,
+ // which causes HTMLTitleElement::childrenChanged(), which ends up Document::setTitle().
+ String valueCopy(value);
+
if (numChildren > 0)
removeChildren();
-
- appendChild(document()->createTextNode(value.impl()), ec);
+
+ appendChild(document()->createTextNode(valueCopy.impl()), ec);
}
}
diff --git a/WebCore/html/HTMLTokenizer.cpp b/WebCore/html/HTMLTokenizer.cpp
index 6fa3e20..390d332 100644
--- a/WebCore/html/HTMLTokenizer.cpp
+++ b/WebCore/html/HTMLTokenizer.cpp
@@ -71,25 +71,17 @@ namespace WebCore {
using namespace HTMLNames;
-#if MOBILE
-// The mobile device needs to be responsive, as such the tokenizer chunk size is reduced.
// This value is used to define how many characters the tokenizer will process before
// yeilding control.
-static const int defaultTokenizerChunkSize = 256;
-#else
+// To increase responsivness reduce the tokenizer chunk size.
static const int defaultTokenizerChunkSize = 4096;
-#endif
-#if MOBILE
-// As the chunks are smaller (above), the tokenizer should not yield for as long a period, otherwise
-// it will take way to long to load a page.
-static const double defaultTokenizerTimeDelay = 0.300;
-#else
// FIXME: We would like this constant to be 200ms.
// Yielding more aggressively results in increased responsiveness and better incremental rendering.
// It slows down overall page-load on slower machines, though, so for now we set a value of 500.
+// For smaller chunks (above) decrease the value of TimerDelay as the the tokenizer should not
+// yield for as long a period otherwise it will take way to long to load a page.
static const double defaultTokenizerTimeDelay = 0.500;
-#endif
static const char commentStart [] = "<!--";
static const char doctypeStart [] = "<!doctype";
@@ -1523,7 +1515,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
m_scriptTagSrcAttrValue = String();
m_scriptTagCharsetAttrValue = String();
if (m_currentToken.attrs && !m_fragment) {
- if (m_doc->frame() && m_doc->frame()->script()->canExecuteScripts()) {
+ if (m_doc->frame() && m_doc->frame()->script()->canExecuteScripts(NotAboutToExecuteScript)) {
if ((a = m_currentToken.attrs->getAttributeItem(srcAttr)))
m_scriptTagSrcAttrValue = m_doc->completeURL(deprecatedParseURL(a->value())).string();
}
@@ -1940,7 +1932,7 @@ void HTMLTokenizer::finish()
PassRefPtr<Node> HTMLTokenizer::processToken()
{
ScriptController* scriptController = (!m_fragment && m_doc->frame()) ? m_doc->frame()->script() : 0;
- if (scriptController && scriptController->canExecuteScripts())
+ if (scriptController && scriptController->canExecuteScripts(NotAboutToExecuteScript))
// FIXME: Why isn't this m_currentScriptTagStartLineNumber? I suspect this is wrong.
scriptController->setEventHandlerLineNumber(m_currentTagStartLineNumber + 1); // Script line numbers are 1 based.
if (m_dest > m_buffer) {
diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp
index be8f884..3db48f1 100644
--- a/WebCore/html/HTMLVideoElement.cpp
+++ b/WebCore/html/HTMLVideoElement.cpp
@@ -104,8 +104,8 @@ void HTMLVideoElement::parseMappedAttribute(MappedAttribute* attr)
m_imageLoader.set(new HTMLImageLoader(this));
m_imageLoader->updateFromElementIgnoringPreviousError();
#else
- if (m_player)
- m_player->setPoster(poster());
+ if (player())
+ player()->setPoster(poster());
#endif
}
} else if (attrName == widthAttr)
@@ -122,7 +122,7 @@ bool HTMLVideoElement::supportsFullscreen() const
if (!page)
return false;
- if (!m_player || !m_player->supportsFullscreen() || !m_player->hasVideo())
+ if (!player() || !player()->supportsFullscreen() || !player()->hasVideo())
return false;
// Check with the platform client.
@@ -131,16 +131,16 @@ bool HTMLVideoElement::supportsFullscreen() const
unsigned HTMLVideoElement::videoWidth() const
{
- if (!m_player)
+ if (!player())
return 0;
- return m_player->naturalSize().width();
+ return player()->naturalSize().width();
}
unsigned HTMLVideoElement::videoHeight() const
{
- if (!m_player)
+ if (!player())
return 0;
- return m_player->naturalSize().height();
+ return player()->naturalSize().height();
}
unsigned HTMLVideoElement::width() const
@@ -196,16 +196,6 @@ void HTMLVideoElement::updatePosterImage()
#endif
}
-void HTMLVideoElement::paint(GraphicsContext* context, const IntRect& destRect)
-{
- MediaPlayer* player = HTMLMediaElement::player();
- if (!player)
- return;
-
- player->setVisible(true); // Make player visible or it won't draw.
- player->paint(context, destRect);
-}
-
void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
{
MediaPlayer* player = HTMLMediaElement::player();
@@ -218,15 +208,15 @@ void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, cons
bool HTMLVideoElement::hasAvailableVideoFrame() const
{
- if (!m_player)
+ if (!player())
return false;
- return m_player->hasAvailableVideoFrame();
+ return player()->hasAvailableVideoFrame();
}
-void HTMLVideoElement::webkitEnterFullScreen(bool isUserGesture, ExceptionCode& ec)
+void HTMLVideoElement::webkitEnterFullscreen(bool isUserGesture, ExceptionCode& ec)
{
- if (m_isFullscreen)
+ if (isFullscreen())
return;
// Generate an exception if this isn't called in response to a user gesture, or if the
@@ -239,9 +229,9 @@ void HTMLVideoElement::webkitEnterFullScreen(bool isUserGesture, ExceptionCode&
enterFullscreen();
}
-void HTMLVideoElement::webkitExitFullScreen()
+void HTMLVideoElement::webkitExitFullscreen()
{
- if (m_isFullscreen)
+ if (isFullscreen())
exitFullscreen();
}
@@ -252,9 +242,15 @@ bool HTMLVideoElement::webkitSupportsFullscreen()
bool HTMLVideoElement::webkitDisplayingFullscreen()
{
- return m_isFullscreen;
+ return isFullscreen();
}
+void HTMLVideoElement::willMoveToNewOwnerDocument()
+{
+ if (m_imageLoader)
+ m_imageLoader->elementWillMoveToNewOwnerDocument();
+ HTMLMediaElement::willMoveToNewOwnerDocument();
+}
}
#endif
diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h
index d12667e..4dad3db 100644
--- a/WebCore/html/HTMLVideoElement.h
+++ b/WebCore/html/HTMLVideoElement.h
@@ -29,7 +29,6 @@
#if ENABLE(VIDEO)
#include "HTMLMediaElement.h"
-#include <wtf/OwnPtr.h>
namespace WebCore {
@@ -39,20 +38,6 @@ class HTMLVideoElement : public HTMLMediaElement {
public:
HTMLVideoElement(const QualifiedName&, Document*);
- virtual int tagPriority() const { return 5; }
- virtual bool rendererIsNeeded(RenderStyle*);
-#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
-#endif
- virtual void attach();
- virtual void detach();
- virtual void parseMappedAttribute(MappedAttribute* attr);
- virtual bool isVideo() const { return true; }
- virtual bool hasVideo() const { return player() && player()->hasVideo(); }
- virtual bool supportsFullscreen() const;
- virtual bool isURLAttribute(Attribute*) const;
- virtual const QualifiedName& imageSourceAttributeName() const;
-
unsigned width() const;
void setWidth(unsigned);
unsigned height() const;
@@ -61,24 +46,43 @@ public:
unsigned videoWidth() const;
unsigned videoHeight() const;
- const KURL& poster() const { return m_posterURL; }
+ virtual const KURL poster() const { return m_posterURL; }
void setPoster(const String&);
-// fullscreen
- void webkitEnterFullScreen(bool isUserGesture, ExceptionCode&);
- void webkitExitFullScreen();
+ // Fullscreen
+ void webkitEnterFullscreen(bool isUserGesture, ExceptionCode&);
+ void webkitExitFullscreen();
bool webkitSupportsFullscreen();
bool webkitDisplayingFullscreen();
+ // FIXME: Maintain "FullScreen" capitalization scheme for backwards compatibility.
+ // https://bugs.webkit.org/show_bug.cgi?id=36081
+ void webkitEnterFullScreen(bool isUserGesture, ExceptionCode& ec) { webkitEnterFullscreen(isUserGesture, ec); }
+ void webkitExitFullScreen() { webkitExitFullscreen(); }
+
bool shouldDisplayPosterImage() const { return m_shouldDisplayPosterImage; }
- void paint(GraphicsContext*, const IntRect&);
// Used by canvas to gain raw pixel access
void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
private:
+ virtual int tagPriority() const { return 5; }
+ virtual bool rendererIsNeeded(RenderStyle*);
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+#endif
+ virtual void attach();
+ virtual void detach();
+ virtual void parseMappedAttribute(MappedAttribute*);
+ virtual bool isVideo() const { return true; }
+ virtual bool hasVideo() const { return player() && player()->hasVideo(); }
+ virtual bool supportsFullscreen() const;
+ virtual bool isURLAttribute(Attribute*) const;
+ virtual const QualifiedName& imageSourceAttributeName() const;
+
virtual bool hasAvailableVideoFrame() const;
virtual void updatePosterImage();
+ virtual void willMoveToNewOwnerDocument();
OwnPtr<HTMLImageLoader> m_imageLoader;
KURL m_posterURL;
diff --git a/WebCore/html/HTMLVideoElement.idl b/WebCore/html/HTMLVideoElement.idl
index c4764ac..1b21c54 100644
--- a/WebCore/html/HTMLVideoElement.idl
+++ b/WebCore/html/HTMLVideoElement.idl
@@ -33,6 +33,10 @@ module html {
readonly attribute boolean webkitSupportsFullscreen;
readonly attribute boolean webkitDisplayingFullscreen;
+
+ [NeedsUserGestureCheck] void webkitEnterFullscreen()
+ raises (DOMException);
+ void webkitExitFullscreen();
[NeedsUserGestureCheck] void webkitEnterFullScreen()
raises (DOMException);
diff --git a/WebCore/html/HTMLViewSourceDocument.cpp b/WebCore/html/HTMLViewSourceDocument.cpp
index ba718d1..2d800b4 100644
--- a/WebCore/html/HTMLViewSourceDocument.cpp
+++ b/WebCore/html/HTMLViewSourceDocument.cpp
@@ -54,7 +54,7 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(Frame* frame, const String& mimeT
Tokenizer* HTMLViewSourceDocument::createTokenizer()
{
// Use HTMLTokenizer if applicable, otherwise use TextTokenizer.
- if (m_type == "text/html" || m_type == "application/xhtml+xml" || m_type == "image/svg+xml" || implementation()->isXMLMIMEType(m_type)
+ if (m_type == "text/html" || m_type == "application/xhtml+xml" || m_type == "image/svg+xml" || DOMImplementation::isXMLMIMEType(m_type)
#if ENABLE(XHTMLMP)
|| m_type == "application/vnd.wap.xhtml+xml"
#endif
diff --git a/WebCore/html/PreloadScanner.cpp b/WebCore/html/PreloadScanner.cpp
index 527b9f8..ee7e761 100644
--- a/WebCore/html/PreloadScanner.cpp
+++ b/WebCore/html/PreloadScanner.cpp
@@ -34,13 +34,13 @@
#include "CachedResourceClient.h"
#include "CachedScript.h"
#include "CSSHelper.h"
-#include "CString.h"
#include "DocLoader.h"
#include "Document.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLLinkElement.h"
#include "HTMLNames.h"
+#include <wtf/text/CString.h>
#include <wtf/CurrentTime.h>
#include <wtf/unicode/Unicode.h>
diff --git a/WebCore/html/StepRange.cpp b/WebCore/html/StepRange.cpp
new file mode 100644
index 0000000..7c270f2
--- /dev/null
+++ b/WebCore/html/StepRange.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "StepRange.h"
+
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "PlatformString.h"
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+StepRange::StepRange(const HTMLInputElement* element)
+{
+ if (element->hasAttribute(precisionAttr)) {
+ step = 1.0;
+ hasStep = !equalIgnoringCase(element->getAttribute(precisionAttr), "float");
+ } else
+ hasStep = element->getAllowedValueStep(&step);
+
+ maximum = element->maximum();
+ minimum = element->minimum();
+}
+
+double StepRange::clampValue(double value)
+{
+ double clampedValue = max(minimum, min(value, maximum));
+ if (!hasStep)
+ return clampedValue;
+ // Rounds clampedValue to minimum + N * step.
+ clampedValue = minimum + round((clampedValue - minimum) / step) * step;
+ if (clampedValue > maximum)
+ clampedValue -= step;
+ ASSERT(clampedValue >= minimum);
+ ASSERT(clampedValue <= maximum);
+ return clampedValue;
+}
+
+double StepRange::clampValue(const String& stringValue)
+{
+ double value;
+ bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(stringValue, &value);
+ if (!parseSuccess)
+ value = (minimum + maximum) / 2;
+ return clampValue(value);
+}
+
+double StepRange::valueFromElement(HTMLInputElement* element, bool* wasClamped)
+{
+ double oldValue;
+ bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(element->value(), &oldValue);
+ if (!parseSuccess)
+ oldValue = (minimum + maximum) / 2;
+ double newValue = clampValue(oldValue);
+
+ if (wasClamped)
+ *wasClamped = !parseSuccess || newValue != oldValue;
+
+ return newValue;
+}
+
+}
diff --git a/WebCore/html/StepRange.h b/WebCore/html/StepRange.h
new file mode 100644
index 0000000..2f5013a
--- /dev/null
+++ b/WebCore/html/StepRange.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StepRange_h
+#define StepRange_h
+
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class HTMLInputElement;
+class String;
+
+class StepRange : public Noncopyable {
+public:
+ bool hasStep;
+ double step;
+ double minimum;
+ double maximum; // maximum must be >= minimum.
+
+ explicit StepRange(const HTMLInputElement*);
+ double clampValue(double value);
+ double clampValue(const String& stringValue);
+
+ // Clamp the middle value according to the step
+ double defaultValue()
+ {
+ return clampValue((minimum + maximum) / 2);
+ }
+
+ // Map value into 0-1 range
+ double proportionFromValue(double value)
+ {
+ if (minimum == maximum)
+ return 0;
+
+ return (value - minimum) / (maximum - minimum);
+ }
+
+ // Map from 0-1 range to value
+ double valueFromProportion(double proportion)
+ {
+ return minimum + proportion * (maximum - minimum);
+ }
+
+ double valueFromElement(HTMLInputElement*, bool* wasClamped = 0);
+};
+
+}
+
+#endif // StepRange_h
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 6fe74f9..0baa0e6 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -39,7 +39,6 @@
#include "CSSMutableStyleDeclaration.h"
#include "CSSPropertyNames.h"
#include "CSSStyleSelector.h"
-#include "Document.h"
#include "ExceptionCode.h"
#include "FloatConversion.h"
#include "GraphicsContext.h"
@@ -90,12 +89,18 @@ private:
CanvasRenderingContext2D* m_canvasContext;
};
-
-
-CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas)
+CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode)
: CanvasRenderingContext(canvas)
, m_stateStack(1)
+ , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode)
+#if ENABLE(DASHBOARD_SUPPORT)
+ , m_usesDashboardCompatibilityMode(usesDashboardCompatibilityMode)
+#endif
{
+#if !ENABLE(DASHBOARD_SUPPORT)
+ ASSERT_UNUSED(usesDashboardCompatibilityMode, !usesDashboardCompatibilityMode);
+#endif
+
// Make sure that even if the drawingContext() has a different default
// thickness, it is in sync with the canvas thickness.
setLineWidth(lineWidth());
@@ -636,9 +641,8 @@ void CanvasRenderingContext2D::rect(float x, float y, float width, float height)
#if ENABLE(DASHBOARD_SUPPORT)
void CanvasRenderingContext2D::clearPathForDashboardBackwardCompatibilityMode()
{
- if (Settings* settings = canvas()->document()->settings())
- if (settings->usesDashboardBackwardCompatibilityMode())
- m_path.clear();
+ if (m_usesDashboardCompatibilityMode)
+ m_path.clear();
}
#endif
@@ -941,7 +945,7 @@ static inline FloatRect normalizeRect(const FloatRect& rect)
void CanvasRenderingContext2D::checkOrigin(const KURL& url)
{
- if (canvas()->document()->securityOrigin()->taintsCanvas(url))
+ if (canvas()->securityOrigin().taintsCanvas(url))
canvas()->setOriginTainted();
}
@@ -950,26 +954,45 @@ void CanvasRenderingContext2D::checkOrigin(const String& url)
checkOrigin(KURL(KURL(), url));
}
-void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y)
+void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionCode& ec)
{
- ASSERT(image);
+ if (!image) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
IntSize s = size(image);
- ExceptionCode ec;
drawImage(image, x, y, s.width(), s.height(), ec);
}
void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
float x, float y, float width, float height, ExceptionCode& ec)
{
- ASSERT(image);
+ if (!image) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
IntSize s = size(image);
drawImage(image, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec);
}
+void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
+ float sx, float sy, float sw, float sh,
+ float dx, float dy, float dw, float dh, ExceptionCode& ec)
+{
+ if (!image) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
+ drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec);
+}
+
void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect,
ExceptionCode& ec)
{
- ASSERT(image);
+ if (!image) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
ec = 0;
@@ -1004,24 +1027,39 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec
c->drawImage(cachedImage->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
}
-void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, float x, float y)
+void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, float x, float y, ExceptionCode& ec)
{
- ASSERT(canvas);
- ExceptionCode ec;
+ if (!canvas) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
drawImage(canvas, x, y, canvas->width(), canvas->height(), ec);
}
void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas,
float x, float y, float width, float height, ExceptionCode& ec)
{
- ASSERT(canvas);
+ if (!canvas) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
drawImage(canvas, FloatRect(0, 0, canvas->width(), canvas->height()), FloatRect(x, y, width, height), ec);
}
+void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas,
+ float sx, float sy, float sw, float sh,
+ float dx, float dy, float dw, float dh, ExceptionCode& ec)
+{
+ drawImage(canvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec);
+}
+
void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect,
const FloatRect& dstRect, ExceptionCode& ec)
{
- ASSERT(sourceCanvas);
+ if (!sourceCanvas) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
ec = 0;
@@ -1057,26 +1095,41 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
}
#if ENABLE(VIDEO)
-void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y)
+void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionCode& ec)
{
- ASSERT(video);
+ if (!video) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
IntSize s = size(video);
- ExceptionCode ec;
drawImage(video, x, y, s.width(), s.height(), ec);
}
void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
float x, float y, float width, float height, ExceptionCode& ec)
{
- ASSERT(video);
+ if (!video) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
IntSize s = size(video);
drawImage(video, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec);
}
+void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
+ float sx, float sy, float sw, float sh,
+ float dx, float dy, float dw, float dh, ExceptionCode& ec)
+{
+ drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec);
+}
+
void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRect& srcRect, const FloatRect& dstRect,
ExceptionCode& ec)
{
- ASSERT(video);
+ if (!video) {
+ ec = TYPE_MISMATCH_ERR;
+ return;
+ }
ec = 0;
FloatRect videoRect = FloatRect(FloatPoint(), size(video));
@@ -1161,9 +1214,8 @@ void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
void CanvasRenderingContext2D::prepareGradientForDashboard(CanvasGradient* gradient) const
{
#if ENABLE(DASHBOARD_SUPPORT)
- if (Settings* settings = canvas()->document()->settings())
- if (settings->usesDashboardBackwardCompatibilityMode())
- gradient->setDashboardCompatibilityMode();
+ if (m_usesDashboardCompatibilityMode)
+ gradient->setDashboardCompatibilityMode();
#else
UNUSED_PARAM(gradient);
#endif
@@ -1196,6 +1248,10 @@ PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float
PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image,
const String& repetitionType, ExceptionCode& ec)
{
+ if (!image) {
+ ec = TYPE_MISMATCH_ERR;
+ return 0;
+ }
bool repeatX, repeatY;
ec = 0;
CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec);
@@ -1211,13 +1267,21 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme
if (!cachedImage || !image->cachedImage()->image())
return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true);
+<<<<<<< HEAD
bool originClean = !canvas()->document()->securityOrigin()->taintsCanvas(KURL(KURL(), cachedImage->url())) && cachedImage->image()->hasSingleSecurityOrigin();
+=======
+ bool originClean = !canvas()->securityOrigin().taintsCanvas(KURL(KURL(), cachedImage->url())) && cachedImage->image()->hasSingleSecurityOrigin();
+>>>>>>> webkit.org at r58033
return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean);
}
PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas,
const String& repetitionType, ExceptionCode& ec)
{
+ if (!canvas) {
+ ec = TYPE_MISMATCH_ERR;
+ return 0;
+ }
if (!canvas->width() || !canvas->height()) {
ec = INVALID_STATE_ERR;
return 0;
@@ -1369,7 +1433,7 @@ String CanvasRenderingContext2D::font() const
void CanvasRenderingContext2D::setFont(const String& newFont)
{
RefPtr<CSSMutableStyleDeclaration> tempDecl = CSSMutableStyleDeclaration::create();
- CSSParser parser(!canvas()->document()->inCompatMode()); // Use the parse mode of the canvas' document when parsing CSS.
+ CSSParser parser(!m_usesCSSCompatibilityParseMode);
String declarationText("font: ");
declarationText += newFont;
@@ -1383,11 +1447,11 @@ void CanvasRenderingContext2D::setFont(const String& newFont)
// Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work
// relative to the canvas.
RefPtr<RenderStyle> newStyle = RenderStyle::create();
- if (canvas()->computedStyle())
- newStyle->setFontDescription(canvas()->computedStyle()->fontDescription());
+ if (RenderStyle* computedStyle = canvas()->computedStyle())
+ newStyle->setFontDescription(computedStyle->fontDescription());
// Now map the font property into the style.
- CSSStyleSelector* styleSelector = canvas()->document()->styleSelector();
+ CSSStyleSelector* styleSelector = canvas()->styleSelector();
styleSelector->applyPropertyToStyle(CSSPropertyFont, tempDecl->getPropertyCSSValue(CSSPropertyFont).get(), newStyle.get());
state().m_font = newStyle->font();
@@ -1461,8 +1525,9 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
// FIXME: Handle maxWidth.
// FIXME: Need to turn off font smoothing.
- bool rtl = canvas()->computedStyle() ? canvas()->computedStyle()->direction() == RTL : false;
- bool override = canvas()->computedStyle() ? canvas()->computedStyle()->unicodeBidi() == Override : false;
+ RenderStyle* computedStyle = canvas()->computedStyle();
+ bool rtl = computedStyle ? computedStyle->direction() == RTL : false;
+ bool override = computedStyle ? computedStyle->unicodeBidi() == Override : false;
unsigned length = text.length();
const UChar* string = text.characters();
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.h b/WebCore/html/canvas/CanvasRenderingContext2D.h
index 553ffd2..2bac902 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.h
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.h
@@ -57,7 +57,7 @@ namespace WebCore {
class CanvasRenderingContext2D : public CanvasRenderingContext {
public:
- CanvasRenderingContext2D(HTMLCanvasElement*);
+ CanvasRenderingContext2D(HTMLCanvasElement*, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode);
virtual ~CanvasRenderingContext2D();
@@ -154,15 +154,18 @@ namespace WebCore {
void clearShadow();
- void drawImage(HTMLImageElement*, float x, float y);
+ void drawImage(HTMLImageElement*, float x, float y, ExceptionCode&);
void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionCode&);
+ void drawImage(HTMLImageElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&);
void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
- void drawImage(HTMLCanvasElement*, float x, float y);
+ void drawImage(HTMLCanvasElement*, float x, float y, ExceptionCode&);
void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionCode&);
+ void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&);
void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
#if ENABLE(VIDEO)
- void drawImage(HTMLVideoElement*, float x, float y);
+ void drawImage(HTMLVideoElement*, float x, float y, ExceptionCode&);
void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionCode&);
+ void drawImage(HTMLVideoElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&);
void drawImage(HTMLVideoElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
#endif
@@ -263,6 +266,10 @@ namespace WebCore {
void checkOrigin(const String&);
Vector<State, 1> m_stateStack;
+ bool m_usesCSSCompatibilityParseMode;
+#if ENABLE(DASHBOARD_SUPPORT)
+ bool m_usesDashboardCompatibilityMode;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.idl b/WebCore/html/canvas/CanvasRenderingContext2D.idl
index f93a752..a3c83ca 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.idl
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.idl
@@ -20,7 +20,7 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
module html {
@@ -82,8 +82,7 @@ module html {
attribute DOMString font;
attribute DOMString textAlign;
attribute DOMString textBaseline;
- [Custom] void fillText(/* 4 */);
- [Custom] void strokeText(/* 4 */);
+
TextMetrics measureText(in DOMString text);
// other
@@ -98,6 +97,61 @@ module html {
void clearShadow();
+#if defined(V8_BINDING) && V8_BINDING
+ void fillText(in DOMString text, in float x, in float y, in [Optional] float maxWidth);
+ void strokeText(in DOMString text, in float x, in float y, in [Optional] float maxWidth);
+
+ void setStrokeColor(in DOMString color, in [Optional] float alpha);
+ void setStrokeColor(in float grayLevel, in [Optional] float alpha);
+ void setStrokeColor(in float r, in float g, in float b, in float a);
+ void setStrokeColor(in float c, in float m, in float y, in float k, in float a);
+
+ void setFillColor(in DOMString color, in [Optional] float alpha);
+ void setFillColor(in float grayLevel, in [Optional] float alpha);
+ void setFillColor(in float r, in float g, in float b, in float a);
+ void setFillColor(in float c, in float m, in float y, in float k, in float a);
+
+ void strokeRect(in float x, in float y, in float width, in float height, in [Optional] float lineWidth);
+
+ void drawImage(in HTMLImageElement image, in float x, in float y)
+ raises (DOMException);
+ void drawImage(in HTMLImageElement image, in float x, in float y, in float width, in float height)
+ raises (DOMException);
+ void drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh)
+ raises (DOMException);
+ void drawImage(in HTMLCanvasElement canvas, in float x, in float y)
+ raises (DOMException);
+ void drawImage(in HTMLCanvasElement canvas, in float x, in float y, in float width, in float height)
+ raises (DOMException);
+ void drawImage(in HTMLCanvasElement canvas, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh)
+ raises (DOMException);
+#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
+ void drawImage(in HTMLVideoElement video, in float x, in float y)
+ raises (DOMException);
+ void drawImage(in HTMLVideoElement video, in float x, in float y, in float width, in float height)
+ raises (DOMException);
+ void drawImage(in HTMLVideoElement video, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh)
+ raises (DOMException);
+#endif
+ void drawImageFromRect(in HTMLImageElement image,
+ in float sx, in float sy, in float sw, in float sh,
+ in float dx, in float dy, in float dw, in float dh, in DOMString compositeOperation);
+
+ void setShadow(in float width, in float height, in float blur, in [Optional] DOMString color, in [Optional] float alpha);
+ void setShadow(in float width, in float height, in float blur, in float grayLevel, in [Optional] float alpha);
+ void setShadow(in float width, in float height, in float blur, in float r, in float g, in float b, in float a);
+ void setShadow(in float width, in float height, in float blur, in float c, in float m, in float y, in float k, in float a);
+
+ CanvasPattern createPattern(in HTMLCanvasElement canvas, in [ConvertNullToNullString] DOMString repetitionType)
+ raises (DOMException);
+ CanvasPattern createPattern(in HTMLImageElement image, in [ConvertNullToNullString] DOMString repetitionType)
+ raises (DOMException);
+ void putImageData(in ImageData imagedata, in float dx, in float dy, in [Optional] float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight)
+ raises(DOMException);
+#else
+ // FIXME: Remove 'else' once JSC supports overloads too.
+ [Custom] void fillText(/* 4 */);
+ [Custom] void strokeText(/* 4 */);
[Custom] void setStrokeColor(/* 1 */);
[Custom] void setFillColor(/* 1 */);
[Custom] void strokeRect(/* 4 */);
@@ -105,16 +159,17 @@ module html {
[Custom] void drawImageFromRect(/* 10 */);
[Custom] void setShadow(/* 3 */);
[Custom] void createPattern(/* 2 */);
-
+ [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */);
+#endif // defined(V8_BINDING)
+
attribute [Custom] custom strokeStyle;
attribute [Custom] custom fillStyle;
-
+
// pixel manipulation
ImageData createImageData(in float sw, in float sh)
raises (DOMException);
ImageData getImageData(in float sx, in float sy, in float sw, in float sh)
raises(DOMException);
- [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */);
};
}
diff --git a/WebCore/html/canvas/CanvasStyle.cpp b/WebCore/html/canvas/CanvasStyle.cpp
index 5352473..3515e03 100644
--- a/WebCore/html/canvas/CanvasStyle.cpp
+++ b/WebCore/html/canvas/CanvasStyle.cpp
@@ -173,22 +173,12 @@ void CanvasStyle::applyFillColor(GraphicsContext* context)
return;
switch (m_type) {
case ColorString: {
- Color c = Color(m_color);
- if (c.isValid()) {
- context->setFillColor(c.rgb(), DeviceColorSpace);
- break;
- }
RGBA32 rgba = 0; // default is transparent black
if (CSSParser::parseColor(rgba, m_color))
context->setFillColor(rgba, DeviceColorSpace);
break;
}
case ColorStringWithAlpha: {
- Color c = Color(m_color);
- if (c.isValid()) {
- context->setFillColor(colorWithOverrideAlpha(c.rgb(), m_alpha), DeviceColorSpace);
- break;
- }
RGBA32 color = 0; // default is transparent black
if (CSSParser::parseColor(color, m_color))
context->setFillColor(colorWithOverrideAlpha(color, m_alpha), DeviceColorSpace);
diff --git a/WebCore/html/canvas/WebGLArray.cpp b/WebCore/html/canvas/WebGLArray.cpp
index c5a712d..038aea4 100644
--- a/WebCore/html/canvas/WebGLArray.cpp
+++ b/WebCore/html/canvas/WebGLArray.cpp
@@ -46,13 +46,33 @@ WebGLArray::~WebGLArray()
void WebGLArray::setImpl(WebGLArray* array, unsigned byteOffset, ExceptionCode& ec)
{
- if (byteOffset + array->byteLength() > byteLength()) {
+ if (byteOffset > byteLength() ||
+ byteOffset + array->byteLength() > byteLength() ||
+ byteOffset + array->byteLength() < byteOffset) {
+ // Out of range offset or overflow
ec = INDEX_SIZE_ERR;
return;
}
char* base = static_cast<char*>(baseAddress());
- memcpy(base + byteOffset, array->baseAddress(), array->byteLength());
+ memmove(base + byteOffset, array->baseAddress(), array->byteLength());
+}
+
+void WebGLArray::calculateOffsetAndLength(int start, int end, unsigned arraySize,
+ unsigned* offset, unsigned* length)
+{
+ if (start < 0)
+ start += arraySize;
+ if (start < 0)
+ start = 0;
+ if (end < 0)
+ end += arraySize;
+ if (end < 0)
+ end = 0;
+ if (end < start)
+ end = start;
+ *offset = static_cast<unsigned>(start);
+ *length = static_cast<unsigned>(end - start);
}
}
diff --git a/WebCore/html/canvas/WebGLArray.h b/WebCore/html/canvas/WebGLArray.h
index 11065cc..7d67474 100644
--- a/WebCore/html/canvas/WebGLArray.h
+++ b/WebCore/html/canvas/WebGLArray.h
@@ -26,7 +26,9 @@
#ifndef WebGLArray_h
#define WebGLArray_h
+#include <algorithm>
#include "ExceptionCode.h"
+#include <limits.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -58,7 +60,7 @@ class WebGLArray : public RefCounted<WebGLArray> {
virtual unsigned length() const = 0;
virtual unsigned byteLength() const = 0;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length) = 0;
+ virtual PassRefPtr<WebGLArray> slice(int start, int end) = 0;
virtual ~WebGLArray();
@@ -67,6 +69,48 @@ class WebGLArray : public RefCounted<WebGLArray> {
void setImpl(WebGLArray* array, unsigned byteOffset, ExceptionCode& ec);
+ void calculateOffsetAndLength(int start, int end, unsigned arraySize,
+ unsigned* offset, unsigned* length);
+
+ // Helper to verify that a given sub-range of an ArrayBuffer is
+ // within range.
+ template <typename T>
+ static bool verifySubRange(PassRefPtr<WebGLArrayBuffer> buffer,
+ unsigned byteOffset,
+ unsigned numElements)
+ {
+ if (!buffer)
+ return false;
+ if (sizeof(T) > 1 && byteOffset % sizeof(T))
+ return false;
+ if (byteOffset > buffer->byteLength())
+ return false;
+ unsigned remainingElements = (buffer->byteLength() - byteOffset) / sizeof(T);
+ if (numElements > remainingElements)
+ return false;
+ return true;
+ }
+
+ // Input offset is in number of elements from this array's view;
+ // output offset is in number of bytes from the underlying buffer's view.
+ template <typename T>
+ static void clampOffsetAndNumElements(PassRefPtr<WebGLArrayBuffer> buffer,
+ unsigned arrayByteOffset,
+ unsigned *offset,
+ unsigned *numElements)
+ {
+ unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T);
+ if (*offset > maxOffset) {
+ *offset = buffer->byteLength();
+ *numElements = 0;
+ return;
+ }
+ *offset = arrayByteOffset + *offset * sizeof(T);
+ *offset = std::min(buffer->byteLength(), *offset);
+ unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T);
+ *numElements = std::min(remainingElements, *numElements);
+ }
+
// This is the address of the WebGLArrayBuffer's storage, plus the byte offset.
void* m_baseAddress;
diff --git a/WebCore/html/canvas/WebGLArray.idl b/WebCore/html/canvas/WebGLArray.idl
index 02e1f51..2cc00d0 100644
--- a/WebCore/html/canvas/WebGLArray.idl
+++ b/WebCore/html/canvas/WebGLArray.idl
@@ -30,6 +30,6 @@ module html {
readonly attribute unsigned long byteLength;
readonly attribute unsigned long length;
- WebGLArray slice(in unsigned long offset, in unsigned long length);
+ [Custom] WebGLArray slice(in long start, in long end);
};
}
diff --git a/WebCore/html/canvas/WebGLArrayBuffer.cpp b/WebCore/html/canvas/WebGLArrayBuffer.cpp
index c565691..7d3cd33 100644
--- a/WebCore/html/canvas/WebGLArrayBuffer.cpp
+++ b/WebCore/html/canvas/WebGLArrayBuffer.cpp
@@ -33,21 +33,27 @@
namespace WebCore {
-PassRefPtr<WebGLArrayBuffer> WebGLArrayBuffer::create(unsigned sizeInBytes)
+PassRefPtr<WebGLArrayBuffer> WebGLArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
{
- return adoptRef(new WebGLArrayBuffer(sizeInBytes));
+ void* data = tryAllocate(numElements, elementByteSize);
+ if (!data)
+ return 0;
+ return adoptRef(new WebGLArrayBuffer(data, numElements * elementByteSize));
}
PassRefPtr<WebGLArrayBuffer> WebGLArrayBuffer::create(WebGLArrayBuffer* other)
{
- RefPtr<WebGLArrayBuffer> buffer = adoptRef(new WebGLArrayBuffer(other->byteLength()));
+ void* data = tryAllocate(other->byteLength(), 1);
+ if (!data)
+ return 0;
+ RefPtr<WebGLArrayBuffer> buffer = adoptRef(new WebGLArrayBuffer(data, other->byteLength()));
memcpy(buffer->data(), other->data(), other->byteLength());
return buffer.release();
}
-WebGLArrayBuffer::WebGLArrayBuffer(unsigned sizeInBytes) {
- m_sizeInBytes = sizeInBytes;
- m_data = WTF::fastZeroedMalloc(sizeInBytes);
+WebGLArrayBuffer::WebGLArrayBuffer(void* data, unsigned sizeInBytes)
+ : m_sizeInBytes(sizeInBytes)
+ , m_data(data) {
}
void* WebGLArrayBuffer::data() {
@@ -66,6 +72,19 @@ WebGLArrayBuffer::~WebGLArrayBuffer() {
WTF::fastFree(m_data);
}
+void* WebGLArrayBuffer::tryAllocate(unsigned numElements, unsigned elementByteSize) {
+ void* result;
+ // Do not allow 32-bit overflow of the total size
+ if (numElements) {
+ unsigned totalSize = numElements * elementByteSize;
+ if (totalSize / numElements != elementByteSize)
+ return 0;
+ }
+ if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result))
+ return result;
+ return 0;
+}
+
}
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/html/canvas/WebGLArrayBuffer.h b/WebCore/html/canvas/WebGLArrayBuffer.h
index a076e16..59e0ddd 100644
--- a/WebCore/html/canvas/WebGLArrayBuffer.h
+++ b/WebCore/html/canvas/WebGLArrayBuffer.h
@@ -33,7 +33,7 @@ namespace WebCore {
class WebGLArrayBuffer : public RefCounted<WebGLArrayBuffer> {
public:
- static PassRefPtr<WebGLArrayBuffer> create(unsigned sizeInBytes);
+ static PassRefPtr<WebGLArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
static PassRefPtr<WebGLArrayBuffer> create(WebGLArrayBuffer*);
void* data();
@@ -43,7 +43,9 @@ class WebGLArrayBuffer : public RefCounted<WebGLArrayBuffer> {
~WebGLArrayBuffer();
private:
- WebGLArrayBuffer(unsigned sizeInBytes);
+ WebGLArrayBuffer(void* data, unsigned sizeInBytes);
+ WebGLArrayBuffer(unsigned numElements, unsigned elementByteSize);
+ static void* tryAllocate(unsigned numElements, unsigned elementByteSize);
unsigned m_sizeInBytes;
void* m_data;
};
diff --git a/WebCore/html/canvas/WebGLByteArray.cpp b/WebCore/html/canvas/WebGLByteArray.cpp
index 1c2849b..603e4d1 100644
--- a/WebCore/html/canvas/WebGLByteArray.cpp
+++ b/WebCore/html/canvas/WebGLByteArray.cpp
@@ -35,7 +35,7 @@ namespace WebCore {
PassRefPtr<WebGLByteArray> WebGLByteArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(signed char));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(signed char));
return create(buffer, 0, length);
}
@@ -47,19 +47,16 @@ PassRefPtr<WebGLByteArray> WebGLByteArray::create(signed char* array, unsigned l
return a;
}
-PassRefPtr<WebGLByteArray> WebGLByteArray::create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+PassRefPtr<WebGLByteArray> WebGLByteArray::create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
{
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(signed char))) > buffer->byteLength())
- return NULL;
- }
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<signed char>(buf, byteOffset, length))
+ return 0;
- return adoptRef(new WebGLByteArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLByteArray(buf, byteOffset, length));
}
-WebGLByteArray::WebGLByteArray(PassRefPtr<WebGLArrayBuffer> buffer, int offset, unsigned length)
+WebGLByteArray::WebGLByteArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned offset, unsigned length)
: WebGLArray(buffer, offset)
, m_size(length)
{
@@ -73,15 +70,12 @@ unsigned WebGLByteArray::byteLength() const {
return m_size * sizeof(signed char);
}
-PassRefPtr<WebGLArray> WebGLByteArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(signed char);
- unsigned limitByte = startByte + length * sizeof(signed char);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLByteArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<signed char>(buffer().get(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLByteArray::set(WebGLByteArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLByteArray.h b/WebCore/html/canvas/WebGLByteArray.h
index c517c03..60d301c 100644
--- a/WebCore/html/canvas/WebGLByteArray.h
+++ b/WebCore/html/canvas/WebGLByteArray.h
@@ -43,13 +43,13 @@ class WebGLByteArray : public WebGLArray {
static PassRefPtr<WebGLByteArray> create(unsigned length);
static PassRefPtr<WebGLByteArray> create(signed char* array, unsigned length);
- static PassRefPtr<WebGLByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
char* data() { return static_cast<char*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -90,7 +90,7 @@ class WebGLByteArray : public WebGLArray {
private:
WebGLByteArray(PassRefPtr<WebGLArrayBuffer> buffer,
- int offset,
+ unsigned offset,
unsigned length);
unsigned m_size;
};
diff --git a/WebCore/html/canvas/WebGLFloatArray.cpp b/WebCore/html/canvas/WebGLFloatArray.cpp
index 6192898..ca93c4c 100644
--- a/WebCore/html/canvas/WebGLFloatArray.cpp
+++ b/WebCore/html/canvas/WebGLFloatArray.cpp
@@ -34,7 +34,7 @@ namespace WebCore {
PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(float));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(float));
return create(buffer, 0, length);
}
@@ -46,22 +46,16 @@ PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(float* array, unsigned lengt
return a;
}
-PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+PassRefPtr<WebGLFloatArray> WebGLFloatArray::create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
{
- // Make sure the offset results in valid alignment.
- if ((byteOffset % sizeof(float)) != 0)
- return NULL;
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<float>(buf, byteOffset, length))
+ return 0;
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(float))) > buffer->byteLength())
- return NULL;
- }
- return adoptRef(new WebGLFloatArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLFloatArray(buf, byteOffset, length));
}
-WebGLFloatArray::WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+WebGLFloatArray::WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
: WebGLArray(buffer, byteOffset)
, m_size(length)
{
@@ -75,15 +69,12 @@ unsigned WebGLFloatArray::byteLength() const {
return m_size * sizeof(float);
}
-PassRefPtr<WebGLArray> WebGLFloatArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(float);
- unsigned limitByte = startByte + length * sizeof(float);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLFloatArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<float>(buffer(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLFloatArray::set(WebGLFloatArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLFloatArray.h b/WebCore/html/canvas/WebGLFloatArray.h
index 4607962..5b4e6c9 100644
--- a/WebCore/html/canvas/WebGLFloatArray.h
+++ b/WebCore/html/canvas/WebGLFloatArray.h
@@ -40,13 +40,13 @@ class WebGLFloatArray : public WebGLArray {
static PassRefPtr<WebGLFloatArray> create(unsigned length);
static PassRefPtr<WebGLFloatArray> create(float* array, unsigned length);
- static PassRefPtr<WebGLFloatArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLFloatArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
float* data() { return static_cast<float*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -86,7 +86,7 @@ class WebGLFloatArray : public WebGLArray {
void set(WebGLFloatArray* array, unsigned offset, ExceptionCode& ec);
private:
- WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ WebGLFloatArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned m_size;
};
diff --git a/WebCore/html/canvas/WebGLFramebuffer.cpp b/WebCore/html/canvas/WebGLFramebuffer.cpp
index 7ade990..614437b 100644
--- a/WebCore/html/canvas/WebGLFramebuffer.cpp
+++ b/WebCore/html/canvas/WebGLFramebuffer.cpp
@@ -39,10 +39,28 @@ PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx
WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx)
: CanvasObject(ctx)
+ , m_isDepthAttached(false)
+ , m_isStencilAttached(false)
+ , m_isDepthStencilAttached(false)
{
setObject(context()->graphicsContext3D()->createFramebuffer());
}
+void WebGLFramebuffer::setIsAttached(unsigned long attachment, bool isAttached)
+{
+ switch (attachment) {
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ m_isDepthAttached = isAttached;
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ m_isStencilAttached = isAttached;
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ m_isDepthStencilAttached = isAttached;
+ break;
+ }
+}
+
void WebGLFramebuffer::_deleteObject(Platform3DObject object)
{
context()->graphicsContext3D()->deleteFramebuffer(object);
diff --git a/WebCore/html/canvas/WebGLFramebuffer.h b/WebCore/html/canvas/WebGLFramebuffer.h
index 10b6772..b9402a0 100644
--- a/WebCore/html/canvas/WebGLFramebuffer.h
+++ b/WebCore/html/canvas/WebGLFramebuffer.h
@@ -39,10 +39,21 @@ namespace WebCore {
static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*);
+ void setIsAttached(unsigned long attachment, bool isAttached);
+
+ bool isDepthAttached() const { return m_isDepthAttached; }
+ bool isStencilAttached() const { return m_isStencilAttached; }
+ bool isDepthStencilAttached() const { return m_isDepthStencilAttached; }
+
protected:
WebGLFramebuffer(WebGLRenderingContext*);
virtual void _deleteObject(Platform3DObject);
+
+ private:
+ bool m_isDepthAttached;
+ bool m_isStencilAttached;
+ bool m_isDepthStencilAttached;
};
} // namespace WebCore
diff --git a/WebCore/html/canvas/WebGLIntArray.cpp b/WebCore/html/canvas/WebGLIntArray.cpp
index 4617010..21b7a88 100644
--- a/WebCore/html/canvas/WebGLIntArray.cpp
+++ b/WebCore/html/canvas/WebGLIntArray.cpp
@@ -35,7 +35,7 @@ namespace WebCore {
PassRefPtr<WebGLIntArray> WebGLIntArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(int));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(int));
return create(buffer, 0, length);
}
@@ -48,24 +48,17 @@ PassRefPtr<WebGLIntArray> WebGLIntArray::create(int* array, unsigned length)
}
PassRefPtr<WebGLIntArray> WebGLIntArray::create(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length)
{
- // Make sure the offset results in valid alignment.
- if ((byteOffset % sizeof(int)) != 0)
- return NULL;
-
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(int))) > buffer->byteLength())
- return NULL;
- }
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<int>(buf, byteOffset, length))
+ return 0;
- return adoptRef(new WebGLIntArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLIntArray(buf, byteOffset, length));
}
-WebGLIntArray::WebGLIntArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+WebGLIntArray::WebGLIntArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
: WebGLArray(buffer, byteOffset)
, m_size(length)
{
@@ -79,15 +72,12 @@ unsigned WebGLIntArray::byteLength() const {
return m_size * sizeof(int);
}
-PassRefPtr<WebGLArray> WebGLIntArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(int);
- unsigned limitByte = startByte + length * sizeof(int);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLIntArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<int>(buffer(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLIntArray::set(WebGLIntArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLIntArray.h b/WebCore/html/canvas/WebGLIntArray.h
index 25108ac..5929e75 100644
--- a/WebCore/html/canvas/WebGLIntArray.h
+++ b/WebCore/html/canvas/WebGLIntArray.h
@@ -41,13 +41,13 @@ class WebGLIntArray : public WebGLArray {
static PassRefPtr<WebGLIntArray> create(unsigned length);
static PassRefPtr<WebGLIntArray> create(int* array, unsigned length);
- static PassRefPtr<WebGLIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
int* data() { return static_cast<int*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -87,7 +87,7 @@ class WebGLIntArray : public WebGLArray {
private:
WebGLIntArray(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length);
unsigned m_size;
};
diff --git a/WebCore/html/canvas/WebGLProgram.cpp b/WebCore/html/canvas/WebGLProgram.cpp
index c2606c1..750df45 100644
--- a/WebCore/html/canvas/WebGLProgram.cpp
+++ b/WebCore/html/canvas/WebGLProgram.cpp
@@ -48,6 +48,41 @@ void WebGLProgram::_deleteObject(Platform3DObject object)
context()->graphicsContext3D()->deleteProgram(object);
}
+bool WebGLProgram::cacheActiveAttribLocations()
+{
+ m_activeAttribLocations.clear();
+ if (!object())
+ return false;
+ GraphicsContext3D* context3d = context()->graphicsContext3D();
+ int linkStatus;
+ context3d->getProgramiv(this, GraphicsContext3D::LINK_STATUS, &linkStatus);
+ if (!linkStatus)
+ return false;
+
+ int numAttribs = 0;
+ context3d->getProgramiv(this, GraphicsContext3D::ACTIVE_ATTRIBUTES, &numAttribs);
+ m_activeAttribLocations.resize(static_cast<size_t>(numAttribs));
+ for (int i = 0; i < numAttribs; ++i) {
+ ActiveInfo info;
+ context3d->getActiveAttrib(this, i, info);
+ m_activeAttribLocations[i] = context3d->getAttribLocation(this, info.name.charactersWithNullTermination());
+ }
+
+ return true;
+}
+
+int WebGLProgram::numActiveAttribLocations()
+{
+ return static_cast<int>(m_activeAttribLocations.size());
+}
+
+int WebGLProgram::getActiveAttribLocation(int index)
+{
+ if (index < 0 || index >= numActiveAttribLocations())
+ return -1;
+ return m_activeAttribLocations[static_cast<size_t>(index)];
+}
+
}
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/html/canvas/WebGLProgram.h b/WebCore/html/canvas/WebGLProgram.h
index 8804d39..56bce15 100644
--- a/WebCore/html/canvas/WebGLProgram.h
+++ b/WebCore/html/canvas/WebGLProgram.h
@@ -30,6 +30,7 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -38,11 +39,20 @@ namespace WebCore {
virtual ~WebGLProgram() { deleteObject(); }
static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*);
+
+ // cacheActiveAttribLocation() is only called once after linkProgram()
+ // succeeds.
+ bool cacheActiveAttribLocations();
+ int numActiveAttribLocations();
+ int getActiveAttribLocation(int index);
protected:
WebGLProgram(WebGLRenderingContext*);
virtual void _deleteObject(Platform3DObject);
+
+ private:
+ Vector<int> m_activeAttribLocations;
};
} // namespace WebCore
diff --git a/WebCore/html/canvas/WebGLRenderbuffer.cpp b/WebCore/html/canvas/WebGLRenderbuffer.cpp
index 286ad2e..cad4298 100644
--- a/WebCore/html/canvas/WebGLRenderbuffer.cpp
+++ b/WebCore/html/canvas/WebGLRenderbuffer.cpp
@@ -44,12 +44,14 @@ PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* c
WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx)
: CanvasObject(ctx)
+ , m_internalformat(GraphicsContext3D::RGBA4)
{
setObject(context()->graphicsContext3D()->createRenderbuffer());
}
WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx, Platform3DObject obj)
: CanvasObject(ctx)
+ , m_internalformat(GraphicsContext3D::RGBA4)
{
setObject(obj, false);
}
diff --git a/WebCore/html/canvas/WebGLRenderbuffer.h b/WebCore/html/canvas/WebGLRenderbuffer.h
index 790fdcd..1bdf1b7 100644
--- a/WebCore/html/canvas/WebGLRenderbuffer.h
+++ b/WebCore/html/canvas/WebGLRenderbuffer.h
@@ -43,11 +43,17 @@ namespace WebCore {
// FIXME: should consider canonicalizing these objects
static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*, Platform3DObject renderbuffer);
+ void setInternalformat(unsigned long internalformat) { m_internalformat = internalformat; }
+ unsigned long getInternalformat() const { return m_internalformat; }
+
protected:
WebGLRenderbuffer(WebGLRenderingContext*);
WebGLRenderbuffer(WebGLRenderingContext*, Platform3DObject);
virtual void _deleteObject(Platform3DObject);
+
+ private:
+ unsigned long m_internalformat;
};
} // namespace WebCore
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index 6cb3348..d9af757 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -30,6 +30,7 @@
#include "WebGLRenderingContext.h"
#include "CanvasPixelArray.h"
+#include "FrameView.h"
#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
#include "ImageBuffer.h"
@@ -38,6 +39,7 @@
#include "RenderBox.h"
#include "RenderLayer.h"
#include "WebGLActiveInfo.h"
+#include "WebGLUnsignedShortArray.h"
#include "WebGLBuffer.h"
#include "WebGLContextAttributes.h"
#include "WebGLFramebuffer.h"
@@ -46,12 +48,6 @@
#include "WebGLTexture.h"
#include "WebGLShader.h"
#include "WebGLUniformLocation.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLImageElement.h"
-#include "ImageBuffer.h"
-#include "NotImplemented.h"
-#include "RenderBox.h"
-#include "RenderLayer.h"
#include <wtf/ByteArray.h>
@@ -78,7 +74,9 @@ private:
PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
{
- OwnPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs->attributes()));
+ HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow();
+ OwnPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs->attributes(), hostWindow));
+
if (!context)
return 0;
@@ -91,12 +89,23 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
, m_needsUpdate(true)
, m_markedCanvasDirty(false)
, m_activeTextureUnit(0)
+ , m_packAlignment(4)
+ , m_unpackAlignment(4)
{
ASSERT(m_context);
int numVertexAttribs = 0;
m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
m_maxVertexAttribs = numVertexAttribs;
+ int implementationColorReadFormat = GraphicsContext3D::RGBA;
+ m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT, &implementationColorReadFormat);
+ m_implementationColorReadFormat = implementationColorReadFormat;
+ int implementationColorReadType = GraphicsContext3D::UNSIGNED_BYTE;
+ m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE, &implementationColorReadType);
+ // FIXME: remove the getError() when IMPLEMENTATION_COLOR_READ_FORMAT/TYPE are supported.
+ m_context->getError();
+ m_implementationColorReadType = implementationColorReadType;
m_context->reshape(canvas()->width(), canvas()->height());
+ m_context->viewport(0, 0, canvas()->width(), canvas()->height());
}
WebGLRenderingContext::~WebGLRenderingContext()
@@ -107,9 +116,10 @@ WebGLRenderingContext::~WebGLRenderingContext()
void WebGLRenderingContext::markContextChanged()
{
#if USE(ACCELERATED_COMPOSITING)
- if (canvas()->renderBox() && canvas()->renderBox()->hasLayer()) {
- canvas()->renderBox()->layer()->rendererContentChanged();
- } else {
+ RenderBox* renderBox = canvas()->renderBox();
+ if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
+ renderBox->layer()->rendererContentChanged();
+ else {
#endif
if (!m_markedCanvasDirty) {
// Make sure the canvas's image buffer is allocated.
@@ -141,8 +151,9 @@ void WebGLRenderingContext::reshape(int width, int height)
{
if (m_needsUpdate) {
#if USE(ACCELERATED_COMPOSITING)
- if (canvas()->renderBox() && canvas()->renderBox()->hasLayer())
- canvas()->renderBox()->layer()->rendererContentChanged();
+ RenderBox* renderBox = canvas()->renderBox();
+ if (renderBox && renderBox->hasLayer())
+ renderBox->layer()->rendererContentChanged();
#endif
m_needsUpdate = false;
}
@@ -186,10 +197,8 @@ void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* sha
void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return;
- }
m_context->bindAttribLocation(program, index, name);
cleanupAfterGraphicsCall(false);
}
@@ -412,10 +421,8 @@ void WebGLRenderingContext::colorMask(bool red, bool green, bool blue, bool alph
void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(shader))
return;
- }
m_context->compileShader(shader);
cleanupAfterGraphicsCall(false);
}
@@ -555,10 +562,8 @@ void WebGLRenderingContext::depthRange(double zNear, double zFar)
void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this || !shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program) || !validateWebGLObject(shader))
return;
- }
m_context->detachShader(program, shader);
cleanupAfterGraphicsCall(false);
}
@@ -691,12 +696,20 @@ bool WebGLRenderingContext::validateIndexArrayPrecise(unsigned long count, unsig
bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
{
+ if (!m_currentProgram)
+ return false;
+
// Look in each enabled vertex attrib and find the smallest buffer size
long smallestNumElements = LONG_MAX;
- for (unsigned i = 0; i < m_vertexAttribState.size(); ++i) {
- const VertexAttribState& state = m_vertexAttribState[i];
- if (state.enabled && state.numElements < smallestNumElements)
- smallestNumElements = state.numElements;
+ int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
+ int numAttribStates = static_cast<int>(m_vertexAttribState.size());
+ for (int i = 0; i < numActiveAttribLocations; ++i) {
+ int loc = m_currentProgram->getActiveAttribLocation(i);
+ if (loc >=0 && loc < numAttribStates) {
+ const VertexAttribState& state = m_vertexAttribState[loc];
+ if (state.enabled && state.numElements < smallestNumElements)
+ smallestNumElements = state.numElements;
+ }
}
if (smallestNumElements == LONG_MAX)
@@ -705,6 +718,19 @@ bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
return numElementsRequired <= smallestNumElements;
}
+bool WebGLRenderingContext::validateWebGLObject(CanvasObject* object)
+{
+ if (!object) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ if (object->context() != this) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return false;
+ }
+ return true;
+}
+
void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long count, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
@@ -789,6 +815,45 @@ void WebGLRenderingContext::framebufferRenderbuffer(unsigned long target, unsign
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
+ if (buffer->object()) {
+ bool isConflicted = false;
+ bool isDepthOrStencil = true;
+ switch (attachment) {
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ if (m_framebufferBinding->isDepthStencilAttached() || m_framebufferBinding->isStencilAttached())
+ isConflicted = true;
+ if (buffer->getInternalformat() != GraphicsContext3D::DEPTH_COMPONENT16)
+ isConflicted = true;
+ break;
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ if (m_framebufferBinding->isDepthStencilAttached() || m_framebufferBinding->isDepthAttached())
+ isConflicted = true;
+ if (buffer->getInternalformat() != GraphicsContext3D::STENCIL_INDEX8)
+ isConflicted = true;
+ break;
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ if (m_framebufferBinding->isDepthAttached() || m_framebufferBinding->isStencilAttached())
+ isConflicted = true;
+ if (buffer->getInternalformat() != GraphicsContext3D::DEPTH_STENCIL)
+ isConflicted = true;
+ break;
+ default:
+ isDepthOrStencil = false;
+ }
+ if (isConflicted) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+ if (isDepthOrStencil)
+ m_framebufferBinding->setIsAttached(attachment, true);
+ } else { // Detach
+ switch (attachment) {
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ m_framebufferBinding->setIsAttached(attachment, false);
+ }
+ }
m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, buffer);
cleanupAfterGraphicsCall(false);
}
@@ -827,10 +892,8 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram*
{
UNUSED_PARAM(ec);
ActiveInfo info;
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return 0;
- }
if (!m_context->getActiveAttrib(program, index, info)) {
return 0;
}
@@ -841,10 +904,8 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram
{
UNUSED_PARAM(ec);
ActiveInfo info;
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return 0;
- }
if (!m_context->getActiveUniform(program, index, info)) {
return 0;
}
@@ -896,7 +957,8 @@ WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(unsigned l
if (target != GraphicsContext3D::FRAMEBUFFER
|| (attachment != GraphicsContext3D::COLOR_ATTACHMENT0
&& attachment != GraphicsContext3D::DEPTH_ATTACHMENT
- && attachment != GraphicsContext3D::STENCIL_ATTACHMENT)
+ && attachment != GraphicsContext3D::STENCIL_ATTACHMENT
+ && attachment != GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT)
|| (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
&& pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
&& pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
@@ -1115,10 +1177,8 @@ WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionC
WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, unsigned long pname, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return WebGLGetInfo();
- }
WebGLStateRestorer(this, false);
int value = 0;
@@ -1145,10 +1205,8 @@ WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, u
String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return "";
- }
WebGLStateRestorer(this, false);
return m_context->getProgramInfoLog(program);
}
@@ -1175,8 +1233,11 @@ WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long targe
m_context->getRenderbufferParameteriv(target, pname, &value);
return WebGLGetInfo(static_cast<long>(value));
case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
- m_context->getRenderbufferParameteriv(target, pname, &value);
- return WebGLGetInfo(static_cast<unsigned long>(value));
+ if (!m_renderbufferBinding) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return WebGLGetInfo();
+ }
+ return WebGLGetInfo(m_renderbufferBinding->getInternalformat());
default:
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
return WebGLGetInfo();
@@ -1186,10 +1247,8 @@ WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long targe
WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsigned long pname, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(shader))
return WebGLGetInfo();
- }
WebGLStateRestorer(this, false);
int value = 0;
switch (pname) {
@@ -1213,10 +1272,8 @@ WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsi
String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(shader))
return "";
- }
WebGLStateRestorer(this, false);
return m_context->getShaderInfoLog(shader);
}
@@ -1224,10 +1281,8 @@ String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCod
String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(shader))
return "";
- }
WebGLStateRestorer(this, false);
return m_context->getShaderSource(shader);
}
@@ -1264,7 +1319,9 @@ WebGLGetInfo WebGLRenderingContext::getTexParameter(unsigned long target, unsign
WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || uniformLocation->program() != program || program->context() != this) {
+ if (!validateWebGLObject(program))
+ return WebGLGetInfo();
+ if (uniformLocation->program() != program) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return WebGLGetInfo();
}
@@ -1393,12 +1450,13 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return 0;
- }
WebGLStateRestorer(this, false);
- return WebGLUniformLocation::create(program, m_context->getUniformLocation(program, name));
+ long uniformLocation = m_context->getUniformLocation(program, name);
+ if (uniformLocation == -1)
+ return 0;
+ return WebGLUniformLocation::create(program, uniformLocation);
}
WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigned long pname, ExceptionCode& ec)
@@ -1519,18 +1577,26 @@ void WebGLRenderingContext::lineWidth(double width)
void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return;
- }
-
m_context->linkProgram(program);
+ program->cacheActiveAttribLocations();
cleanupAfterGraphicsCall(false);
}
void WebGLRenderingContext::pixelStorei(unsigned long pname, long param)
{
m_context->pixelStorei(pname, param);
+ if (param == 1 || param == 2 || param == 4 || param == 8) {
+ switch (pname) {
+ case GraphicsContext3D::PACK_ALIGNMENT:
+ m_packAlignment = static_cast<int>(param);
+ break;
+ case GraphicsContext3D::UNPACK_ALIGNMENT:
+ m_unpackAlignment = static_cast<int>(param);
+ break;
+ }
+ }
cleanupAfterGraphicsCall(false);
}
@@ -1542,7 +1608,76 @@ void WebGLRenderingContext::polygonOffset(double factor, double units)
PassRefPtr<WebGLArray> WebGLRenderingContext::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
{
- RefPtr<WebGLArray> array = m_context->readPixels(x, y, width, height, format, type);
+ // Validate enums.
+ unsigned long componentsPerPixel = 0;
+ switch (format) {
+ case GraphicsContext3D::ALPHA:
+ componentsPerPixel = 1;
+ break;
+ case GraphicsContext3D::RGB:
+ componentsPerPixel = 3;
+ break;
+ case GraphicsContext3D::RGBA:
+ componentsPerPixel = 4;
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return 0;
+ }
+ unsigned long bytesPerComponent = 0;
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_BYTE:
+ bytesPerComponent = sizeof(unsigned char);
+ break;
+ case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+ case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+ case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+ componentsPerPixel = 1;
+ bytesPerComponent = sizeof(unsigned short);
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return 0;
+ }
+ if (!(format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE || format == m_implementationColorReadFormat && type == m_implementationColorReadFormat)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return 0;
+ }
+ // Calculate array size, taking into consideration of PACK_ALIGNMENT.
+ unsigned long bytesPerRow = componentsPerPixel * bytesPerComponent * width;
+ unsigned long padding = 0;
+ unsigned long residualBytes = bytesPerRow % m_packAlignment;
+ if (residualBytes) {
+ padding = m_packAlignment - residualBytes;
+ bytesPerRow += padding;
+ }
+ // The last row needs no padding.
+ unsigned long totalBytes = bytesPerRow * height - padding;
+ unsigned long num = totalBytes / bytesPerComponent;
+ RefPtr<WebGLArray> array;
+ if (type == GraphicsContext3D::UNSIGNED_BYTE)
+ array = WebGLUnsignedByteArray::create(num);
+ else
+ array = WebGLUnsignedShortArray::create(num);
+ void* data = array->baseAddress();
+ m_context->readPixels(x, y, width, height, format, type, data);
+#if PLATFORM(CG)
+ // FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
+ // when alpha is off, readPixels should set alpha to 255 instead of 0.
+ if ((format == GraphicsContext3D::ALPHA || format == GraphicsContext3D::RGBA) && !m_context->getContextAttributes().alpha) {
+ if (type == GraphicsContext3D::UNSIGNED_BYTE) {
+ unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
+ for (unsigned long iy = 0; iy < height; ++iy) {
+ for (unsigned long ix = 0; ix < width; ++ix) {
+ pixels[componentsPerPixel - 1] = 255;
+ pixels += componentsPerPixel;
+ }
+ pixels += padding;
+ }
+ }
+ // FIXME: check whether we need to do the same with UNSIGNED_SHORT.
+ }
+#endif
cleanupAfterGraphicsCall(false);
return array;
}
@@ -1555,8 +1690,21 @@ void WebGLRenderingContext::releaseShaderCompiler()
void WebGLRenderingContext::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
{
- m_context->renderbufferStorage(target, internalformat, width, height);
- cleanupAfterGraphicsCall(false);
+ switch (internalformat) {
+ case GraphicsContext3D::DEPTH_COMPONENT16:
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RGB5_A1:
+ case GraphicsContext3D::RGB565:
+ case GraphicsContext3D::STENCIL_INDEX8:
+ case GraphicsContext3D::DEPTH_STENCIL:
+ m_context->renderbufferStorage(target, internalformat, width, height);
+ if (m_renderbufferBinding)
+ m_renderbufferBinding->setInternalformat(internalformat);
+ cleanupAfterGraphicsCall(false);
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ }
}
void WebGLRenderingContext::sampleCoverage(double value, bool invert)
@@ -1574,10 +1722,8 @@ void WebGLRenderingContext::scissor(long x, long y, unsigned long width, unsigne
void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(shader))
return;
- }
m_context->shaderSource(shader, string);
cleanupAfterGraphicsCall(false);
}
@@ -1634,12 +1780,10 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageDat
bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
// FIXME: For now we ignore any errors returned
- // FIXME: Need a form of this call that can take both a pixel buffer and flipY and premultiplyAlpha flags
- UNUSED_PARAM(flipY);
- UNUSED_PARAM(premultiplyAlpha);
ec = 0;
- m_context->texImage2D(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels->data()->data()->data());
- //RLP: m_context->texImage2D(target, level, pixels, flipY, premultiplyAlpha);
+ Vector<uint8_t> data;
+ m_context->extractImageData(pixels, flipY, premultiplyAlpha, data);
+ m_context->texImage2D(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data());
cleanupAfterGraphicsCall(false);
}
@@ -1724,11 +1868,10 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
// FIXME: For now we ignore any errors returned
- UNUSED_PARAM(flipY);
- UNUSED_PARAM(premultiplyAlpha);
ec = 0;
- m_context->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels->data()->data()->data());
- //RLP: m_context->texSubImage2D(target, level, xoffset, yoffset, pixels, flipY, premultiplyAlpha);
+ Vector<uint8_t> data;
+ m_context->extractImageData(pixels, flipY, premultiplyAlpha, data);
+ m_context->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data());
cleanupAfterGraphicsCall(false);
}
@@ -1790,7 +1933,12 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1802,7 +1950,12 @@ void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1818,7 +1971,12 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1834,7 +1992,12 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1846,7 +2009,12 @@ void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1862,7 +2030,12 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1878,7 +2051,12 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1890,7 +2068,12 @@ void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1907,7 +2090,12 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1924,7 +2112,12 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1936,7 +2129,12 @@ void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1953,7 +2151,12 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1970,7 +2173,12 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1982,7 +2190,12 @@ void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -1999,7 +2212,12 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2016,7 +2234,12 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2028,7 +2251,12 @@ void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2045,7 +2273,12 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2062,7 +2295,12 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2074,7 +2312,12 @@ void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2091,7 +2334,12 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2108,7 +2356,12 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2120,7 +2373,12 @@ void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2137,7 +2395,12 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Web
void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2154,7 +2417,12 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2171,7 +2439,12 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2188,7 +2461,12 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2205,7 +2483,12 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2222,7 +2505,12 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -2239,7 +2527,12 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location || location->program() != m_currentProgram) {
+ if (!location) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index 90d4fab..9c58a53 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -309,6 +309,8 @@ class WebKitCSSMatrix;
bool validateIndexArrayPrecise(unsigned long count, unsigned long type, long offset, long& numElementsRequired);
bool validateRenderingState(long numElements);
+ bool validateWebGLObject(CanvasObject* object);
+
OwnPtr<GraphicsContext3D> m_context;
bool m_needsUpdate;
bool m_markedCanvasDirty;
@@ -342,6 +344,11 @@ class WebKitCSSMatrix;
TextureUnitState m_textureUnits[32];
unsigned long m_activeTextureUnit;
+ int m_packAlignment;
+ int m_unpackAlignment;
+ unsigned long m_implementationColorReadFormat;
+ unsigned long m_implementationColorReadType;
+
// Helpers for getParameter and others
WebGLGetInfo getBooleanParameter(unsigned long pname);
WebGLGetInfo getFloatParameter(unsigned long pname);
diff --git a/WebCore/html/canvas/WebGLRenderingContext.idl b/WebCore/html/canvas/WebGLRenderingContext.idl
index ce01f43..a257452 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.idl
+++ b/WebCore/html/canvas/WebGLRenderingContext.idl
@@ -423,6 +423,7 @@ module html {
const unsigned int DEPTH_COMPONENT16 = 0x81A5;
const unsigned int STENCIL_INDEX = 0x1901;
const unsigned int STENCIL_INDEX8 = 0x8D48;
+ const unsigned int DEPTH_STENCIL = 0x84F9;
const unsigned int RENDERBUFFER_WIDTH = 0x8D42;
const unsigned int RENDERBUFFER_HEIGHT = 0x8D43;
@@ -442,6 +443,7 @@ module html {
const unsigned int COLOR_ATTACHMENT0 = 0x8CE0;
const unsigned int DEPTH_ATTACHMENT = 0x8D00;
const unsigned int STENCIL_ATTACHMENT = 0x8D20;
+ const unsigned int DEPTH_STENCIL_ATTACHMENT = 0x821A;
const unsigned int NONE = 0;
@@ -518,7 +520,7 @@ module html {
void disable(in unsigned long cap);
void disableVertexAttribArray(in unsigned long index) raises(DOMException);
void drawArrays(in unsigned long mode, in long first, in unsigned long count) raises(DOMException);
- void drawElements (in unsigned long mode, in long count, in unsigned long type, in unsigned long offset) raises(DOMException);
+ void drawElements(in unsigned long mode, in long count, in unsigned long type, in unsigned long offset) raises(DOMException);
void enable(in unsigned long cap);
void enableVertexAttribArray(in unsigned long index) raises(DOMException);
diff --git a/WebCore/html/canvas/WebGLShortArray.cpp b/WebCore/html/canvas/WebGLShortArray.cpp
index f96a290..a9b0f0d 100644
--- a/WebCore/html/canvas/WebGLShortArray.cpp
+++ b/WebCore/html/canvas/WebGLShortArray.cpp
@@ -34,7 +34,7 @@ namespace WebCore {
PassRefPtr<WebGLShortArray> WebGLShortArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(short));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(short));
return create(buffer, 0, length);
}
@@ -47,24 +47,17 @@ PassRefPtr<WebGLShortArray> WebGLShortArray::create(short* array, unsigned lengt
}
PassRefPtr<WebGLShortArray> WebGLShortArray::create(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length)
{
- // Make sure the offset results in valid alignment.
- if ((byteOffset % sizeof(short)) != 0)
- return NULL;
-
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(short))) > buffer->byteLength())
- return NULL;
- }
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<short>(buf, byteOffset, length))
+ return 0;
- return adoptRef(new WebGLShortArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLShortArray(buf, byteOffset, length));
}
-WebGLShortArray::WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+WebGLShortArray::WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
: WebGLArray(buffer, byteOffset)
, m_size(length)
{
@@ -78,15 +71,12 @@ unsigned WebGLShortArray::byteLength() const {
return m_size * sizeof(short);
}
-PassRefPtr<WebGLArray> WebGLShortArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(short);
- unsigned limitByte = startByte + length * sizeof(short);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLShortArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<short>(buffer(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLShortArray::set(WebGLShortArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLShortArray.h b/WebCore/html/canvas/WebGLShortArray.h
index 70c66ca..af4befb 100644
--- a/WebCore/html/canvas/WebGLShortArray.h
+++ b/WebCore/html/canvas/WebGLShortArray.h
@@ -40,13 +40,13 @@ class WebGLShortArray : public WebGLArray {
static PassRefPtr<WebGLShortArray> create(unsigned length);
static PassRefPtr<WebGLShortArray> create(short* array, unsigned length);
- static PassRefPtr<WebGLShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
short* data() { return static_cast<short*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -85,7 +85,7 @@ class WebGLShortArray : public WebGLArray {
void set(WebGLShortArray* array, unsigned offset, ExceptionCode& ec);
private:
- WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ WebGLShortArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned m_size;
};
diff --git a/WebCore/html/canvas/WebGLUnsignedByteArray.cpp b/WebCore/html/canvas/WebGLUnsignedByteArray.cpp
index 3fd1b50..81e0135 100644
--- a/WebCore/html/canvas/WebGLUnsignedByteArray.cpp
+++ b/WebCore/html/canvas/WebGLUnsignedByteArray.cpp
@@ -35,7 +35,7 @@ namespace WebCore {
PassRefPtr<WebGLUnsignedByteArray> WebGLUnsignedByteArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(unsigned char));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(unsigned char));
return create(buffer, 0, length);
}
@@ -48,20 +48,17 @@ PassRefPtr<WebGLUnsignedByteArray> WebGLUnsignedByteArray::create(unsigned char*
}
PassRefPtr<WebGLUnsignedByteArray> WebGLUnsignedByteArray::create(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length)
{
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(unsigned char))) > buffer->byteLength())
- return NULL;
- }
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<unsigned char>(buf, byteOffset, length))
+ return 0;
- return adoptRef(new WebGLUnsignedByteArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLUnsignedByteArray(buf, byteOffset, length));
}
-WebGLUnsignedByteArray::WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+WebGLUnsignedByteArray::WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
: WebGLArray(buffer, byteOffset)
, m_size(length)
{
@@ -75,15 +72,12 @@ unsigned WebGLUnsignedByteArray::byteLength() const {
return m_size * sizeof(unsigned char);
}
-PassRefPtr<WebGLArray> WebGLUnsignedByteArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(unsigned char);
- unsigned limitByte = startByte + length * sizeof(unsigned char);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLUnsignedByteArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<unsigned char>(buffer(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLUnsignedByteArray::set(WebGLUnsignedByteArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLUnsignedByteArray.h b/WebCore/html/canvas/WebGLUnsignedByteArray.h
index 6909de5..505b2fd 100644
--- a/WebCore/html/canvas/WebGLUnsignedByteArray.h
+++ b/WebCore/html/canvas/WebGLUnsignedByteArray.h
@@ -41,13 +41,13 @@ class WebGLUnsignedByteArray : public WebGLArray {
static PassRefPtr<WebGLUnsignedByteArray> create(unsigned length);
static PassRefPtr<WebGLUnsignedByteArray> create(unsigned char* array, unsigned length);
- static PassRefPtr<WebGLUnsignedByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLUnsignedByteArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned char* data() { return static_cast<unsigned char*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -86,7 +86,7 @@ class WebGLUnsignedByteArray : public WebGLArray {
void set(WebGLUnsignedByteArray* array, unsigned offset, ExceptionCode& ec);
private:
- WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ WebGLUnsignedByteArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned m_size;
};
diff --git a/WebCore/html/canvas/WebGLUnsignedIntArray.cpp b/WebCore/html/canvas/WebGLUnsignedIntArray.cpp
index 97910f9..59d895f 100644
--- a/WebCore/html/canvas/WebGLUnsignedIntArray.cpp
+++ b/WebCore/html/canvas/WebGLUnsignedIntArray.cpp
@@ -35,7 +35,7 @@ namespace WebCore {
PassRefPtr<WebGLUnsignedIntArray> WebGLUnsignedIntArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(unsigned int));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(unsigned int));
return create(buffer, 0, length);
}
@@ -48,25 +48,17 @@ PassRefPtr<WebGLUnsignedIntArray> WebGLUnsignedIntArray::create(unsigned int* ar
}
PassRefPtr<WebGLUnsignedIntArray> WebGLUnsignedIntArray::create(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length)
{
- // Make sure the offset results in valid alignment.
- if ((byteOffset % sizeof(unsigned int)) != 0) {
- return NULL;
- }
-
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(unsigned int))) > buffer->byteLength())
- return NULL;
- }
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<unsigned int>(buf, byteOffset, length))
+ return 0;
- return adoptRef(new WebGLUnsignedIntArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLUnsignedIntArray(buf, byteOffset, length));
}
-WebGLUnsignedIntArray::WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length)
+WebGLUnsignedIntArray::WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length)
: WebGLArray(buffer, byteOffset)
, m_size(length)
{
@@ -80,15 +72,12 @@ unsigned WebGLUnsignedIntArray::byteLength() const {
return m_size * sizeof(unsigned int);
}
-PassRefPtr<WebGLArray> WebGLUnsignedIntArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(unsigned int);
- unsigned limitByte = startByte + length * sizeof(unsigned int);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLUnsignedIntArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<unsigned int>(buffer(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLUnsignedIntArray::set(WebGLUnsignedIntArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLUnsignedIntArray.h b/WebCore/html/canvas/WebGLUnsignedIntArray.h
index b0d9b65..6e9b220 100644
--- a/WebCore/html/canvas/WebGLUnsignedIntArray.h
+++ b/WebCore/html/canvas/WebGLUnsignedIntArray.h
@@ -41,13 +41,13 @@ class WebGLUnsignedIntArray : public WebGLArray {
static PassRefPtr<WebGLUnsignedIntArray> create(unsigned length);
static PassRefPtr<WebGLUnsignedIntArray> create(unsigned int* array, unsigned length);
- static PassRefPtr<WebGLUnsignedIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLUnsignedIntArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned int* data() { return static_cast<unsigned int*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -86,7 +86,7 @@ class WebGLUnsignedIntArray : public WebGLArray {
void set(WebGLUnsignedIntArray* array, unsigned offset, ExceptionCode& ec);
private:
- WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ WebGLUnsignedIntArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned m_size;
};
diff --git a/WebCore/html/canvas/WebGLUnsignedShortArray.cpp b/WebCore/html/canvas/WebGLUnsignedShortArray.cpp
index 86fae8c..c283a81 100644
--- a/WebCore/html/canvas/WebGLUnsignedShortArray.cpp
+++ b/WebCore/html/canvas/WebGLUnsignedShortArray.cpp
@@ -35,7 +35,7 @@ namespace WebCore {
PassRefPtr<WebGLUnsignedShortArray> WebGLUnsignedShortArray::create(unsigned length)
{
- RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length * sizeof(unsigned short));
+ RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(length, sizeof(unsigned short));
return create(buffer, 0, length);
}
@@ -48,26 +48,18 @@ PassRefPtr<WebGLUnsignedShortArray> WebGLUnsignedShortArray::create(unsigned sho
}
PassRefPtr<WebGLUnsignedShortArray> WebGLUnsignedShortArray::create(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length)
{
- // Make sure the offset results in valid alignment.
- if ((byteOffset % sizeof(unsigned short)) != 0) {
- return NULL;
- }
-
- if (buffer) {
- // Check to make sure we are talking about a valid region of
- // the given WebGLArrayBuffer's storage.
- if ((byteOffset + (length * sizeof(unsigned short))) > buffer->byteLength())
- return NULL;
- }
+ RefPtr<WebGLArrayBuffer> buf(buffer);
+ if (!verifySubRange<unsigned short>(buf, byteOffset, length))
+ return 0;
- return adoptRef(new WebGLUnsignedShortArray(buffer, byteOffset, length));
+ return adoptRef(new WebGLUnsignedShortArray(buf, byteOffset, length));
}
WebGLUnsignedShortArray::WebGLUnsignedShortArray(PassRefPtr<WebGLArrayBuffer> buffer,
- int byteOffset,
+ unsigned byteOffset,
unsigned length)
: WebGLArray(buffer, byteOffset)
, m_size(length)
@@ -82,15 +74,12 @@ unsigned WebGLUnsignedShortArray::byteLength() const {
return m_size * sizeof(unsigned short);
}
-PassRefPtr<WebGLArray> WebGLUnsignedShortArray::slice(unsigned offset, unsigned length) {
- // Check to make sure the specified region is within the bounds of
- // the WebGLArrayBuffer.
- unsigned startByte = m_byteOffset + offset * sizeof(unsigned short);
- unsigned limitByte = startByte + length * sizeof(unsigned short);
- unsigned bufferLength = buffer()->byteLength();
- if (startByte >= bufferLength || limitByte > bufferLength)
- return 0;
- return create(buffer(), startByte, length);
+PassRefPtr<WebGLArray> WebGLUnsignedShortArray::slice(int start, int end)
+{
+ unsigned offset, length;
+ calculateOffsetAndLength(start, end, m_size, &offset, &length);
+ clampOffsetAndNumElements<unsigned short>(buffer(), m_byteOffset, &offset, &length);
+ return create(buffer(), offset, length);
}
void WebGLUnsignedShortArray::set(WebGLUnsignedShortArray* array, unsigned offset, ExceptionCode& ec) {
diff --git a/WebCore/html/canvas/WebGLUnsignedShortArray.h b/WebCore/html/canvas/WebGLUnsignedShortArray.h
index 3bad1b6..94b428a 100644
--- a/WebCore/html/canvas/WebGLUnsignedShortArray.h
+++ b/WebCore/html/canvas/WebGLUnsignedShortArray.h
@@ -41,13 +41,13 @@ class WebGLUnsignedShortArray : public WebGLArray {
static PassRefPtr<WebGLUnsignedShortArray> create(unsigned length);
static PassRefPtr<WebGLUnsignedShortArray> create(unsigned short* array, unsigned length);
- static PassRefPtr<WebGLUnsignedShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, int byteOffset, unsigned length);
+ static PassRefPtr<WebGLUnsignedShortArray> create(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset, unsigned length);
unsigned short* data() { return static_cast<unsigned short*>(baseAddress()); }
virtual unsigned length() const;
virtual unsigned byteLength() const;
- virtual PassRefPtr<WebGLArray> slice(unsigned offset, unsigned length);
+ virtual PassRefPtr<WebGLArray> slice(int start, int end);
void set(unsigned index, double value)
{
@@ -87,7 +87,7 @@ class WebGLUnsignedShortArray : public WebGLArray {
void set(WebGLUnsignedShortArray* array, unsigned offset, ExceptionCode& ec);
private:
- WebGLUnsignedShortArray(PassRefPtr<WebGLArrayBuffer> buffer,int byteOffset,unsigned length);
+ WebGLUnsignedShortArray(PassRefPtr<WebGLArrayBuffer> buffer, unsigned byteOffset,unsigned length);
unsigned m_size;
};