summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/Platform
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-13 16:23:25 +0100
committerBen Murdoch <benm@google.com>2011-05-16 11:35:02 +0100
commit65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch)
treef478babb801e720de7bfaee23443ffe029f58731 /Source/WebKit2/Platform
parent47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff)
downloadexternal_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz
external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'Source/WebKit2/Platform')
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentCoder.h50
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentCoders.h301
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp225
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.h161
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp162
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.h127
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Arguments.h401
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Attachment.cpp73
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Attachment.h91
-rw-r--r--Source/WebKit2/Platform/CoreIPC/BinarySemaphore.cpp64
-rw-r--r--Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h54
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Connection.cpp453
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Connection.h362
-rw-r--r--Source/WebKit2/Platform/CoreIPC/CoreIPCMessageKinds.h51
-rw-r--r--Source/WebKit2/Platform/CoreIPC/DataReference.cpp45
-rw-r--r--Source/WebKit2/Platform/CoreIPC/DataReference.h70
-rw-r--r--Source/WebKit2/Platform/CoreIPC/HandleMessage.h248
-rw-r--r--Source/WebKit2/Platform/CoreIPC/MessageID.h156
-rw-r--r--Source/WebKit2/Platform/CoreIPC/MessageSender.h73
-rw-r--r--Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp205
-rw-r--r--Source/WebKit2/Platform/CoreIPC/mac/ConnectionMac.cpp424
-rw-r--r--Source/WebKit2/Platform/CoreIPC/mac/MachPort.h75
-rw-r--r--Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp142
-rw-r--r--Source/WebKit2/Platform/CoreIPC/win/ConnectionWin.cpp315
-rw-r--r--Source/WebKit2/Platform/Logging.cpp53
-rw-r--r--Source/WebKit2/Platform/Logging.h50
-rw-r--r--Source/WebKit2/Platform/Module.cpp43
-rw-r--r--Source/WebKit2/Platform/Module.h74
-rw-r--r--Source/WebKit2/Platform/PlatformProcessIdentifier.h48
-rw-r--r--Source/WebKit2/Platform/Region.cpp454
-rw-r--r--Source/WebKit2/Platform/Region.h144
-rw-r--r--Source/WebKit2/Platform/RunLoop.cpp72
-rw-r--r--Source/WebKit2/Platform/RunLoop.h154
-rw-r--r--Source/WebKit2/Platform/SharedMemory.h105
-rw-r--r--Source/WebKit2/Platform/WorkItem.h187
-rw-r--r--Source/WebKit2/Platform/WorkQueue.cpp50
-rw-r--r--Source/WebKit2/Platform/WorkQueue.h176
-rw-r--r--Source/WebKit2/Platform/cg/CGUtilities.cpp64
-rw-r--r--Source/WebKit2/Platform/cg/CGUtilities.h35
-rw-r--r--Source/WebKit2/Platform/gtk/RunLoopGtk.cpp135
-rw-r--r--Source/WebKit2/Platform/gtk/SharedMemoryGtk.cpp84
-rw-r--r--Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp202
-rw-r--r--Source/WebKit2/Platform/mac/MachUtilities.cpp67
-rw-r--r--Source/WebKit2/Platform/mac/MachUtilities.h36
-rw-r--r--Source/WebKit2/Platform/mac/ModuleMac.mm62
-rw-r--r--Source/WebKit2/Platform/mac/RunLoopMac.mm131
-rw-r--r--Source/WebKit2/Platform/mac/SharedMemoryMac.cpp171
-rw-r--r--Source/WebKit2/Platform/mac/WorkQueueMac.cpp202
-rw-r--r--Source/WebKit2/Platform/qt/MappedMemoryPool.cpp114
-rw-r--r--Source/WebKit2/Platform/qt/MappedMemoryPool.h109
-rw-r--r--Source/WebKit2/Platform/qt/ModuleQt.cpp48
-rw-r--r--Source/WebKit2/Platform/qt/RunLoopQt.cpp145
-rw-r--r--Source/WebKit2/Platform/qt/SharedMemoryQt.cpp178
-rw-r--r--Source/WebKit2/Platform/qt/WorkQueueQt.cpp132
-rw-r--r--Source/WebKit2/Platform/win/ModuleWin.cpp55
-rw-r--r--Source/WebKit2/Platform/win/RunLoopWin.cpp170
-rw-r--r--Source/WebKit2/Platform/win/SharedMemoryWin.cpp188
-rw-r--r--Source/WebKit2/Platform/win/WorkQueueWin.cpp234
58 files changed, 8500 insertions, 0 deletions
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentCoder.h b/Source/WebKit2/Platform/CoreIPC/ArgumentCoder.h
new file mode 100644
index 0000000..bd15f51
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/ArgumentCoder.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ArgumentCoder_h
+#define ArgumentCoder_h
+
+#include <wtf/TypeTraits.h>
+
+namespace CoreIPC {
+
+class ArgumentDecoder;
+class ArgumentEncoder;
+
+template<typename T> struct ArgumentCoder {
+ static void encode(ArgumentEncoder* encoder, const T& t)
+ {
+ t.encode(encoder);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, T& t)
+ {
+ return T::decode(decoder, t);
+ }
+};
+
+}
+
+#endif // ArgumentCoder_h
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentCoders.h b/Source/WebKit2/Platform/CoreIPC/ArgumentCoders.h
new file mode 100644
index 0000000..1cc1a7d
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/ArgumentCoders.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SimpleArgumentCoder_h
+#define SimpleArgumentCoder_h
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include <utility>
+#include <wtf/HashMap.h>
+#include <wtf/TypeTraits.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace CoreIPC {
+
+// An argument coder works on POD types
+template<typename T> struct SimpleArgumentCoder {
+ static void encode(ArgumentEncoder* encoder, const T& t)
+ {
+ encoder->encodeBytes(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
+ }
+ static bool decode(ArgumentDecoder* decoder, T& t)
+ {
+ return decoder->decodeBytes(reinterpret_cast<uint8_t*>(&t), sizeof(T));
+ }
+};
+
+template<typename T, typename U> struct ArgumentCoder<std::pair<T, U> > {
+ static void encode(ArgumentEncoder* encoder, const std::pair<T, U>& pair)
+ {
+ encoder->encode(pair.first);
+ encoder->encode(pair.second);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, std::pair<T, U>& pair)
+ {
+ T first;
+ if (!decoder->decode(first))
+ return false;
+
+ U second;
+ if (!decoder->decode(second))
+ return false;
+
+ pair.first = first;
+ pair.second = second;
+ return true;
+ }
+};
+
+template<bool fixedSizeElements, typename T> struct VectorArgumentCoder;
+
+template<typename T> struct VectorArgumentCoder<false, T> {
+ static void encode(ArgumentEncoder* encoder, const Vector<T>& vector)
+ {
+ encoder->encodeUInt64(vector.size());
+ for (size_t i = 0; i < vector.size(); ++i)
+ encoder->encode(vector[i]);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Vector<T>& vector)
+ {
+ uint64_t size;
+ if (!decoder->decodeUInt64(size))
+ return false;
+
+ Vector<T> tmp;
+ for (size_t i = 0; i < size; ++i) {
+ T element;
+ if (!decoder->decode(element))
+ return false;
+
+ tmp.append(element);
+ }
+
+ tmp.shrinkToFit();
+ vector.swap(tmp);
+ return true;
+ }
+};
+
+template<typename T> struct VectorArgumentCoder<true, T> {
+ static void encode(ArgumentEncoder* encoder, const Vector<T>& vector)
+ {
+ encoder->encodeUInt64(vector.size());
+ // FIXME: If we could tell the encoder to align the buffer, we could just do an encodeBytes here.
+ for (size_t i = 0; i < vector.size(); ++i)
+ encoder->encode(vector[i]);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Vector<T>& vector)
+ {
+ uint64_t size;
+ if (!decoder->decodeUInt64(size))
+ return false;
+
+ // Since we know the total size of the elements, we can allocate the vector in
+ // one fell swoop. Before allocating we must however make sure that the decoder buffer
+ // is big enough.
+ if (!decoder->bufferIsLargeEnoughToContain<T>(size)) {
+ decoder->markInvalid();
+ return false;
+ }
+
+ Vector<T> tmp;
+ tmp.reserveCapacity(size);
+
+ for (size_t i = 0; i < size; ++i) {
+ T element;
+ if (!decoder->decode(element))
+ return false;
+
+ tmp.uncheckedAppend(element);
+ }
+
+ vector.swap(tmp);
+ return true;
+ }
+};
+
+template<typename T> struct ArgumentCoder<Vector<T> > : VectorArgumentCoder<WTF::IsArithmetic<T>::value, T> { };
+
+// Specialization for Vector<uint8_t>
+template<> struct ArgumentCoder<Vector<uint8_t> > {
+ static void encode(ArgumentEncoder* encoder, const Vector<uint8_t>& vector)
+ {
+ encoder->encodeBytes(vector.data(), vector.size());
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Vector<uint8_t>& vector)
+ {
+ return decoder->decodeBytes(vector);
+ }
+};
+
+template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct ArgumentCoder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> > {
+ typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
+
+ static void encode(ArgumentEncoder* encoder, const HashMapType& hashMap)
+ {
+ encoder->encodeUInt64(hashMap.size());
+ for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
+ encoder->encode(*it);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, HashMapType& hashMap)
+ {
+ uint64_t hashMapSize;
+ if (!decoder->decode(hashMapSize))
+ return false;
+
+ HashMapType tempHashMap;
+ for (uint64_t i = 0; i < hashMapSize; ++i) {
+ KeyArg key;
+ MappedArg value;
+ if (!decoder->decode(key))
+ return false;
+ if (!decoder->decode(value))
+ return false;
+
+ if (!tempHashMap.add(key, value).second) {
+ // The hash map already has the specified key, bail.
+ decoder->markInvalid();
+ return false;
+ }
+ }
+
+ hashMap.swap(tempHashMap);
+ return true;
+ }
+};
+
+template<> struct ArgumentCoder<CString> {
+ static void encode(ArgumentEncoder* encoder, const CString& string)
+ {
+ // Special case the null string.
+ if (string.isNull()) {
+ encoder->encodeUInt32(std::numeric_limits<uint32_t>::max());
+ return;
+ }
+
+ uint32_t length = string.length();
+ encoder->encode(length);
+ encoder->encodeBytes(reinterpret_cast<const uint8_t*>(string.data()), length);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, CString& result)
+ {
+ uint32_t length;
+ if (!decoder->decode(length))
+ return false;
+
+ if (length == std::numeric_limits<uint32_t>::max()) {
+ // This is the null string.
+ result = CString();
+ return true;
+ }
+
+ // Before allocating the string, make sure that the decoder buffer is big enough.
+ if (!decoder->bufferIsLargeEnoughToContain<char>(length)) {
+ decoder->markInvalid();
+ return false;
+ }
+
+ char* buffer;
+ CString string = CString::newUninitialized(length, buffer);
+ if (!decoder->decodeBytes(reinterpret_cast<uint8_t*>(buffer), length))
+ return false;
+
+ result = string;
+ return true;
+ }
+};
+
+template<> struct ArgumentCoder<String> {
+ static void encode(ArgumentEncoder* encoder, const String& string)
+ {
+ // Special case the null string.
+ if (string.isNull()) {
+ encoder->encodeUInt32(std::numeric_limits<uint32_t>::max());
+ return;
+ }
+
+ uint32_t length = string.length();
+ encoder->encode(length);
+ encoder->encodeBytes(reinterpret_cast<const uint8_t*>(string.characters()), length * sizeof(UChar));
+ }
+
+ static bool decode(ArgumentDecoder* decoder, String& result)
+ {
+ uint32_t length;
+ if (!decoder->decode(length))
+ return false;
+
+ if (length == std::numeric_limits<uint32_t>::max()) {
+ // This is the null string.
+ result = String();
+ return true;
+ }
+
+ // Before allocating the string, make sure that the decoder buffer is big enough.
+ if (!decoder->bufferIsLargeEnoughToContain<UChar>(length)) {
+ decoder->markInvalid();
+ return false;
+ }
+
+ UChar* buffer;
+ String string = String::createUninitialized(length, buffer);
+ if (!decoder->decodeBytes(reinterpret_cast<uint8_t*>(buffer), length * sizeof(UChar)))
+ return false;
+
+ result = string;
+ return true;
+ }
+};
+
+template<> struct ArgumentCoder<AtomicString> {
+ static void encode(ArgumentEncoder* encoder, const AtomicString& atomicString)
+ {
+ encoder->encode(atomicString.string());
+ }
+
+ static bool decode(ArgumentDecoder* decoder, AtomicString& atomicString)
+ {
+ String string;
+ if (!decoder->decode(string))
+ return false;
+
+ atomicString = string;
+ return true;
+ }
+};
+
+} // namespace CoreIPC
+
+#endif // SimpleArgumentCoder_h
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp b/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp
new file mode 100644
index 0000000..336f72f
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ArgumentDecoder.h"
+
+#include "DataReference.h"
+#include <stdio.h>
+
+namespace CoreIPC {
+
+ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize)
+{
+ initialize(buffer, bufferSize);
+}
+
+ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Deque<Attachment>& attachments)
+{
+ initialize(buffer, bufferSize);
+
+ m_attachments.swap(attachments);
+}
+
+ArgumentDecoder::~ArgumentDecoder()
+{
+ ASSERT(m_buffer);
+ fastFree(m_buffer);
+ // FIXME: We need to dispose of the mach ports in cases of failure.
+}
+
+void ArgumentDecoder::initialize(const uint8_t* buffer, size_t bufferSize)
+{
+ m_buffer = static_cast<uint8_t*>(fastMalloc(bufferSize));
+ m_bufferPos = m_buffer;
+ m_bufferEnd = m_buffer + bufferSize;
+ memcpy(m_buffer, buffer, bufferSize);
+
+ // Decode the destination ID.
+ decodeUInt64(m_destinationID);
+}
+
+static inline uint8_t* roundUpToAlignment(uint8_t* ptr, unsigned alignment)
+{
+ return (uint8_t*)(((uintptr_t)ptr + alignment - 1) & ~(uintptr_t)(alignment - 1));
+}
+
+bool ArgumentDecoder::alignBufferPosition(unsigned alignment, size_t size)
+{
+ uint8_t* buffer = roundUpToAlignment(m_bufferPos, alignment);
+ if (buffer + size > m_bufferEnd) {
+ // We've walked off the end of this buffer.
+ markInvalid();
+ return false;
+ }
+
+ m_bufferPos = buffer;
+ return true;
+}
+
+bool ArgumentDecoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const
+{
+ return roundUpToAlignment(m_bufferPos, alignment) + size <= m_bufferEnd;
+}
+
+bool ArgumentDecoder::decodeBytes(Vector<uint8_t>& buffer)
+{
+ uint64_t size;
+ if (!decodeUInt64(size))
+ return false;
+
+ if (!alignBufferPosition(1, size))
+ return false;
+
+ buffer.resize(size);
+ if (size > 0)
+ memcpy(&buffer[0], m_bufferPos, size);
+ m_bufferPos += size;
+ return true;
+}
+
+bool ArgumentDecoder::decodeBytes(DataReference& dataReference)
+{
+ uint64_t size;
+ if (!decodeUInt64(size))
+ return false;
+
+ if (!alignBufferPosition(1, size))
+ return false;
+
+ uint8_t* data = m_bufferPos;
+ m_bufferPos += size;
+
+ dataReference = DataReference(data, size);
+ return true;
+}
+
+bool ArgumentDecoder::decodeBytes(uint8_t* buffer, size_t bufferSize)
+{
+ // FIXME: Decoding the size is not strictly necessary here since we know the size upfront.
+ uint64_t size;
+ if (!decodeUInt64(size))
+ return false;
+
+ ASSERT(size == bufferSize);
+ if (size != bufferSize)
+ return false;
+
+ if (!alignBufferPosition(1, size))
+ return false;
+
+ memcpy(buffer, m_bufferPos, size);
+ m_bufferPos += size;
+ return true;
+}
+
+bool ArgumentDecoder::decodeBool(bool& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<bool*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::decodeUInt32(uint32_t& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<uint32_t*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::decodeUInt64(uint64_t& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<uint64_t*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::decodeInt32(int32_t& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<uint32_t*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::decodeInt64(int64_t& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<uint64_t*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::decodeFloat(float& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<float*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::decodeDouble(double& result)
+{
+ if (!alignBufferPosition(__alignof(result), sizeof(result)))
+ return false;
+
+ result = *reinterpret_cast<double*>(m_bufferPos);
+ m_bufferPos += sizeof(result);
+ return true;
+}
+
+bool ArgumentDecoder::removeAttachment(Attachment& attachment)
+{
+ if (m_attachments.isEmpty())
+ return false;
+
+ attachment = m_attachments.takeFirst();
+ return true;
+}
+
+#ifndef NDEBUG
+void ArgumentDecoder::debug()
+{
+ printf("ArgumentDecoder::debug()\n");
+ printf("Number of Attachments: %d\n", (int)m_attachments.size());
+ printf("Size of buffer: %d\n", (int)(m_bufferEnd - m_buffer));
+}
+#endif
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.h b/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.h
new file mode 100644
index 0000000..dcf67ad
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ArgumentDecoder_h
+#define ArgumentDecoder_h
+
+#include "ArgumentCoder.h"
+#include "Attachment.h"
+#include <wtf/Deque.h>
+#include <wtf/TypeTraits.h>
+#include <wtf/Vector.h>
+
+namespace CoreIPC {
+
+class DataReference;
+
+class ArgumentDecoder {
+public:
+ ArgumentDecoder(const uint8_t* buffer, size_t bufferSize);
+ ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Deque<Attachment>&);
+ ~ArgumentDecoder();
+
+ uint64_t destinationID() const { return m_destinationID; }
+
+ bool isInvalid() const { return m_bufferPos > m_bufferEnd; }
+ void markInvalid() { m_bufferPos = m_bufferEnd + 1; }
+
+ bool decodeBytes(Vector<uint8_t>&);
+ bool decodeBytes(uint8_t*, size_t);
+
+ // The data in the data reference here will only be valid for the lifetime of the ArgumentDecoder object.
+ bool decodeBytes(DataReference&);
+
+ bool decodeBool(bool&);
+ bool decodeUInt32(uint32_t&);
+ bool decodeUInt64(uint64_t&);
+ bool decodeInt32(int32_t&);
+ bool decodeInt64(int64_t&);
+ bool decodeFloat(float&);
+ bool decodeDouble(double&);
+
+ template<typename T> bool decodeEnum(T& result)
+ {
+ COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits);
+
+ uint64_t value;
+ if (!decodeUInt64(value))
+ return false;
+
+ result = static_cast<T>(value);
+ return true;
+ }
+
+ template<typename T>
+ bool bufferIsLargeEnoughToContain(size_t numElements) const
+ {
+ COMPILE_ASSERT(WTF::IsArithmetic<T>::value, type_must_have_known_encoded_size);
+
+ if (numElements > std::numeric_limits<size_t>::max() / sizeof(T))
+ return false;
+
+ return bufferIsLargeEnoughToContain(__alignof(T), numElements * sizeof(T));
+ }
+
+ // Generic type decode function.
+ template<typename T> bool decode(T& t)
+ {
+ return ArgumentCoder<T>::decode(this, t);
+ }
+
+ // This overload exists so we can pass temporaries to decode. In the Star Trek future, it
+ // can take an rvalue reference instead.
+ template<typename T> bool decode(const T& t)
+ {
+ return decode(const_cast<T&>(t));
+ }
+
+ bool removeAttachment(Attachment&);
+
+#ifndef NDEBUG
+ void debug();
+#endif
+
+private:
+ ArgumentDecoder(const ArgumentDecoder*);
+ ArgumentDecoder* operator=(const ArgumentDecoder*);
+
+ void initialize(const uint8_t* buffer, size_t bufferSize);
+
+ bool alignBufferPosition(unsigned alignment, size_t size);
+ bool bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const;
+
+ uint64_t m_destinationID;
+
+ uint8_t* m_buffer;
+ uint8_t* m_bufferPos;
+ uint8_t* m_bufferEnd;
+
+ Deque<Attachment> m_attachments;
+};
+
+template<> inline bool ArgumentDecoder::decode(bool& n)
+{
+ return decodeBool(n);
+}
+
+template<> inline bool ArgumentDecoder::decode(uint32_t& n)
+{
+ return decodeUInt32(n);
+}
+
+template<> inline bool ArgumentDecoder::decode(uint64_t& n)
+{
+ return decodeUInt64(n);
+}
+
+template<> inline bool ArgumentDecoder::decode(int32_t& n)
+{
+ return decodeInt32(n);
+}
+
+template<> inline bool ArgumentDecoder::decode(int64_t& n)
+{
+ return decodeInt64(n);
+}
+
+template<> inline bool ArgumentDecoder::decode(float& n)
+{
+ return decodeFloat(n);
+}
+
+template<> inline bool ArgumentDecoder::decode(double& n)
+{
+ return decodeDouble(n);
+}
+
+} // namespace CoreIPC
+
+#endif // ArgumentDecoder_h
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp b/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp
new file mode 100644
index 0000000..1340c0a
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ArgumentEncoder.h"
+
+#include <algorithm>
+#include <stdio.h>
+
+namespace CoreIPC {
+
+PassOwnPtr<ArgumentEncoder> ArgumentEncoder::create(uint64_t destinationID)
+{
+ return adoptPtr(new ArgumentEncoder(destinationID));
+}
+
+ArgumentEncoder::ArgumentEncoder(uint64_t destinationID)
+ : m_buffer(0)
+ , m_bufferPointer(0)
+ , m_bufferSize(0)
+ , m_bufferCapacity(0)
+{
+ // Encode the destination ID.
+ encodeUInt64(destinationID);
+}
+
+ArgumentEncoder::~ArgumentEncoder()
+{
+ if (m_buffer)
+ fastFree(m_buffer);
+ // FIXME: We need to dispose of the attachments in cases of failure.
+}
+
+static inline size_t roundUpToAlignment(size_t value, unsigned alignment)
+{
+ return ((value + alignment - 1) / alignment) * alignment;
+}
+
+uint8_t* ArgumentEncoder::grow(unsigned alignment, size_t size)
+{
+ size_t alignedSize = roundUpToAlignment(m_bufferSize, alignment);
+
+ if (alignedSize + size > m_bufferCapacity) {
+ size_t newCapacity = std::max(alignedSize + size, std::max(static_cast<size_t>(32), m_bufferCapacity + m_bufferCapacity / 4 + 1));
+ if (!m_buffer)
+ m_buffer = static_cast<uint8_t*>(fastMalloc(newCapacity));
+ else
+ m_buffer = static_cast<uint8_t*>(fastRealloc(m_buffer, newCapacity));
+
+ // FIXME: What should we do if allocating memory fails?
+
+ m_bufferCapacity = newCapacity;
+ }
+
+ m_bufferSize = alignedSize + size;
+ m_bufferPointer = m_buffer + alignedSize + size;
+
+ return m_buffer + alignedSize;
+}
+
+void ArgumentEncoder::encodeBytes(const uint8_t* bytes, size_t size)
+{
+ // Encode the size.
+ encodeUInt64(static_cast<uint64_t>(size));
+
+ uint8_t* buffer = grow(1, size);
+
+ memcpy(buffer, bytes, size);
+}
+
+void ArgumentEncoder::encodeBool(bool n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<bool*>(buffer) = n;
+}
+
+void ArgumentEncoder::encodeUInt32(uint32_t n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<uint32_t*>(buffer) = n;
+}
+
+void ArgumentEncoder::encodeUInt64(uint64_t n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<uint64_t*>(buffer) = n;
+}
+
+void ArgumentEncoder::encodeInt32(int32_t n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<int32_t*>(buffer) = n;
+}
+
+void ArgumentEncoder::encodeInt64(int64_t n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<int64_t*>(buffer) = n;
+}
+
+void ArgumentEncoder::encodeFloat(float n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<float*>(buffer) = n;
+}
+
+void ArgumentEncoder::encodeDouble(double n)
+{
+ uint8_t* buffer = grow(__alignof(n), sizeof(n));
+
+ *reinterpret_cast<double*>(buffer) = n;
+}
+
+void ArgumentEncoder::addAttachment(const Attachment& attachment)
+{
+ m_attachments.append(attachment);
+}
+
+Vector<Attachment> ArgumentEncoder::releaseAttachments()
+{
+ Vector<Attachment> newList;
+ newList.swap(m_attachments);
+ return newList;
+}
+
+#ifndef NDEBUG
+void ArgumentEncoder::debug()
+{
+ printf("ArgumentEncoder::debug()\n");
+ printf("Number of Attachments: %d\n", (int)m_attachments.size());
+ printf("Size of buffer: %d\n", (int)m_bufferSize);
+}
+#endif
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.h b/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.h
new file mode 100644
index 0000000..97f0262
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ArgumentEncoder_h
+#define ArgumentEncoder_h
+
+#include "ArgumentCoder.h"
+#include "Attachment.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/TypeTraits.h>
+#include <wtf/Vector.h>
+
+namespace CoreIPC {
+
+class ArgumentEncoder;
+
+class ArgumentEncoder {
+public:
+ static PassOwnPtr<ArgumentEncoder> create(uint64_t destinationID);
+ ~ArgumentEncoder();
+
+ void encodeBytes(const uint8_t*, size_t);
+
+ void encodeBool(bool);
+ void encodeUInt32(uint32_t);
+ void encodeUInt64(uint64_t);
+ void encodeInt32(int32_t);
+ void encodeInt64(int64_t);
+ void encodeFloat(float);
+ void encodeDouble(double);
+
+ template<typename T> void encodeEnum(T t)
+ {
+ COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits);
+
+ encodeUInt64(static_cast<uint64_t>(t));
+ }
+
+ // Generic type encode function.
+ template<typename T> void encode(const T& t)
+ {
+ ArgumentCoder<T>::encode(this, t);
+ }
+
+ uint8_t* buffer() const { return m_buffer; }
+ size_t bufferSize() const { return m_bufferSize; }
+
+ void addAttachment(const Attachment&);
+ Vector<Attachment> releaseAttachments();
+
+#ifndef NDEBUG
+ void debug();
+#endif
+
+private:
+ explicit ArgumentEncoder(uint64_t destinationID);
+ uint8_t* grow(unsigned alignment, size_t size);
+
+ uint8_t* m_buffer;
+ uint8_t* m_bufferPointer;
+
+ size_t m_bufferSize;
+ size_t m_bufferCapacity;
+
+ Vector<Attachment> m_attachments;
+};
+
+template<> inline void ArgumentEncoder::encode(const bool& n)
+{
+ encodeBool(n);
+}
+
+template<> inline void ArgumentEncoder::encode(const uint32_t& n)
+{
+ encodeUInt32(n);
+}
+
+template<> inline void ArgumentEncoder::encode(const uint64_t& n)
+{
+ encodeUInt64(n);
+}
+
+template<> inline void ArgumentEncoder::encode(const int32_t& n)
+{
+ encodeInt32(n);
+}
+
+template<> inline void ArgumentEncoder::encode(const int64_t& n)
+{
+ encodeInt64(n);
+}
+
+template<> inline void ArgumentEncoder::encode(const float& n)
+{
+ encodeFloat(n);
+}
+
+template<> inline void ArgumentEncoder::encode(const double& n)
+{
+ encodeDouble(n);
+}
+
+} // namespace CoreIPC
+
+#endif // ArgumentEncoder_h
diff --git a/Source/WebKit2/Platform/CoreIPC/Arguments.h b/Source/WebKit2/Platform/CoreIPC/Arguments.h
new file mode 100644
index 0000000..ba7c7e8
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/Arguments.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Arguments_h
+#define Arguments_h
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include <wtf/TypeTraits.h>
+
+namespace CoreIPC {
+
+struct Arguments0 {
+ typedef Arguments0 ValueType;
+
+ void encode(ArgumentEncoder*) const
+ {
+ }
+
+ static bool decode(ArgumentDecoder*, Arguments0&)
+ {
+ return true;
+ }
+};
+
+inline Arguments0 In()
+{
+ return Arguments0();
+}
+
+inline Arguments0 Out()
+{
+ return Arguments0();
+}
+
+template<typename T1> struct Arguments1 {
+ typedef Arguments1<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type> ValueType;
+
+ Arguments1()
+ {
+ }
+
+ Arguments1(T1 t1)
+ : argument1(t1)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ encoder->encode(argument1);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments1& result)
+ {
+ return decoder->decode(result.argument1);
+ }
+
+ T1 argument1;
+};
+
+template<typename T1> Arguments1<const T1&> In(const T1& t1)
+{
+ return Arguments1<const T1&>(t1);
+}
+
+template<typename T1> Arguments1<T1&> Out(T1& t1)
+{
+ return Arguments1<T1&>(t1);
+}
+
+template<typename T1, typename T2> struct Arguments2 : Arguments1<T1> {
+ typedef Arguments2<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type> ValueType;
+
+ Arguments2()
+ {
+ }
+
+ Arguments2(T1 t1, T2 t2)
+ : Arguments1<T1>(t1)
+ , argument2(t2)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments1<T1>::encode(encoder);
+ encoder->encode(argument2);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments2& result)
+ {
+ if (!Arguments1<T1>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument2);
+ }
+
+ T2 argument2;
+};
+
+template<typename T1, typename T2> Arguments2<const T1&, const T2&> In(const T1& t1, const T2& t2)
+{
+ return Arguments2<const T1&, const T2&>(t1, t2);
+}
+
+template<typename T1, typename T2> Arguments2<T1&, T2&> Out(T1& t1, T2& t2)
+{
+ return Arguments2<T1&, T2&>(t1, t2);
+}
+
+template<typename T1, typename T2, typename T3> struct Arguments3 : Arguments2<T1, T2> {
+ typedef Arguments3<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T3>::Type>::Type> ValueType;
+
+ Arguments3()
+ {
+ }
+
+ Arguments3(T1 t1, T2 t2, T3 t3)
+ : Arguments2<T1, T2>(t1, t2)
+ , argument3(t3)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments2<T1, T2>::encode(encoder);
+ encoder->encode(argument3);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments3& result)
+ {
+ if (!Arguments2<T1, T2>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument3);
+ }
+
+ T3 argument3;
+};
+
+template<typename T1, typename T2, typename T3> Arguments3<const T1&, const T2&, const T3&> In(const T1& t1, const T2& t2, const T3 &t3)
+{
+ return Arguments3<const T1&, const T2&, const T3&>(t1, t2, t3);
+}
+
+template<typename T1, typename T2, typename T3> Arguments3<T1&, T2&, T3&> Out(T1& t1, T2& t2, T3& t3)
+{
+ return Arguments3<T1&, T2&, T3&>(t1, t2, t3);
+}
+
+template<typename T1, typename T2, typename T3, typename T4> struct Arguments4 : Arguments3<T1, T2, T3> {
+ typedef Arguments4<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T3>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T4>::Type>::Type> ValueType;
+
+ Arguments4()
+ {
+ }
+
+ Arguments4(T1 t1, T2 t2, T3 t3, T4 t4)
+ : Arguments3<T1, T2, T3>(t1, t2, t3)
+ , argument4(t4)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments3<T1, T2, T3>::encode(encoder);
+ encoder->encode(argument4);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments4& result)
+ {
+ if (!Arguments3<T1, T2, T3>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument4);
+ }
+
+ T4 argument4;
+};
+
+template<typename T1, typename T2, typename T3, typename T4> Arguments4<const T1&, const T2&, const T3&, const T4&> In(const T1& t1, const T2& t2, const T3 &t3, const T4& t4)
+{
+ return Arguments4<const T1&, const T2&, const T3&, const T4&>(t1, t2, t3, t4);
+}
+
+template<typename T1, typename T2, typename T3, typename T4> Arguments4<T1&, T2&, T3&, T4&> Out(T1& t1, T2& t2, T3& t3, T4& t4)
+{
+ return Arguments4<T1&, T2&, T3&, T4&>(t1, t2, t3, t4);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5> struct Arguments5 : Arguments4<T1, T2, T3, T4> {
+ typedef Arguments5<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T3>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T4>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T5>::Type>::Type> ValueType;
+
+ Arguments5()
+ {
+ }
+
+ Arguments5(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
+ : Arguments4<T1, T2, T3, T4>(t1, t2, t3, t4)
+ , argument5(t5)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments4<T1, T2, T3, T4>::encode(encoder);
+ encoder->encode(argument5);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments5& result)
+ {
+ if (!Arguments4<T1, T2, T3, T4>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument5);
+ }
+
+ T5 argument5;
+};
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5> Arguments5<const T1&, const T2&, const T3&, const T4&, const T5&> In(const T1& t1, const T2& t2, const T3 &t3, const T4& t4, const T5& t5)
+{
+ return Arguments5<const T1&, const T2&, const T3&, const T4&, const T5&>(t1, t2, t3, t4, t5);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5> Arguments5<T1&, T2&, T3&, T4&, T5&> Out(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5)
+{
+ return Arguments5<T1&, T2&, T3&, T4&, T5&>(t1, t2, t3, t4, t5);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> struct Arguments6 : Arguments5<T1, T2, T3, T4, T5> {
+ typedef Arguments6<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T3>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T4>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T5>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T6>::Type>::Type> ValueType;
+
+ Arguments6()
+ {
+ }
+
+ Arguments6(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
+ : Arguments5<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5)
+ , argument6(t6)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments5<T1, T2, T3, T4, T5>::encode(encoder);
+ encoder->encode(argument6);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments6& result)
+ {
+ if (!Arguments5<T1, T2, T3, T4, T5>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument6);
+ }
+
+ T6 argument6;
+};
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> Arguments6<const T1&, const T2&, const T3&, const T4&, const T5&, const T6&> In(const T1& t1, const T2& t2, const T3 &t3, const T4& t4, const T5& t5, const T6& t6)
+{
+ return Arguments6<const T1&, const T2&, const T3&, const T4&, const T5&, const T6&>(t1, t2, t3, t4, t5, t6);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> Arguments6<T1&, T2&, T3&, T4&, T5&, T6&> Out(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6)
+{
+ return Arguments6<T1&, T2&, T3&, T4&, T5&, T6&>(t1, t2, t3, t4, t5, t6);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> struct Arguments7 : Arguments6<T1, T2, T3, T4, T5, T6> {
+ typedef Arguments7<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T3>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T4>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T5>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T6>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T7>::Type>::Type> ValueType;
+
+ Arguments7()
+ {
+ }
+
+ Arguments7(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
+ : Arguments6<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6)
+ , argument7(t7)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments6<T1, T2, T3, T4, T5, T6>::encode(encoder);
+ encoder->encode(argument7);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments7& result)
+ {
+ if (!Arguments6<T1, T2, T3, T4, T5, T6>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument7);
+ }
+
+ T7 argument7;
+};
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> Arguments7<const T1&, const T2&, const T3&, const T4&, const T5&, const T6&, const T7&> In(const T1& t1, const T2& t2, const T3 &t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7)
+{
+ return Arguments7<const T1&, const T2&, const T3&, const T4&, const T5&, const T6&, const T7&>(t1, t2, t3, t4, t5, t6, t7);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> Arguments7<T1&, T2&, T3&, T4&, T5&, T6&, T7&> Out(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7)
+{
+ return Arguments7<T1&, T2&, T3&, T4&, T5&, T6&, T7&>(t1, t2, t3, t4, t5, t6, t7);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> struct Arguments8 : Arguments7<T1, T2, T3, T4, T5, T6, T7> {
+ typedef Arguments8<typename WTF::RemoveConst<typename WTF::RemoveReference<T1>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T2>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T3>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T4>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T5>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T6>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T7>::Type>::Type,
+ typename WTF::RemoveConst<typename WTF::RemoveReference<T8>::Type>::Type> ValueType;
+
+ Arguments8() { }
+
+ Arguments8(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
+ : Arguments7<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7)
+ , argument8(t8)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ Arguments7<T1, T2, T3, T4, T5, T6, T7>::encode(encoder);
+ encoder->encode(argument8);
+ }
+
+ static bool decode(ArgumentDecoder* decoder, Arguments8& result)
+ {
+ if (!Arguments7<T1, T2, T3, T4, T5, T6, T7>::decode(decoder, result))
+ return false;
+
+ return decoder->decode(result.argument8);
+ }
+
+ T8 argument8;
+};
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> Arguments8<const T1&, const T2&, const T3&, const T4&, const T5&, const T6&, const T7&, const T8&> In(const T1& t1, const T2& t2, const T3 &t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8)
+{
+ return Arguments8<const T1&, const T2&, const T3&, const T4&, const T5&, const T6&, const T7&, const T8&>(t1, t2, t3, t4, t5, t6, t7, t8);
+}
+
+template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> Arguments8<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&> Out(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8)
+{
+ return Arguments8<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>(t1, t2, t3, t4, t5, t6, t7, t8);
+}
+
+} // namespace CoreIPC
+
+#endif // Arguments_h
diff --git a/Source/WebKit2/Platform/CoreIPC/Attachment.cpp b/Source/WebKit2/Platform/CoreIPC/Attachment.cpp
new file mode 100644
index 0000000..c8d35f4
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/Attachment.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Attachment.h"
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+
+namespace CoreIPC {
+
+Attachment::Attachment()
+ : m_type(Uninitialized)
+{
+}
+
+#if PLATFORM(MAC)
+Attachment::Attachment(mach_port_name_t port, mach_msg_type_name_t disposition)
+ : m_type(MachPortType)
+{
+ m_port.port = port;
+ m_port.disposition = disposition;
+}
+
+Attachment::Attachment(void* address, mach_msg_size_t size, mach_msg_copy_options_t copyOptions, bool deallocate)
+ : m_type(MachOOLMemoryType)
+{
+ m_oolMemory.address = address;
+ m_oolMemory.size = size;
+ m_oolMemory.copyOptions = copyOptions;
+ m_oolMemory.deallocate = deallocate;
+}
+
+void Attachment::release()
+{
+ m_type = Uninitialized;
+}
+#endif
+
+void Attachment::encode(ArgumentEncoder* encoder) const
+{
+ encoder->addAttachment(*this);
+}
+
+bool Attachment::decode(ArgumentDecoder* decoder, Attachment& attachment)
+{
+ if (!decoder->removeAttachment(attachment))
+ return false;
+ return true;
+}
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/Attachment.h b/Source/WebKit2/Platform/CoreIPC/Attachment.h
new file mode 100644
index 0000000..55a09c9
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/Attachment.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Attachment_h
+#define Attachment_h
+
+namespace CoreIPC {
+
+class ArgumentDecoder;
+class ArgumentEncoder;
+
+class Attachment {
+public:
+ Attachment();
+
+ enum Type {
+ Uninitialized,
+#if PLATFORM(MAC)
+ MachPortType,
+ MachOOLMemoryType
+#endif
+ };
+
+#if PLATFORM(MAC)
+ Attachment(mach_port_name_t port, mach_msg_type_name_t disposition);
+ Attachment(void* address, mach_msg_size_t size, mach_msg_copy_options_t copyOptions, bool deallocate);
+#endif
+
+ Type type() const { return m_type; }
+
+#if PLATFORM(MAC)
+ void release();
+
+ // MachPortType
+ mach_port_name_t port() const { ASSERT(m_type == MachPortType); return m_port.port; }
+ mach_msg_type_name_t disposition() const { ASSERT(m_type == MachPortType); return m_port.disposition; }
+
+ // MachOOLMemoryType
+ void* address() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.address; }
+ mach_msg_size_t size() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.size; }
+ mach_msg_copy_options_t copyOptions() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.copyOptions; }
+ bool deallocate() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.deallocate; }
+#endif
+
+ void encode(ArgumentEncoder*) const;
+ static bool decode(ArgumentDecoder*, Attachment&);
+
+private:
+ Type m_type;
+
+#if PLATFORM(MAC)
+ union {
+ struct {
+ mach_port_name_t port;
+ mach_msg_type_name_t disposition;
+ } m_port;
+ struct {
+ void* address;
+ mach_msg_size_t size;
+ mach_msg_copy_options_t copyOptions;
+ bool deallocate;
+ } m_oolMemory;
+ };
+#endif
+};
+
+} // namespace CoreIPC
+
+#endif // Attachment_h
diff --git a/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.cpp b/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.cpp
new file mode 100644
index 0000000..c975dff
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "BinarySemaphore.h"
+
+namespace CoreIPC {
+
+BinarySemaphore::BinarySemaphore()
+ : m_isSet(false)
+{
+}
+
+BinarySemaphore::~BinarySemaphore()
+{
+}
+
+void BinarySemaphore::signal()
+{
+ MutexLocker locker(m_mutex);
+
+ m_isSet = true;
+ m_condition.signal();
+}
+
+bool BinarySemaphore::wait(double absoluteTime)
+{
+ MutexLocker locker(m_mutex);
+
+ bool timedOut = false;
+ while (!m_isSet) {
+ timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
+ if (timedOut)
+ return false;
+ }
+
+ // Reset the semaphore.
+ m_isSet = false;
+ return true;
+}
+
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h b/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h
new file mode 100644
index 0000000..8113236
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BinarySemaphore_h
+#define BinarySemaphore_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace CoreIPC {
+
+class BinarySemaphore {
+ WTF_MAKE_NONCOPYABLE(BinarySemaphore);
+
+public:
+ BinarySemaphore();
+ ~BinarySemaphore();
+
+ void signal();
+ bool wait(double absoluteTime);
+
+private:
+ bool m_isSet;
+
+ Mutex m_mutex;
+ ThreadCondition m_condition;
+};
+
+} // namespace CoreIPC
+
+
+#endif // BinarySemaphore_h
diff --git a/Source/WebKit2/Platform/CoreIPC/Connection.cpp b/Source/WebKit2/Platform/CoreIPC/Connection.cpp
new file mode 100644
index 0000000..da92ce4
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/Connection.cpp
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Connection.h"
+
+#include "CoreIPCMessageKinds.h"
+#include "RunLoop.h"
+#include "WorkItem.h"
+#include <wtf/CurrentTime.h>
+
+using namespace std;
+
+namespace CoreIPC {
+
+PassRefPtr<Connection> Connection::createServerConnection(Identifier identifier, Client* client, RunLoop* clientRunLoop)
+{
+ return adoptRef(new Connection(identifier, true, client, clientRunLoop));
+}
+
+PassRefPtr<Connection> Connection::createClientConnection(Identifier identifier, Client* client, RunLoop* clientRunLoop)
+{
+ return adoptRef(new Connection(identifier, false, client, clientRunLoop));
+}
+
+Connection::Connection(Identifier identifier, bool isServer, Client* client, RunLoop* clientRunLoop)
+ : m_client(client)
+ , m_isServer(isServer)
+ , m_syncRequestID(0)
+ , m_isConnected(false)
+ , m_connectionQueue("com.apple.CoreIPC.ReceiveQueue")
+ , m_clientRunLoop(clientRunLoop)
+ , m_inDispatchMessageCount(0)
+ , m_didReceiveInvalidMessage(false)
+ , m_shouldWaitForSyncReplies(true)
+{
+ ASSERT(m_client);
+
+ platformInitialize(identifier);
+}
+
+Connection::~Connection()
+{
+ ASSERT(!isValid());
+
+ m_connectionQueue.invalidate();
+}
+
+void Connection::invalidate()
+{
+ if (!isValid()) {
+ // Someone already called invalidate().
+ return;
+ }
+
+ // Reset the client.
+ m_client = 0;
+
+ m_connectionQueue.scheduleWork(WorkItem::create(this, &Connection::platformInvalidate));
+}
+
+void Connection::markCurrentlyDispatchedMessageAsInvalid()
+{
+ // This should only be called while processing a message.
+ ASSERT(m_inDispatchMessageCount > 0);
+
+ m_didReceiveInvalidMessage = true;
+}
+
+PassOwnPtr<ArgumentEncoder> Connection::createSyncMessageArgumentEncoder(uint64_t destinationID, uint64_t& syncRequestID)
+{
+ OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
+
+ // Encode the sync request ID.
+ syncRequestID = ++m_syncRequestID;
+ argumentEncoder->encode(syncRequestID);
+
+ return argumentEncoder.release();
+}
+
+bool Connection::sendMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments)
+{
+ if (!isValid())
+ return false;
+
+ MutexLocker locker(m_outgoingMessagesLock);
+ m_outgoingMessages.append(OutgoingMessage(messageID, arguments));
+
+ // FIXME: We should add a boolean flag so we don't call this when work has already been scheduled.
+ m_connectionQueue.scheduleWork(WorkItem::create(this, &Connection::sendOutgoingMessages));
+ return true;
+}
+
+bool Connection::sendSyncReply(PassOwnPtr<ArgumentEncoder> arguments)
+{
+ return sendMessage(MessageID(CoreIPCMessage::SyncMessageReply), arguments);
+}
+
+PassOwnPtr<ArgumentDecoder> Connection::waitForMessage(MessageID messageID, uint64_t destinationID, double timeout)
+{
+ // First, check if this message is already in the incoming messages queue.
+ {
+ MutexLocker locker(m_incomingMessagesLock);
+
+ for (size_t i = 0; i < m_incomingMessages.size(); ++i) {
+ const IncomingMessage& message = m_incomingMessages[i];
+
+ if (message.messageID() == messageID && message.arguments()->destinationID() == destinationID) {
+ OwnPtr<ArgumentDecoder> arguments(message.arguments());
+
+ // Erase the incoming message.
+ m_incomingMessages.remove(i);
+ return arguments.release();
+ }
+ }
+ }
+
+ double absoluteTime = currentTime() + timeout;
+
+ std::pair<unsigned, uint64_t> messageAndDestination(std::make_pair(messageID.toInt(), destinationID));
+
+ {
+ MutexLocker locker(m_waitForMessageMutex);
+
+ // We don't support having multiple clients wait for the same message.
+ ASSERT(!m_waitForMessageMap.contains(messageAndDestination));
+
+ // Insert our pending wait.
+ m_waitForMessageMap.set(messageAndDestination, 0);
+ }
+
+ // Now wait for it to be set.
+ while (true) {
+ MutexLocker locker(m_waitForMessageMutex);
+
+ HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(messageAndDestination);
+ if (it->second) {
+ OwnPtr<ArgumentDecoder> arguments(it->second);
+ m_waitForMessageMap.remove(it);
+
+ return arguments.release();
+ }
+
+ // Now we wait.
+ if (!m_waitForMessageCondition.timedWait(m_waitForMessageMutex, absoluteTime)) {
+ // We timed out, now remove the pending wait.
+ m_waitForMessageMap.remove(messageAndDestination);
+
+ break;
+ }
+ }
+
+ return PassOwnPtr<ArgumentDecoder>();
+}
+
+PassOwnPtr<ArgumentDecoder> Connection::sendSyncMessage(MessageID messageID, uint64_t syncRequestID, PassOwnPtr<ArgumentEncoder> encoder, double timeout)
+{
+ // We only allow sending sync messages from the client run loop.
+ ASSERT(RunLoop::current() == m_clientRunLoop);
+
+ if (!isValid())
+ return 0;
+
+ // Push the pending sync reply information on our stack.
+ {
+ MutexLocker locker(m_syncReplyStateMutex);
+ if (!m_shouldWaitForSyncReplies)
+ return 0;
+
+ m_pendingSyncReplies.append(PendingSyncReply(syncRequestID));
+ }
+
+ // First send the message.
+ sendMessage(messageID, encoder);
+
+ // Then wait for a reply. Waiting for a reply could involve dispatching incoming sync messages, so
+ // keep an extra reference to the connection here in case it's invalidated.
+ RefPtr<Connection> protect(this);
+ OwnPtr<ArgumentDecoder> reply = waitForSyncReply(syncRequestID, timeout);
+
+ // Finally, pop the pending sync reply information.
+ {
+ MutexLocker locker(m_syncReplyStateMutex);
+ ASSERT(m_pendingSyncReplies.last().syncRequestID == syncRequestID);
+ m_pendingSyncReplies.removeLast();
+
+ if (m_pendingSyncReplies.isEmpty()) {
+ // This was the bottom-most sendSyncMessage call in the stack. If we have any pending incoming
+ // sync messages, they need to be dispatched.
+ if (!m_syncMessagesReceivedWhileWaitingForSyncReply.isEmpty()) {
+ // Add the messages.
+ MutexLocker locker(m_incomingMessagesLock);
+ m_incomingMessages.append(m_syncMessagesReceivedWhileWaitingForSyncReply);
+ m_syncMessagesReceivedWhileWaitingForSyncReply.clear();
+
+ // Schedule for the messages to be sent.
+ m_clientRunLoop->scheduleWork(WorkItem::create(this, &Connection::dispatchMessages));
+ }
+ }
+ }
+
+ return reply.release();
+}
+
+PassOwnPtr<ArgumentDecoder> Connection::waitForSyncReply(uint64_t syncRequestID, double timeout)
+{
+ double absoluteTime = currentTime() + timeout;
+
+ bool timedOut = false;
+ while (!timedOut) {
+ {
+ MutexLocker locker(m_syncReplyStateMutex);
+
+ // First, check if we have any incoming sync messages that we need to process.
+ Vector<IncomingMessage> syncMessagesReceivedWhileWaitingForSyncReply;
+ m_syncMessagesReceivedWhileWaitingForSyncReply.swap(syncMessagesReceivedWhileWaitingForSyncReply);
+
+ if (!syncMessagesReceivedWhileWaitingForSyncReply.isEmpty()) {
+ // Make sure to unlock the mutex here because we're calling out to client code which could in turn send
+ // another sync message and we don't want that to deadlock.
+ m_syncReplyStateMutex.unlock();
+
+ for (size_t i = 0; i < syncMessagesReceivedWhileWaitingForSyncReply.size(); ++i) {
+ IncomingMessage& message = syncMessagesReceivedWhileWaitingForSyncReply[i];
+ OwnPtr<ArgumentDecoder> arguments = message.releaseArguments();
+
+ dispatchSyncMessage(message.messageID(), arguments.get());
+ }
+ m_syncReplyStateMutex.lock();
+ }
+
+ // Second, check if there is a sync reply at the top of the stack.
+ ASSERT(!m_pendingSyncReplies.isEmpty());
+
+ PendingSyncReply& pendingSyncReply = m_pendingSyncReplies.last();
+ ASSERT(pendingSyncReply.syncRequestID == syncRequestID);
+
+ // We found the sync reply, or the connection was closed.
+ if (pendingSyncReply.didReceiveReply || !m_shouldWaitForSyncReplies)
+ return pendingSyncReply.releaseReplyDecoder();
+ }
+
+ // We didn't find a sync reply yet, keep waiting.
+ timedOut = !m_waitForSyncReplySemaphore.wait(absoluteTime);
+ }
+
+ // We timed out.
+ return 0;
+}
+
+void Connection::processIncomingMessage(MessageID messageID, PassOwnPtr<ArgumentDecoder> arguments)
+{
+ // Check if this is a sync reply.
+ if (messageID == MessageID(CoreIPCMessage::SyncMessageReply)) {
+ MutexLocker locker(m_syncReplyStateMutex);
+ ASSERT(!m_pendingSyncReplies.isEmpty());
+
+ PendingSyncReply& pendingSyncReply = m_pendingSyncReplies.last();
+ ASSERT(pendingSyncReply.syncRequestID == arguments->destinationID());
+
+ pendingSyncReply.replyDecoder = arguments.leakPtr();
+ pendingSyncReply.didReceiveReply = true;
+
+ m_waitForSyncReplySemaphore.signal();
+ return;
+ }
+
+ // Check if this is a sync message. If it is, and we're waiting for a sync reply this message
+ // needs to be dispatched. If we don't we'll end up with a deadlock where both sync message senders are
+ // stuck waiting for a reply.
+ if (messageID.isSync()) {
+ MutexLocker locker(m_syncReplyStateMutex);
+ if (!m_pendingSyncReplies.isEmpty()) {
+ m_syncMessagesReceivedWhileWaitingForSyncReply.append(IncomingMessage(messageID, arguments));
+
+ // The message has been added, now wake up the client thread.
+ m_waitForSyncReplySemaphore.signal();
+ return;
+ }
+ }
+
+ // Check if we're waiting for this message.
+ {
+ MutexLocker locker(m_waitForMessageMutex);
+
+ HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(std::make_pair(messageID.toInt(), arguments->destinationID()));
+ if (it != m_waitForMessageMap.end()) {
+ it->second = arguments.leakPtr();
+
+ m_waitForMessageCondition.signal();
+ return;
+ }
+ }
+
+ MutexLocker locker(m_incomingMessagesLock);
+ m_incomingMessages.append(IncomingMessage(messageID, arguments));
+
+ m_clientRunLoop->scheduleWork(WorkItem::create(this, &Connection::dispatchMessages));
+}
+
+void Connection::connectionDidClose()
+{
+ // The connection is now invalid.
+ platformInvalidate();
+
+ {
+ MutexLocker locker(m_syncReplyStateMutex);
+
+ ASSERT(m_shouldWaitForSyncReplies);
+ m_shouldWaitForSyncReplies = false;
+
+ if (!m_pendingSyncReplies.isEmpty())
+ m_waitForSyncReplySemaphore.signal();
+ }
+
+ m_client->didCloseOnConnectionWorkQueue(&m_connectionQueue, this);
+
+ m_clientRunLoop->scheduleWork(WorkItem::create(this, &Connection::dispatchConnectionDidClose));
+}
+
+void Connection::dispatchConnectionDidClose()
+{
+ // If the connection has been explicitly invalidated before dispatchConnectionDidClose was called,
+ // then the client will be null here.
+ if (!m_client)
+ return;
+
+
+ // Because we define a connection as being "valid" based on wheter it has a null client, we null out
+ // the client before calling didClose here. Otherwise, sendSync will try to send a message to the connection and
+ // will then wait indefinitely for a reply.
+ Client* client = m_client;
+ m_client = 0;
+
+ client->didClose(this);
+}
+
+bool Connection::canSendOutgoingMessages() const
+{
+ return m_isConnected && platformCanSendOutgoingMessages();
+}
+
+void Connection::sendOutgoingMessages()
+{
+ if (!canSendOutgoingMessages())
+ return;
+
+ while (true) {
+ OutgoingMessage message;
+ {
+ MutexLocker locker(m_outgoingMessagesLock);
+ if (m_outgoingMessages.isEmpty())
+ break;
+ message = m_outgoingMessages.takeFirst();
+ }
+
+ if (!sendOutgoingMessage(message.messageID(), adoptPtr(message.arguments())))
+ break;
+ }
+}
+
+void Connection::dispatchSyncMessage(MessageID messageID, ArgumentDecoder* arguments)
+{
+ ASSERT(messageID.isSync());
+
+ // Decode the sync request ID.
+ uint64_t syncRequestID = 0;
+
+ if (!arguments->decodeUInt64(syncRequestID) || !syncRequestID) {
+ // We received an invalid sync message.
+ arguments->markInvalid();
+ return;
+ }
+
+ // Create our reply encoder.
+ ArgumentEncoder* replyEncoder = ArgumentEncoder::create(syncRequestID).leakPtr();
+
+ // Hand off both the decoder and encoder to the client..
+ SyncReplyMode syncReplyMode = m_client->didReceiveSyncMessage(this, messageID, arguments, replyEncoder);
+
+ // FIXME: If the message was invalid, we should send back a SyncMessageError.
+ ASSERT(!arguments->isInvalid());
+
+ if (syncReplyMode == ManualReply) {
+ // The client will take ownership of the reply encoder and send it at some point in the future.
+ // We won't do anything here.
+ return;
+ }
+
+ // Send the reply.
+ sendSyncReply(replyEncoder);
+}
+
+void Connection::dispatchMessages()
+{
+ Vector<IncomingMessage> incomingMessages;
+
+ {
+ MutexLocker locker(m_incomingMessagesLock);
+ m_incomingMessages.swap(incomingMessages);
+ }
+
+ // Dispatch messages.
+ for (size_t i = 0; i < incomingMessages.size(); ++i) {
+ // If someone calls invalidate while we're invalidating messages, we should stop.
+ if (!m_client)
+ return;
+
+ IncomingMessage& message = incomingMessages[i];
+ OwnPtr<ArgumentDecoder> arguments = message.releaseArguments();
+
+ m_inDispatchMessageCount++;
+
+ bool oldDidReceiveInvalidMessage = m_didReceiveInvalidMessage;
+ m_didReceiveInvalidMessage = false;
+
+ if (message.messageID().isSync())
+ dispatchSyncMessage(message.messageID(), arguments.get());
+ else
+ m_client->didReceiveMessage(this, message.messageID(), arguments.get());
+
+ m_didReceiveInvalidMessage |= arguments->isInvalid();
+ m_inDispatchMessageCount--;
+
+ if (m_didReceiveInvalidMessage)
+ m_client->didReceiveInvalidMessage(this, message.messageID());
+
+ m_didReceiveInvalidMessage = oldDidReceiveInvalidMessage;
+ }
+}
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/Connection.h b/Source/WebKit2/Platform/CoreIPC/Connection.h
new file mode 100644
index 0000000..b7e5b0f
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/Connection.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Connection_h
+#define Connection_h
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include "Arguments.h"
+#include "BinarySemaphore.h"
+#include "MessageID.h"
+#include "WorkQueue.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Threading.h>
+
+#if PLATFORM(MAC)
+#include <mach/mach_port.h>
+#elif PLATFORM(WIN)
+#include <string>
+#elif PLATFORM(QT)
+#include <QString>
+class QLocalServer;
+class QLocalSocket;
+#endif
+
+class RunLoop;
+
+namespace CoreIPC {
+
+class MessageID;
+
+enum SyncReplyMode {
+ AutomaticReply,
+ ManualReply
+};
+
+#define MESSAGE_CHECK_BASE(assertion, connection) do \
+ if (!(assertion)) { \
+ ASSERT(assertion); \
+ (connection)->markCurrentlyDispatchedMessageAsInvalid(); \
+ return; \
+ } \
+while (0)
+
+class Connection : public ThreadSafeShared<Connection> {
+public:
+ class MessageReceiver {
+ protected:
+ virtual ~MessageReceiver() { }
+
+ public:
+ virtual void didReceiveMessage(Connection*, MessageID, ArgumentDecoder*) = 0;
+ virtual SyncReplyMode didReceiveSyncMessage(Connection*, MessageID, ArgumentDecoder*, ArgumentEncoder*) { ASSERT_NOT_REACHED(); return AutomaticReply; }
+ };
+
+ class Client : public MessageReceiver {
+ protected:
+ virtual ~Client() { }
+
+ public:
+ virtual void didClose(Connection*) = 0;
+ virtual void didReceiveInvalidMessage(Connection*, MessageID) = 0;
+
+ // Called on the connection work queue when the connection is closed, before
+ // didCall is called on the client thread.
+ virtual void didCloseOnConnectionWorkQueue(WorkQueue*, Connection*) { }
+ };
+
+#if PLATFORM(MAC)
+ typedef mach_port_t Identifier;
+#elif PLATFORM(WIN)
+ typedef HANDLE Identifier;
+ static bool createServerAndClientIdentifiers(Identifier& serverIdentifier, Identifier& clientIdentifier);
+#elif PLATFORM(QT)
+ typedef const QString Identifier;
+#elif PLATFORM(GTK)
+ typedef int Identifier;
+#endif
+
+ static PassRefPtr<Connection> createServerConnection(Identifier, Client*, RunLoop* clientRunLoop);
+ static PassRefPtr<Connection> createClientConnection(Identifier, Client*, RunLoop* clientRunLoop);
+ ~Connection();
+
+#if PLATFORM(MAC)
+ void setShouldCloseConnectionOnMachExceptions();
+#endif
+
+ bool open();
+ void invalidate();
+ void markCurrentlyDispatchedMessageAsInvalid();
+
+ // FIXME: This variant of send is deprecated, all clients should move to the overload that takes a message.
+ template<typename E, typename T> bool send(E messageID, uint64_t destinationID, const T& arguments);
+
+ template<typename T> bool send(const T& message, uint64_t destinationID);
+
+ static const unsigned long long NoTimeout = 10000000000ULL;
+ // FIXME: This variant of sendSync is deprecated, all clients should move to the overload that takes a message.
+ template<typename E, typename T, typename U> bool sendSync(E messageID, uint64_t destinationID, const T& arguments, const U& reply, double timeout = NoTimeout);
+
+ template<typename T> bool sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout = NoTimeout);
+
+ template<typename E> PassOwnPtr<ArgumentDecoder> waitFor(E messageID, uint64_t destinationID, double timeout);
+
+ PassOwnPtr<ArgumentEncoder> createSyncMessageArgumentEncoder(uint64_t destinationID, uint64_t& syncRequestID);
+ bool sendMessage(MessageID, PassOwnPtr<ArgumentEncoder>);
+ bool sendSyncReply(PassOwnPtr<ArgumentEncoder>);
+
+private:
+ template<typename T> class Message {
+ public:
+ Message()
+ : m_arguments(0)
+ {
+ }
+
+ Message(MessageID messageID, PassOwnPtr<T> arguments)
+ : m_messageID(messageID)
+ , m_arguments(arguments.leakPtr())
+ {
+ }
+
+ MessageID messageID() const { return m_messageID; }
+ T* arguments() const { return m_arguments; }
+
+ PassOwnPtr<T> releaseArguments()
+ {
+ T* arguments = m_arguments;
+ m_arguments = 0;
+
+ return arguments;
+ }
+
+ private:
+ MessageID m_messageID;
+ T* m_arguments;
+ };
+
+public:
+ typedef Message<ArgumentEncoder> OutgoingMessage;
+
+private:
+ Connection(Identifier, bool isServer, Client*, RunLoop* clientRunLoop);
+ void platformInitialize(Identifier);
+ void platformInvalidate();
+
+ bool isValid() const { return m_client; }
+
+ PassOwnPtr<ArgumentDecoder> waitForMessage(MessageID, uint64_t destinationID, double timeout);
+
+ PassOwnPtr<ArgumentDecoder> sendSyncMessage(MessageID, uint64_t syncRequestID, PassOwnPtr<ArgumentEncoder>, double timeout);
+ PassOwnPtr<ArgumentDecoder> waitForSyncReply(uint64_t syncRequestID, double timeout);
+
+ // Called on the connection work queue.
+ void processIncomingMessage(MessageID, PassOwnPtr<ArgumentDecoder>);
+ bool canSendOutgoingMessages() const;
+ bool platformCanSendOutgoingMessages() const;
+ void sendOutgoingMessages();
+ bool sendOutgoingMessage(MessageID, PassOwnPtr<ArgumentEncoder>);
+ void connectionDidClose();
+
+ // Called on the listener thread.
+ void dispatchConnectionDidClose();
+ void dispatchMessages();
+ void dispatchSyncMessage(MessageID, ArgumentDecoder*);
+
+ Client* m_client;
+ bool m_isServer;
+ uint64_t m_syncRequestID;
+
+ bool m_isConnected;
+ WorkQueue m_connectionQueue;
+ RunLoop* m_clientRunLoop;
+
+ uint32_t m_inDispatchMessageCount;
+ bool m_didReceiveInvalidMessage;
+
+ // Incoming messages.
+ typedef Message<ArgumentDecoder> IncomingMessage;
+
+ Mutex m_incomingMessagesLock;
+ Vector<IncomingMessage> m_incomingMessages;
+
+ // Outgoing messages.
+ Mutex m_outgoingMessagesLock;
+ Deque<OutgoingMessage> m_outgoingMessages;
+
+ ThreadCondition m_waitForMessageCondition;
+ Mutex m_waitForMessageMutex;
+ HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*> m_waitForMessageMap;
+
+ // Represents a sync request for which we're waiting on a reply.
+ struct PendingSyncReply {
+ // The request ID.
+ uint64_t syncRequestID;
+
+ // The reply decoder, will be null if there was an error processing the sync
+ // message on the other side.
+ ArgumentDecoder* replyDecoder;
+
+ // Will be set to true once a reply has been received or an error occurred.
+ bool didReceiveReply;
+
+ PendingSyncReply()
+ : syncRequestID(0)
+ , replyDecoder(0)
+ , didReceiveReply(false)
+ {
+ }
+
+ explicit PendingSyncReply(uint64_t syncRequestID)
+ : syncRequestID(syncRequestID)
+ , replyDecoder(0)
+ , didReceiveReply(0)
+ {
+ }
+
+ PassOwnPtr<ArgumentDecoder> releaseReplyDecoder()
+ {
+ OwnPtr<ArgumentDecoder> reply = adoptPtr(replyDecoder);
+ replyDecoder = 0;
+
+ return reply.release();
+ }
+ };
+
+ BinarySemaphore m_waitForSyncReplySemaphore;
+
+ Mutex m_syncReplyStateMutex;
+ bool m_shouldWaitForSyncReplies;
+ Vector<PendingSyncReply> m_pendingSyncReplies;
+ Vector<IncomingMessage> m_syncMessagesReceivedWhileWaitingForSyncReply;
+
+#if PLATFORM(MAC)
+ // Called on the connection queue.
+ void receiveSourceEventHandler();
+ void initializeDeadNameSource();
+ void exceptionSourceEventHandler();
+
+ mach_port_t m_sendPort;
+ mach_port_t m_receivePort;
+
+ // If setShouldCloseConnectionOnMachExceptions has been called, this has
+ // the exception port that exceptions from the other end will be sent on.
+ mach_port_t m_exceptionPort;
+
+#elif PLATFORM(WIN)
+ // Called on the connection queue.
+ void readEventHandler();
+ void writeEventHandler();
+
+ Vector<uint8_t> m_readBuffer;
+ OVERLAPPED m_readState;
+ OwnPtr<ArgumentEncoder> m_pendingWriteArguments;
+ OVERLAPPED m_writeState;
+ HANDLE m_connectionPipe;
+#elif PLATFORM(QT)
+ // Called on the connection queue.
+ void readyReadHandler();
+
+ Vector<uint8_t> m_readBuffer;
+ size_t m_currentMessageSize;
+ QLocalSocket* m_socket;
+ QString m_serverName;
+#elif PLATFORM(GTK)
+ void readEventHandler();
+ void processCompletedMessage();
+ bool messageProcessingCompleted() { return !m_currentMessageSize; }
+
+ int m_socket;
+ Vector<uint8_t> m_readBuffer;
+ size_t m_currentMessageSize;
+ size_t m_pendingBytes;
+#endif
+};
+
+template<typename E, typename T>
+bool Connection::send(E messageID, uint64_t destinationID, const T& arguments)
+{
+ OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
+ argumentEncoder->encode(arguments);
+
+ return sendMessage(MessageID(messageID), argumentEncoder.release());
+}
+
+template<typename T> bool Connection::send(const T& message, uint64_t destinationID)
+{
+ OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
+ argumentEncoder->encode(message);
+
+ return sendMessage(MessageID(T::messageID), argumentEncoder.release());
+}
+
+template<typename E, typename T, typename U>
+inline bool Connection::sendSync(E messageID, uint64_t destinationID, const T& arguments, const U& reply, double timeout)
+{
+ uint64_t syncRequestID = 0;
+ OwnPtr<ArgumentEncoder> argumentEncoder = createSyncMessageArgumentEncoder(destinationID, syncRequestID);
+
+ // Encode the input arguments.
+ argumentEncoder->encode(arguments);
+
+ // Now send the message and wait for a reply.
+ OwnPtr<ArgumentDecoder> replyDecoder = sendSyncMessage(MessageID(messageID, MessageID::SyncMessage), syncRequestID, argumentEncoder.release(), timeout);
+ if (!replyDecoder)
+ return false;
+
+ // Decode the reply.
+ return replyDecoder->decode(const_cast<U&>(reply));
+}
+
+template<typename T> bool Connection::sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout)
+{
+ uint64_t syncRequestID = 0;
+ OwnPtr<ArgumentEncoder> argumentEncoder = createSyncMessageArgumentEncoder(destinationID, syncRequestID);
+
+ // Encode the rest of the input arguments.
+ argumentEncoder->encode(message);
+
+ // Now send the message and wait for a reply.
+ OwnPtr<ArgumentDecoder> replyDecoder = sendSyncMessage(MessageID(T::messageID, MessageID::SyncMessage), syncRequestID, argumentEncoder.release(), timeout);
+ if (!replyDecoder)
+ return false;
+
+ // Decode the reply.
+ return replyDecoder->decode(const_cast<typename T::Reply&>(reply));
+}
+
+template<typename E> inline PassOwnPtr<ArgumentDecoder> Connection::waitFor(E messageID, uint64_t destinationID, double timeout)
+{
+ return waitForMessage(MessageID(messageID), destinationID, timeout);
+}
+
+} // namespace CoreIPC
+
+#endif // Connection_h
diff --git a/Source/WebKit2/Platform/CoreIPC/CoreIPCMessageKinds.h b/Source/WebKit2/Platform/CoreIPC/CoreIPCMessageKinds.h
new file mode 100644
index 0000000..b2a2813
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/CoreIPCMessageKinds.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CoreIPCMessageKinds_h
+#define CoreIPCMessageKinds_h
+
+#include "MessageID.h"
+
+namespace CoreIPC {
+
+namespace CoreIPCMessage {
+
+enum Kind {
+ InitializeConnection,
+ SyncMessageReply,
+#if PLATFORM(MAC)
+ SetExceptionPort,
+#endif
+};
+
+} // namespace CoreIPCMessage
+
+template<> struct MessageKindTraits<CoreIPCMessage::Kind> {
+ static const MessageClass messageClass = MessageClassCoreIPC;
+};
+
+} // namespace CoreIPC
+
+#endif // CoreIPCMessageKinds_h
diff --git a/Source/WebKit2/Platform/CoreIPC/DataReference.cpp b/Source/WebKit2/Platform/CoreIPC/DataReference.cpp
new file mode 100644
index 0000000..308fd6e
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/DataReference.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DataReference.h"
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+
+namespace CoreIPC {
+
+void DataReference::encode(ArgumentEncoder* encoder) const
+{
+ encoder->encodeBytes(m_data, m_size);
+}
+
+bool DataReference::decode(ArgumentDecoder* decoder, DataReference& dataReference)
+{
+ return decoder->decodeBytes(dataReference);
+}
+
+} // namespace CoreIPC
+
+
diff --git a/Source/WebKit2/Platform/CoreIPC/DataReference.h b/Source/WebKit2/Platform/CoreIPC/DataReference.h
new file mode 100644
index 0000000..1657bea
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/DataReference.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DataReference_h
+#define DataReference_h
+
+#include <inttypes.h>
+
+namespace CoreIPC {
+
+class ArgumentDecoder;
+class ArgumentEncoder;
+
+class DataReference {
+public:
+ DataReference()
+ : m_data(0)
+ , m_size(0)
+ {
+ }
+
+ DataReference(const uint8_t* data, size_t size)
+ : m_data(data)
+ , m_size(size)
+ {
+ }
+
+ bool isEmpty() const { return size() == 0; }
+
+ size_t size() const { return m_size; }
+ const uint8_t* data() const
+ {
+ if (isEmpty())
+ return 0;
+ return m_data;
+ }
+
+ void encode(ArgumentEncoder* encoder) const;
+ static bool decode(ArgumentDecoder* decoder, DataReference& dataReference);
+
+private:
+ const uint8_t* m_data;
+ size_t m_size;
+};
+
+} // namespace CoreIPC
+
+#endif // DataReference_h
diff --git a/Source/WebKit2/Platform/CoreIPC/HandleMessage.h b/Source/WebKit2/Platform/CoreIPC/HandleMessage.h
new file mode 100644
index 0000000..534e825
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/HandleMessage.h
@@ -0,0 +1,248 @@
+#ifndef HandleMessage_h
+#define HandleMessage_h
+
+#include "Arguments.h"
+
+namespace CoreIPC {
+
+// Dispatch functions with no reply arguments.
+
+template<typename C, typename MF>
+void callMemberFunction(const Arguments0&, C* object, MF function)
+{
+ (object->*function)();
+}
+
+template<typename C, typename MF, typename P1>
+void callMemberFunction(const Arguments1<P1>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename P2>
+void callMemberFunction(const Arguments2<P1, P2>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3>
+void callMemberFunction(const Arguments3<P1, P2, P3>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4>
+void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5>
+void callMemberFunction(const Arguments5<P1, P2, P3, P4, P5>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
+void callMemberFunction(const Arguments6<P1, P2, P3, P4, P5, P6>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, args.argument6);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
+void callMemberFunction(const Arguments7<P1, P2, P3, P4, P5, P6, P7>& args, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, args.argument6, args.argument7);
+}
+
+// Dispatch functions with reply arguments.
+
+template<typename C, typename MF>
+void callMemberFunction(const Arguments0&, Arguments0&, C* object, MF function)
+{
+ (object->*function)();
+}
+
+template<typename C, typename MF, typename R1>
+void callMemberFunction(const Arguments0&, Arguments1<R1>& replyArgs, C* object, MF function)
+{
+ (object->*function)(replyArgs.argument1);
+}
+
+template<typename C, typename MF, typename R1, typename R2>
+void callMemberFunction(const Arguments0&, Arguments2<R1, R2>& replyArgs, C* object, MF function)
+{
+ (object->*function)(replyArgs.argument1, replyArgs.argument2);
+}
+
+template<typename C, typename MF, typename P1>
+void callMemberFunction(const Arguments1<P1>& args, Arguments0&, C* object, MF function)
+{
+ (object->*function)(args.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename R1>
+void callMemberFunction(const Arguments1<P1>& args, Arguments1<R1>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, replyArgs.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename R1, typename R2>
+void callMemberFunction(const Arguments1<P1>& args, Arguments2<R1, R2>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, replyArgs.argument1, replyArgs.argument2);
+}
+
+template<typename C, typename MF, typename P1, typename R1, typename R2, typename R3>
+void callMemberFunction(const Arguments1<P1>& args, Arguments3<R1, R2, R3>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, replyArgs.argument1, replyArgs.argument2, replyArgs.argument3);
+}
+
+template<typename C, typename MF, typename P1, typename P2>
+void callMemberFunction(const Arguments2<P1, P2>& args, Arguments0&, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2);
+}
+
+template<typename C, typename MF, typename P1, typename R1, typename R2, typename R3, typename R4>
+void callMemberFunction(const Arguments1<P1>& args, Arguments4<R1, R2, R3, R4>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, replyArgs.argument1, replyArgs.argument2, replyArgs.argument3, replyArgs.argument4);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename R1>
+void callMemberFunction(const Arguments2<P1, P2>& args, Arguments1<R1>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, replyArgs.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename R1, typename R2>
+void callMemberFunction(const Arguments2<P1, P2>& args, Arguments2<R1, R2>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, replyArgs.argument1, replyArgs.argument2);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename R1>
+void callMemberFunction(const Arguments3<P1, P2, P3>& args, Arguments1<R1>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, replyArgs.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename R1, typename R2>
+void callMemberFunction(const Arguments3<P1, P2, P3>& args, Arguments2<R1, R2>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, replyArgs.argument1, replyArgs.argument2);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename R1>
+void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, Arguments1<R1>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, replyArgs.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename R1>
+void callMemberFunction(const Arguments7<P1, P2, P3, P4, P5, P6, P7>& args, Arguments1<R1>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, args.argument6, args.argument7, replyArgs.argument1);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename R1, typename R2>
+void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, Arguments2<R1, R2>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, replyArgs.argument1, replyArgs.argument2);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename R1, typename R2>
+void callMemberFunction(const Arguments5<P1, P2, P3, P4, P5>& args, Arguments2<R1, R2>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, replyArgs.argument1, replyArgs.argument2);
+}
+
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename R1, typename R2, typename R3>
+void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, Arguments3<R1, R2, R3>& replyArgs, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, replyArgs.argument1, replyArgs.argument2, replyArgs.argument3);
+}
+
+// Variadic dispatch functions.
+
+template<typename C, typename MF>
+void callMemberFunction(const Arguments0&, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(argumentDecoder);
+}
+
+template<typename C, typename MF, typename P1>
+void callMemberFunction(const Arguments1<P1>& args, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(args.argument1, argumentDecoder);
+}
+
+template<typename C, typename MF, typename P1, typename P2>
+void callMemberFunction(const Arguments2<P1, P2>& args, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, argumentDecoder);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3>
+void callMemberFunction(const Arguments3<P1, P2, P3>& args, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, argumentDecoder);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4>
+void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, argumentDecoder);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5>
+void callMemberFunction(const Arguments5<P1, P2, P3, P4, P5>& args, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, argumentDecoder);
+}
+
+template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
+void callMemberFunction(const Arguments6<P1, P2, P3, P4, P5, P6>& args, ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, args.argument6, argumentDecoder);
+}
+
+
+// Main dispatch functions
+
+template<typename T, typename C, typename MF>
+void handleMessage(ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ typename T::DecodeType::ValueType arguments;
+ if (!argumentDecoder->decode(arguments))
+ return;
+ callMemberFunction(arguments, object, function);
+}
+
+template<typename T, typename C, typename MF>
+void handleMessage(ArgumentDecoder* argumentDecoder, ArgumentEncoder* replyEncoder, C* object, MF function)
+{
+ typename T::DecodeType::ValueType arguments;
+ if (!argumentDecoder->decode(arguments))
+ return;
+
+ typename T::Reply::ValueType replyArguments;
+ callMemberFunction(arguments, replyArguments, object, function);
+ replyEncoder->encode(replyArguments);
+}
+
+template<typename T, typename C, typename MF>
+void handleMessageVariadic(ArgumentDecoder* argumentDecoder, C* object, MF function)
+{
+ typename T::DecodeType::ValueType arguments;
+ if (!argumentDecoder->decode(arguments))
+ return;
+ callMemberFunction(arguments, argumentDecoder, object, function);
+}
+
+} // namespace CoreIPC
+
+#endif // HandleMessage_h
diff --git a/Source/WebKit2/Platform/CoreIPC/MessageID.h b/Source/WebKit2/Platform/CoreIPC/MessageID.h
new file mode 100644
index 0000000..724302c
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/MessageID.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MessageID_h
+#define MessageID_h
+
+namespace CoreIPC {
+
+enum MessageClass {
+ MessageClassReserved = 0,
+
+ // Messages sent by Core IPC.
+ MessageClassCoreIPC,
+
+ // Messages sent by the UI process to the web process.
+ MessageClassAuthenticationManager,
+ MessageClassDrawingArea,
+ MessageClassDrawingAreaLegacy,
+ MessageClassInjectedBundle,
+ MessageClassWebDatabaseManager,
+ MessageClassWebGeolocationManagerProxy,
+ MessageClassWebInspector,
+ MessageClassWebPage,
+ MessageClassWebProcess,
+
+ // Messages sent by the web process to the UI process.
+ MessageClassDownloadProxy,
+ MessageClassDrawingAreaProxy,
+ MessageClassDrawingAreaProxyLegacy,
+ MessageClassWebContext,
+ MessageClassWebContextLegacy,
+ MessageClassWebDatabaseManagerProxy,
+ MessageClassWebGeolocationManager,
+ MessageClassWebInspectorProxy,
+ MessageClassWebPageProxy,
+ MessageClassWebProcessProxy,
+ MessageClassWebProcessProxyLegacy,
+
+ // Messages sent by the UI process to the plug-in process.
+ MessageClassPluginProcess,
+
+ // Messages sent by the plug-in process to the UI process.
+ MessageClassPluginProcessProxy,
+
+ // Messages sent by the web process to the plug-in process.
+ MessageClassWebProcessConnection,
+ MessageClassPluginControllerProxy,
+
+ // Messages sent by the plug-in process to the web process.
+ MessageClassPluginProxy,
+
+ // NPObject messages sent by both the plug-in process and the web process.
+ MessageClassNPObjectMessageReceiver,
+};
+
+template<typename> struct MessageKindTraits { };
+
+
+/*
+ MessageID Layout (the most significant bit is reserved and therefore always zero)
+
+ ---------
+ | Flags | 7 bits
+ |-------|
+ | Class | 8 bits
+ |-------|
+ | Msg | 16 bits
+ | Kind |
+ ---------
+*/
+
+class MessageID {
+public:
+ enum Flags {
+ SyncMessage = 1 << 0,
+ };
+
+ MessageID()
+ : m_messageID(0)
+ {
+ }
+
+ template <typename EnumType>
+ explicit MessageID(EnumType messageKind, unsigned char flags = 0)
+ : m_messageID(stripMostSignificantBit(flags << 24 | (MessageKindTraits<EnumType>::messageClass) << 16 | messageKind))
+ {
+ }
+
+ template <typename EnumType>
+ EnumType get() const
+ {
+ ASSERT(getClass() == MessageKindTraits<EnumType>::messageClass);
+ return static_cast<EnumType>(m_messageID & 0xffff);
+ }
+
+ template <MessageClass K>
+ bool is() const
+ {
+ return getClass() == K;
+ }
+
+ template <typename EnumType>
+ bool operator==(EnumType messageKind) const
+ {
+ return m_messageID == MessageID(messageKind).m_messageID;
+ }
+
+ static MessageID fromInt(unsigned i)
+ {
+ MessageID messageID;
+ messageID.m_messageID = stripMostSignificantBit(i);
+
+ return messageID;
+ }
+
+ unsigned toInt() const { return m_messageID; }
+
+ bool isSync() const { return getFlags() & SyncMessage; }
+
+private:
+ static inline unsigned stripMostSignificantBit(unsigned value)
+ {
+ return value & 0x7fffffff;
+ }
+
+ unsigned char getFlags() const { return (m_messageID & 0xff000000) >> 24; }
+ unsigned char getClass() const { return (m_messageID & 0x00ff0000) >> 16; }
+
+ unsigned m_messageID;
+};
+
+} // namespace CoreIPC
+
+#endif // MessageID_h
diff --git a/Source/WebKit2/Platform/CoreIPC/MessageSender.h b/Source/WebKit2/Platform/CoreIPC/MessageSender.h
new file mode 100644
index 0000000..e2ba0b5
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/MessageSender.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MessageSender_h
+#define MessageSender_h
+
+#include <wtf/Assertions.h>
+#include "Connection.h"
+
+namespace CoreIPC {
+
+template<typename T> class MessageSender {
+public:
+ template<typename U> bool send(const U& message)
+ {
+ return send(message, static_cast<T*>(this)->destinationID());
+ }
+
+ template<typename U> bool send(const U& message, uint64_t destinationID)
+ {
+ OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
+ argumentEncoder->encode(message);
+
+ return static_cast<T*>(this)->sendMessage(MessageID(U::messageID), argumentEncoder.release());
+ }
+
+ bool sendMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> argumentEncoder)
+ {
+ Connection* connection = static_cast<T*>(this)->connection();
+ ASSERT(connection);
+
+ return connection->sendMessage(messageID, argumentEncoder);
+ }
+
+ template<typename U> bool sendSync(const U& message, const typename U::Reply& reply, double timeout = Connection::NoTimeout)
+ {
+ return sendSync(message, reply, static_cast<T*>(this)->destinationID(), timeout);
+ }
+
+ template<typename U> bool sendSync(const U& message, const typename U::Reply& reply, uint64_t destinationID, double timeout = Connection::NoTimeout)
+ {
+ Connection* connection = static_cast<T*>(this)->connection();
+ ASSERT(connection);
+
+ return connection->sendSync(message, reply, destinationID, timeout);
+ }
+};
+
+} // namespace CoreIPC
+
+#endif // MessageSender_h
diff --git a/Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp b/Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp
new file mode 100644
index 0000000..65b1254
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Connection.h"
+
+#include "ArgumentEncoder.h"
+#include "WorkItem.h"
+#include <errno.h>
+#include <glib.h>
+#include <sys/fcntl.h>
+
+using namespace std;
+
+namespace CoreIPC {
+
+static const size_t initialMessageBufferSize = 4096;
+
+static int readBytesFromSocket(int fileDescriptor, uint8_t* ptr, size_t length)
+{
+ ASSERT(fileDescriptor > 0);
+ ASSERT(buffer);
+ ASSERT(length > 0);
+
+ ssize_t numberOfBytesRead = 0;
+ size_t pendingBytesToRead = length;
+ uint8_t* buffer = ptr;
+
+ while (pendingBytesToRead > 0) {
+ if ((numberOfBytesRead = read(fileDescriptor, buffer, pendingBytesToRead)) < 0) {
+ if (errno == EINTR)
+ numberOfBytesRead = 0;
+ else if (errno == EAGAIN || errno == EWOULDBLOCK)
+ break;
+ else
+ return 0;
+ } else if (!numberOfBytesRead)
+ break;
+
+ buffer += numberOfBytesRead;
+ pendingBytesToRead -= numberOfBytesRead;
+ }
+
+ return (length - pendingBytesToRead);
+}
+
+static bool writeBytesToSocket(int fileDescriptor, uint8_t* ptr, size_t length)
+{
+ ASSERT(fileDescriptor > 0);
+ ASSERT(buffer);
+ ASSERT(length > 0);
+
+ ssize_t numberOfBytesWritten = 0;
+ size_t pendingBytesToWrite = length;
+ uint8_t* buffer = ptr;
+
+ // Keep writing to the socket till the complete message has been written.
+ while (pendingBytesToWrite > 0) {
+ if ((numberOfBytesWritten = write(fileDescriptor, buffer, pendingBytesToWrite)) < 0) {
+ if (errno == EINTR)
+ numberOfBytesWritten = 0;
+ else
+ return false;
+ }
+ buffer += numberOfBytesWritten;
+ pendingBytesToWrite -= numberOfBytesWritten;
+ }
+
+ // Write operation failed if complete message is not written.
+ return !pendingBytesToWrite;
+}
+
+void Connection::platformInitialize(Identifier identifier)
+{
+ m_currentMessageSize = 0;
+ m_pendingBytes = 0;
+ m_readBuffer.resize(initialMessageBufferSize);
+ m_socket = identifier;
+ m_isConnected = true;
+}
+
+void Connection::platformInvalidate()
+{
+ if (!m_isConnected)
+ return;
+
+ m_connectionQueue.unregisterEventSourceHandler(m_socket);
+ if (m_socket > 0) {
+ close(m_socket);
+ m_socket = -1;
+ }
+
+ m_isConnected = false;
+}
+
+void Connection::processCompletedMessage()
+{
+ size_t realBufferSize = m_currentMessageSize - sizeof(MessageID);
+ unsigned messageID = *reinterpret_cast<unsigned*>(m_readBuffer.data() + realBufferSize);
+
+ processIncomingMessage(MessageID::fromInt(messageID), adoptPtr(new ArgumentDecoder(m_readBuffer.data(), realBufferSize)));
+
+ // Prepare for the next message.
+ m_currentMessageSize = 0;
+ m_pendingBytes = 0;
+}
+
+void Connection::readEventHandler()
+{
+ if (m_socket < 0)
+ return;
+
+ // Handle any previously unprocessed message.
+ if (!messageProcessingCompleted()) {
+ if ((m_pendingBytes -= readBytesFromSocket(m_socket, (m_readBuffer.data() + (m_currentMessageSize - m_pendingBytes)), m_pendingBytes)) > 0)
+ return;
+
+ // Message received completely. Process the message now.
+ processCompletedMessage();
+ }
+
+ // Prepare to read the next message.
+ uint8_t sizeBuffer[sizeof(size_t)];
+ memset(sizeBuffer, 0, sizeof(size_t));
+
+ while (messageProcessingCompleted()) {
+ if (readBytesFromSocket(m_socket, sizeBuffer, sizeof(size_t)))
+ m_currentMessageSize = *reinterpret_cast<size_t*>(sizeBuffer);
+
+ if (!m_currentMessageSize)
+ break;
+
+ if (m_readBuffer.size() < m_currentMessageSize)
+ m_readBuffer.grow(m_currentMessageSize);
+
+ m_pendingBytes = m_currentMessageSize - readBytesFromSocket(m_socket, m_readBuffer.data(), m_currentMessageSize);
+ if (m_pendingBytes > 0) // Message partially received.
+ break;
+
+ // Message received completely. Process the message now.
+ processCompletedMessage();
+
+ memset(sizeBuffer, 0, sizeof(size_t));
+ }
+}
+
+bool Connection::open()
+{
+ int flags = fcntl(m_socket, F_GETFL, 0);
+ fcntl(m_socket, F_SETFL, flags | O_NONBLOCK);
+
+ // Register callbacks for connection termination and input data on the WorkQueue.
+ m_connectionQueue.registerEventSourceHandler(m_socket, (G_IO_HUP | G_IO_ERR), WorkItem::create(this, &Connection::connectionDidClose));
+ m_connectionQueue.registerEventSourceHandler(m_socket, G_IO_IN, WorkItem::create(this, &Connection::readEventHandler));
+ return true;
+}
+
+bool Connection::platformCanSendOutgoingMessages() const
+{
+ return (m_socket > 0);
+}
+
+bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments)
+{
+ if (m_socket < 0)
+ return false;
+
+ // We put the message ID last.
+ arguments->encodeUInt32(messageID.toInt());
+
+ size_t bufferSize = arguments->bufferSize();
+
+ // Send the message size first.
+ if (!writeBytesToSocket(m_socket, reinterpret_cast<uint8_t*>(&bufferSize), sizeof(size_t)))
+ return false;
+
+ if (!writeBytesToSocket(m_socket, arguments->buffer(), arguments->bufferSize()))
+ return false;
+
+ return true;
+}
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/mac/ConnectionMac.cpp b/Source/WebKit2/Platform/CoreIPC/mac/ConnectionMac.cpp
new file mode 100644
index 0000000..5e7bbbc
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/mac/ConnectionMac.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Connection.h"
+
+#include "CoreIPCMessageKinds.h"
+#include "MachPort.h"
+#include "MachUtilities.h"
+#include "RunLoop.h"
+#include <mach/vm_map.h>
+
+using namespace std;
+
+namespace CoreIPC {
+
+static const size_t inlineMessageMaxSize = 4096;
+
+enum {
+ MessageBodyIsOOL = 1 << 31
+};
+
+void Connection::platformInvalidate()
+{
+ if (!m_isConnected)
+ return;
+
+ m_isConnected = false;
+
+ ASSERT(m_sendPort);
+ ASSERT(m_receivePort);
+
+ // Unregister our ports.
+ m_connectionQueue.unregisterMachPortEventHandler(m_sendPort);
+ m_sendPort = MACH_PORT_NULL;
+
+ m_connectionQueue.unregisterMachPortEventHandler(m_receivePort);
+ m_receivePort = MACH_PORT_NULL;
+
+ if (m_exceptionPort) {
+ m_connectionQueue.unregisterMachPortEventHandler(m_exceptionPort);
+ m_exceptionPort = MACH_PORT_NULL;
+ }
+}
+
+void Connection::platformInitialize(Identifier identifier)
+{
+ m_exceptionPort = MACH_PORT_NULL;
+
+ if (m_isServer) {
+ m_receivePort = identifier;
+ m_sendPort = MACH_PORT_NULL;
+ } else {
+ m_receivePort = MACH_PORT_NULL;
+ m_sendPort = identifier;
+ }
+}
+
+bool Connection::open()
+{
+ if (m_isServer) {
+ ASSERT(m_receivePort);
+ ASSERT(!m_sendPort);
+
+ } else {
+ ASSERT(!m_receivePort);
+ ASSERT(m_sendPort);
+
+ // Create the receive port.
+ mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_receivePort);
+
+ m_isConnected = true;
+
+ // Send the initialize message, which contains a send right for the server to use.
+ send(CoreIPCMessage::InitializeConnection, 0, MachPort(m_receivePort, MACH_MSG_TYPE_MAKE_SEND));
+
+ // Set the dead name handler for our send port.
+ initializeDeadNameSource();
+ }
+
+ // Change the message queue length for the receive port.
+ setMachPortQueueLength(m_receivePort, MACH_PORT_QLIMIT_LARGE);
+
+ // Register the data available handler.
+ m_connectionQueue.registerMachPortEventHandler(m_receivePort, WorkQueue::MachPortDataAvailable, WorkItem::create(this, &Connection::receiveSourceEventHandler));
+
+ // If we have an exception port, register the data available handler and send over the port to the other end.
+ if (m_exceptionPort) {
+ m_connectionQueue.registerMachPortEventHandler(m_exceptionPort, WorkQueue::MachPortDataAvailable, WorkItem::create(this, &Connection::exceptionSourceEventHandler));
+
+ send(CoreIPCMessage::SetExceptionPort, 0, MachPort(m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND));
+ }
+
+ return true;
+}
+
+static inline size_t machMessageSize(size_t bodySize, size_t numberOfPortDescriptors = 0, size_t numberOfOOLMemoryDescriptors = 0)
+{
+ size_t size = sizeof(mach_msg_header_t) + bodySize;
+ if (numberOfPortDescriptors || numberOfOOLMemoryDescriptors) {
+ size += sizeof(mach_msg_body_t);
+ if (numberOfPortDescriptors)
+ size += (numberOfPortDescriptors * sizeof(mach_msg_port_descriptor_t));
+ if (numberOfOOLMemoryDescriptors)
+ size += (numberOfOOLMemoryDescriptors * sizeof(mach_msg_ool_ports_descriptor_t));
+ }
+ return round_msg(size);
+}
+
+bool Connection::platformCanSendOutgoingMessages() const
+{
+ return true;
+}
+
+bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments)
+{
+ Vector<Attachment> attachments = arguments->releaseAttachments();
+
+ size_t numberOfPortDescriptors = 0;
+ size_t numberOfOOLMemoryDescriptors = 0;
+ for (size_t i = 0; i < attachments.size(); ++i) {
+ Attachment::Type type = attachments[i].type();
+ if (type == Attachment::MachPortType)
+ numberOfPortDescriptors++;
+ else if (type == Attachment::MachOOLMemoryType)
+ numberOfOOLMemoryDescriptors++;
+ }
+
+ size_t messageSize = machMessageSize(arguments->bufferSize(), numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
+ char buffer[inlineMessageMaxSize];
+
+ bool messageBodyIsOOL = false;
+ if (messageSize > sizeof(buffer)) {
+ messageBodyIsOOL = true;
+
+ attachments.append(Attachment(arguments->buffer(), arguments->bufferSize(), MACH_MSG_VIRTUAL_COPY, false));
+ numberOfOOLMemoryDescriptors++;
+ messageSize = machMessageSize(0, numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
+ }
+
+ bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0);
+
+ mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(&buffer);
+ header->msgh_bits = isComplex ? MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND | MACH_MSGH_BITS_COMPLEX, 0) : MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
+ header->msgh_size = messageSize;
+ header->msgh_remote_port = m_sendPort;
+ header->msgh_local_port = MACH_PORT_NULL;
+ header->msgh_id = messageID.toInt();
+ if (messageBodyIsOOL)
+ header->msgh_id |= MessageBodyIsOOL;
+
+ uint8_t* messageData;
+
+ if (isComplex) {
+ mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
+ body->msgh_descriptor_count = numberOfPortDescriptors + numberOfOOLMemoryDescriptors;
+
+ uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
+ for (size_t i = 0; i < attachments.size(); ++i) {
+ Attachment attachment = attachments[i];
+
+ mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
+ switch (attachment.type()) {
+ case Attachment::MachPortType:
+ descriptor->port.name = attachment.port();
+ descriptor->port.disposition = attachment.disposition();
+ descriptor->port.type = MACH_MSG_PORT_DESCRIPTOR;
+
+ descriptorData += sizeof(mach_msg_port_descriptor_t);
+ break;
+ case Attachment::MachOOLMemoryType:
+ descriptor->out_of_line.address = attachment.address();
+ descriptor->out_of_line.size = attachment.size();
+ descriptor->out_of_line.copy = attachment.copyOptions();
+ descriptor->out_of_line.deallocate = attachment.deallocate();
+ descriptor->out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;
+
+ descriptorData += sizeof(mach_msg_ool_descriptor_t);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ messageData = descriptorData;
+ } else
+ messageData = (uint8_t*)(header + 1);
+
+ // Copy the data if it is not being sent out-of-line.
+ if (!messageBodyIsOOL)
+ memcpy(messageData, arguments->buffer(), arguments->bufferSize());
+
+ ASSERT(m_sendPort);
+
+ // Send the message.
+ kern_return_t kr = mach_msg(header, MACH_SEND_MSG, messageSize, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (kr != KERN_SUCCESS) {
+ // FIXME: What should we do here?
+ }
+
+ return true;
+}
+
+void Connection::initializeDeadNameSource()
+{
+ m_connectionQueue.registerMachPortEventHandler(m_sendPort, WorkQueue::MachPortDeadNameNotification, WorkItem::create(this, &Connection::connectionDidClose));
+}
+
+static PassOwnPtr<ArgumentDecoder> createArgumentDecoder(mach_msg_header_t* header)
+{
+ if (!(header->msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
+ // We have a simple message.
+ size_t bodySize = header->msgh_size - sizeof(mach_msg_header_t);
+ uint8_t* body = reinterpret_cast<uint8_t*>(header + 1);
+
+ return adoptPtr(new ArgumentDecoder(body, bodySize));
+ }
+
+ bool messageBodyIsOOL = header->msgh_id & MessageBodyIsOOL;
+
+ mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
+ mach_msg_size_t numDescriptors = body->msgh_descriptor_count;
+ ASSERT(numDescriptors);
+
+ // Build attachment list
+ Deque<Attachment> attachments;
+ uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
+
+ // If the message body was sent out-of-line, don't treat the last descriptor
+ // as an attachment, since it is really the message body.
+ if (messageBodyIsOOL)
+ --numDescriptors;
+
+ for (mach_msg_size_t i = 0; i < numDescriptors; ++i) {
+ mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
+
+ switch (descriptor->type.type) {
+ case MACH_MSG_PORT_DESCRIPTOR:
+ attachments.append(Attachment(descriptor->port.name, descriptor->port.disposition));
+ descriptorData += sizeof(mach_msg_port_descriptor_t);
+ break;
+ case MACH_MSG_OOL_DESCRIPTOR:
+ attachments.append(Attachment(descriptor->out_of_line.address, descriptor->out_of_line.size,
+ descriptor->out_of_line.copy, descriptor->out_of_line.deallocate));
+ descriptorData += sizeof(mach_msg_ool_descriptor_t);
+ break;
+ default:
+ ASSERT(false && "Unhandled descriptor type");
+ }
+ }
+
+ if (messageBodyIsOOL) {
+ mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
+ ASSERT(descriptor->type.type == MACH_MSG_OOL_DESCRIPTOR);
+ Attachment messageBodyAttachment(descriptor->out_of_line.address, descriptor->out_of_line.size,
+ descriptor->out_of_line.copy, descriptor->out_of_line.deallocate);
+
+ uint8_t* messageBody = static_cast<uint8_t*>(messageBodyAttachment.address());
+ size_t messageBodySize = messageBodyAttachment.size();
+
+ ArgumentDecoder* argumentDecoder;
+
+ if (attachments.isEmpty())
+ argumentDecoder = new ArgumentDecoder(messageBody, messageBodySize);
+ else
+ argumentDecoder = new ArgumentDecoder(messageBody, messageBodySize, attachments);
+
+ vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(messageBodyAttachment.address()), messageBodyAttachment.size());
+
+ return adoptPtr(argumentDecoder);
+ }
+
+ uint8_t* messageBody = descriptorData;
+ size_t messageBodySize = header->msgh_size - (descriptorData - reinterpret_cast<uint8_t*>(header));
+
+ return adoptPtr(new ArgumentDecoder(messageBody, messageBodySize, attachments));
+}
+
+// The receive buffer size should always include the maximum trailer size.
+static const size_t receiveBufferSize = inlineMessageMaxSize + MAX_TRAILER_SIZE;
+typedef Vector<char, receiveBufferSize> ReceiveBuffer;
+
+static mach_msg_header_t* readFromMachPort(mach_port_t machPort, ReceiveBuffer& buffer)
+{
+ buffer.resize(receiveBufferSize);
+
+ mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
+ kern_return_t kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
+ if (kr == MACH_RCV_TIMED_OUT)
+ return 0;
+
+ if (kr == MACH_RCV_TOO_LARGE) {
+ // The message was too large, resize the buffer and try again.
+ buffer.resize(header->msgh_size + MAX_TRAILER_SIZE);
+ header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
+
+ kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
+ ASSERT(kr != MACH_RCV_TOO_LARGE);
+ }
+
+ if (kr != MACH_MSG_SUCCESS) {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
+ return header;
+}
+
+void Connection::receiveSourceEventHandler()
+{
+ ReceiveBuffer buffer;
+
+ mach_msg_header_t* header = readFromMachPort(m_receivePort, buffer);
+ if (!header)
+ return;
+
+ MessageID messageID = MessageID::fromInt(header->msgh_id);
+ OwnPtr<ArgumentDecoder> arguments = createArgumentDecoder(header);
+ ASSERT(arguments);
+
+ if (messageID == MessageID(CoreIPCMessage::InitializeConnection)) {
+ ASSERT(m_isServer);
+ ASSERT(!m_isConnected);
+ ASSERT(!m_sendPort);
+
+ MachPort port;
+ if (!arguments->decode(port)) {
+ // FIXME: Disconnect.
+ return;
+ }
+
+ m_sendPort = port.port();
+
+ // Set the dead name source if needed.
+ if (m_sendPort)
+ initializeDeadNameSource();
+
+ m_isConnected = true;
+
+ // Send any pending outgoing messages.
+ sendOutgoingMessages();
+
+ return;
+ }
+
+ if (messageID == MessageID(CoreIPCMessage::SetExceptionPort)) {
+ MachPort exceptionPort;
+ if (!arguments->decode(exceptionPort))
+ return;
+
+ setMachExceptionPort(exceptionPort.port());
+ return;
+ }
+
+ processIncomingMessage(messageID, arguments.release());
+}
+
+void Connection::exceptionSourceEventHandler()
+{
+ ReceiveBuffer buffer;
+
+ mach_msg_header_t* header = readFromMachPort(m_exceptionPort, buffer);
+ if (!header)
+ return;
+
+ // We've read the exception message. Now send it on to the real exception port.
+
+ // The remote port should have a send once right.
+ ASSERT(MACH_MSGH_BITS_REMOTE(header->msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE);
+
+ // Now get the real exception port.
+ mach_port_t exceptionPort = machExceptionPort();
+
+ // First, get the complex bit from the source message.
+ mach_msg_bits_t messageBits = header->msgh_bits & MACH_MSGH_BITS_COMPLEX;
+ messageBits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE);
+
+ header->msgh_bits = messageBits;
+ header->msgh_local_port = header->msgh_remote_port;
+ header->msgh_remote_port = exceptionPort;
+
+ // Now send along the message.
+ kern_return_t kr = mach_msg(header, MACH_SEND_MSG, header->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (kr != KERN_SUCCESS) {
+ LOG_ERROR("Failed to send message to real exception port, error %x", kr);
+ ASSERT_NOT_REACHED();
+ }
+
+ connectionDidClose();
+}
+
+void Connection::setShouldCloseConnectionOnMachExceptions()
+{
+ ASSERT(m_exceptionPort == MACH_PORT_NULL);
+
+ if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_exceptionPort) != KERN_SUCCESS)
+ ASSERT_NOT_REACHED();
+
+ if (mach_port_insert_right(mach_task_self(), m_exceptionPort, m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)
+ ASSERT_NOT_REACHED();
+}
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/mac/MachPort.h b/Source/WebKit2/Platform/CoreIPC/mac/MachPort.h
new file mode 100644
index 0000000..ecce16e
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/mac/MachPort.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MachPort_h
+#define MachPort_h
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include "Attachment.h"
+
+namespace CoreIPC {
+
+class MachPort {
+public:
+ MachPort()
+ : m_port(MACH_PORT_NULL)
+ , m_disposition(0)
+ {
+ }
+
+ MachPort(mach_port_name_t port, mach_msg_type_name_t disposition)
+ : m_port(port)
+ , m_disposition(disposition)
+ {
+ }
+
+ void encode(ArgumentEncoder* encoder) const
+ {
+ encoder->encode(Attachment(m_port, m_disposition));
+ }
+
+ static bool decode(ArgumentDecoder* decoder, MachPort& p)
+ {
+ Attachment attachment;
+ if (!decoder->decode(attachment))
+ return false;
+
+ p.m_port = attachment.port();
+ p.m_disposition = attachment.disposition();
+ return true;
+ }
+
+ mach_port_name_t port() const { return m_port; }
+ mach_msg_type_name_t disposition() const { return m_disposition; }
+
+private:
+ mach_port_name_t m_port;
+ mach_msg_type_name_t m_disposition;
+};
+
+} // namespace CoreIPC
+
+#endif // MachPort_h
diff --git a/Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp b/Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp
new file mode 100644
index 0000000..c0736b8
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Connection.h"
+
+#include "ArgumentEncoder.h"
+#include "ProcessLauncher.h"
+#include "WorkItem.h"
+#include <QApplication>
+#include <QLocalServer>
+#include <QLocalSocket>
+
+using namespace std;
+
+namespace CoreIPC {
+
+// This is what other ports use...
+static const size_t messageMaxSize = 4096;
+
+void Connection::platformInitialize(Identifier identifier)
+{
+ m_serverName = identifier;
+ m_socket = 0;
+ m_readBuffer.resize(messageMaxSize);
+ m_currentMessageSize = 0;
+}
+
+void Connection::platformInvalidate()
+{
+ m_socket->disconnect();
+ if (!m_isServer)
+ m_socket->deleteLater();
+ m_socket = 0;
+}
+
+void Connection::readyReadHandler()
+{
+ while (m_socket->bytesAvailable()) {
+ if (!m_currentMessageSize) {
+ size_t numberOfBytesRead = m_socket->read(reinterpret_cast<char*>(m_readBuffer.data()), sizeof(size_t));
+ ASSERT_UNUSED(numberOfBytesRead, numberOfBytesRead);
+ m_currentMessageSize = *reinterpret_cast<size_t*>(m_readBuffer.data());
+ }
+
+ if (m_socket->bytesAvailable() < m_currentMessageSize)
+ return;
+
+ if (m_readBuffer.size() < m_currentMessageSize)
+ m_readBuffer.grow(m_currentMessageSize);
+
+ size_t numberOfBytesRead = m_socket->read(reinterpret_cast<char*>(m_readBuffer.data()), m_currentMessageSize);
+ ASSERT_UNUSED(numberOfBytesRead, numberOfBytesRead);
+
+ // The messageID is encoded at the end of the buffer.
+ size_t realBufferSize = m_currentMessageSize - sizeof(uint32_t);
+ uint32_t messageID = *reinterpret_cast<uint32_t*>(m_readBuffer.data() + realBufferSize);
+
+ processIncomingMessage(MessageID::fromInt(messageID), adoptPtr(new ArgumentDecoder(m_readBuffer.data(), realBufferSize)));
+
+ m_currentMessageSize = 0;
+ }
+}
+
+bool Connection::open()
+{
+ ASSERT(!m_socket);
+
+ if (m_isServer) {
+ m_socket = WebKit::ProcessLauncher::takePendingConnection();
+ m_isConnected = m_socket;
+ if (m_isConnected) {
+ m_connectionQueue.moveSocketToWorkThread(m_socket);
+ m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
+ }
+ } else {
+ m_socket = new QLocalSocket();
+ m_socket->connectToServer(m_serverName);
+ m_connectionQueue.moveSocketToWorkThread(m_socket);
+ m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
+ m_connectionQueue.connectSignal(m_socket, SIGNAL(disconnected()), WorkItem::create(this, &Connection::connectionDidClose));
+ m_isConnected = m_socket->waitForConnected();
+ }
+ return m_isConnected;
+}
+
+bool Connection::platformCanSendOutgoingMessages() const
+{
+ return m_socket;
+}
+
+bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments)
+{
+ ASSERT(m_socket);
+
+ // We put the message ID last.
+ arguments->encodeUInt32(messageID.toInt());
+
+ size_t bufferSize = arguments->bufferSize();
+
+ // Write message size first
+ // FIXME: Should just do a single write.
+ qint64 bytesWrittenForSize = m_socket->write(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
+ if (bytesWrittenForSize != sizeof(bufferSize)) {
+ connectionDidClose();
+ return false;
+ }
+
+ qint64 bytesWrittenForBuffer = m_socket->write(reinterpret_cast<char*>(arguments->buffer()), arguments->bufferSize());
+ if (bytesWrittenForBuffer != arguments->bufferSize()) {
+ connectionDidClose();
+ return false;
+ }
+
+ m_socket->flush();
+
+ return true;
+}
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/CoreIPC/win/ConnectionWin.cpp b/Source/WebKit2/Platform/CoreIPC/win/ConnectionWin.cpp
new file mode 100644
index 0000000..695da78
--- /dev/null
+++ b/Source/WebKit2/Platform/CoreIPC/win/ConnectionWin.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Connection.h"
+
+#include "ArgumentEncoder.h"
+#include "WorkItem.h"
+#include <wtf/RandomNumber.h>
+#include <wtf/text/WTFString.h>
+
+using namespace std;
+// We explicitly don't use the WebCore namespace here because CoreIPC should only use WTF types and
+// WTF::String is really in WTF.
+using WTF::String;
+
+namespace CoreIPC {
+
+// FIXME: Rename this or use a different constant on windows.
+static const size_t inlineMessageMaxSize = 4096;
+
+bool Connection::createServerAndClientIdentifiers(HANDLE& serverIdentifier, HANDLE& clientIdentifier)
+{
+ String pipeName;
+
+ while (true) {
+ unsigned uniqueID = randomNumber() * std::numeric_limits<unsigned>::max();
+ pipeName = String::format("\\\\.\\pipe\\com.apple.WebKit.%x", uniqueID);
+
+ serverIdentifier = ::CreateNamedPipe(pipeName.charactersWithNullTermination(),
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, inlineMessageMaxSize, inlineMessageMaxSize,
+ 0, 0);
+ if (!serverIdentifier && ::GetLastError() == ERROR_PIPE_BUSY) {
+ // There was already a pipe with this name, try again.
+ continue;
+ }
+
+ break;
+ }
+
+ if (!serverIdentifier)
+ return false;
+
+ clientIdentifier = ::CreateFileW(pipeName.charactersWithNullTermination(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+ if (!clientIdentifier) {
+ ::CloseHandle(serverIdentifier);
+ return false;
+ }
+
+ DWORD mode = PIPE_READMODE_MESSAGE;
+ if (!::SetNamedPipeHandleState(clientIdentifier, &mode, 0, 0)) {
+ ::CloseHandle(serverIdentifier);
+ ::CloseHandle(clientIdentifier);
+ return false;
+ }
+
+ return true;
+}
+
+void Connection::platformInitialize(Identifier identifier)
+{
+ memset(&m_readState, 0, sizeof(m_readState));
+ m_readState.hEvent = ::CreateEventW(0, FALSE, FALSE, 0);
+
+ memset(&m_writeState, 0, sizeof(m_writeState));
+ m_writeState.hEvent = ::CreateEventW(0, FALSE, FALSE, 0);
+
+ m_connectionPipe = identifier;
+
+ // We connected the two ends of the pipe in createServerAndClientIdentifiers.
+ m_isConnected = true;
+}
+
+void Connection::platformInvalidate()
+{
+ if (m_connectionPipe == INVALID_HANDLE_VALUE)
+ return;
+
+ m_connectionQueue.unregisterAndCloseHandle(m_readState.hEvent);
+ m_readState.hEvent = 0;
+
+ m_connectionQueue.unregisterAndCloseHandle(m_writeState.hEvent);
+ m_writeState.hEvent = 0;
+
+ ::CloseHandle(m_connectionPipe);
+ m_connectionPipe = INVALID_HANDLE_VALUE;
+}
+
+void Connection::readEventHandler()
+{
+ if (m_connectionPipe == INVALID_HANDLE_VALUE)
+ return;
+
+ while (true) {
+ // Check if we got some data.
+ DWORD numberOfBytesRead = 0;
+ if (!::GetOverlappedResult(m_connectionPipe, &m_readState, &numberOfBytesRead, FALSE)) {
+ DWORD error = ::GetLastError();
+
+ switch (error) {
+ case ERROR_BROKEN_PIPE:
+ connectionDidClose();
+ return;
+ case ERROR_MORE_DATA: {
+ // Read the rest of the message out of the pipe.
+
+ DWORD bytesToRead = 0;
+ if (!::PeekNamedPipe(m_connectionPipe, 0, 0, 0, 0, &bytesToRead)) {
+ DWORD error = ::GetLastError();
+ if (error == ERROR_BROKEN_PIPE) {
+ connectionDidClose();
+ return;
+ }
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ // ::GetOverlappedResult told us there's more data. ::PeekNamedPipe shouldn't
+ // contradict it!
+ ASSERT(bytesToRead);
+ if (!bytesToRead)
+ break;
+
+ m_readBuffer.grow(m_readBuffer.size() + bytesToRead);
+ if (!::ReadFile(m_connectionPipe, m_readBuffer.data() + numberOfBytesRead, bytesToRead, 0, &m_readState)) {
+ DWORD error = ::GetLastError();
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ continue;
+ }
+
+ // FIXME: We should figure out why we're getting this error.
+ case ERROR_IO_INCOMPLETE:
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ if (!m_readBuffer.isEmpty()) {
+ // We have a message, let's dispatch it.
+
+ // The messageID is encoded at the end of the buffer.
+ // Note that we assume here that the message is the same size as m_readBuffer. We can
+ // assume this because we always size m_readBuffer to exactly match the size of the message,
+ // either when receiving ERROR_MORE_DATA from ::GetOverlappedResult above or when
+ // ::PeekNamedPipe tells us the size below. We never set m_readBuffer to a size larger
+ // than the message.
+ ASSERT(m_readBuffer.size() >= sizeof(MessageID));
+ size_t realBufferSize = m_readBuffer.size() - sizeof(MessageID);
+
+ unsigned messageID = *reinterpret_cast<unsigned*>(m_readBuffer.data() + realBufferSize);
+
+ processIncomingMessage(MessageID::fromInt(messageID), adoptPtr(new ArgumentDecoder(m_readBuffer.data(), realBufferSize)));
+ }
+
+ // Find out the size of the next message in the pipe (if there is one) so that we can read
+ // it all in one operation. (This is just an optimization to avoid an extra pass through the
+ // loop (if we chose a buffer size that was too small) or allocating extra memory (if we
+ // chose a buffer size that was too large).)
+ DWORD bytesToRead = 0;
+ if (!::PeekNamedPipe(m_connectionPipe, 0, 0, 0, 0, &bytesToRead)) {
+ DWORD error = ::GetLastError();
+ if (error == ERROR_BROKEN_PIPE) {
+ connectionDidClose();
+ return;
+ }
+ ASSERT_NOT_REACHED();
+ }
+ if (!bytesToRead) {
+ // There's no message waiting in the pipe. Schedule a read of the first byte of the
+ // next message. We'll find out the message's actual size when it arrives. (If we
+ // change this to read more than a single byte for performance reasons, we'll have to
+ // deal with m_readBuffer potentially being larger than the message we read after
+ // calling ::GetOverlappedResult above.)
+ bytesToRead = 1;
+ }
+
+ m_readBuffer.resize(bytesToRead);
+
+ // Either read the next available message (which should occur synchronously), or start an
+ // asynchronous read of the next message that becomes available.
+ BOOL result = ::ReadFile(m_connectionPipe, m_readBuffer.data(), m_readBuffer.size(), 0, &m_readState);
+ if (result) {
+ // There was already a message waiting in the pipe, and we read it synchronously.
+ // Process it.
+ continue;
+ }
+
+ DWORD error = ::GetLastError();
+
+ if (error == ERROR_IO_PENDING) {
+ // There are no messages in the pipe currently. readEventHandler will be called again once there is a message.
+ return;
+ }
+
+ if (error == ERROR_MORE_DATA) {
+ // Either a message is available when we didn't think one was, or the message is larger
+ // than ::PeekNamedPipe told us. The former seems far more likely. Probably the message
+ // became available between our calls to ::PeekNamedPipe and ::ReadFile above. Go back
+ // to the top of the loop to use ::GetOverlappedResult to retrieve the available data.
+ continue;
+ }
+
+ // FIXME: We need to handle other errors here.
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void Connection::writeEventHandler()
+{
+ if (m_connectionPipe == INVALID_HANDLE_VALUE)
+ return;
+
+ DWORD numberOfBytesWritten = 0;
+ if (!::GetOverlappedResult(m_connectionPipe, &m_writeState, &numberOfBytesWritten, FALSE)) {
+ DWORD error = ::GetLastError();
+ if (error == ERROR_IO_INCOMPLETE) {
+ // FIXME: We should figure out why we're getting this error.
+ return;
+ }
+ ASSERT_NOT_REACHED();
+ }
+
+ // The pending write has finished, so we are now done with its arguments. Clearing this member
+ // will allow us to send messages again.
+ m_pendingWriteArguments = 0;
+
+ // Now that the pending write has finished, we can try to send a new message.
+ sendOutgoingMessages();
+}
+
+bool Connection::open()
+{
+ // Start listening for read and write state events.
+ m_connectionQueue.registerHandle(m_readState.hEvent, WorkItem::create(this, &Connection::readEventHandler));
+ m_connectionQueue.registerHandle(m_writeState.hEvent, WorkItem::create(this, &Connection::writeEventHandler));
+
+ // Schedule a read.
+ m_connectionQueue.scheduleWork(WorkItem::create(this, &Connection::readEventHandler));
+
+ return true;
+}
+
+bool Connection::platformCanSendOutgoingMessages() const
+{
+ // We only allow sending one asynchronous message at a time. If we wanted to send more than one
+ // at once, we'd have to use multiple OVERLAPPED structures and hold onto multiple pending
+ // ArgumentEncoders (one of each for each simultaneous asynchronous message).
+ return !m_pendingWriteArguments;
+}
+
+bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments)
+{
+ ASSERT(!m_pendingWriteArguments);
+
+ // Just bail if the handle has been closed.
+ if (m_connectionPipe == INVALID_HANDLE_VALUE)
+ return false;
+
+ // We put the message ID last.
+ arguments->encodeUInt32(messageID.toInt());
+
+ // Write the outgoing message.
+
+ if (::WriteFile(m_connectionPipe, arguments->buffer(), arguments->bufferSize(), 0, &m_writeState)) {
+ // We successfully sent this message.
+ return true;
+ }
+
+ DWORD error = ::GetLastError();
+
+ if (error == ERROR_NO_DATA) {
+ // The pipe is being closed.
+ connectionDidClose();
+ return false;
+ }
+
+ if (error != ERROR_IO_PENDING) {
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ // The message will be sent soon. Hold onto the arguments so that they won't be destroyed
+ // before the write completes.
+ m_pendingWriteArguments = arguments;
+
+ // We can only send one asynchronous message at a time (see comment in platformCanSendOutgoingMessages).
+ return false;
+}
+
+} // namespace CoreIPC
diff --git a/Source/WebKit2/Platform/Logging.cpp b/Source/WebKit2/Platform/Logging.cpp
new file mode 100644
index 0000000..ca312ef
--- /dev/null
+++ b/Source/WebKit2/Platform/Logging.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Logging.h"
+
+#if !LOG_DISABLED
+
+WTFLogChannel LogSessionState = { 0x00000001, "WebKit2LogLevel", WTFLogChannelOff };
+WTFLogChannel LogContextMenu = { 0x00000002, "WebKit2LogLevel", WTFLogChannelOff };
+WTFLogChannel LogTextInput = { 0x00000004, "WebKit2LogLevel", WTFLogChannelOff };
+WTFLogChannel LogView = { 0x00000008, "WebKit2LogLevel", WTFLogChannelOff };
+
+static inline void initializeLogChannel(WTFLogChannel* channel)
+{
+ // FIXME: This is a build fix. Each platform will need to define their own initializeLogChannel().
+}
+
+void initializeLogChannelsIfNecessary()
+{
+ static bool haveInitializedLogChannels = false;
+ if (haveInitializedLogChannels)
+ return;
+ haveInitializedLogChannels = true;
+
+ initializeLogChannel(&LogContextMenu);
+ initializeLogChannel(&LogSessionState);
+ initializeLogChannel(&LogTextInput);
+ initializeLogChannel(&LogView);
+}
+
+#endif // LOG_DISABLED
diff --git a/Source/WebKit2/Platform/Logging.h b/Source/WebKit2/Platform/Logging.h
new file mode 100644
index 0000000..b2cc391
--- /dev/null
+++ b/Source/WebKit2/Platform/Logging.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Logging_h
+#define Logging_h
+
+#include <wtf/Assertions.h>
+
+#if !LOG_DISABLED
+
+#ifndef LOG_CHANNEL_PREFIX
+#define LOG_CHANNEL_PREFIX Log
+#endif
+
+EXTERN_C_BEGIN
+
+extern WTFLogChannel LogContextMenu;
+extern WTFLogChannel LogSessionState;
+extern WTFLogChannel LogTextInput;
+extern WTFLogChannel LogView;
+
+void initializeLogChannelsIfNecessary(void);
+
+EXTERN_C_END
+
+#endif // LOG_DISABLED
+
+#endif // Logging_h
diff --git a/Source/WebKit2/Platform/Module.cpp b/Source/WebKit2/Platform/Module.cpp
new file mode 100644
index 0000000..7a2def5
--- /dev/null
+++ b/Source/WebKit2/Platform/Module.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Module.h"
+
+namespace WebKit {
+
+Module::Module(const String& path)
+ : m_path(path)
+#if PLATFORM(WIN)
+ , m_module(0)
+#endif
+{
+}
+
+Module::~Module()
+{
+ unload();
+}
+
+}
diff --git a/Source/WebKit2/Platform/Module.h b/Source/WebKit2/Platform/Module.h
new file mode 100644
index 0000000..0825bf6
--- /dev/null
+++ b/Source/WebKit2/Platform/Module.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Module_h
+#define Module_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(MAC)
+#include <wtf/RetainPtr.h>
+#endif
+
+#if PLATFORM(QT)
+#include <QLibrary>
+#endif
+
+namespace WebKit {
+
+class Module : public Noncopyable {
+public:
+ Module(const String& path);
+ ~Module();
+
+ bool load();
+ // Note: On Mac this leaks the CFBundle to avoid crashes when a bundle is unloaded and there are
+ // live Objective-C objects whose methods come from that bundle.
+ void unload();
+
+ template<typename FunctionType> FunctionType functionPointer(const char* functionName) const;
+
+private:
+ void* platformFunctionPointer(const char* functionName) const;
+
+ String m_path;
+#if PLATFORM(MAC)
+ RetainPtr<CFBundleRef> m_bundle;
+#elif PLATFORM(WIN)
+ HMODULE m_module;
+#elif PLATFORM(QT)
+ QLibrary m_lib;
+#endif
+};
+
+template<typename FunctionType> FunctionType Module::functionPointer(const char* functionName) const
+{
+ return reinterpret_cast<FunctionType>(platformFunctionPointer(functionName));
+}
+
+}
+
+#endif
diff --git a/Source/WebKit2/Platform/PlatformProcessIdentifier.h b/Source/WebKit2/Platform/PlatformProcessIdentifier.h
new file mode 100644
index 0000000..0363692
--- /dev/null
+++ b/Source/WebKit2/Platform/PlatformProcessIdentifier.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef PlatformProcessIdentifier_h
+#define PlatformProcessIdentifier_h
+
+#if PLATFORM(QT)
+class QProcess;
+#endif
+
+namespace WebKit {
+
+#if PLATFORM(MAC)
+typedef pid_t PlatformProcessIdentifier;
+#elif PLATFORM(WIN)
+typedef HANDLE PlatformProcessIdentifier;
+#elif PLATFORM(QT)
+typedef QProcess* PlatformProcessIdentifier;
+#elif PLATFORM(GTK)
+typedef pid_t PlatformProcessIdentifier;
+#endif
+
+} // namespace WebKit
+
+#endif // PlatformProcessIdentifier_h
diff --git a/Source/WebKit2/Platform/Region.cpp b/Source/WebKit2/Platform/Region.cpp
new file mode 100644
index 0000000..a1cc24c
--- /dev/null
+++ b/Source/WebKit2/Platform/Region.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Region.h"
+
+// A region class based on the paper "Scanline Coherent Shape Algebra"
+// by Jonathan E. Steinhart from the book "Graphics Gems II".
+//
+// This implementation uses two vectors instead of linked list, and
+// also compresses regions when possible.
+
+using namespace WebCore;
+
+namespace WebKit {
+
+Region::Region()
+{
+}
+
+Region::Region(const IntRect& rect)
+ : m_bounds(rect)
+ , m_shape(rect)
+{
+}
+
+Vector<IntRect> Region::rects() const
+{
+ Vector<IntRect> rects;
+
+ for (Shape::SpanIterator span = m_shape.spans_begin(), end = m_shape.spans_end(); span != end && span + 1 != end; ++span) {
+ int y = span->y;
+ int height = (span + 1)->y - y;
+
+ for (Shape::SegmentIterator segment = m_shape.segments_begin(span), end = m_shape.segments_end(span); segment != end && segment + 1 != end; segment += 2) {
+ int x = *segment;
+ int width = *(segment + 1) - x;
+
+ rects.append(IntRect(x, y, width, height));
+ }
+ }
+
+ return rects;
+}
+
+Region::Shape::Shape()
+{
+}
+
+Region::Shape::Shape(const IntRect& rect)
+{
+ appendSpan(rect.y());
+ appendSegment(rect.x());
+ appendSegment(rect.right());
+ appendSpan(rect.bottom());
+}
+
+void Region::Shape::appendSpan(int y)
+{
+ m_spans.append(Span(y, m_segments.size()));
+}
+
+bool Region::Shape::canCoalesce(SegmentIterator begin, SegmentIterator end)
+{
+ if (m_spans.isEmpty())
+ return false;
+
+ SegmentIterator lastSpanBegin = m_segments.data() + m_spans.last().segmentIndex;
+ SegmentIterator lastSpanEnd = m_segments.data() + m_segments.size();
+
+ // Check if both spans have an equal number of segments.
+ if (lastSpanEnd - lastSpanBegin != end - begin)
+ return false;
+
+ // Check if both spans are equal.
+ if (!std::equal(begin, end, lastSpanBegin))
+ return false;
+
+ // Since the segments are equal the second segment can just be ignored.
+ return true;
+}
+
+void Region::Shape::appendSpan(int y, SegmentIterator begin, SegmentIterator end)
+{
+ if (canCoalesce(begin, end))
+ return;
+
+ appendSpan(y);
+ m_segments.appendRange(begin, end);
+}
+
+void Region::Shape::appendSpans(const Shape& shape, SpanIterator begin, SpanIterator end)
+{
+ for (SpanIterator it = begin; it != end; ++it)
+ appendSpan(it->y, shape.segments_begin(it), shape.segments_end(it));
+}
+
+void Region::Shape::appendSegment(int x)
+{
+ m_segments.append(x);
+}
+
+Region::Shape::SpanIterator Region::Shape::spans_begin() const
+{
+ return m_spans.data();
+}
+
+Region::Shape::SpanIterator Region::Shape::spans_end() const
+{
+ return m_spans.data() + m_spans.size();
+}
+
+Region::Shape::SegmentIterator Region::Shape::segments_begin(SpanIterator it) const
+{
+ ASSERT(it >= m_spans.data());
+ ASSERT(it < m_spans.data() + m_spans.size());
+
+ // Check if this span has any segments.
+ if (it->segmentIndex == m_segments.size())
+ return 0;
+
+ return &m_segments[it->segmentIndex];
+}
+
+Region::Shape::SegmentIterator Region::Shape::segments_end(SpanIterator it) const
+{
+ ASSERT(it >= m_spans.data());
+ ASSERT(it < m_spans.data() + m_spans.size());
+
+ // Check if this span has any segments.
+ if (it->segmentIndex == m_segments.size())
+ return 0;
+
+ ASSERT(it + 1 < m_spans.data() + m_spans.size());
+ size_t segmentIndex = (it + 1)->segmentIndex;
+
+ ASSERT(segmentIndex <= m_segments.size());
+ return m_segments.data() + segmentIndex;
+}
+
+#ifndef NDEBUG
+void Region::Shape::dump() const
+{
+ for (Shape::SpanIterator span = spans_begin(), end = spans_end(); span != end; ++span) {
+ printf("%6d: (", span->y);
+
+ for (Shape::SegmentIterator segment = segments_begin(span), end = segments_end(span); segment != end; ++segment)
+ printf("%d ", *segment);
+ printf(")\n");
+ }
+
+ printf("\n");
+}
+#endif
+
+IntRect Region::Shape::bounds() const
+{
+ if (isEmpty())
+ return IntRect();
+
+ SpanIterator span = spans_begin();
+ int minY = span->y;
+
+ SpanIterator lastSpan = spans_end() - 1;
+ int maxY = lastSpan->y;
+
+ int minX = std::numeric_limits<int>::max();
+ int maxX = std::numeric_limits<int>::min();
+
+ while (span != lastSpan) {
+ SegmentIterator firstSegment = segments_begin(span);
+ SegmentIterator lastSegment = segments_end(span) - 1;
+
+ if (firstSegment && lastSegment) {
+ ASSERT(firstSegment != lastSegment);
+
+ if (*firstSegment < minX)
+ minX = *firstSegment;
+
+ if (*lastSegment > maxX)
+ maxX = *lastSegment;
+ }
+
+ ++span;
+ }
+
+ ASSERT(minX <= maxX);
+ ASSERT(minY <= maxY);
+
+ return IntRect(minX, minY, maxX - minX, maxY - minY);
+}
+
+void Region::Shape::translate(const IntSize& offset)
+{
+ for (size_t i = 0; i < m_segments.size(); ++i)
+ m_segments[i] += offset.width();
+ for (size_t i = 0; i < m_spans.size(); ++i)
+ m_spans[i].y += offset.height();
+}
+
+void Region::Shape::swap(Shape& other)
+{
+ m_segments.swap(other.m_segments);
+ m_spans.swap(other.m_spans);
+}
+
+enum {
+ Shape1,
+ Shape2,
+};
+
+template<typename Operation>
+Region::Shape Region::Shape::shapeOperation(const Shape& shape1, const Shape& shape2)
+{
+ COMPILE_ASSERT(!(!Operation::shouldAddRemainingSegmentsFromSpan1 && Operation::shouldAddRemainingSegmentsFromSpan2), invalid_segment_combination);
+ COMPILE_ASSERT(!(!Operation::shouldAddRemainingSpansFromShape1 && Operation::shouldAddRemainingSpansFromShape2), invalid_span_combination);
+
+ Shape result;
+ if (Operation::trySimpleOperation(shape1, shape2, result))
+ return result;
+
+ SpanIterator spans1 = shape1.spans_begin();
+ SpanIterator spans1End = shape1.spans_end();
+
+ SpanIterator spans2 = shape2.spans_begin();
+ SpanIterator spans2End = shape2.spans_end();
+
+ SegmentIterator segments1 = 0;
+ SegmentIterator segments1End = 0;
+
+ SegmentIterator segments2 = 0;
+ SegmentIterator segments2End = 0;
+
+ // Iterate over all spans.
+ while (spans1 != spans1End && spans2 != spans2End) {
+ int y;
+ int test = spans1->y - spans2->y;
+
+ if (test <= 0) {
+ y = spans1->y;
+
+ segments1 = shape1.segments_begin(spans1);
+ segments1End = shape1.segments_end(spans1);
+ ++spans1;
+ }
+ if (test >= 0) {
+ y = spans2->y;
+
+ segments2 = shape2.segments_begin(spans2);
+ segments2End = shape2.segments_end(spans2);
+ ++spans2;
+ }
+
+ int flag = 0;
+ int oldFlag = 0;
+
+ SegmentIterator s1 = segments1;
+ SegmentIterator s2 = segments2;
+
+ Vector<int> segments;
+
+ // Now iterate over the segments in each span and construct a new vector of segments.
+ while (s1 != segments1End && s2 != segments2End) {
+ int test = *s1 - *s2;
+ int x;
+
+ if (test <= 0) {
+ x = *s1;
+ flag = flag ^ 1;
+ ++s1;
+ }
+ if (test >= 0) {
+ x = *s2;
+ flag = flag ^ 2;
+ ++s2;
+ }
+
+ if (flag == Operation::opCode || oldFlag == Operation::opCode)
+ segments.append(x);
+
+ oldFlag = flag;
+ }
+
+ // Add any remaining segments.
+ if (Operation::shouldAddRemainingSegmentsFromSpan1 && s1 != segments1End)
+ segments.appendRange(s1, segments1End);
+ else if (Operation::shouldAddRemainingSegmentsFromSpan2 && s2 != segments2End)
+ segments.appendRange(s2, segments2End);
+
+ // Add the span.
+ if (!segments.isEmpty() || !result.isEmpty())
+ result.appendSpan(y, segments.data(), segments.data() + segments.size());
+ }
+
+ // Add any remaining spans.
+ if (Operation::shouldAddRemainingSpansFromShape1 && spans1 != spans1End)
+ result.appendSpans(shape1, spans1, spans1End);
+ else if (Operation::shouldAddRemainingSpansFromShape2 && spans2 != spans2End)
+ result.appendSpans(shape2, spans2, spans2End);
+
+ return result;
+}
+
+struct Region::Shape::UnionOperation {
+ static bool trySimpleOperation(const Shape& shape1, const Shape& shape2, Shape& result)
+ {
+ if (shape1.isEmpty()) {
+ result = shape2;
+ return true;
+ }
+
+ if (shape2.isEmpty()) {
+ result = shape1;
+ return true;
+ }
+
+ return false;
+ }
+
+ static const int opCode = 0;
+
+ static const bool shouldAddRemainingSegmentsFromSpan1 = true;
+ static const bool shouldAddRemainingSegmentsFromSpan2 = true;
+ static const bool shouldAddRemainingSpansFromShape1 = true;
+ static const bool shouldAddRemainingSpansFromShape2 = true;
+};
+
+Region::Shape Region::Shape::unionShapes(const Shape& shape1, const Shape& shape2)
+{
+ return shapeOperation<UnionOperation>(shape1, shape2);
+}
+
+struct Region::Shape::IntersectOperation {
+ static bool trySimpleOperation(const Shape& shape1, const Shape& shape2, Shape& result)
+ {
+ if (shape1.isEmpty()) {
+ result = Shape();
+ return true;
+ }
+
+ if (shape2.isEmpty()) {
+ result = shape1;
+ return true;
+ }
+
+ return false;
+ }
+
+ static const int opCode = 3;
+
+ static const bool shouldAddRemainingSegmentsFromSpan1 = false;
+ static const bool shouldAddRemainingSegmentsFromSpan2 = false;
+ static const bool shouldAddRemainingSpansFromShape1 = false;
+ static const bool shouldAddRemainingSpansFromShape2 = false;
+};
+
+Region::Shape Region::Shape::intersectShapes(const Shape& shape1, const Shape& shape2)
+{
+ return shapeOperation<IntersectOperation>(shape1, shape2);
+}
+
+struct Region::Shape::SubtractOperation {
+ static bool trySimpleOperation(const Shape& shape1, const Shape& shape2, Region::Shape& result)
+ {
+
+ if (shape1.isEmpty() || shape2.isEmpty()) {
+ result = Shape();
+ return true;
+ }
+
+ return false;
+ }
+
+ static const int opCode = 1;
+
+ static const bool shouldAddRemainingSegmentsFromSpan1 = true;
+ static const bool shouldAddRemainingSegmentsFromSpan2 = false;
+ static const bool shouldAddRemainingSpansFromShape1 = true;
+ static const bool shouldAddRemainingSpansFromShape2 = false;
+};
+
+Region::Shape Region::Shape::subtractShapes(const Shape& shape1, const Shape& shape2)
+{
+ return shapeOperation<SubtractOperation>(shape1, shape2);
+}
+
+#ifndef NDEBUG
+void Region::dump() const
+{
+ printf("Bounds: (%d, %d, %d, %d)\n",
+ m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height());
+ m_shape.dump();
+}
+#endif
+
+void Region::intersect(const Region& region)
+{
+ if (!m_bounds.intersects(region.m_bounds)) {
+ m_shape = Shape();
+ m_bounds = IntRect();
+ return;
+ }
+
+ Shape intersectedShape = Shape::intersectShapes(m_shape, region.m_shape);
+
+ m_shape.swap(intersectedShape);
+ m_bounds = m_shape.bounds();
+}
+
+void Region::unite(const Region& region)
+{
+ Shape unitedShape = Shape::unionShapes(m_shape, region.m_shape);
+
+ m_shape.swap(unitedShape);
+ m_bounds.unite(region.m_bounds);
+}
+
+void Region::subtract(const Region& region)
+{
+ Shape subtractedShape = Shape::subtractShapes(m_shape, region.m_shape);
+
+ m_shape.swap(subtractedShape);
+ m_bounds = m_shape.bounds();
+}
+
+void Region::translate(const IntSize& offset)
+{
+ m_bounds.move(offset);
+ m_shape.translate(offset);
+}
+
+} // namespace WebKit
+
diff --git a/Source/WebKit2/Platform/Region.h b/Source/WebKit2/Platform/Region.h
new file mode 100644
index 0000000..b44519f
--- /dev/null
+++ b/Source/WebKit2/Platform/Region.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Region_h
+#define Region_h
+
+#include <WebCore/IntRect.h>
+#include <wtf/Vector.h>
+
+#include <vector>
+
+namespace WebKit {
+
+class Region {
+public:
+ Region();
+ Region(const WebCore::IntRect&);
+
+ WebCore::IntRect bounds() const { return m_bounds; }
+ bool isEmpty() const { return m_bounds.isEmpty(); }
+
+ Vector<WebCore::IntRect> rects() const;
+
+ void unite(const Region&);
+ void intersect(const Region&);
+ void subtract(const Region&);
+
+ void translate(const WebCore::IntSize&);
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+private:
+ struct Span {
+ Span(int y, size_t segmentIndex)
+ : y(y), segmentIndex(segmentIndex)
+ {
+ }
+
+ int y;
+ size_t segmentIndex;
+ };
+
+ class Shape {
+ public:
+ Shape();
+ Shape(const WebCore::IntRect&);
+
+ WebCore::IntRect bounds() const;
+ bool isEmpty() const { return m_spans.isEmpty(); }
+
+ typedef const Span* SpanIterator;
+ SpanIterator spans_begin() const;
+ SpanIterator spans_end() const;
+
+ typedef const int* SegmentIterator;
+ SegmentIterator segments_begin(SpanIterator) const;
+ SegmentIterator segments_end(SpanIterator) const;
+
+ static Shape unionShapes(const Shape& shape1, const Shape& shape2);
+ static Shape intersectShapes(const Shape& shape1, const Shape& shape2);
+ static Shape subtractShapes(const Shape& shape1, const Shape& shape2);
+
+ void translate(const WebCore::IntSize&);
+ void swap(Shape&);
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+ private:
+ struct UnionOperation;
+ struct IntersectOperation;
+ struct SubtractOperation;
+
+ template<typename Operation>
+ static Shape shapeOperation(const Shape& shape1, const Shape& shape2);
+
+ void appendSegment(int x);
+ void appendSpan(int y);
+ void appendSpan(int y, SegmentIterator begin, SegmentIterator end);
+ void appendSpans(const Shape&, SpanIterator begin, SpanIterator end);
+
+ bool canCoalesce(SegmentIterator begin, SegmentIterator end);
+
+ // FIXME: These vectors should have inline sizes. Figure out a good optimal value.
+ Vector<int> m_segments;
+ Vector<Span> m_spans;
+ };
+
+ WebCore::IntRect m_bounds;
+ Shape m_shape;
+};
+
+static inline Region intersect(const Region& a, const Region& b)
+{
+ Region result(a);
+ result.intersect(b);
+
+ return result;
+}
+
+static inline Region subtract(const Region& a, const Region& b)
+{
+ Region result(a);
+ result.subtract(b);
+
+ return result;
+}
+
+static inline Region translate(const Region& region, const WebCore::IntSize& offset)
+{
+ Region result(region);
+ result.translate(offset);
+
+ return result;
+}
+
+} // namespace WebKit
+
+#endif // Region_h
diff --git a/Source/WebKit2/Platform/RunLoop.cpp b/Source/WebKit2/Platform/RunLoop.cpp
new file mode 100644
index 0000000..606aba1
--- /dev/null
+++ b/Source/WebKit2/Platform/RunLoop.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "RunLoop.h"
+
+#include "WorkItem.h"
+#include <wtf/StdLibExtras.h>
+
+static RunLoop* s_mainRunLoop;
+
+void RunLoop::initializeMainRunLoop()
+{
+ if (s_mainRunLoop)
+ return;
+ s_mainRunLoop = RunLoop::current();
+}
+
+RunLoop* RunLoop::current()
+{
+ DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<RunLoop>, runLoopData, ());
+ return &*runLoopData;
+}
+
+RunLoop* RunLoop::main()
+{
+ ASSERT(s_mainRunLoop);
+ return s_mainRunLoop;
+}
+
+void RunLoop::performWork()
+{
+ Vector<WorkItem*> workItemQueue;
+ {
+ MutexLocker locker(m_workItemQueueLock);
+ m_workItemQueue.swap(workItemQueue);
+ }
+
+ for (size_t i = 0; i < workItemQueue.size(); ++i) {
+ OwnPtr<WorkItem> item(workItemQueue[i]);
+ item->execute();
+ }
+}
+
+void RunLoop::scheduleWork(PassOwnPtr<WorkItem> item)
+{
+ MutexLocker locker(m_workItemQueueLock);
+ m_workItemQueue.append(item.leakPtr());
+
+ wakeUp();
+}
diff --git a/Source/WebKit2/Platform/RunLoop.h b/Source/WebKit2/Platform/RunLoop.h
new file mode 100644
index 0000000..aa87506
--- /dev/null
+++ b/Source/WebKit2/Platform/RunLoop.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RunLoop_h
+#define RunLoop_h
+
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/ThreadSpecific.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+#if PLATFORM(GTK)
+typedef struct _GSource GSource;
+typedef struct _GMainLoop GMainLoop;
+typedef struct _GMainContext GMainContext;
+typedef int gboolean;
+#endif
+
+class WorkItem;
+
+class RunLoop {
+public:
+ // Must be called from the main thread.
+ static void initializeMainRunLoop();
+
+ static RunLoop* current();
+ static RunLoop* main();
+
+ void scheduleWork(PassOwnPtr<WorkItem>);
+
+ static void run();
+ void stop();
+
+ class TimerBase {
+ friend class RunLoop;
+ public:
+ TimerBase(RunLoop*);
+ virtual ~TimerBase();
+
+ void startRepeating(double repeatInterval) { start(repeatInterval, true); }
+ void startOneShot(double interval) { start(interval, false); }
+
+ void stop();
+ bool isActive() const;
+
+ virtual void fired() = 0;
+
+ private:
+ void start(double nextFireInterval, bool repeat);
+
+ RunLoop* m_runLoop;
+
+#if PLATFORM(WIN)
+ static void timerFired(RunLoop*, uint64_t ID);
+ uint64_t m_ID;
+ bool m_isRepeating;
+#elif PLATFORM(MAC)
+ static void timerFired(CFRunLoopTimerRef, void*);
+ CFRunLoopTimerRef m_timer;
+#elif PLATFORM(QT)
+ static void timerFired(RunLoop*, int ID);
+ int m_ID;
+ bool m_isRepeating;
+#elif PLATFORM(GTK)
+ static gboolean oneShotTimerFired(RunLoop::TimerBase*);
+ static gboolean repeatingTimerFired(RunLoop::TimerBase*);
+ void resetTimerSource();
+ GSource* m_timerSource;
+#endif
+ };
+
+ template <typename TimerFiredClass>
+ class Timer : public TimerBase {
+ public:
+ typedef void (TimerFiredClass::*TimerFiredFunction)();
+
+ Timer(RunLoop* runLoop, TimerFiredClass* o, TimerFiredFunction f)
+ : TimerBase(runLoop)
+ , m_object(o)
+ , m_function(f)
+ {
+ }
+
+ private:
+ virtual void fired() { (m_object->*m_function)(); }
+
+ TimerFiredClass* m_object;
+ TimerFiredFunction m_function;
+ };
+
+private:
+ friend class WTF::ThreadSpecific<RunLoop>;
+
+ RunLoop();
+ ~RunLoop();
+
+ void performWork();
+ void wakeUp();
+
+ Mutex m_workItemQueueLock;
+ Vector<WorkItem*> m_workItemQueue;
+
+#if PLATFORM(WIN)
+ static bool registerRunLoopMessageWindowClass();
+ static LRESULT CALLBACK RunLoopWndProc(HWND, UINT, WPARAM, LPARAM);
+ LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+ HWND m_runLoopMessageWindow;
+
+ typedef HashMap<uint64_t, TimerBase*> TimerMap;
+ TimerMap m_activeTimers;
+#elif PLATFORM(MAC)
+ static void performWork(void*);
+ CFRunLoopRef m_runLoop;
+ CFRunLoopSourceRef m_runLoopSource;
+#elif PLATFORM(QT)
+ typedef HashMap<int, TimerBase*> TimerMap;
+ TimerMap m_activeTimers;
+ class TimerObject;
+ TimerObject* m_timerObject;
+#elif PLATFORM(GTK)
+public:
+ static gboolean queueWork(RunLoop*);
+ GMainLoop* mainLoop();
+private:
+ GMainContext* m_runLoopContext;
+ GMainLoop* m_runLoopMain;
+#endif
+};
+
+#endif // RunLoop_h
diff --git a/Source/WebKit2/Platform/SharedMemory.h b/Source/WebKit2/Platform/SharedMemory.h
new file mode 100644
index 0000000..05dc0dd
--- /dev/null
+++ b/Source/WebKit2/Platform/SharedMemory.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SharedMemory_h
+#define SharedMemory_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#if PLATFORM(QT)
+#include <QtGlobal>
+QT_BEGIN_NAMESPACE
+class QSharedMemory;
+QT_END_NAMESPACE
+#include <wtf/text/WTFString.h>
+#endif
+
+namespace CoreIPC {
+ class ArgumentDecoder;
+ class ArgumentEncoder;
+}
+
+namespace WebKit {
+
+class SharedMemory : public RefCounted<SharedMemory> {
+public:
+ enum Protection {
+ ReadOnly,
+ ReadWrite
+ };
+
+ class Handle : Noncopyable {
+ public:
+ Handle();
+ ~Handle();
+
+ bool isNull() const;
+
+ void encode(CoreIPC::ArgumentEncoder*) const;
+ static bool decode(CoreIPC::ArgumentDecoder*, Handle&);
+
+ private:
+ friend class SharedMemory;
+#if PLATFORM(MAC)
+ mutable mach_port_t m_port;
+#elif PLATFORM(WIN)
+ mutable HANDLE m_handle;
+#elif PLATFORM(QT)
+ mutable String m_key;
+#endif
+ size_t m_size;
+ };
+
+ // Create a shared memory object with the given size. Will return 0 on failure.
+ static PassRefPtr<SharedMemory> create(size_t);
+
+ // Create a shared memory object from the given handle and the requested protection. Will return 0 on failure.
+ static PassRefPtr<SharedMemory> create(const Handle&, Protection);
+
+ ~SharedMemory();
+
+ bool createHandle(Handle&, Protection);
+
+ size_t size() const { return m_size; }
+ void* data() const { return m_data; }
+
+ // Return the system page size in bytes.
+ static unsigned systemPageSize();
+
+private:
+ size_t m_size;
+ void* m_data;
+#if PLATFORM(WIN)
+ HANDLE m_handle;
+#elif PLATFORM(QT)
+ QSharedMemory* m_impl;
+#endif
+};
+
+};
+
+#endif // SharedMemory_h
diff --git a/Source/WebKit2/Platform/WorkItem.h b/Source/WebKit2/Platform/WorkItem.h
new file mode 100644
index 0000000..64bff58
--- /dev/null
+++ b/Source/WebKit2/Platform/WorkItem.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkItem_h
+#define WorkItem_h
+
+#include <wtf/PassOwnPtr.h>
+
+class WorkItem {
+public:
+ template<typename C>
+ static PassOwnPtr<WorkItem> create(C*, void (C::*)());
+
+ template<typename C, typename T0>
+ static PassOwnPtr<WorkItem> create(C*, void (C::*)(T0), T0);
+
+ template<typename C, typename T0, typename T1>
+ static PassOwnPtr<WorkItem> create(C*, void (C::*)(T0, T1), T0, T1);
+
+ static PassOwnPtr<WorkItem> create(void (*)());
+
+ virtual ~WorkItem() { }
+ virtual void execute() = 0;
+
+protected:
+ WorkItem() { }
+
+private:
+ WorkItem(const WorkItem&);
+ WorkItem& operator=(const WorkItem&);
+};
+
+template <typename C>
+class MemberFunctionWorkItem0 : private WorkItem {
+ // We only allow WorkItem to create this.
+ friend class WorkItem;
+
+ typedef void (C::*FunctionType)();
+
+ MemberFunctionWorkItem0(C* ptr, FunctionType function)
+ : m_ptr(ptr)
+ , m_function(function)
+ {
+ m_ptr->ref();
+ }
+
+ ~MemberFunctionWorkItem0()
+ {
+ m_ptr->deref();
+ }
+
+ virtual void execute()
+ {
+ (m_ptr->*m_function)();
+ }
+
+ C* m_ptr;
+ FunctionType m_function;
+};
+
+template<typename C, typename T0>
+class MemberFunctionWorkItem1 : private WorkItem {
+ // We only allow WorkItem to create this.
+ friend class WorkItem;
+
+ typedef void (C::*FunctionType)(T0);
+
+ MemberFunctionWorkItem1(C* ptr, FunctionType function, T0 t0)
+ : m_ptr(ptr)
+ , m_function(function)
+ , m_t0(t0)
+ {
+ m_ptr->ref();
+ }
+
+ ~MemberFunctionWorkItem1()
+ {
+ m_ptr->deref();
+ }
+
+ virtual void execute()
+ {
+ (m_ptr->*m_function)(m_t0);
+ }
+
+ C* m_ptr;
+ FunctionType m_function;
+ T0 m_t0;
+};
+
+template<typename C, typename T0, typename T1>
+class MemberFunctionWorkItem2 : private WorkItem {
+ // We only allow WorkItem to create this.
+ friend class WorkItem;
+
+ typedef void (C::*FunctionType)(T0, T1);
+
+ MemberFunctionWorkItem2(C* ptr, FunctionType function, T0 t0, T1 t1)
+ : m_ptr(ptr)
+ , m_function(function)
+ , m_t0(t0)
+ , m_t1(t1)
+ {
+ m_ptr->ref();
+ }
+
+ ~MemberFunctionWorkItem2()
+ {
+ m_ptr->deref();
+ }
+
+ virtual void execute()
+ {
+ (m_ptr->*m_function)(m_t0, m_t1);
+ }
+
+ C* m_ptr;
+ FunctionType m_function;
+ T0 m_t0;
+ T1 m_t1;
+};
+
+template<typename C>
+PassOwnPtr<WorkItem> WorkItem::create(C* ptr, void (C::*function)())
+{
+ return adoptPtr(static_cast<WorkItem*>(new MemberFunctionWorkItem0<C>(ptr, function)));
+}
+
+template<typename C, typename T0>
+PassOwnPtr<WorkItem> WorkItem::create(C* ptr, void (C::*function)(T0), T0 t0)
+{
+ return adoptPtr(static_cast<WorkItem*>(new MemberFunctionWorkItem1<C, T0>(ptr, function, t0)));
+}
+
+template<typename C, typename T0, typename T1>
+PassOwnPtr<WorkItem> WorkItem::create(C* ptr, void (C::*function)(T0, T1), T0 t0, T1 t1)
+{
+ return adoptPtr(static_cast<WorkItem*>(new MemberFunctionWorkItem2<C, T0, T1>(ptr, function, t0, t1)));
+}
+
+class FunctionWorkItem0 : private WorkItem {
+ // We only allow WorkItem to create this.
+ friend class WorkItem;
+
+ typedef void (*FunctionType)();
+
+ FunctionWorkItem0(FunctionType function)
+ : m_function(function)
+ {
+ }
+
+ virtual void execute()
+ {
+ (*m_function)();
+ }
+
+ FunctionType m_function;
+};
+
+inline PassOwnPtr<WorkItem> WorkItem::create(void (*function)())
+{
+ return adoptPtr(static_cast<WorkItem*>(new FunctionWorkItem0(function)));
+}
+
+#endif // WorkItem_h
diff --git a/Source/WebKit2/Platform/WorkQueue.cpp b/Source/WebKit2/Platform/WorkQueue.cpp
new file mode 100644
index 0000000..de82c80
--- /dev/null
+++ b/Source/WebKit2/Platform/WorkQueue.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "WorkQueue.h"
+
+WorkQueue::WorkQueue(const char* name)
+ : m_isValid(true)
+{
+ platformInitialize(name);
+}
+
+WorkQueue::~WorkQueue()
+{
+#if !ASSERT_DISABLED
+ MutexLocker locker(m_isValidMutex);
+ ASSERT(!m_isValid);
+#endif
+}
+
+void WorkQueue::invalidate()
+{
+ {
+ MutexLocker locker(m_isValidMutex);
+ m_isValid = false;
+ }
+
+ platformInvalidate();
+}
diff --git a/Source/WebKit2/Platform/WorkQueue.h b/Source/WebKit2/Platform/WorkQueue.h
new file mode 100644
index 0000000..78fa8b7
--- /dev/null
+++ b/Source/WebKit2/Platform/WorkQueue.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkQueue_h
+#define WorkQueue_h
+
+#if PLATFORM(MAC)
+#if HAVE(DISPATCH_H)
+#include <dispatch/dispatch.h>
+#endif
+#endif
+
+#include "WorkItem.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(QT)
+class QLocalSocket;
+class QObject;
+class QThread;
+#elif PLATFORM(GTK)
+typedef struct _GMainContext GMainContext;
+typedef struct _GMainLoop GMainLoop;
+#endif
+
+class WorkQueue {
+public:
+ explicit WorkQueue(const char* name);
+ ~WorkQueue();
+
+ // Will schedule the given work item to run as soon as possible.
+ void scheduleWork(PassOwnPtr<WorkItem>);
+
+ // Will schedule the given work item to run after the given delay (in seconds).
+ void scheduleWorkAfterDelay(PassOwnPtr<WorkItem>, double delay);
+
+ void invalidate();
+
+#if PLATFORM(MAC)
+ enum MachPortEventType {
+ // Fired when there is data on the given receive right.
+ MachPortDataAvailable,
+
+ // Fired when the receive right for this send right has been destroyed.
+ MachPortDeadNameNotification
+ };
+
+ // Will execute the given work item whenever the given mach port event fires.
+ // Note that this will adopt the mach port and destroy it when the work queue is invalidated.
+ void registerMachPortEventHandler(mach_port_t, MachPortEventType, PassOwnPtr<WorkItem>);
+ void unregisterMachPortEventHandler(mach_port_t);
+#elif PLATFORM(WIN)
+ void registerHandle(HANDLE, PassOwnPtr<WorkItem>);
+ void unregisterAndCloseHandle(HANDLE);
+#elif PLATFORM(QT)
+ void connectSignal(QObject*, const char* signal, PassOwnPtr<WorkItem>);
+ void disconnectSignal(QObject*, const char* signal);
+
+ void moveSocketToWorkThread(QLocalSocket*);
+#elif PLATFORM(GTK)
+ void registerEventSourceHandler(int, int, PassOwnPtr<WorkItem>);
+ void unregisterEventSourceHandler(int);
+#endif
+
+private:
+ // FIXME: Use an atomic boolean here instead.
+ Mutex m_isValidMutex;
+ bool m_isValid;
+
+ void platformInitialize(const char* name);
+ void platformInvalidate();
+
+#if PLATFORM(MAC)
+#if HAVE(DISPATCH_H)
+ static void executeWorkItem(void*);
+ Mutex m_eventSourcesMutex;
+ class EventSource;
+ HashMap<mach_port_t, EventSource*> m_eventSources;
+ dispatch_queue_t m_dispatchQueue;
+#endif
+#elif PLATFORM(WIN)
+ class WorkItemWin : public ThreadSafeShared<WorkItemWin> {
+ public:
+ static PassRefPtr<WorkItemWin> create(PassOwnPtr<WorkItem>, WorkQueue*);
+ virtual ~WorkItemWin();
+
+ WorkItem* item() const { return m_item.get(); }
+ WorkQueue* queue() const { return m_queue; }
+
+ protected:
+ WorkItemWin(PassOwnPtr<WorkItem>, WorkQueue*);
+
+ private:
+ OwnPtr<WorkItem> m_item;
+ WorkQueue* m_queue;
+ };
+
+ class HandleWorkItem : public WorkItemWin {
+ public:
+ static PassRefPtr<HandleWorkItem> createByAdoptingHandle(HANDLE, PassOwnPtr<WorkItem>, WorkQueue*);
+ virtual ~HandleWorkItem();
+
+ void setWaitHandle(HANDLE waitHandle) { m_waitHandle = waitHandle; }
+ HANDLE waitHandle() const { return m_waitHandle; }
+
+ private:
+ HandleWorkItem(HANDLE, PassOwnPtr<WorkItem>, WorkQueue*);
+
+ HANDLE m_handle;
+ HANDLE m_waitHandle;
+ };
+
+ static void CALLBACK handleCallback(void* context, BOOLEAN timerOrWaitFired);
+ static DWORD WINAPI workThreadCallback(void* context);
+
+ bool tryRegisterAsWorkThread();
+ void unregisterAsWorkThread();
+ void performWorkOnRegisteredWorkThread();
+
+ static void unregisterWaitAndDestroyItemSoon(PassRefPtr<HandleWorkItem>);
+ static DWORD WINAPI unregisterWaitAndDestroyItemCallback(void* context);
+
+ volatile LONG m_isWorkThreadRegistered;
+
+ Mutex m_workItemQueueLock;
+ Vector<RefPtr<WorkItemWin> > m_workItemQueue;
+
+ Mutex m_handlesLock;
+ HashMap<HANDLE, RefPtr<HandleWorkItem> > m_handles;
+#elif PLATFORM(QT)
+ class WorkItemQt;
+ HashMap<QObject*, WorkItemQt*> m_signalListeners;
+ QThread* m_workThread;
+ friend class WorkItemQt;
+#elif PLATFORM(GTK)
+ static void* startWorkQueueThread(WorkQueue*);
+ void workQueueThreadBody();
+
+ ThreadIdentifier m_workQueueThread;
+ GMainContext* m_eventContext;
+ Mutex m_eventLoopLock;
+ GMainLoop* m_eventLoop;
+ Mutex m_eventSourcesLock;
+ class EventSource;
+ HashMap<int, Vector<EventSource*> > m_eventSources;
+ typedef HashMap<int, Vector<EventSource*> >::iterator EventSourceIterator;
+#endif
+};
+
+#endif // WorkQueue_h
diff --git a/Source/WebKit2/Platform/cg/CGUtilities.cpp b/Source/WebKit2/Platform/cg/CGUtilities.cpp
new file mode 100644
index 0000000..1e5dd33
--- /dev/null
+++ b/Source/WebKit2/Platform/cg/CGUtilities.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CGUtilities.h"
+
+#include <wtf/RetainPtr.h>
+
+namespace WebKit {
+
+void paintBitmapContext(CGContextRef context, CGContextRef bitmapContext, CGPoint destination, CGRect source)
+{
+ void* bitmapData = CGBitmapContextGetData(bitmapContext);
+ ASSERT(bitmapData);
+
+ size_t imageWidth = CGBitmapContextGetWidth(bitmapContext);
+ size_t imageHeight = CGBitmapContextGetHeight(bitmapContext);
+
+ size_t bytesPerRow = CGBitmapContextGetBytesPerRow(bitmapContext);
+
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithData(0, bitmapData, bytesPerRow * imageHeight, 0));
+ RetainPtr<CGImageRef> image(AdoptCF, CGImageCreate(imageWidth, imageHeight,
+ CGBitmapContextGetBitsPerComponent(bitmapContext),
+ CGBitmapContextGetBitsPerPixel(bitmapContext),
+ bytesPerRow,
+ CGBitmapContextGetColorSpace(bitmapContext),
+ CGBitmapContextGetBitmapInfo(bitmapContext),
+ dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+
+ CGContextSaveGState(context);
+
+ CGContextClipToRect(context, CGRectMake(destination.x, destination.y, source.size.width, source.size.height));
+ CGContextScaleCTM(context, 1, -1);
+
+ CGFloat destX = destination.x - source.origin.x;
+ CGFloat destY = -static_cast<CGFloat>(imageHeight) - destination.y + source.origin.y;
+
+ CGContextDrawImage(context, CGRectMake(destX, destY, imageWidth, imageHeight), image.get());
+ CGContextRestoreGState(context);
+}
+
+} // namespace WebKit
+
diff --git a/Source/WebKit2/Platform/cg/CGUtilities.h b/Source/WebKit2/Platform/cg/CGUtilities.h
new file mode 100644
index 0000000..3dca654
--- /dev/null
+++ b/Source/WebKit2/Platform/cg/CGUtilities.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CGUtilities_h
+#define CGUtilities_h
+
+namespace WebKit {
+
+void paintBitmapContext(CGContextRef, CGContextRef bitmapContext, CGPoint destination, CGRect source);
+
+} // namespace WebKit
+
+#endif // CGUtilities_h
diff --git a/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp b/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp
new file mode 100644
index 0000000..2c183fa
--- /dev/null
+++ b/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "RunLoop.h"
+
+#include "WKBase.h"
+#include <glib.h>
+
+RunLoop::RunLoop()
+{
+ m_runLoopContext = g_main_context_default();
+ ASSERT(m_runLoopContext);
+ m_runLoopMain = g_main_loop_new(m_runLoopContext, FALSE);
+ ASSERT(m_runLoopMain);
+}
+
+RunLoop::~RunLoop()
+{
+ if (m_runLoopMain) {
+ g_main_loop_quit(m_runLoopMain);
+ g_main_loop_unref(m_runLoopMain);
+ }
+
+ if (m_runLoopContext)
+ g_main_context_unref(m_runLoopContext);
+}
+
+void RunLoop::run()
+{
+ g_main_loop_run(RunLoop::main()->mainLoop());
+}
+
+GMainLoop* RunLoop::mainLoop()
+{
+ return m_runLoopMain;
+}
+
+void RunLoop::stop()
+{
+ g_main_loop_quit(m_runLoopMain);
+}
+
+gboolean RunLoop::queueWork(RunLoop* runLoop)
+{
+ runLoop->performWork();
+ return FALSE;
+}
+
+void RunLoop::wakeUp()
+{
+ GSource* source = g_timeout_source_new(0);
+ g_source_set_callback(source, reinterpret_cast<GSourceFunc>(&RunLoop::queueWork), this, 0);
+ g_source_attach(source, m_runLoopContext);
+
+ g_main_context_wakeup(m_runLoopContext);
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_timerSource(0)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::resetTimerSource()
+{
+ m_timerSource = 0;
+}
+
+gboolean RunLoop::TimerBase::oneShotTimerFired(RunLoop::TimerBase* timer)
+{
+ timer->fired();
+ timer->resetTimerSource();
+ return FALSE;
+}
+
+gboolean RunLoop::TimerBase::repeatingTimerFired(RunLoop::TimerBase* timer)
+{
+ timer->fired();
+ return TRUE;
+}
+
+void RunLoop::TimerBase::start(double fireInterval, bool repeat)
+{
+ if (m_timerSource)
+ stop();
+
+ m_timerSource = g_timeout_source_new(static_cast<guint>(fireInterval));
+ if (repeat)
+ g_source_set_callback(m_timerSource, reinterpret_cast<GSourceFunc>(&RunLoop::TimerBase::repeatingTimerFired), this, 0);
+ else
+ g_source_set_callback(m_timerSource, reinterpret_cast<GSourceFunc>(&RunLoop::TimerBase::oneShotTimerFired), this, 0);
+ g_source_attach(m_timerSource, m_runLoop->m_runLoopContext);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ if (!m_timerSource)
+ return;
+
+ g_source_destroy(m_timerSource);
+ m_timerSource = 0;
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_timerSource;
+}
diff --git a/Source/WebKit2/Platform/gtk/SharedMemoryGtk.cpp b/Source/WebKit2/Platform/gtk/SharedMemoryGtk.cpp
new file mode 100644
index 0000000..93fda95
--- /dev/null
+++ b/Source/WebKit2/Platform/gtk/SharedMemoryGtk.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "SharedMemory.h"
+
+#include "NotImplemented.h"
+
+namespace WebKit {
+
+SharedMemory::Handle::Handle()
+{
+ notImplemented();
+}
+
+SharedMemory::Handle::~Handle()
+{
+ notImplemented();
+}
+
+void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
+{
+ notImplemented();
+}
+
+bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
+{
+ notImplemented();
+ return false;
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
+{
+ notImplemented();
+ return 0;
+}
+
+SharedMemory::~SharedMemory()
+{
+ notImplemented();
+}
+
+bool SharedMemory::createHandle(Handle& handle, Protection protection)
+{
+ notImplemented();
+ return false;
+}
+
+unsigned SharedMemory::systemPageSize()
+{
+ unsigned pageSize = 0;
+
+ return pageSize;
+}
+
+}
diff --git a/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp b/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp
new file mode 100644
index 0000000..995b531
--- /dev/null
+++ b/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "WorkQueue.h"
+
+#include "NotImplemented.h"
+#include "WKBase.h"
+#include <glib.h>
+
+// WorkQueue::EventSource
+class WorkQueue::EventSource {
+public:
+ EventSource(GSource* dispatchSource, PassOwnPtr<WorkItem> workItem, WorkQueue* workQueue)
+ : m_dispatchSource(dispatchSource)
+ , m_workItem(workItem)
+ , m_workQueue(workQueue)
+ {
+ }
+
+ GSource* dispatchSource() { return m_dispatchSource; }
+
+ static gboolean performWorkOnce(EventSource* eventSource)
+ {
+ ASSERT(eventSource);
+ WorkQueue* queue = eventSource->m_workQueue;
+ {
+ MutexLocker locker(queue->m_isValidMutex);
+ if (!queue->m_isValid)
+ return FALSE;
+ }
+
+ eventSource->m_workItem->execute();
+ return FALSE;
+ }
+
+ static gboolean performWork(GIOChannel* channel, GIOCondition condition, EventSource* eventSource)
+ {
+ ASSERT(eventSource);
+
+ if (!(condition & G_IO_IN) && !(condition & G_IO_HUP) && !(condition & G_IO_ERR))
+ return FALSE;
+
+ WorkQueue* queue = eventSource->m_workQueue;
+ {
+ MutexLocker locker(queue->m_isValidMutex);
+ if (!queue->m_isValid)
+ return FALSE;
+ }
+
+ eventSource->m_workItem->execute();
+
+ if ((condition & G_IO_HUP) || (condition & G_IO_ERR))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ static void deleteEventSource(EventSource* eventSource)
+ {
+ ASSERT(eventSource);
+ delete eventSource;
+ }
+
+public:
+ GSource* m_dispatchSource;
+ PassOwnPtr<WorkItem> m_workItem;
+ WorkQueue* m_workQueue;
+};
+
+// WorkQueue
+void WorkQueue::platformInitialize(const char* name)
+{
+ m_eventContext = g_main_context_new();
+ ASSERT(m_eventContext);
+ m_eventLoop = g_main_loop_new(m_eventContext, FALSE);
+ ASSERT(m_eventLoop);
+ m_workQueueThread = createThread(reinterpret_cast<WTF::ThreadFunction>(&WorkQueue::startWorkQueueThread), this, name);
+}
+
+void WorkQueue::platformInvalidate()
+{
+ MutexLocker locker(m_eventLoopLock);
+
+ if (m_eventLoop) {
+ if (g_main_loop_is_running(m_eventLoop))
+ g_main_loop_quit(m_eventLoop);
+
+ g_main_loop_unref(m_eventLoop);
+ m_eventLoop = 0;
+ }
+
+ if (m_eventContext) {
+ g_main_context_unref(m_eventContext);
+ m_eventContext = 0;
+ }
+}
+
+void* WorkQueue::startWorkQueueThread(WorkQueue* workQueue)
+{
+ workQueue->workQueueThreadBody();
+ return 0;
+}
+
+void WorkQueue::workQueueThreadBody()
+{
+ g_main_loop_run(m_eventLoop);
+}
+
+void WorkQueue::registerEventSourceHandler(int fileDescriptor, int condition, PassOwnPtr<WorkItem> item)
+{
+ GIOChannel* channel = g_io_channel_unix_new(fileDescriptor);
+ ASSERT(channel);
+ GSource* dispatchSource = g_io_create_watch(channel, static_cast<GIOCondition>(condition));
+ ASSERT(dispatchSource);
+ EventSource* eventSource = new EventSource(dispatchSource, item, this);
+ ASSERT(eventSource);
+
+ g_source_set_callback(dispatchSource, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWork),
+ eventSource, reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));
+
+ // Set up the event sources under the mutex since this is shared across multiple threads.
+ {
+ MutexLocker locker(m_eventSourcesLock);
+ ASSERT(!m_eventSources.contains(fileDescriptor));
+ Vector<EventSource*> sources;
+ EventSourceIterator it = m_eventSources.find(fileDescriptor);
+ if (it != m_eventSources.end())
+ sources = it->second;
+
+ sources.append(eventSource);
+ m_eventSources.set(fileDescriptor, sources);
+ }
+
+ // Attach the event source to the GMainContext under the mutex since this is shared across multiple threads.
+ {
+ MutexLocker locker(m_eventLoopLock);
+ g_source_attach(dispatchSource, m_eventContext);
+ }
+}
+
+void WorkQueue::unregisterEventSourceHandler(int fileDescriptor)
+{
+ ASSERT(fileDescriptor);
+
+ MutexLocker locker(m_eventSourcesLock);
+
+ EventSourceIterator it = m_eventSources.find(fileDescriptor);
+ ASSERT(it != m_eventSources.end());
+ ASSERT(m_eventSources.contains(fileDescriptor));
+
+ if (it != m_eventSources.end()) {
+ Vector<EventSource*> sources = it->second;
+ for (unsigned i = 0; i < sources.size(); i++)
+ g_source_destroy(sources[i]->dispatchSource());
+
+ m_eventSources.remove(it);
+ }
+}
+
+void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
+{
+ GSource* dispatchSource = g_timeout_source_new(0);
+ ASSERT(dispatchSource);
+ EventSource* eventSource = new EventSource(dispatchSource, item, this);
+
+ g_source_set_callback(dispatchSource,
+ reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce),
+ eventSource,
+ reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));
+ {
+ MutexLocker locker(m_eventLoopLock);
+ g_source_attach(dispatchSource, m_eventContext);
+ }
+}
+
+void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem>, double)
+{
+ notImplemented();
+}
diff --git a/Source/WebKit2/Platform/mac/MachUtilities.cpp b/Source/WebKit2/Platform/mac/MachUtilities.cpp
new file mode 100644
index 0000000..edb17dc
--- /dev/null
+++ b/Source/WebKit2/Platform/mac/MachUtilities.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "MachUtilities.h"
+
+#include <mach/task.h>
+
+void setMachPortQueueLength(mach_port_t receivePort, mach_port_msgcount_t queueLength)
+{
+ mach_port_limits_t portLimits;
+ portLimits.mpl_qlimit = queueLength;
+
+ mach_port_set_attributes(mach_task_self(), receivePort, MACH_PORT_LIMITS_INFO, reinterpret_cast<mach_port_info_t>(&portLimits), MACH_PORT_LIMITS_INFO_COUNT);
+}
+
+mach_port_t machExceptionPort()
+{
+ exception_mask_t exceptionMasks[EXC_TYPES_COUNT];
+ exception_port_t exceptionHandlers[EXC_TYPES_COUNT];
+ exception_behavior_t exceptionBehaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t exceptionFlavors[EXC_TYPES_COUNT];
+ mach_msg_type_number_t numExceptionMasks;
+
+ kern_return_t kr = task_get_exception_ports(mach_task_self(), EXC_MASK_CRASH, exceptionMasks, &numExceptionMasks, exceptionHandlers, exceptionBehaviors, exceptionFlavors);
+ if (kr != KERN_SUCCESS) {
+ ASSERT_NOT_REACHED();
+ return MACH_PORT_NULL;
+ }
+
+ // We're just interested in the first exception handler.
+ return exceptionHandlers[0];
+}
+
+void setMachExceptionPort(mach_port_t exceptionPort)
+{
+ // Assert that we dont try to call setMachExceptionPort more than once per process.
+#if !ASSERT_DISABLED
+ static mach_port_t taskExceptionPort = MACH_PORT_NULL;
+ ASSERT(taskExceptionPort == MACH_PORT_NULL);
+ taskExceptionPort = exceptionPort;
+#endif
+
+ if (task_set_exception_ports(mach_task_self(), EXC_MASK_CRASH, exceptionPort, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, MACHINE_THREAD_STATE) != KERN_SUCCESS)
+ ASSERT_NOT_REACHED();
+}
diff --git a/Source/WebKit2/Platform/mac/MachUtilities.h b/Source/WebKit2/Platform/mac/MachUtilities.h
new file mode 100644
index 0000000..a8d0d6f
--- /dev/null
+++ b/Source/WebKit2/Platform/mac/MachUtilities.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MachUtilities_h
+#define MachUtilities_h
+
+#include <mach/mach_port.h>
+
+void setMachPortQueueLength(mach_port_t, mach_port_msgcount_t queueLength);
+
+mach_port_t machExceptionPort();
+void setMachExceptionPort(mach_port_t exceptionPort);
+
+#endif // MachUtilities_h
diff --git a/Source/WebKit2/Platform/mac/ModuleMac.mm b/Source/WebKit2/Platform/mac/ModuleMac.mm
new file mode 100644
index 0000000..fa38745
--- /dev/null
+++ b/Source/WebKit2/Platform/mac/ModuleMac.mm
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Module.h"
+
+namespace WebKit {
+
+bool Module::load()
+{
+ RetainPtr<CFStringRef> bundlePath(AdoptCF, m_path.createCFString());
+ RetainPtr<CFURLRef> bundleURL(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundlePath.get(), kCFURLPOSIXPathStyle, FALSE));
+ if (!bundleURL)
+ return false;
+
+ RetainPtr<CFBundleRef> bundle(AdoptCF, CFBundleCreate(kCFAllocatorDefault, bundleURL.get()));
+ if (!bundle)
+ return false;
+
+ if (!CFBundleLoadExecutable(bundle.get()))
+ return false;
+
+ m_bundle.adoptCF(bundle.releaseRef());
+ return true;
+}
+
+void Module::unload()
+{
+ // See the comment in Module.h for why we leak the bundle here.
+ m_bundle.releaseRef();
+}
+
+void* Module::platformFunctionPointer(const char* functionName) const
+{
+ if (!m_bundle)
+ return 0;
+ RetainPtr<CFStringRef> functionNameString(AdoptCF, CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, functionName, kCFStringEncodingASCII, kCFAllocatorNull));
+ return CFBundleGetFunctionPointerForName(m_bundle.get(), functionNameString.get());
+}
+
+}
diff --git a/Source/WebKit2/Platform/mac/RunLoopMac.mm b/Source/WebKit2/Platform/mac/RunLoopMac.mm
new file mode 100644
index 0000000..ca044f3
--- /dev/null
+++ b/Source/WebKit2/Platform/mac/RunLoopMac.mm
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "RunLoop.h"
+
+#include "WorkItem.h"
+
+void RunLoop::performWork(void* context)
+{
+ static_cast<RunLoop*>(context)->performWork();
+}
+
+RunLoop::RunLoop()
+{
+ m_runLoop = CFRunLoopGetCurrent();
+
+ CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, performWork };
+ m_runLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ CFRunLoopAddSource(m_runLoop, m_runLoopSource, kCFRunLoopCommonModes);
+}
+
+RunLoop::~RunLoop()
+{
+ // FIXME: Tear down the work item queue here.
+ CFRunLoopSourceInvalidate(m_runLoopSource);
+ CFRelease(m_runLoopSource);
+}
+
+void RunLoop::run()
+{
+ if (current() == main()) {
+ // Use -[NSApplication run] for the main run loop.
+ [NSApp run];
+ } else {
+ // Otherwise, use NSRunLoop. We do this because it sets up an autorelease pool for us.
+ [[NSRunLoop currentRunLoop] run];
+ }
+}
+
+void RunLoop::stop()
+{
+ ASSERT(m_runLoop == CFRunLoopGetCurrent());
+
+ if (m_runLoop == main()->m_runLoop) {
+ [NSApp stop:nil];
+ NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined
+ location:NSMakePoint(0, 0)
+ modifierFlags:0
+ timestamp:0.0
+ windowNumber:0
+ context:nil
+ subtype: 0
+ data1:0
+ data2:0];
+ [NSApp postEvent:event atStart:true];
+ } else
+ CFRunLoopStop(m_runLoop);
+}
+
+void RunLoop::wakeUp()
+{
+ CFRunLoopSourceSignal(m_runLoopSource);
+ CFRunLoopWakeUp(m_runLoop);
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(CFRunLoopTimerRef, void* context)
+{
+ TimerBase* timer = static_cast<TimerBase*>(context);
+ timer->fired();
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_timer(0)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ if (m_timer)
+ stop();
+
+ CFRunLoopTimerContext context = { 0, this, 0, 0, 0 };
+ CFTimeInterval repeatInterval = repeat ? nextFireInterval : 0;
+ m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + nextFireInterval, repeatInterval, 0, 0, timerFired, &context);
+ CFRunLoopAddTimer(m_runLoop->m_runLoop, m_timer, kCFRunLoopCommonModes);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ if (!m_timer)
+ return;
+
+ CFRunLoopTimerInvalidate(m_timer);
+ CFRelease(m_timer);
+ m_timer = 0;
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_timer && CFRunLoopTimerIsValid(m_timer);
+}
diff --git a/Source/WebKit2/Platform/mac/SharedMemoryMac.cpp b/Source/WebKit2/Platform/mac/SharedMemoryMac.cpp
new file mode 100644
index 0000000..07f942c
--- /dev/null
+++ b/Source/WebKit2/Platform/mac/SharedMemoryMac.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "SharedMemory.h"
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include "Arguments.h"
+#include "MachPort.h"
+#include <mach/mach_port.h>
+#include <mach/mach_vm.h>
+#include <mach/vm_map.h>
+#include <wtf/RefPtr.h>
+
+namespace WebKit {
+
+SharedMemory::Handle::Handle()
+ : m_port(MACH_PORT_NULL)
+ , m_size(0)
+{
+}
+
+SharedMemory::Handle::~Handle()
+{
+ if (m_port)
+ mach_port_deallocate(mach_task_self(), m_port);
+}
+
+bool SharedMemory::Handle::isNull() const
+{
+ return !m_port;
+}
+
+void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
+{
+ encoder->encodeUInt64(m_size);
+ encoder->encode(CoreIPC::MachPort(m_port, MACH_MSG_TYPE_COPY_SEND));
+ m_port = MACH_PORT_NULL;
+}
+
+bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
+{
+ ASSERT(!handle.m_port);
+ ASSERT(!handle.m_size);
+
+ uint64_t size;
+ if (!decoder->decodeUInt64(size))
+ return false;
+
+ CoreIPC::MachPort machPort;
+ if (!decoder->decode(CoreIPC::Out(machPort)))
+ return false;
+
+ handle.m_size = size;
+ handle.m_port = machPort.port();
+ return true;
+}
+
+static inline void* toPointer(mach_vm_address_t address)
+{
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(address));
+}
+
+static inline mach_vm_address_t toVMAddress(void* pointer)
+{
+ return static_cast<mach_vm_address_t>(reinterpret_cast<uintptr_t>(pointer));
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
+{
+ mach_vm_address_t address;
+ kern_return_t kr = mach_vm_allocate(mach_task_self(), &address, round_page(size), VM_FLAGS_ANYWHERE);
+ if (kr != KERN_SUCCESS)
+ return 0;
+
+ RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory));
+ sharedMemory->m_size = size;
+ sharedMemory->m_data = toPointer(address);
+
+ return sharedMemory.release();
+}
+
+static inline vm_prot_t machProtection(SharedMemory::Protection protection)
+{
+ switch (protection) {
+ case SharedMemory::ReadOnly:
+ return VM_PROT_READ;
+ case SharedMemory::ReadWrite:
+ return VM_PROT_READ | VM_PROT_WRITE;
+ }
+
+ ASSERT_NOT_REACHED();
+ return VM_PROT_NONE;
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
+{
+ if (handle.isNull())
+ return 0;
+
+ // Map the memory.
+ vm_prot_t vmProtection = machProtection(protection);
+ mach_vm_address_t mappedAddress = 0;
+ kern_return_t kr = mach_vm_map(mach_task_self(), &mappedAddress, handle.m_size, 0, VM_FLAGS_ANYWHERE, handle.m_port, 0, false, vmProtection, vmProtection, VM_INHERIT_NONE);
+ if (kr != KERN_SUCCESS)
+ return 0;
+
+ RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory));
+ sharedMemory->m_size = handle.m_size;
+ sharedMemory->m_data = toPointer(mappedAddress);
+
+ return sharedMemory.release();
+}
+
+SharedMemory::~SharedMemory()
+{
+ if (!m_data)
+ return;
+
+ kern_return_t kr = mach_vm_deallocate(mach_task_self(), toVMAddress(m_data), round_page(m_size));
+ ASSERT_UNUSED(kr, kr == KERN_SUCCESS);
+}
+
+bool SharedMemory::createHandle(Handle& handle, Protection protection)
+{
+ ASSERT(!handle.m_port);
+ ASSERT(!handle.m_size);
+
+ mach_vm_address_t address = toVMAddress(m_data);
+ memory_object_size_t size = round_page(m_size);
+
+ // Create a mach port that represents the shared memory.
+ mach_port_t port;
+ kern_return_t kr = mach_make_memory_entry_64(mach_task_self(), &size, address, machProtection(protection), &port, MACH_PORT_NULL);
+ if (kr != KERN_SUCCESS)
+ return false;
+
+ handle.m_port = port;
+ handle.m_size = size;
+
+ return true;
+}
+
+unsigned SharedMemory::systemPageSize()
+{
+ return vm_page_size;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/Platform/mac/WorkQueueMac.cpp b/Source/WebKit2/Platform/mac/WorkQueueMac.cpp
new file mode 100644
index 0000000..3651f8c
--- /dev/null
+++ b/Source/WebKit2/Platform/mac/WorkQueueMac.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "WorkQueue.h"
+
+#include <mach/mach_port.h>
+#include <wtf/PassOwnPtr.h>
+
+#if HAVE(DISPATCH_H)
+
+void WorkQueue::executeWorkItem(void* item)
+{
+ WorkQueue* queue = static_cast<WorkQueue*>(dispatch_get_context(dispatch_get_current_queue()));
+ OwnPtr<WorkItem> workItem(static_cast<WorkItem*>(item));
+
+ {
+ MutexLocker locker(queue->m_isValidMutex);
+ if (!queue->m_isValid)
+ return;
+ }
+
+ workItem->execute();
+}
+
+void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
+{
+ dispatch_async_f(m_dispatchQueue, item.leakPtr(), executeWorkItem);
+}
+
+void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem> item, double delay)
+{
+ dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
+
+ dispatch_after_f(delayTime, m_dispatchQueue, item.leakPtr(), executeWorkItem);
+}
+
+class WorkQueue::EventSource {
+public:
+ EventSource(MachPortEventType eventType, dispatch_source_t dispatchSource, PassOwnPtr<WorkItem> workItem)
+ : m_eventType(eventType)
+ , m_dispatchSource(dispatchSource)
+ , m_workItem(workItem)
+ {
+ }
+
+ dispatch_source_t dispatchSource() const { return m_dispatchSource; }
+
+ static void eventHandler(void* source)
+ {
+ EventSource* eventSource = static_cast<EventSource*>(source);
+
+ eventSource->m_workItem->execute();
+ }
+
+ static void cancelHandler(void* source)
+ {
+ EventSource* eventSource = static_cast<EventSource*>(source);
+
+ mach_port_t machPort = dispatch_source_get_handle(eventSource->m_dispatchSource);
+
+ switch (eventSource->m_eventType) {
+ case MachPortDataAvailable:
+ // Release our receive right.
+ mach_port_mod_refs(mach_task_self(), machPort, MACH_PORT_RIGHT_RECEIVE, -1);
+ break;
+ case MachPortDeadNameNotification:
+ // Release our send right.
+ mach_port_deallocate(mach_task_self(), machPort);
+ break;
+ }
+ }
+
+ static void finalizeHandler(void* source)
+ {
+ EventSource* eventSource = static_cast<EventSource*>(source);
+
+ delete eventSource;
+ }
+
+private:
+ MachPortEventType m_eventType;
+
+ // This is a weak reference, since m_dispatchSource references the event source.
+ dispatch_source_t m_dispatchSource;
+
+ OwnPtr<WorkItem> m_workItem;
+};
+
+void WorkQueue::registerMachPortEventHandler(mach_port_t machPort, MachPortEventType eventType, PassOwnPtr<WorkItem> workItem)
+{
+ dispatch_source_type_t sourceType = 0;
+ switch (eventType) {
+ case MachPortDataAvailable:
+ sourceType = DISPATCH_SOURCE_TYPE_MACH_RECV;
+ break;
+ case MachPortDeadNameNotification:
+ sourceType = DISPATCH_SOURCE_TYPE_MACH_SEND;
+ break;
+ }
+
+ dispatch_source_t dispatchSource = dispatch_source_create(sourceType, machPort, 0, m_dispatchQueue);
+
+ EventSource* eventSource = new EventSource(eventType, dispatchSource, workItem);
+ dispatch_set_context(dispatchSource, eventSource);
+
+ dispatch_source_set_event_handler_f(dispatchSource, &EventSource::eventHandler);
+ dispatch_source_set_cancel_handler_f(dispatchSource, &EventSource::cancelHandler);
+ dispatch_set_finalizer_f(dispatchSource, &EventSource::finalizeHandler);
+
+ // Add the source to our set of sources.
+ {
+ MutexLocker locker(m_eventSourcesMutex);
+
+ ASSERT(!m_eventSources.contains(machPort));
+
+ m_eventSources.set(machPort, eventSource);
+
+ // And start it!
+ dispatch_resume(dispatchSource);
+ }
+}
+
+void WorkQueue::unregisterMachPortEventHandler(mach_port_t machPort)
+{
+ ASSERT(machPort);
+
+ MutexLocker locker(m_eventSourcesMutex);
+
+ HashMap<mach_port_t, EventSource*>::iterator it = m_eventSources.find(machPort);
+ ASSERT(it != m_eventSources.end());
+
+ ASSERT(m_eventSources.contains(machPort));
+
+ EventSource* eventSource = it->second;
+ // Cancel and release the source. It will be deleted in its finalize handler.
+ dispatch_source_cancel(eventSource->dispatchSource());
+ dispatch_release(eventSource->dispatchSource());
+
+ m_eventSources.remove(it);
+}
+
+void WorkQueue::platformInitialize(const char* name)
+{
+ m_dispatchQueue = dispatch_queue_create(name, 0);
+ dispatch_set_context(m_dispatchQueue, this);
+}
+
+void WorkQueue::platformInvalidate()
+{
+#if !ASSERT_DISABLED
+ MutexLocker locker(m_eventSourcesMutex);
+ ASSERT(m_eventSources.isEmpty());
+#endif
+
+ dispatch_release(m_dispatchQueue);
+}
+
+#else /* !HAVE(DISPATCH_H) */
+
+void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
+{
+}
+
+void WorkQueue::registerMachPortEventHandler(mach_port_t, MachPortEventType, PassOwnPtr<WorkItem>)
+{
+}
+
+void WorkQueue::unregisterMachPortEventHandler(mach_port_t)
+{
+}
+
+void WorkQueue::platformInitialize(const char*)
+{
+}
+
+void WorkQueue::platformInvalidate()
+{
+}
+
+#endif
diff --git a/Source/WebKit2/Platform/qt/MappedMemoryPool.cpp b/Source/WebKit2/Platform/qt/MappedMemoryPool.cpp
new file mode 100644
index 0000000..d36d82b
--- /dev/null
+++ b/Source/WebKit2/Platform/qt/MappedMemoryPool.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "MappedMemoryPool.h"
+
+#include "CleanupHandler.h"
+#include "StdLibExtras.h"
+#include <QDir>
+#include <QIODevice>
+#include <QTemporaryFile>
+
+namespace WebKit {
+
+MappedMemoryPool* MappedMemoryPool::theInstance = 0;
+
+MappedMemoryPool* MappedMemoryPool::instance()
+{
+ if (!theInstance) {
+ theInstance = new MappedMemoryPool;
+
+ // Do not leave mapping files on the disk.
+ CleanupHandler::instance()->markForCleanup(theInstance);
+ }
+
+ return theInstance;
+}
+
+MappedMemoryPool::~MappedMemoryPool()
+{
+ CleanupHandler::instance()->unmark(theInstance);
+
+ for (unsigned n = 0; n < m_pool.size(); ++n) {
+ MappedMemory& current = m_pool.at(n);
+ if (!current.file)
+ continue;
+ current.file->remove();
+ delete current.file;
+ }
+ m_pool.clear();
+}
+
+MappedMemory* MappedMemoryPool::mapMemory(size_t size)
+{
+ for (unsigned n = 0; n < m_pool.size(); ++n) {
+ MappedMemory& current = m_pool.at(n);
+ if (current.dataSize >= size && current.isFree()) {
+ current.markUsed();
+ return &current;
+ }
+ }
+
+ MappedMemory newMap;
+ newMap.dataSize = size;
+ newMap.file = new QTemporaryFile(QDir::tempPath() + "/WebKit2UpdateChunk");
+ newMap.file->open(QIODevice::ReadWrite);
+ newMap.fileName = newMap.file->fileName();
+ newMap.file->resize(newMap.mapSize());
+ newMap.mappedBytes = newMap.file->map(0, newMap.mapSize());
+ newMap.file->close();
+ newMap.markUsed();
+ m_pool.append(newMap);
+ return &m_pool.last();
+}
+
+MappedMemory* MappedMemoryPool::mapFile(QString fileName, size_t size)
+{
+ for (unsigned n = 0; n < m_pool.size(); ++n) {
+ MappedMemory& current = m_pool.at(n);
+ if (current.fileName == fileName) {
+ ASSERT(!current.isFree());
+ return &current;
+ }
+ }
+
+ MappedMemory newMap;
+ newMap.file = new QFile(fileName);
+ newMap.fileName = fileName;
+ newMap.dataSize = size;
+ ASSERT(newMap.file->exists());
+ ASSERT(newMap.file->size() >= newMap.mapSize());
+ newMap.file->open(QIODevice::ReadWrite);
+ newMap.mappedBytes = newMap.file->map(0, newMap.mapSize());
+ ASSERT(newMap.mappedBytes);
+ ASSERT(!newMap.isFree());
+ newMap.file->close();
+ m_pool.append(newMap);
+ return &m_pool.last();
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/Platform/qt/MappedMemoryPool.h b/Source/WebKit2/Platform/qt/MappedMemoryPool.h
new file mode 100644
index 0000000..8d6af8c
--- /dev/null
+++ b/Source/WebKit2/Platform/qt/MappedMemoryPool.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2010 University of Szeged
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MappedMemoryPool_h
+#define MappedMemoryPool_h
+
+#include <QFile>
+#include <QObject>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace WebKit {
+
+class MappedMemoryPool;
+
+struct MappedMemory {
+
+ QString mappedFileName() const
+ {
+ ASSERT(file);
+ ASSERT(mappedBytes);
+ return fileName;
+ }
+
+ void markFree()
+ {
+ ASSERT(mappedBytes);
+ dataPtr->isFree = true;
+ }
+
+ uchar* data() const
+ {
+ ASSERT(mappedBytes);
+ return dataPtr->bytes;
+ }
+
+private:
+ friend class MappedMemoryPool;
+
+ MappedMemory()
+ : file(0)
+ , mappedBytes(0)
+ , dataSize(0)
+ {
+ }
+
+ void markUsed() { dataPtr->isFree = false; }
+
+ size_t mapSize() const { return dataSize + sizeof(Data); }
+ bool isFree() const { return dataPtr->isFree; }
+
+ struct Data {
+ uint32_t isFree; // keep bytes aligned
+ uchar bytes[];
+ };
+
+ QFile* file;
+ QString fileName;
+ union {
+ uchar* mappedBytes;
+ Data* dataPtr;
+ };
+ size_t dataSize;
+};
+
+class MappedMemoryPool : QObject {
+ Q_OBJECT
+public:
+ static MappedMemoryPool* instance();
+
+ MappedMemory* mapMemory(size_t size);
+ MappedMemory* mapFile(QString fileName, size_t size);
+
+private:
+ MappedMemoryPool() { }
+ ~MappedMemoryPool();
+
+ static MappedMemoryPool* theInstance;
+
+ Vector<MappedMemory> m_pool;
+};
+
+} // namespace WebKit
+
+#endif // MappedMemoryPool_h
diff --git a/Source/WebKit2/Platform/qt/ModuleQt.cpp b/Source/WebKit2/Platform/qt/ModuleQt.cpp
new file mode 100644
index 0000000..8a68cf4
--- /dev/null
+++ b/Source/WebKit2/Platform/qt/ModuleQt.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 University of Szeged.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Module.h"
+
+namespace WebKit {
+
+bool Module::load()
+{
+ m_lib.setFileName(static_cast<QString>(m_path));
+ return m_lib.load();
+}
+
+void Module::unload()
+{
+ m_lib.unload();
+}
+
+void* Module::platformFunctionPointer(const char* functionName) const
+{
+ // Unfortunately QLibrary::resolve is not const.
+ return const_cast<QLibrary*>(&m_lib)->resolve(functionName);
+}
+
+}
diff --git a/Source/WebKit2/Platform/qt/RunLoopQt.cpp b/Source/WebKit2/Platform/qt/RunLoopQt.cpp
new file mode 100644
index 0000000..d7d859d
--- /dev/null
+++ b/Source/WebKit2/Platform/qt/RunLoopQt.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "RunLoop.h"
+
+#include "WorkItem.h"
+
+#include <QApplication>
+#include <QAbstractEventDispatcher>
+#include <QObject>
+#include <QMetaMethod>
+#include <QMetaObject>
+#include <QTimerEvent>
+
+class RunLoop::TimerObject : public QObject
+{
+ Q_OBJECT
+public:
+ TimerObject(RunLoop* runLoop) : m_runLoop(runLoop)
+ {
+ int methodIndex = metaObject()->indexOfMethod("performWork()");
+ m_method = metaObject()->method(methodIndex);
+ }
+
+ Q_SLOT void performWork() { m_runLoop->performWork(); }
+ inline void wakeUp() { m_method.invoke(this, Qt::QueuedConnection); }
+
+protected:
+ virtual void timerEvent(QTimerEvent* event)
+ {
+ RunLoop::TimerBase::timerFired(m_runLoop, event->timerId());
+ }
+
+private:
+ RunLoop* m_runLoop;
+ QMetaMethod m_method;
+};
+
+void RunLoop::run()
+{
+ QCoreApplication::exec();
+}
+
+void RunLoop::stop()
+{
+ QCoreApplication::exit();
+}
+
+RunLoop::RunLoop()
+ : m_timerObject(new TimerObject(this))
+{
+}
+
+RunLoop::~RunLoop()
+{
+ delete m_timerObject;
+}
+
+void RunLoop::wakeUp()
+{
+ m_timerObject->wakeUp();
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(RunLoop* runLoop, int ID)
+{
+ TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+ ASSERT(it != runLoop->m_activeTimers.end());
+ TimerBase* timer = it->second;
+
+ if (!timer->m_isRepeating) {
+ // Stop the timer (calling stop would need another hash table lookup).
+ runLoop->m_activeTimers.remove(it);
+ runLoop->m_timerObject->killTimer(timer->m_ID);
+ timer->m_ID = 0;
+ }
+
+ timer->fired();
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_ID(0)
+ , m_isRepeating(false)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ stop();
+ int millis = static_cast<int>(nextFireInterval * 1000);
+ m_isRepeating = repeat;
+ m_ID = m_runLoop->m_timerObject->startTimer(millis);
+ ASSERT(m_ID);
+ m_runLoop->m_activeTimers.set(m_ID, this);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ if (!m_ID)
+ return;
+ TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
+ if (it == m_runLoop->m_activeTimers.end())
+ return;
+
+ m_runLoop->m_activeTimers.remove(it);
+ m_runLoop->m_timerObject->killTimer(m_ID);
+ m_ID = 0;
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_ID;
+}
+
+#include "RunLoopQt.moc"
diff --git a/Source/WebKit2/Platform/qt/SharedMemoryQt.cpp b/Source/WebKit2/Platform/qt/SharedMemoryQt.cpp
new file mode 100644
index 0000000..f5fecfc
--- /dev/null
+++ b/Source/WebKit2/Platform/qt/SharedMemoryQt.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2010 University of Szeged
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "SharedMemory.h"
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include "CleanupHandler.h"
+#include "WebCoreArgumentCoders.h"
+#include <unistd.h>
+#include <QCoreApplication>
+#include <QLatin1String>
+#include <QSharedMemory>
+#include <QString>
+#include <QUuid>
+#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
+
+namespace WebKit {
+
+SharedMemory::Handle::Handle()
+ : m_key()
+ , m_size(0)
+{
+}
+
+SharedMemory::Handle::~Handle()
+{
+}
+
+bool SharedMemory::Handle::isNull() const
+{
+ return m_key.isNull();
+}
+
+void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
+{
+ encoder->encodeUInt64(m_size);
+ encoder->encode(m_key);
+ m_key = String();
+}
+
+bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
+{
+ ASSERT_ARG(handle, !handle.m_size);
+ ASSERT_ARG(handle, handle.m_key.isNull());
+
+ uint64_t size;
+ if (!decoder->decodeUInt64(size))
+ return false;
+
+ String key;
+ if (!decoder->decode(key))
+ return false;
+
+ handle.m_size = size;
+ handle.m_key = key;
+
+ return true;
+}
+
+static QString createUniqueKey()
+{
+ return QLatin1String("QWKSharedMemoryKey") + QUuid::createUuid().toString();
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
+{
+ RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory));
+ QSharedMemory* impl = new QSharedMemory(createUniqueKey());
+ bool created = impl->create(size);
+ ASSERT_UNUSED(created, created);
+
+ sharedMemory->m_impl = impl;
+ sharedMemory->m_size = size;
+ sharedMemory->m_data = impl->data();
+
+ // Do not leave the shared memory segment behind.
+ CleanupHandler::instance()->markForCleanup(impl);
+
+ return sharedMemory.release();
+}
+
+static inline QSharedMemory::AccessMode accessMode(SharedMemory::Protection protection)
+{
+ switch (protection) {
+ case SharedMemory::ReadOnly:
+ return QSharedMemory::ReadOnly;
+ case SharedMemory::ReadWrite:
+ return QSharedMemory::ReadWrite;
+ }
+
+ ASSERT_NOT_REACHED();
+ return QSharedMemory::ReadWrite;
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
+{
+ if (handle.isNull())
+ return 0;
+
+ QSharedMemory* impl = new QSharedMemory(QString(handle.m_key));
+ bool attached = impl->attach(accessMode(protection));
+ if (!attached) {
+ delete impl;
+ return 0;
+ }
+
+ RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory));
+ sharedMemory->m_impl = impl;
+ ASSERT(handle.m_size == impl->size());
+ sharedMemory->m_size = handle.m_size;
+ sharedMemory->m_data = impl->data();
+
+ // Do not leave the shared memory segment behind.
+ CleanupHandler::instance()->markForCleanup(impl);
+
+ return sharedMemory.release();
+}
+
+SharedMemory::~SharedMemory()
+{
+ if (CleanupHandler::instance()->hasStartedDeleting())
+ return;
+
+ CleanupHandler::instance()->unmark(m_impl);
+ delete m_impl;
+}
+
+bool SharedMemory::createHandle(Handle& handle, Protection protection)
+{
+ ASSERT_ARG(handle, handle.m_key.isNull());
+ ASSERT_ARG(handle, !handle.m_size);
+
+ QString key = m_impl->key();
+ if (key.isNull())
+ return false;
+ handle.m_key = String(key);
+ handle.m_size = m_size;
+
+ return true;
+}
+
+unsigned SharedMemory::systemPageSize()
+{
+ static unsigned pageSize = 0;
+
+ if (!pageSize)
+ pageSize = getpagesize();
+
+ return pageSize;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/Platform/qt/WorkQueueQt.cpp b/Source/WebKit2/Platform/qt/WorkQueueQt.cpp
new file mode 100644
index 0000000..271984f
--- /dev/null
+++ b/Source/WebKit2/Platform/qt/WorkQueueQt.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "WorkQueue.h"
+
+#include <QLocalSocket>
+#include <QObject>
+#include <QThread>
+#include <wtf/Threading.h>
+#include "NotImplemented.h"
+
+class WorkQueue::WorkItemQt : public QObject {
+ Q_OBJECT
+public:
+ WorkItemQt(WorkQueue* workQueue, WorkItem* workItem)
+ : m_queue(workQueue)
+ , m_source(0)
+ , m_signal(0)
+ , m_workItem(workItem)
+ {
+ }
+
+ WorkItemQt(WorkQueue* workQueue, QObject* source, const char* signal, WorkItem* workItem)
+ : m_queue(workQueue)
+ , m_source(source)
+ , m_signal(signal)
+ , m_workItem(workItem)
+ {
+ connect(m_source, m_signal, SLOT(execute()), Qt::QueuedConnection);
+ }
+
+ ~WorkItemQt()
+ {
+ delete m_workItem;
+ }
+
+ Q_SLOT void execute()
+ {
+ if (m_queue->m_isValid)
+ m_workItem->execute();
+ }
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ execute();
+ delete this;
+ }
+
+ WorkQueue* m_queue;
+ QObject* m_source;
+ const char* m_signal;
+ WorkItem* m_workItem;
+};
+
+void WorkQueue::connectSignal(QObject* o, const char* signal, PassOwnPtr<WorkItem> workItem)
+{
+ WorkQueue::WorkItemQt* itemQt = new WorkQueue::WorkItemQt(this, o, signal, workItem.leakPtr());
+ itemQt->moveToThread(m_workThread);
+ m_signalListeners.add(o, itemQt);
+}
+
+void WorkQueue::disconnectSignal(QObject* o, const char* name)
+{
+ HashMap<QObject*, WorkItemQt*>::iterator it = m_signalListeners.find(o);
+ for (; it != m_signalListeners.end(); ++it) {
+ if (strcmp(it->second->m_signal, name))
+ continue;
+ delete it->second;
+ m_signalListeners.remove(it);
+ return;
+ }
+}
+
+void WorkQueue::moveSocketToWorkThread(QLocalSocket* socket)
+{
+ ASSERT(m_workThread);
+ ASSERT(socket);
+
+ socket->setParent(0);
+ socket->moveToThread(m_workThread);
+}
+
+void WorkQueue::platformInitialize(const char*)
+{
+ m_workThread = new QThread();
+ m_workThread->start();
+}
+
+void WorkQueue::platformInvalidate()
+{
+ m_workThread->exit();
+ m_workThread->wait();
+ delete m_workThread;
+ deleteAllValues(m_signalListeners);
+}
+
+void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
+{
+ WorkQueue::WorkItemQt* itemQt = new WorkQueue::WorkItemQt(this, item.leakPtr());
+ itemQt->startTimer(0);
+ itemQt->moveToThread(m_workThread);
+}
+
+void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem>, double)
+{
+ notImplemented();
+}
+
+#include "WorkQueueQt.moc"
diff --git a/Source/WebKit2/Platform/win/ModuleWin.cpp b/Source/WebKit2/Platform/win/ModuleWin.cpp
new file mode 100644
index 0000000..2c2250d
--- /dev/null
+++ b/Source/WebKit2/Platform/win/ModuleWin.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Module.h"
+
+#include <shlwapi.h>
+
+namespace WebKit {
+
+bool Module::load()
+{
+ ASSERT(!::PathIsRelativeW(m_path.charactersWithNullTermination()));
+ m_module = ::LoadLibraryExW(m_path.charactersWithNullTermination(), 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+ return m_module;
+}
+
+void Module::unload()
+{
+ if (!m_module)
+ return;
+ ::FreeLibrary(m_module);
+ m_module = 0;
+}
+
+void* Module::platformFunctionPointer(const char* functionName) const
+{
+ if (!m_module)
+ return 0;
+
+ return ::GetProcAddress(m_module, functionName);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/Platform/win/RunLoopWin.cpp b/Source/WebKit2/Platform/win/RunLoopWin.cpp
new file mode 100644
index 0000000..4dfb4b5
--- /dev/null
+++ b/Source/WebKit2/Platform/win/RunLoopWin.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "RunLoop.h"
+
+#include "WorkItem.h"
+
+static const UINT PerformWorkMessage = WM_USER + 1;
+static const LPWSTR kRunLoopMessageWindowClassName = L"RunLoopMessageWindow";
+
+LRESULT CALLBACK RunLoop::RunLoopWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
+
+ if (RunLoop* runLoop = reinterpret_cast<RunLoop*>(longPtr))
+ return runLoop->wndProc(hWnd, message, wParam, lParam);
+
+ if (message == WM_CREATE) {
+ LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
+
+ // Associate the RunLoop with the window.
+ ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
+ return 0;
+ }
+
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+LRESULT RunLoop::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case PerformWorkMessage:
+ performWork();
+ return 0;
+ case WM_TIMER:
+ RunLoop::TimerBase::timerFired(this, wParam);
+ return 0;
+ }
+
+ return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void RunLoop::run()
+{
+ MSG message;
+ while (BOOL result = ::GetMessage(&message, 0, 0, 0)) {
+ if (result == -1)
+ break;
+ ::TranslateMessage(&message);
+ ::DispatchMessage(&message);
+ }
+}
+
+void RunLoop::stop()
+{
+ ::PostQuitMessage(0);
+}
+
+bool RunLoop::registerRunLoopMessageWindowClass()
+{
+ // FIXME: This really only needs to be called once.
+
+ WNDCLASSEX windowClass = { 0 };
+ windowClass.cbSize = sizeof(windowClass);
+ windowClass.lpfnWndProc = RunLoop::RunLoopWndProc;
+ windowClass.cbWndExtra = sizeof(RunLoop*);
+ windowClass.lpszClassName = kRunLoopMessageWindowClassName;
+
+ return !!::RegisterClassEx(&windowClass);
+}
+
+RunLoop::RunLoop()
+{
+ registerRunLoopMessageWindowClass();
+
+ m_runLoopMessageWindow = ::CreateWindow(kRunLoopMessageWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ HWND_MESSAGE, 0, 0, this);
+ ASSERT(::IsWindow(m_runLoopMessageWindow));
+}
+
+RunLoop::~RunLoop()
+{
+ // FIXME: Tear down the work item queue here.
+}
+
+void RunLoop::wakeUp()
+{
+ // FIXME: No need to wake up the run loop if we've already called scheduleWork
+ // before the run loop has had the time to respond.
+ ::PostMessage(m_runLoopMessageWindow, PerformWorkMessage, reinterpret_cast<WPARAM>(this), 0);
+}
+
+// RunLoop::Timer
+
+void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
+{
+ TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+ ASSERT(it != runLoop->m_activeTimers.end());
+ TimerBase* timer = it->second;
+
+ if (!timer->m_isRepeating) {
+ runLoop->m_activeTimers.remove(it);
+ ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+ }
+
+ timer->fired();
+}
+
+static uint64_t generateTimerID()
+{
+ static uint64_t uniqueTimerID = 1;
+ return uniqueTimerID++;
+}
+
+RunLoop::TimerBase::TimerBase(RunLoop* runLoop)
+ : m_runLoop(runLoop)
+ , m_ID(generateTimerID())
+ , m_isRepeating(false)
+{
+}
+
+RunLoop::TimerBase::~TimerBase()
+{
+ stop();
+}
+
+void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
+{
+ m_isRepeating = repeat;
+ m_runLoop->m_activeTimers.set(m_ID, this);
+ ::SetTimer(m_runLoop->m_runLoopMessageWindow, m_ID, nextFireInterval, 0);
+}
+
+void RunLoop::TimerBase::stop()
+{
+ TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
+ if (it == m_runLoop->m_activeTimers.end())
+ return;
+
+ m_runLoop->m_activeTimers.remove(it);
+ ::KillTimer(m_runLoop->m_runLoopMessageWindow, m_ID);
+}
+
+bool RunLoop::TimerBase::isActive() const
+{
+ return m_runLoop->m_activeTimers.contains(m_ID);
+}
diff --git a/Source/WebKit2/Platform/win/SharedMemoryWin.cpp b/Source/WebKit2/Platform/win/SharedMemoryWin.cpp
new file mode 100644
index 0000000..260783a
--- /dev/null
+++ b/Source/WebKit2/Platform/win/SharedMemoryWin.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "SharedMemory.h"
+
+#include "ArgumentDecoder.h"
+#include "ArgumentEncoder.h"
+#include <wtf/RefPtr.h>
+
+namespace WebKit {
+
+SharedMemory::Handle::Handle()
+ : m_handle(0)
+ , m_size(0)
+{
+}
+
+SharedMemory::Handle::~Handle()
+{
+ if (!m_handle)
+ return;
+
+ ::CloseHandle(m_handle);
+}
+
+void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
+{
+ encoder->encodeUInt64(m_size);
+
+ // Hand off ownership of our HANDLE to the receiving process. It will close it for us.
+ // FIXME: If the receiving process crashes before it receives the memory, the memory will be
+ // leaked. See <http://webkit.org/b/47502>.
+ encoder->encodeUInt64(reinterpret_cast<uint64_t>(m_handle));
+ m_handle = 0;
+
+ // Send along our PID so that the receiving process can duplicate the HANDLE for its own use.
+ encoder->encodeUInt32(::GetCurrentProcessId());
+}
+
+bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
+{
+ ASSERT_ARG(handle, !handle.m_handle);
+ ASSERT_ARG(handle, !handle.m_size);
+
+ uint64_t size;
+ if (!decoder->decodeUInt64(size))
+ return false;
+
+ uint64_t sourceHandle;
+ if (!decoder->decodeUInt64(sourceHandle))
+ return false;
+
+ uint32_t sourcePID;
+ if (!decoder->decodeUInt32(sourcePID))
+ return false;
+
+ HANDLE sourceProcess = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, sourcePID);
+ if (!sourceProcess)
+ return false;
+
+ // Copy the handle into our process and close the handle that the sending process created for us.
+ HANDLE duplicatedHandle;
+ BOOL success = ::DuplicateHandle(sourceProcess, reinterpret_cast<HANDLE>(sourceHandle), ::GetCurrentProcess(), &duplicatedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+ ::CloseHandle(sourceProcess);
+
+ if (!success)
+ return false;
+
+ handle.m_handle = duplicatedHandle;
+ handle.m_size = size;
+ return true;
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
+{
+ HANDLE handle = ::CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, 0);
+ if (!handle)
+ return 0;
+
+ void* baseAddress = ::MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, size);
+ if (!baseAddress) {
+ ::CloseHandle(handle);
+ return 0;
+ }
+
+ RefPtr<SharedMemory> memory = adoptRef(new SharedMemory);
+ memory->m_size = size;
+ memory->m_data = baseAddress;
+ memory->m_handle = handle;
+
+ return memory.release();
+}
+
+static DWORD accessRights(SharedMemory::Protection protection)
+{
+ switch (protection) {
+ case SharedMemory::ReadOnly:
+ return FILE_MAP_READ;
+ case SharedMemory::ReadWrite:
+ // FILE_MAP_WRITE implies read access, too.
+ return FILE_MAP_WRITE;
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
+{
+ DWORD desiredAccess = accessRights(protection);
+
+ void* baseAddress = ::MapViewOfFile(handle.m_handle, desiredAccess, 0, 0, handle.m_size);
+ if (!baseAddress)
+ return 0;
+
+ RefPtr<SharedMemory> memory = adoptRef(new SharedMemory);
+ memory->m_size = handle.m_size;
+ memory->m_data = baseAddress;
+
+ // Adopt the HANDLE.
+ memory->m_handle = handle.m_handle;
+ handle.m_handle = 0;
+
+ return memory.release();
+}
+
+SharedMemory::~SharedMemory()
+{
+ ASSERT(m_data);
+ ASSERT(m_handle);
+
+ ::UnmapViewOfFile(m_data);
+ ::CloseHandle(m_handle);
+}
+
+bool SharedMemory::createHandle(Handle& handle, Protection protection)
+{
+ ASSERT_ARG(handle, !handle.m_handle);
+ ASSERT_ARG(handle, !handle.m_size);
+
+ HANDLE processHandle = ::GetCurrentProcess();
+
+ HANDLE duplicatedHandle;
+ if (!::DuplicateHandle(processHandle, m_handle, processHandle, &duplicatedHandle, accessRights(protection), FALSE, 0))
+ return false;
+
+ handle.m_handle = duplicatedHandle;
+ handle.m_size = m_size;
+ return true;
+}
+
+unsigned SharedMemory::systemPageSize()
+{
+ static unsigned pageSize = 0;
+
+ if (!pageSize) {
+ SYSTEM_INFO systemInfo;
+ ::GetSystemInfo(&systemInfo);
+ pageSize = systemInfo.dwPageSize;
+ }
+
+ return pageSize;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/Platform/win/WorkQueueWin.cpp b/Source/WebKit2/Platform/win/WorkQueueWin.cpp
new file mode 100644
index 0000000..f527432
--- /dev/null
+++ b/Source/WebKit2/Platform/win/WorkQueueWin.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "WorkQueue.h"
+
+#include <wtf/Threading.h>
+#include "NotImplemented.h"
+
+inline WorkQueue::WorkItemWin::WorkItemWin(PassOwnPtr<WorkItem> item, WorkQueue* queue)
+ : m_item(item)
+ , m_queue(queue)
+{
+}
+
+PassRefPtr<WorkQueue::WorkItemWin> WorkQueue::WorkItemWin::create(PassOwnPtr<WorkItem> item, WorkQueue* queue)
+{
+ return adoptRef(new WorkItemWin(item, queue));
+}
+
+WorkQueue::WorkItemWin::~WorkItemWin()
+{
+}
+
+inline WorkQueue::HandleWorkItem::HandleWorkItem(HANDLE handle, PassOwnPtr<WorkItem> item, WorkQueue* queue)
+ : WorkItemWin(item, queue)
+ , m_handle(handle)
+ , m_waitHandle(0)
+{
+ ASSERT_ARG(handle, handle);
+}
+
+PassRefPtr<WorkQueue::HandleWorkItem> WorkQueue::HandleWorkItem::createByAdoptingHandle(HANDLE handle, PassOwnPtr<WorkItem> item, WorkQueue* queue)
+{
+ return adoptRef(new HandleWorkItem(handle, item, queue));
+}
+
+WorkQueue::HandleWorkItem::~HandleWorkItem()
+{
+ ::CloseHandle(m_handle);
+}
+
+void WorkQueue::handleCallback(void* context, BOOLEAN timerOrWaitFired)
+{
+ ASSERT_ARG(context, context);
+ ASSERT_ARG(timerOrWaitFired, !timerOrWaitFired);
+
+ WorkItemWin* item = static_cast<WorkItemWin*>(context);
+ WorkQueue* queue = item->queue();
+
+ {
+ MutexLocker lock(queue->m_workItemQueueLock);
+ queue->m_workItemQueue.append(item);
+
+ // If no other thread is performing work, we can do it on this thread.
+ if (!queue->tryRegisterAsWorkThread()) {
+ // Some other thread is performing work. Since we hold the queue lock, we can be sure
+ // that the work thread is not exiting due to an empty queue and will process the work
+ // item we just added to it. If we weren't holding the lock we'd have to signal
+ // m_performWorkEvent to make sure the work item got picked up.
+ return;
+ }
+ }
+
+ queue->performWorkOnRegisteredWorkThread();
+}
+
+void WorkQueue::registerHandle(HANDLE handle, PassOwnPtr<WorkItem> item)
+{
+ RefPtr<HandleWorkItem> handleItem = HandleWorkItem::createByAdoptingHandle(handle, item, this);
+
+ {
+ MutexLocker lock(m_handlesLock);
+ ASSERT_ARG(handle, !m_handles.contains(handle));
+ m_handles.set(handle, handleItem);
+ }
+
+ HANDLE waitHandle;
+ if (!::RegisterWaitForSingleObject(&waitHandle, handle, handleCallback, handleItem.get(), INFINITE, WT_EXECUTEDEFAULT)) {
+ DWORD error = ::GetLastError();
+ ASSERT_NOT_REACHED();
+ }
+ handleItem->setWaitHandle(waitHandle);
+}
+
+void WorkQueue::unregisterAndCloseHandle(HANDLE handle)
+{
+ RefPtr<HandleWorkItem> item;
+ {
+ MutexLocker locker(m_handlesLock);
+ ASSERT_ARG(handle, m_handles.contains(handle));
+ item = m_handles.take(handle);
+ }
+
+ unregisterWaitAndDestroyItemSoon(item.release());
+}
+
+DWORD WorkQueue::workThreadCallback(void* context)
+{
+ ASSERT_ARG(context, context);
+
+ WorkQueue* queue = static_cast<WorkQueue*>(context);
+
+ if (!queue->tryRegisterAsWorkThread())
+ return 0;
+
+ queue->performWorkOnRegisteredWorkThread();
+ return 0;
+}
+
+void WorkQueue::performWorkOnRegisteredWorkThread()
+{
+ ASSERT(m_isWorkThreadRegistered);
+
+ bool isValid = true;
+
+ m_workItemQueueLock.lock();
+
+ while (isValid && !m_workItemQueue.isEmpty()) {
+ Vector<RefPtr<WorkItemWin> > workItemQueue;
+ m_workItemQueue.swap(workItemQueue);
+
+ // Allow more work to be scheduled while we're not using the queue directly.
+ m_workItemQueueLock.unlock();
+ for (size_t i = 0; i < workItemQueue.size(); ++i) {
+ MutexLocker locker(m_isValidMutex);
+ isValid = m_isValid;
+ if (!isValid)
+ break;
+ workItemQueue[i]->item()->execute();
+ }
+ m_workItemQueueLock.lock();
+ }
+
+ // One invariant we maintain is that any work scheduled while a work thread is registered will
+ // be handled by that work thread. Unregister as the work thread while the queue lock is still
+ // held so that no work can be scheduled while we're still registered.
+ unregisterAsWorkThread();
+
+ m_workItemQueueLock.unlock();
+}
+
+void WorkQueue::platformInitialize(const char* name)
+{
+ m_isWorkThreadRegistered = 0;
+}
+
+bool WorkQueue::tryRegisterAsWorkThread()
+{
+ LONG result = ::InterlockedCompareExchange(&m_isWorkThreadRegistered, 1, 0);
+ ASSERT(!result || result == 1);
+ return !result;
+}
+
+void WorkQueue::unregisterAsWorkThread()
+{
+ LONG result = ::InterlockedCompareExchange(&m_isWorkThreadRegistered, 0, 1);
+ ASSERT_UNUSED(result, result == 1);
+}
+
+void WorkQueue::platformInvalidate()
+{
+#if !ASSERT_DISABLED
+ MutexLocker lock(m_handlesLock);
+ ASSERT(m_handles.isEmpty());
+#endif
+}
+
+void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item)
+{
+ MutexLocker locker(m_workItemQueueLock);
+
+ m_workItemQueue.append(WorkItemWin::create(item, this));
+
+ // Spawn a work thread to perform the work we just added. As an optimization, we avoid
+ // spawning the thread if a work thread is already registered. This prevents multiple work
+ // threads from being spawned in most cases. (Note that when a work thread has been spawned but
+ // hasn't registered itself yet, m_isWorkThreadRegistered will be false and we'll end up
+ // spawning a second work thread here. But work thread registration process will ensure that
+ // only one thread actually ends up performing work.)
+ if (!m_isWorkThreadRegistered)
+ ::QueueUserWorkItem(workThreadCallback, this, WT_EXECUTEDEFAULT);
+}
+
+void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem>, double)
+{
+ notImplemented();
+}
+
+void WorkQueue::unregisterWaitAndDestroyItemSoon(PassRefPtr<HandleWorkItem> item)
+{
+ // We're going to make a blocking call to ::UnregisterWaitEx before closing the handle. (The
+ // blocking version of ::UnregisterWaitEx is much simpler than the non-blocking version.) If we
+ // do this on the current thread, we'll deadlock if we're currently in a callback function for
+ // the wait we're unregistering. So instead we do it asynchronously on some other worker thread.
+
+ ::QueueUserWorkItem(unregisterWaitAndDestroyItemCallback, item.leakRef(), WT_EXECUTEDEFAULT);
+}
+
+DWORD WINAPI WorkQueue::unregisterWaitAndDestroyItemCallback(void* context)
+{
+ ASSERT_ARG(context, context);
+ RefPtr<HandleWorkItem> item = adoptRef(static_cast<HandleWorkItem*>(context));
+
+ // Now that we know we're not in a callback function for the wait we're unregistering, we can
+ // make a blocking call to ::UnregisterWaitEx.
+ if (!::UnregisterWaitEx(item->waitHandle(), INVALID_HANDLE_VALUE)) {
+ DWORD error = ::GetLastError();
+ ASSERT_NOT_REACHED();
+ }
+
+ return 0;
+}