summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/Platform/CoreIPC
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/Platform/CoreIPC')
-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
24 files changed, 4328 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