summaryrefslogtreecommitdiff
path: root/Source/WebKit2/Platform
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/Platform
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebKit2/Platform')
-rw-r--r--Source/WebKit2/Platform/IPC/ArgumentCoder.h8
-rw-r--r--Source/WebKit2/Platform/IPC/ArgumentCoders.cpp40
-rw-r--r--Source/WebKit2/Platform/IPC/ArgumentCoders.h259
-rw-r--r--Source/WebKit2/Platform/IPC/Arguments.h391
-rw-r--r--Source/WebKit2/Platform/IPC/Attachment.cpp12
-rw-r--r--Source/WebKit2/Platform/IPC/Attachment.h50
-rw-r--r--Source/WebKit2/Platform/IPC/Connection.cpp748
-rw-r--r--Source/WebKit2/Platform/IPC/Connection.h340
-rw-r--r--Source/WebKit2/Platform/IPC/DataReference.cpp23
-rw-r--r--Source/WebKit2/Platform/IPC/DataReference.h35
-rw-r--r--Source/WebKit2/Platform/IPC/Decoder.cpp (renamed from Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp)140
-rw-r--r--Source/WebKit2/Platform/IPC/Decoder.h (renamed from Source/WebKit2/Platform/IPC/ArgumentDecoder.h)91
-rw-r--r--Source/WebKit2/Platform/IPC/Encoder.cpp (renamed from Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp)155
-rw-r--r--Source/WebKit2/Platform/IPC/Encoder.h (renamed from Source/WebKit2/Platform/IPC/ArgumentEncoder.h)60
-rw-r--r--Source/WebKit2/Platform/IPC/HandleMessage.h172
-rw-r--r--Source/WebKit2/Platform/IPC/MessageDecoder.h67
-rw-r--r--Source/WebKit2/Platform/IPC/MessageEncoder.cpp67
-rw-r--r--Source/WebKit2/Platform/IPC/MessageFlags.h1
-rw-r--r--Source/WebKit2/Platform/IPC/MessageReceiver.h41
-rw-r--r--Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp46
-rw-r--r--Source/WebKit2/Platform/IPC/MessageReceiverMap.h9
-rw-r--r--Source/WebKit2/Platform/IPC/MessageSender.cpp4
-rw-r--r--Source/WebKit2/Platform/IPC/MessageSender.h25
-rw-r--r--Source/WebKit2/Platform/IPC/StringReference.cpp10
-rw-r--r--Source/WebKit2/Platform/IPC/StringReference.h8
-rw-r--r--Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp (renamed from Source/WebKit2/Platform/IPC/MessageDecoder.cpp)59
-rw-r--r--Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h (renamed from Source/WebKit2/Platform/IPC/MessageEncoder.h)36
-rw-r--r--Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp24
-rw-r--r--Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp348
-rw-r--r--Source/WebKit2/Platform/IPC/unix/UnixMessage.h113
-rw-r--r--Source/WebKit2/Platform/LogInitialization.h (renamed from Source/WebKit2/Platform/WorkQueue.cpp)27
-rw-r--r--Source/WebKit2/Platform/Logging.cpp37
-rw-r--r--Source/WebKit2/Platform/Logging.h42
-rw-r--r--Source/WebKit2/Platform/Module.cpp2
-rw-r--r--Source/WebKit2/Platform/Module.h14
-rw-r--r--Source/WebKit2/Platform/SharedMemory.h75
-rw-r--r--Source/WebKit2/Platform/WorkQueue.h101
-rw-r--r--Source/WebKit2/Platform/glib/ModuleGlib.cpp (renamed from Source/WebKit2/Platform/gtk/ModuleGtk.cpp)0
-rw-r--r--Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp240
-rw-r--r--Source/WebKit2/Platform/unix/EnvironmentUtilities.cpp124
-rw-r--r--Source/WebKit2/Platform/unix/EnvironmentUtilities.h (renamed from Source/WebKit2/Platform/PlatformProcessIdentifier.h)28
-rw-r--r--Source/WebKit2/Platform/unix/LoggingUnix.cpp (renamed from Source/WebKit2/Platform/gtk/LoggingGtk.cpp)8
-rw-r--r--Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp119
43 files changed, 2141 insertions, 2058 deletions
diff --git a/Source/WebKit2/Platform/IPC/ArgumentCoder.h b/Source/WebKit2/Platform/IPC/ArgumentCoder.h
index 2af313c42..5df6c1b0b 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentCoder.h
+++ b/Source/WebKit2/Platform/IPC/ArgumentCoder.h
@@ -28,16 +28,16 @@
namespace IPC {
-class ArgumentDecoder;
-class ArgumentEncoder;
+class Decoder;
+class Encoder;
template<typename T> struct ArgumentCoder {
- static void encode(ArgumentEncoder& encoder, const T& t)
+ static void encode(Encoder& encoder, const T& t)
{
t.encode(encoder);
}
- static bool decode(ArgumentDecoder& decoder, T& t)
+ static bool decode(Decoder& decoder, T& t)
{
return T::decode(decoder, t);
}
diff --git a/Source/WebKit2/Platform/IPC/ArgumentCoders.cpp b/Source/WebKit2/Platform/IPC/ArgumentCoders.cpp
index 5ca064108..0c986425a 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentCoders.cpp
+++ b/Source/WebKit2/Platform/IPC/ArgumentCoders.cpp
@@ -32,12 +32,27 @@
namespace IPC {
-void ArgumentCoder<AtomicString>::encode(ArgumentEncoder& encoder, const AtomicString& atomicString)
+void ArgumentCoder<std::chrono::system_clock::time_point>::encode(IPC::Encoder& encoder, const std::chrono::system_clock::time_point& timePoint)
+{
+ encoder << static_cast<int64_t>(timePoint.time_since_epoch().count());
+}
+
+bool ArgumentCoder<std::chrono::system_clock::time_point>::decode(Decoder& decoder, std::chrono::system_clock::time_point& result)
+{
+ int64_t time;
+ if (!decoder.decode(time))
+ return false;
+
+ result = std::chrono::system_clock::time_point(std::chrono::system_clock::duration(static_cast<std::chrono::system_clock::rep>(time)));
+ return true;
+}
+
+void ArgumentCoder<AtomicString>::encode(Encoder& encoder, const AtomicString& atomicString)
{
encoder << atomicString.string();
}
-bool ArgumentCoder<AtomicString>::decode(ArgumentDecoder& decoder, AtomicString& atomicString)
+bool ArgumentCoder<AtomicString>::decode(Decoder& decoder, AtomicString& atomicString)
{
String string;
if (!decoder.decode(string))
@@ -47,7 +62,7 @@ bool ArgumentCoder<AtomicString>::decode(ArgumentDecoder& decoder, AtomicString&
return true;
}
-void ArgumentCoder<CString>::encode(ArgumentEncoder& encoder, const CString& string)
+void ArgumentCoder<CString>::encode(Encoder& encoder, const CString& string)
{
// Special case the null string.
if (string.isNull()) {
@@ -60,7 +75,7 @@ void ArgumentCoder<CString>::encode(ArgumentEncoder& encoder, const CString& str
encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.data()), length, 1);
}
-bool ArgumentCoder<CString>::decode(ArgumentDecoder& decoder, CString& result)
+bool ArgumentCoder<CString>::decode(Decoder& decoder, CString& result)
{
uint32_t length;
if (!decoder.decode(length))
@@ -88,7 +103,7 @@ bool ArgumentCoder<CString>::decode(ArgumentDecoder& decoder, CString& result)
}
-void ArgumentCoder<String>::encode(ArgumentEncoder& encoder, const String& string)
+void ArgumentCoder<String>::encode(Encoder& encoder, const String& string)
{
// Special case the null string.
if (string.isNull()) {
@@ -108,7 +123,7 @@ void ArgumentCoder<String>::encode(ArgumentEncoder& encoder, const String& strin
}
template <typename CharacterType>
-static inline bool decodeStringText(ArgumentDecoder& decoder, uint32_t length, String& result)
+static inline bool decodeStringText(Decoder& decoder, uint32_t length, String& result)
{
// Before allocating the string, make sure that the decoder buffer is big enough.
if (!decoder.bufferIsLargeEnoughToContain<CharacterType>(length)) {
@@ -125,7 +140,7 @@ static inline bool decodeStringText(ArgumentDecoder& decoder, uint32_t length, S
return true;
}
-bool ArgumentCoder<String>::decode(ArgumentDecoder& decoder, String& result)
+bool ArgumentCoder<String>::decode(Decoder& decoder, String& result)
{
uint32_t length;
if (!decoder.decode(length))
@@ -147,4 +162,15 @@ bool ArgumentCoder<String>::decode(ArgumentDecoder& decoder, String& result)
return decodeStringText<UChar>(decoder, length, result);
}
+
+void ArgumentCoder<SHA1::Digest>::encode(Encoder& encoder, const SHA1::Digest& digest)
+{
+ encoder.encodeFixedLengthData(digest.data(), sizeof(digest), 1);
+}
+
+bool ArgumentCoder<SHA1::Digest>::decode(Decoder& decoder, SHA1::Digest& digest)
+{
+ return decoder.decodeFixedLengthData(digest.data(), sizeof(digest), 1);
+}
+
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/ArgumentCoders.h b/Source/WebKit2/Platform/IPC/ArgumentCoders.h
index c04b7a989..86166c843 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentCoders.h
+++ b/Source/WebKit2/Platform/IPC/ArgumentCoders.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,38 +23,92 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SimpleArgumentCoder_h
-#define SimpleArgumentCoder_h
+#pragma once
-#include "ArgumentDecoder.h"
-#include "ArgumentEncoder.h"
+#include "Decoder.h"
+#include "Encoder.h"
#include <utility>
#include <wtf/Forward.h>
+#include <wtf/HashCountedSet.h>
#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/OptionSet.h>
+#include <wtf/Optional.h>
+#include <wtf/SHA1.h>
+#include <wtf/Variant.h>
#include <wtf/Vector.h>
namespace IPC {
// An argument coder works on POD types
template<typename T> struct SimpleArgumentCoder {
- static void encode(ArgumentEncoder& encoder, const T& t)
+ static void encode(Encoder& encoder, const T& t)
{
encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(&t), sizeof(T), alignof(T));
}
- static bool decode(ArgumentDecoder& decoder, T& t)
+ static bool decode(Decoder& decoder, T& t)
{
return decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(&t), sizeof(T), alignof(T));
}
};
+template<typename T> struct ArgumentCoder<OptionSet<T>> {
+ static void encode(Encoder& encoder, const OptionSet<T>& optionSet)
+ {
+ encoder << (static_cast<uint64_t>(optionSet.toRaw()));
+ }
+
+ static bool decode(Decoder& decoder, OptionSet<T>& optionSet)
+ {
+ uint64_t value;
+ if (!decoder.decode(value))
+ return false;
+
+ optionSet = OptionSet<T>::fromRaw(value);
+ return true;
+ }
+};
+
+template<typename T> struct ArgumentCoder<std::optional<T>> {
+ static void encode(Encoder& encoder, const std::optional<T>& optional)
+ {
+ if (!optional) {
+ encoder << false;
+ return;
+ }
+
+ encoder << true;
+ encoder << optional.value();
+ }
+
+ static bool decode(Decoder& decoder, std::optional<T>& optional)
+ {
+ bool isEngaged;
+ if (!decoder.decode(isEngaged))
+ return false;
+
+ if (!isEngaged) {
+ optional = std::nullopt;
+ return true;
+ }
+
+ T value;
+ if (!decoder.decode(value))
+ return false;
+
+ optional = WTFMove(value);
+ return true;
+ }
+};
+
template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
- static void encode(ArgumentEncoder& encoder, const std::pair<T, U>& pair)
+ static void encode(Encoder& encoder, const std::pair<T, U>& pair)
{
encoder << pair.first << pair.second;
}
- static bool decode(ArgumentDecoder& decoder, std::pair<T, U>& pair)
+ static bool decode(Decoder& decoder, std::pair<T, U>& pair)
{
T first;
if (!decoder.decode(first))
@@ -70,13 +124,71 @@ template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
}
};
+template<size_t index, typename... Elements>
+struct TupleCoder {
+ static void encode(Encoder& encoder, const std::tuple<Elements...>& tuple)
+ {
+ encoder << std::get<sizeof...(Elements) - index>(tuple);
+ TupleCoder<index - 1, Elements...>::encode(encoder, tuple);
+ }
+
+ static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
+ {
+ if (!decoder.decode(std::get<sizeof...(Elements) - index>(tuple)))
+ return false;
+ return TupleCoder<index - 1, Elements...>::decode(decoder, tuple);
+ }
+};
+
+template<typename... Elements>
+struct TupleCoder<0, Elements...> {
+ static void encode(Encoder&, const std::tuple<Elements...>&)
+ {
+ }
+
+ static bool decode(Decoder&, std::tuple<Elements...>&)
+ {
+ return true;
+ }
+};
+
+template<typename... Elements> struct ArgumentCoder<std::tuple<Elements...>> {
+ static void encode(Encoder& encoder, const std::tuple<Elements...>& tuple)
+ {
+ TupleCoder<sizeof...(Elements), Elements...>::encode(encoder, tuple);
+ }
+
+ static bool decode(Decoder& decoder, std::tuple<Elements...>& tuple)
+ {
+ return TupleCoder<sizeof...(Elements), Elements...>::decode(decoder, tuple);
+ }
+};
+
+
+template<typename Rep, typename Period> struct ArgumentCoder<std::chrono::duration<Rep, Period>> {
+ static void encode(Encoder& encoder, const std::chrono::duration<Rep, Period>& duration)
+ {
+ static_assert(std::is_integral<Rep>::value && std::is_signed<Rep>::value && sizeof(Rep) <= sizeof(int64_t), "Serialization of this Rep type is not supported yet. Only signed integer type which can be fit in an int64_t is currently supported.");
+ encoder << static_cast<int64_t>(duration.count());
+ }
+
+ static bool decode(Decoder& decoder, std::chrono::duration<Rep, Period>& result)
+ {
+ int64_t count;
+ if (!decoder.decode(count))
+ return false;
+ result = std::chrono::duration<Rep, Period>(static_cast<Rep>(count));
+ return true;
+ }
+};
+
template<typename KeyType, typename ValueType> struct ArgumentCoder<WTF::KeyValuePair<KeyType, ValueType>> {
- static void encode(ArgumentEncoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair)
+ static void encode(Encoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair)
{
encoder << pair.key << pair.value;
}
- static bool decode(ArgumentDecoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair)
+ static bool decode(Decoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair)
{
KeyType key;
if (!decoder.decode(key))
@@ -92,29 +204,29 @@ template<typename KeyType, typename ValueType> struct ArgumentCoder<WTF::KeyValu
}
};
-template<bool fixedSizeElements, typename T> struct VectorArgumentCoder;
+template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorArgumentCoder;
-template<typename T> struct VectorArgumentCoder<false, T> {
- static void encode(ArgumentEncoder& encoder, const Vector<T>& vector)
+template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<false, T, inlineCapacity> {
+ static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
{
encoder << static_cast<uint64_t>(vector.size());
for (size_t i = 0; i < vector.size(); ++i)
encoder << vector[i];
}
- static bool decode(ArgumentDecoder& decoder, Vector<T>& vector)
+ static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
{
uint64_t size;
if (!decoder.decode(size))
return false;
- Vector<T> tmp;
+ Vector<T, inlineCapacity> tmp;
for (size_t i = 0; i < size; ++i) {
T element;
if (!decoder.decode(element))
return false;
- tmp.append(element);
+ tmp.append(WTFMove(element));
}
tmp.shrinkToFit();
@@ -123,14 +235,14 @@ template<typename T> struct VectorArgumentCoder<false, T> {
}
};
-template<typename T> struct VectorArgumentCoder<true, T> {
- static void encode(ArgumentEncoder& encoder, const Vector<T>& vector)
+template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<true, T, inlineCapacity> {
+ static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector)
{
encoder << static_cast<uint64_t>(vector.size());
encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T));
}
- static bool decode(ArgumentDecoder& decoder, Vector<T>& vector)
+ static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector)
{
uint64_t size;
if (!decoder.decode(size))
@@ -144,7 +256,7 @@ template<typename T> struct VectorArgumentCoder<true, T> {
return false;
}
- Vector<T> temp;
+ Vector<T, inlineCapacity> temp;
temp.resize(size);
decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T), alignof(T));
@@ -154,19 +266,19 @@ template<typename T> struct VectorArgumentCoder<true, T> {
}
};
-template<typename T> struct ArgumentCoder<Vector<T>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T> { };
+template<typename T, size_t inlineCapacity> struct ArgumentCoder<Vector<T, inlineCapacity>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
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)
+ static void encode(Encoder& encoder, const HashMapType& hashMap)
{
encoder << static_cast<uint64_t>(hashMap.size());
for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
encoder << *it;
}
- static bool decode(ArgumentDecoder& decoder, HashMapType& hashMap)
+ static bool decode(Decoder& decoder, HashMapType& hashMap)
{
uint64_t hashMapSize;
if (!decoder.decode(hashMapSize))
@@ -193,21 +305,104 @@ template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTrai
}
};
+template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
+ typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType;
+
+ static void encode(Encoder& encoder, const HashSetType& hashSet)
+ {
+ encoder << static_cast<uint64_t>(hashSet.size());
+ for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it)
+ encoder << *it;
+ }
+
+ static bool decode(Decoder& decoder, HashSetType& hashSet)
+ {
+ uint64_t hashSetSize;
+ if (!decoder.decode(hashSetSize))
+ return false;
+
+ HashSetType tempHashSet;
+ for (uint64_t i = 0; i < hashSetSize; ++i) {
+ KeyArg key;
+ if (!decoder.decode(key))
+ return false;
+
+ if (!tempHashSet.add(key).isNewEntry) {
+ // The hash map already has the specified key, bail.
+ decoder.markInvalid();
+ return false;
+ }
+ }
+
+ hashSet.swap(tempHashSet);
+ return true;
+ }
+};
+
+template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashCountedSet<KeyArg, HashArg, KeyTraitsArg>> {
+ typedef HashCountedSet<KeyArg, HashArg, KeyTraitsArg> HashCountedSetType;
+
+ static void encode(Encoder& encoder, const HashCountedSetType& hashCountedSet)
+ {
+ encoder << static_cast<uint64_t>(hashCountedSet.size());
+
+ for (auto entry : hashCountedSet) {
+ encoder << entry.key;
+ encoder << entry.value;
+ }
+ }
+
+ static bool decode(Decoder& decoder, HashCountedSetType& hashCountedSet)
+ {
+ uint64_t hashCountedSetSize;
+ if (!decoder.decode(hashCountedSetSize))
+ return false;
+
+ HashCountedSetType tempHashCountedSet;
+ for (uint64_t i = 0; i < hashCountedSetSize; ++i) {
+ KeyArg key;
+ if (!decoder.decode(key))
+ return false;
+
+ unsigned count;
+ if (!decoder.decode(count))
+ return false;
+
+ if (!tempHashCountedSet.add(key, count).isNewEntry) {
+ // The hash counted set already has the specified key, bail.
+ decoder.markInvalid();
+ return false;
+ }
+ }
+
+ hashCountedSet.swap(tempHashCountedSet);
+ return true;
+ }
+};
+
+template<> struct ArgumentCoder<std::chrono::system_clock::time_point> {
+ static void encode(Encoder&, const std::chrono::system_clock::time_point&);
+ static bool decode(Decoder&, std::chrono::system_clock::time_point&);
+};
+
template<> struct ArgumentCoder<AtomicString> {
- static void encode(ArgumentEncoder&, const AtomicString&);
- static bool decode(ArgumentDecoder&, AtomicString&);
+ static void encode(Encoder&, const AtomicString&);
+ static bool decode(Decoder&, AtomicString&);
};
template<> struct ArgumentCoder<CString> {
- static void encode(ArgumentEncoder&, const CString&);
- static bool decode(ArgumentDecoder&, CString&);
+ static void encode(Encoder&, const CString&);
+ static bool decode(Decoder&, CString&);
};
template<> struct ArgumentCoder<String> {
- static void encode(ArgumentEncoder&, const String&);
- static bool decode(ArgumentDecoder&, String&);
+ static void encode(Encoder&, const String&);
+ static bool decode(Decoder&, String&);
};
-} // namespace IPC
+template<> struct ArgumentCoder<SHA1::Digest> {
+ static void encode(Encoder&, const SHA1::Digest&);
+ static bool decode(Decoder&, SHA1::Digest&);
+};
-#endif // ArgumentCoders_h
+} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/Arguments.h b/Source/WebKit2/Platform/IPC/Arguments.h
deleted file mode 100644
index 7921e1a33..000000000
--- a/Source/WebKit2/Platform/IPC/Arguments.h
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * 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"
-
-namespace IPC {
-
-template<size_t index, typename... Elements>
-struct TupleCoder {
- static void encode(ArgumentEncoder& encoder, const std::tuple<Elements...>& tuple)
- {
- encoder << std::get<sizeof...(Elements) - index>(tuple);
- TupleCoder<index - 1, Elements...>::encode(encoder, tuple);
- }
-
- static bool decode(ArgumentDecoder& decoder, std::tuple<Elements...>& tuple)
- {
- if (!decoder.decode(std::get<sizeof...(Elements) - index>(tuple)))
- return false;
- return TupleCoder<index - 1, Elements...>::decode(decoder, tuple);
- }
-};
-
-template<typename... Elements>
-struct TupleCoder<0, Elements...> {
- static void encode(ArgumentEncoder&, const std::tuple<Elements...>&)
- {
- }
-
- static bool decode(ArgumentDecoder&, std::tuple<Elements...>&)
- {
- return true;
- }
-};
-
-template<typename... Elements> struct ArgumentCoder<std::tuple<Elements...>> {
- static void encode(ArgumentEncoder& encoder, const std::tuple<Elements...>& tuple)
- {
- TupleCoder<sizeof...(Elements), Elements...>::encode(encoder, tuple);
- }
-
- static bool decode(ArgumentDecoder& decoder, std::tuple<Elements...>& tuple)
- {
- return TupleCoder<sizeof...(Elements), Elements...>::decode(decoder, tuple);
- }
-};
-
-struct Arguments0 {
- typedef std::tuple<> ValueType;
-
- void encode(ArgumentEncoder&) const
- {
- }
-
- static bool decode(ArgumentDecoder&, Arguments0&)
- {
- return true;
- }
-};
-
-template<typename T1> struct Arguments1 {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type> ValueType;
-
- Arguments1()
- {
- }
-
- Arguments1(T1 t1)
- : argument1(t1)
- {
- }
-
- void encode(ArgumentEncoder& encoder) const
- {
- encoder << argument1;
- }
-
- static bool decode(ArgumentDecoder& decoder, Arguments1& result)
- {
- return decoder.decode(result.argument1);
- }
-
- T1 argument1;
-};
-
-template<typename T1, typename T2> struct Arguments2 : Arguments1<T1> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T3> struct Arguments3 : Arguments2<T1, T2> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T4> struct Arguments4 : Arguments3<T1, T2, T3> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<T3>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T5> struct Arguments5 : Arguments4<T1, T2, T3, T4> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<T3>::type>::type,
- typename std::remove_const<typename std::remove_reference<T4>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T6> struct Arguments6 : Arguments5<T1, T2, T3, T4, T5> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<T3>::type>::type,
- typename std::remove_const<typename std::remove_reference<T4>::type>::type,
- typename std::remove_const<typename std::remove_reference<T5>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T7> struct Arguments7 : Arguments6<T1, T2, T3, T4, T5, T6> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<T3>::type>::type,
- typename std::remove_const<typename std::remove_reference<T4>::type>::type,
- typename std::remove_const<typename std::remove_reference<T5>::type>::type,
- typename std::remove_const<typename std::remove_reference<T6>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T8> struct Arguments8 : Arguments7<T1, T2, T3, T4, T5, T6, T7> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<T3>::type>::type,
- typename std::remove_const<typename std::remove_reference<T4>::type>::type,
- typename std::remove_const<typename std::remove_reference<T5>::type>::type,
- typename std::remove_const<typename std::remove_reference<T6>::type>::type,
- typename std::remove_const<typename std::remove_reference<T7>::type>::type,
- typename std::remove_const<typename std::remove_reference<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 << 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, typename T9, typename T10> struct Arguments10 : Arguments8<T1, T2, T3, T4, T5, T6, T7, T8> {
- typedef std::tuple<typename std::remove_const<typename std::remove_reference<T1>::type>::type,
- typename std::remove_const<typename std::remove_reference<T2>::type>::type,
- typename std::remove_const<typename std::remove_reference<T3>::type>::type,
- typename std::remove_const<typename std::remove_reference<T4>::type>::type,
- typename std::remove_const<typename std::remove_reference<T5>::type>::type,
- typename std::remove_const<typename std::remove_reference<T6>::type>::type,
- typename std::remove_const<typename std::remove_reference<T7>::type>::type,
- typename std::remove_const<typename std::remove_reference<T8>::type>::type,
- typename std::remove_const<typename std::remove_reference<T9>::type>::type,
- typename std::remove_const<typename std::remove_reference<T10>::type>::type> ValueType;
-
- Arguments10() { }
-
- Arguments10(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10)
- : Arguments8<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8)
- , argument9(t9)
- , argument10(t10)
- {
- }
-
- void encode(ArgumentEncoder& encoder) const
- {
- Arguments8<T1, T2, T3, T4, T5, T6, T7, T8>::encode(encoder);
- encoder << argument9;
- encoder << argument10;
- }
-
- static bool decode(ArgumentDecoder& decoder, Arguments10& result)
- {
- if (!Arguments8<T1, T2, T3, T4, T5, T6, T7, T8>::decode(decoder, result))
- return false;
-
- decoder.decode(result.argument9);
- return decoder.decode(result.argument10);
- }
-
- T9 argument9;
- T10 argument10;
-};
-
-} // namespace IPC
-
-#endif // Arguments_h
diff --git a/Source/WebKit2/Platform/IPC/Attachment.cpp b/Source/WebKit2/Platform/IPC/Attachment.cpp
index 9367b1ad2..2c5ce0e7b 100644
--- a/Source/WebKit2/Platform/IPC/Attachment.cpp
+++ b/Source/WebKit2/Platform/IPC/Attachment.cpp
@@ -26,8 +26,8 @@
#include "config.h"
#include "Attachment.h"
-#include "ArgumentDecoder.h"
-#include "ArgumentEncoder.h"
+#include "Decoder.h"
+#include "Encoder.h"
namespace IPC {
@@ -36,7 +36,7 @@ Attachment::Attachment()
{
}
-#if OS(DARWIN)
+#if OS(DARWIN) && !USE(UNIX_DOMAIN_SOCKETS)
Attachment::Attachment(mach_port_name_t port, mach_msg_type_name_t disposition)
: m_type(MachPortType)
, m_port(port)
@@ -50,12 +50,12 @@ void Attachment::release()
}
#endif
-void Attachment::encode(ArgumentEncoder& encoder) const
+void Attachment::encode(Encoder& encoder) const
{
- encoder.addAttachment(*this);
+ encoder.addAttachment(WTFMove(*const_cast<Attachment*>(this)));
}
-bool Attachment::decode(ArgumentDecoder& decoder, Attachment& attachment)
+bool Attachment::decode(Decoder& decoder, Attachment& attachment)
{
if (!decoder.removeAttachment(attachment))
return false;
diff --git a/Source/WebKit2/Platform/IPC/Attachment.h b/Source/WebKit2/Platform/IPC/Attachment.h
index b0f1dce20..a684c0d91 100644
--- a/Source/WebKit2/Platform/IPC/Attachment.h
+++ b/Source/WebKit2/Platform/IPC/Attachment.h
@@ -26,15 +26,15 @@
#ifndef Attachment_h
#define Attachment_h
-#if OS(DARWIN)
+#if OS(DARWIN) && !USE(UNIX_DOMAIN_SOCKETS)
#include <mach/mach_init.h>
#include <mach/mach_traps.h>
#endif
namespace IPC {
-class ArgumentDecoder;
-class ArgumentEncoder;
+class Decoder;
+class Encoder;
class Attachment {
public:
@@ -42,51 +42,51 @@ public:
enum Type {
Uninitialized,
-#if OS(DARWIN)
- MachPortType,
-#elif USE(UNIX_DOMAIN_SOCKETS)
+#if USE(UNIX_DOMAIN_SOCKETS)
SocketType,
- MappedMemoryType
+ MappedMemoryType,
+#elif OS(DARWIN)
+ MachPortType
#endif
};
-#if OS(DARWIN)
- Attachment(mach_port_name_t port, mach_msg_type_name_t disposition);
-#elif USE(UNIX_DOMAIN_SOCKETS)
+#if USE(UNIX_DOMAIN_SOCKETS)
+ Attachment(Attachment&&);
+ Attachment& operator=(Attachment&&);
Attachment(int fileDescriptor, size_t);
Attachment(int fileDescriptor);
+ ~Attachment();
+#elif OS(DARWIN)
+ Attachment(mach_port_name_t, mach_msg_type_name_t disposition);
#endif
Type type() const { return m_type; }
-#if OS(DARWIN)
- void release();
-
- // MachPortType
- mach_port_name_t port() const { return m_port; }
- mach_msg_type_name_t disposition() const { return m_disposition; }
-
-#elif USE(UNIX_DOMAIN_SOCKETS)
+#if USE(UNIX_DOMAIN_SOCKETS)
size_t size() const { return m_size; }
int releaseFileDescriptor() { int temp = m_fileDescriptor; m_fileDescriptor = -1; return temp; }
int fileDescriptor() const { return m_fileDescriptor; }
+#elif OS(DARWIN)
+ void release();
- void dispose();
+ // MachPortType
+ mach_port_name_t port() const { return m_port; }
+ mach_msg_type_name_t disposition() const { return m_disposition; }
#endif
- void encode(ArgumentEncoder&) const;
- static bool decode(ArgumentDecoder&, Attachment&);
+ void encode(Encoder&) const;
+ static bool decode(Decoder&, Attachment&);
private:
Type m_type;
-#if OS(DARWIN)
+#if USE(UNIX_DOMAIN_SOCKETS)
+ int m_fileDescriptor { -1 };
+ size_t m_size;
+#elif OS(DARWIN)
mach_port_name_t m_port;
mach_msg_type_name_t m_disposition;
-#elif USE(UNIX_DOMAIN_SOCKETS)
- int m_fileDescriptor;
- size_t m_size;
#endif
};
diff --git a/Source/WebKit2/Platform/IPC/Connection.cpp b/Source/WebKit2/Platform/IPC/Connection.cpp
index 615e707ba..39a504b9b 100644
--- a/Source/WebKit2/Platform/IPC/Connection.cpp
+++ b/Source/WebKit2/Platform/IPC/Connection.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,6 +26,8 @@
#include "config.h"
#include "Connection.h"
+#include "Logging.h"
+#include <memory>
#include <wtf/CurrentTime.h>
#include <wtf/HashSet.h>
#include <wtf/NeverDestroyed.h>
@@ -33,121 +35,116 @@
#include <wtf/text/WTFString.h>
#include <wtf/threads/BinarySemaphore.h>
+#if PLATFORM(COCOA)
+#include "MachMessage.h"
+#endif
+
+#if USE(UNIX_DOMAIN_SOCKETS)
+#include "UnixMessage.h"
+#endif
+
namespace IPC {
-class Connection::SyncMessageState : public ThreadSafeRefCounted<Connection::SyncMessageState> {
+struct Connection::ReplyHandler {
+ RefPtr<FunctionDispatcher> dispatcher;
+ Function<void (std::unique_ptr<Decoder>)> handler;
+};
+
+struct Connection::WaitForMessageState {
+ WaitForMessageState(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, OptionSet<WaitForOption> waitForOptions)
+ : messageReceiverName(messageReceiverName)
+ , messageName(messageName)
+ , destinationID(destinationID)
+ , waitForOptions(waitForOptions)
+ {
+ }
+
+ StringReference messageReceiverName;
+ StringReference messageName;
+ uint64_t destinationID;
+
+ OptionSet<WaitForOption> waitForOptions;
+ bool messageWaitingInterrupted = false;
+
+ std::unique_ptr<Decoder> decoder;
+};
+
+class Connection::SyncMessageState {
public:
- static PassRefPtr<SyncMessageState> getOrCreate(RunLoop*);
- ~SyncMessageState();
+ static SyncMessageState& singleton();
+
+ SyncMessageState();
+ ~SyncMessageState() = delete;
void wakeUpClientRunLoop()
{
m_waitForSyncReplySemaphore.signal();
}
- bool wait(double absoluteTime)
+ bool wait(TimeWithDynamicClockType absoluteTime)
{
return m_waitForSyncReplySemaphore.wait(absoluteTime);
}
// Returns true if this message will be handled on a client thread that is currently
// waiting for a reply to a synchronous message.
- bool processIncomingMessage(Connection*, std::unique_ptr<MessageDecoder>&);
+ bool processIncomingMessage(Connection&, std::unique_ptr<Decoder>&);
// Dispatch pending sync messages. if allowedConnection is not null, will only dispatch messages
// from that connection and put the other messages back in the queue.
void dispatchMessages(Connection* allowedConnection);
private:
- explicit SyncMessageState(RunLoop*);
-
- typedef HashMap<RunLoop*, SyncMessageState*> SyncMessageStateMap;
- static SyncMessageStateMap& syncMessageStateMap()
- {
- static NeverDestroyed<SyncMessageStateMap> syncMessageStateMap;
- return syncMessageStateMap;
- }
+ void dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(Connection&);
- static Mutex& syncMessageStateMapMutex()
- {
- static NeverDestroyed<Mutex> syncMessageStateMapMutex;
- return syncMessageStateMapMutex;
- }
-
- void dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(Connection*);
-
- RunLoop* m_runLoop;
BinarySemaphore m_waitForSyncReplySemaphore;
// Protects m_didScheduleDispatchMessagesWorkSet and m_messagesToDispatchWhileWaitingForSyncReply.
- Mutex m_mutex;
+ Lock m_mutex;
// The set of connections for which we've scheduled a call to dispatchMessageAndResetDidScheduleDispatchMessagesForConnection.
HashSet<RefPtr<Connection>> m_didScheduleDispatchMessagesWorkSet;
struct ConnectionAndIncomingMessage {
- RefPtr<Connection> connection;
- std::unique_ptr<MessageDecoder> message;
+ Ref<Connection> connection;
+ std::unique_ptr<Decoder> message;
};
Vector<ConnectionAndIncomingMessage> m_messagesToDispatchWhileWaitingForSyncReply;
};
-class Connection::SecondaryThreadPendingSyncReply {
-public:
- // The reply decoder, will be null if there was an error processing the sync message on the other side.
- std::unique_ptr<MessageDecoder> replyDecoder;
-
- BinarySemaphore semaphore;
-};
-
-
-PassRefPtr<Connection::SyncMessageState> Connection::SyncMessageState::getOrCreate(RunLoop* runLoop)
+Connection::SyncMessageState& Connection::SyncMessageState::singleton()
{
- MutexLocker locker(syncMessageStateMapMutex());
- SyncMessageStateMap::AddResult result = syncMessageStateMap().add(runLoop, nullptr);
-
- if (!result.isNewEntry) {
- ASSERT(result.iterator->value);
- return result.iterator->value;
- }
-
- RefPtr<SyncMessageState> syncMessageState = adoptRef(new SyncMessageState(runLoop));
- result.iterator->value = syncMessageState.get();
+ static std::once_flag onceFlag;
+ static LazyNeverDestroyed<SyncMessageState> syncMessageState;
- return syncMessageState.release();
-}
+ std::call_once(onceFlag, [] {
+ syncMessageState.construct();
+ });
-Connection::SyncMessageState::SyncMessageState(RunLoop* runLoop)
- : m_runLoop(runLoop)
-{
+ return syncMessageState;
}
-Connection::SyncMessageState::~SyncMessageState()
+Connection::SyncMessageState::SyncMessageState()
{
- MutexLocker locker(syncMessageStateMapMutex());
-
- ASSERT(syncMessageStateMap().contains(m_runLoop));
- syncMessageStateMap().remove(m_runLoop);
-
- ASSERT(m_messagesToDispatchWhileWaitingForSyncReply.isEmpty());
}
-bool Connection::SyncMessageState::processIncomingMessage(Connection* connection, std::unique_ptr<MessageDecoder>& message)
+bool Connection::SyncMessageState::processIncomingMessage(Connection& connection, std::unique_ptr<Decoder>& message)
{
if (!message->shouldDispatchMessageWhenWaitingForSyncReply())
return false;
- ConnectionAndIncomingMessage connectionAndIncomingMessage;
- connectionAndIncomingMessage.connection = connection;
- connectionAndIncomingMessage.message = std::move(message);
+ ConnectionAndIncomingMessage connectionAndIncomingMessage { connection, WTFMove(message) };
{
- MutexLocker locker(m_mutex);
+ std::lock_guard<Lock> lock(m_mutex);
- if (m_didScheduleDispatchMessagesWorkSet.add(connection).isNewEntry)
- m_runLoop->dispatch(bind(&SyncMessageState::dispatchMessageAndResetDidScheduleDispatchMessagesForConnection, this, RefPtr<Connection>(connection)));
+ if (m_didScheduleDispatchMessagesWorkSet.add(&connection).isNewEntry) {
+ RunLoop::main().dispatch([this, protectedConnection = Ref<Connection>(connection)]() mutable {
+ dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(protectedConnection);
+ });
+ }
- m_messagesToDispatchWhileWaitingForSyncReply.append(std::move(connectionAndIncomingMessage));
+ m_messagesToDispatchWhileWaitingForSyncReply.append(WTFMove(connectionAndIncomingMessage));
}
wakeUpClientRunLoop();
@@ -157,12 +154,12 @@ bool Connection::SyncMessageState::processIncomingMessage(Connection* connection
void Connection::SyncMessageState::dispatchMessages(Connection* allowedConnection)
{
- ASSERT(m_runLoop == RunLoop::current());
+ ASSERT(RunLoop::isMain());
Vector<ConnectionAndIncomingMessage> messagesToDispatchWhileWaitingForSyncReply;
{
- MutexLocker locker(m_mutex);
+ std::lock_guard<Lock> lock(m_mutex);
m_messagesToDispatchWhileWaitingForSyncReply.swap(messagesToDispatchWhileWaitingForSyncReply);
}
@@ -171,46 +168,66 @@ void Connection::SyncMessageState::dispatchMessages(Connection* allowedConnectio
for (size_t i = 0; i < messagesToDispatchWhileWaitingForSyncReply.size(); ++i) {
ConnectionAndIncomingMessage& connectionAndIncomingMessage = messagesToDispatchWhileWaitingForSyncReply[i];
- if (allowedConnection && allowedConnection != connectionAndIncomingMessage.connection) {
+ if (allowedConnection && allowedConnection != connectionAndIncomingMessage.connection.ptr()) {
// This incoming message belongs to another connection and we don't want to dispatch it now
// so mark it to be put back in the message queue.
- messagesToPutBack.append(std::move(connectionAndIncomingMessage));
+ messagesToPutBack.append(WTFMove(connectionAndIncomingMessage));
continue;
}
- connectionAndIncomingMessage.connection->dispatchMessage(std::move(connectionAndIncomingMessage.message));
+ connectionAndIncomingMessage.connection->dispatchMessage(WTFMove(connectionAndIncomingMessage.message));
}
if (!messagesToPutBack.isEmpty()) {
- MutexLocker locker(m_mutex);
+ std::lock_guard<Lock> lock(m_mutex);
for (auto& message : messagesToPutBack)
- m_messagesToDispatchWhileWaitingForSyncReply.append(std::move(message));
+ m_messagesToDispatchWhileWaitingForSyncReply.append(WTFMove(message));
}
}
-void Connection::SyncMessageState::dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(Connection* connection)
+void Connection::SyncMessageState::dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(Connection& connection)
{
{
- MutexLocker locker(m_mutex);
- ASSERT(m_didScheduleDispatchMessagesWorkSet.contains(connection));
- m_didScheduleDispatchMessagesWorkSet.remove(connection);
+ std::lock_guard<Lock> lock(m_mutex);
+ ASSERT(m_didScheduleDispatchMessagesWorkSet.contains(&connection));
+ m_didScheduleDispatchMessagesWorkSet.remove(&connection);
}
- dispatchMessages(connection);
+ dispatchMessages(&connection);
}
-PassRefPtr<Connection> Connection::createServerConnection(Identifier identifier, Client* client, RunLoop* clientRunLoop)
+// Represents a sync request for which we're waiting on a reply.
+struct Connection::PendingSyncReply {
+ // The request ID.
+ uint64_t syncRequestID { 0 };
+
+ // The reply decoder, will be null if there was an error processing the sync
+ // message on the other side.
+ std::unique_ptr<Decoder> replyDecoder;
+
+ // Will be set to true once a reply has been received.
+ bool didReceiveReply { false };
+
+ PendingSyncReply() = default;
+
+ explicit PendingSyncReply(uint64_t syncRequestID)
+ : syncRequestID(syncRequestID)
+ {
+ }
+};
+
+Ref<Connection> Connection::createServerConnection(Identifier identifier, Client& client)
{
- return adoptRef(new Connection(identifier, true, client, clientRunLoop));
+ return adoptRef(*new Connection(identifier, true, client));
}
-PassRefPtr<Connection> Connection::createClientConnection(Identifier identifier, Client* client, RunLoop* clientRunLoop)
+Ref<Connection> Connection::createClientConnection(Identifier identifier, Client& client)
{
- return adoptRef(new Connection(identifier, false, client, clientRunLoop));
+ return adoptRef(*new Connection(identifier, false, client));
}
-Connection::Connection(Identifier identifier, bool isServer, Client* client, RunLoop* clientRunLoop)
+Connection::Connection(Identifier identifier, bool isServer, Client& client)
: m_client(client)
, m_isServer(isServer)
, m_syncRequestID(0)
@@ -219,17 +236,21 @@ Connection::Connection(Identifier identifier, bool isServer, Client* client, Run
, m_didCloseOnConnectionWorkQueueCallback(0)
, m_isConnected(false)
, m_connectionQueue(WorkQueue::create("com.apple.IPC.ReceiveQueue"))
- , m_clientRunLoop(clientRunLoop)
, m_inSendSyncCount(0)
, m_inDispatchMessageCount(0)
, m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount(0)
, m_didReceiveInvalidMessage(false)
- , m_syncMessageState(SyncMessageState::getOrCreate(clientRunLoop))
+ , m_waitingForMessage(nullptr)
, m_shouldWaitForSyncReplies(true)
{
- ASSERT(m_client);
+ ASSERT(RunLoop::isMain());
platformInitialize(identifier);
+
+#if HAVE(QOS_CLASSES)
+ ASSERT(pthread_main_np());
+ m_mainThread = pthread_self();
+#endif
}
Connection::~Connection()
@@ -251,63 +272,52 @@ void Connection::setShouldExitOnSyncMessageSendFailure(bool shouldExitOnSyncMess
m_shouldExitOnSyncMessageSendFailure = shouldExitOnSyncMessageSendFailure;
}
-void Connection::addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue* workQueue, WorkQueueMessageReceiver* workQueueMessageReceiver)
+void Connection::addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue& workQueue, WorkQueueMessageReceiver* workQueueMessageReceiver)
{
- ASSERT(RunLoop::current() == m_clientRunLoop);
- ASSERT(!m_isConnected);
+ ASSERT(RunLoop::isMain());
- m_connectionQueue->dispatch(bind(&Connection::addWorkQueueMessageReceiverOnConnectionWorkQueue, this, messageReceiverName, RefPtr<WorkQueue>(workQueue), RefPtr<WorkQueueMessageReceiver>(workQueueMessageReceiver)));
-}
+ m_connectionQueue->dispatch([protectedThis = makeRef(*this), messageReceiverName = WTFMove(messageReceiverName), workQueue = &workQueue, workQueueMessageReceiver]() mutable {
+ ASSERT(!protectedThis->m_workQueueMessageReceivers.contains(messageReceiverName));
-void Connection::removeWorkQueueMessageReceiver(StringReference messageReceiverName)
-{
- ASSERT(RunLoop::current() == m_clientRunLoop);
-
- m_connectionQueue->dispatch(bind(&Connection::removeWorkQueueMessageReceiverOnConnectionWorkQueue, this, messageReceiverName));
+ protectedThis->m_workQueueMessageReceivers.add(messageReceiverName, std::make_pair(workQueue, workQueueMessageReceiver));
+ });
}
-void Connection::addWorkQueueMessageReceiverOnConnectionWorkQueue(StringReference messageReceiverName, WorkQueue* workQueue, WorkQueueMessageReceiver* workQueueMessageReceiver)
+void Connection::removeWorkQueueMessageReceiver(StringReference messageReceiverName)
{
- ASSERT(workQueue);
- ASSERT(workQueueMessageReceiver);
- ASSERT(!m_workQueueMessageReceivers.contains(messageReceiverName));
-
- m_workQueueMessageReceivers.add(messageReceiverName, std::make_pair(workQueue, workQueueMessageReceiver));
-}
+ ASSERT(RunLoop::isMain());
-void Connection::removeWorkQueueMessageReceiverOnConnectionWorkQueue(StringReference messageReceiverName)
-{
- ASSERT(m_workQueueMessageReceivers.contains(messageReceiverName));
- m_workQueueMessageReceivers.remove(messageReceiverName);
+ m_connectionQueue->dispatch([protectedThis = makeRef(*this), messageReceiverName = WTFMove(messageReceiverName)]() mutable {
+ ASSERT(protectedThis->m_workQueueMessageReceivers.contains(messageReceiverName));
+ protectedThis->m_workQueueMessageReceivers.remove(messageReceiverName);
+ });
}
-void Connection::dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver* workQueueMessageReceiver, MessageDecoder* incomingMessageDecoder)
+void Connection::dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver& workQueueMessageReceiver, Decoder& decoder)
{
- OwnPtr<MessageDecoder> decoder = adoptPtr(incomingMessageDecoder);
-
- if (!decoder->isSyncMessage()) {
- workQueueMessageReceiver->didReceiveMessage(this, *decoder);
+ if (!decoder.isSyncMessage()) {
+ workQueueMessageReceiver.didReceiveMessage(*this, decoder);
return;
}
uint64_t syncRequestID = 0;
- if (!decoder->decode(syncRequestID) || !syncRequestID) {
+ if (!decoder.decode(syncRequestID) || !syncRequestID) {
// We received an invalid sync message.
// FIXME: Handle this.
- decoder->markInvalid();
+ decoder.markInvalid();
return;
}
- auto replyEncoder = std::make_unique<MessageEncoder>("IPC", "SyncMessageReply", syncRequestID);
+ auto replyEncoder = std::make_unique<Encoder>("IPC", "SyncMessageReply", syncRequestID);
// Hand off both the decoder and encoder to the work queue message receiver.
- workQueueMessageReceiver->didReceiveSyncMessage(this, *decoder, replyEncoder);
+ workQueueMessageReceiver.didReceiveSyncMessage(*this, decoder, replyEncoder);
// FIXME: If the message was invalid, we should send back a SyncMessageError.
- ASSERT(!decoder->isInvalid());
+ ASSERT(!decoder.isInvalid());
if (replyEncoder)
- sendSyncReply(std::move(replyEncoder));
+ sendSyncReply(WTFMove(replyEncoder));
}
void Connection::setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback)
@@ -319,15 +329,29 @@ void Connection::setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWo
void Connection::invalidate()
{
+ ASSERT(RunLoop::isMain());
+
if (!isValid()) {
// Someone already called invalidate().
return;
}
- // Reset the client.
- m_client = 0;
+ m_isValid = false;
- m_connectionQueue->dispatch(WTF::bind(&Connection::platformInvalidate, this));
+ {
+ std::lock_guard<Lock> lock(m_replyHandlersLock);
+ for (auto& replyHandler : m_replyHandlers.values()) {
+ replyHandler.dispatcher->dispatch([handler = WTFMove(replyHandler.handler)] {
+ handler(nullptr);
+ });
+ }
+
+ m_replyHandlers.clear();
+ }
+
+ m_connectionQueue->dispatch([protectedThis = makeRef(*this)]() mutable {
+ protectedThis->platformInvalidate();
+ });
}
void Connection::markCurrentlyDispatchedMessageAsInvalid()
@@ -338,9 +362,9 @@ void Connection::markCurrentlyDispatchedMessageAsInvalid()
m_didReceiveInvalidMessage = true;
}
-std::unique_ptr<MessageEncoder> Connection::createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID)
+std::unique_ptr<Encoder> Connection::createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID)
{
- auto encoder = std::make_unique<MessageEncoder>(messageReceiverName, messageName, destinationID);
+ auto encoder = std::make_unique<Encoder>(messageReceiverName, messageName, destinationID);
encoder->setIsSyncMessage(true);
// Encode the sync request ID.
@@ -350,78 +374,126 @@ std::unique_ptr<MessageEncoder> Connection::createSyncMessageEncoder(StringRefer
return encoder;
}
-bool Connection::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned messageSendFlags)
+bool Connection::sendMessage(std::unique_ptr<Encoder> encoder, OptionSet<SendOption> sendOptions)
{
if (!isValid())
return false;
- if (messageSendFlags & DispatchMessageEvenWhenWaitingForSyncReply
+ if (RunLoop::isMain() && m_inDispatchMessageMarkedToUseFullySynchronousModeForTesting && !encoder->isSyncMessage() && !(encoder->messageReceiverName() == "IPC")) {
+ uint64_t syncRequestID;
+ auto wrappedMessage = createSyncMessageEncoder("IPC", "WrappedAsyncMessageForTesting", encoder->destinationID(), syncRequestID);
+ wrappedMessage->setFullySynchronousModeForTesting();
+ wrappedMessage->wrapForTesting(WTFMove(encoder));
+ return static_cast<bool>(sendSyncMessage(syncRequestID, WTFMove(wrappedMessage), Seconds::infinity(), { }));
+ }
+
+ if (sendOptions.contains(SendOption::DispatchMessageEvenWhenWaitingForSyncReply)
&& (!m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage
|| m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount))
encoder->setShouldDispatchMessageWhenWaitingForSyncReply(true);
{
- MutexLocker locker(m_outgoingMessagesLock);
- m_outgoingMessages.append(std::move(encoder));
+ std::lock_guard<Lock> lock(m_outgoingMessagesMutex);
+ m_outgoingMessages.append(WTFMove(encoder));
}
// FIXME: We should add a boolean flag so we don't call this when work has already been scheduled.
- m_connectionQueue->dispatch(WTF::bind(&Connection::sendOutgoingMessages, this));
+ m_connectionQueue->dispatch([protectedThis = makeRef(*this)]() mutable {
+ protectedThis->sendOutgoingMessages();
+ });
return true;
}
-bool Connection::sendSyncReply(std::unique_ptr<MessageEncoder> encoder)
+void Connection::sendMessageWithReply(uint64_t requestID, std::unique_ptr<Encoder> encoder, FunctionDispatcher& replyDispatcher, Function<void (std::unique_ptr<Decoder>)>&& replyHandler)
{
- return sendMessage(std::move(encoder));
+ {
+ std::lock_guard<Lock> lock(m_replyHandlersLock);
+
+ if (!isValid()) {
+ replyDispatcher.dispatch([replyHandler = WTFMove(replyHandler)] {
+ replyHandler(nullptr);
+ });
+ return;
+ }
+
+ ASSERT(!m_replyHandlers.contains(requestID));
+ m_replyHandlers.set(requestID, ReplyHandler { &replyDispatcher, WTFMove(replyHandler) });
+ }
+
+ sendMessage(WTFMove(encoder), { });
+}
+
+bool Connection::sendSyncReply(std::unique_ptr<Encoder> encoder)
+{
+ return sendMessage(WTFMove(encoder), { });
}
-std::unique_ptr<MessageDecoder> Connection::waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout)
+Seconds Connection::timeoutRespectingIgnoreTimeoutsForTesting(Seconds timeout) const
{
+ return m_ignoreTimeoutsForTesting ? Seconds::infinity() : timeout;
+}
+
+std::unique_ptr<Decoder> Connection::waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, Seconds timeout, OptionSet<WaitForOption> waitForOptions)
+{
+ ASSERT(RunLoop::isMain());
+
+ timeout = timeoutRespectingIgnoreTimeoutsForTesting(timeout);
+
+ bool hasIncomingSynchronousMessage = false;
+
// First, check if this message is already in the incoming messages queue.
{
- MutexLocker locker(m_incomingMessagesLock);
+ std::lock_guard<Lock> lock(m_incomingMessagesMutex);
for (auto it = m_incomingMessages.begin(), end = m_incomingMessages.end(); it != end; ++it) {
- std::unique_ptr<MessageDecoder>& message = *it;
+ std::unique_ptr<Decoder>& message = *it;
if (message->messageReceiverName() == messageReceiverName && message->messageName() == messageName && message->destinationID() == destinationID) {
- std::unique_ptr<MessageDecoder> returnedMessage = std::move(message);
+ std::unique_ptr<Decoder> returnedMessage = WTFMove(message);
m_incomingMessages.remove(it);
return returnedMessage;
}
+
+ if (message->isSyncMessage())
+ hasIncomingSynchronousMessage = true;
}
}
- std::pair<std::pair<StringReference, StringReference>, uint64_t> messageAndDestination(std::make_pair(std::make_pair(messageReceiverName, messageName), destinationID));
-
+ // Don't even start waiting if we have InterruptWaitingIfSyncMessageArrives and there's a sync message already in the queue.
+ if (hasIncomingSynchronousMessage && waitForOptions.contains(WaitForOption::InterruptWaitingIfSyncMessageArrives)) {
+ m_waitingForMessage = nullptr;
+ return nullptr;
+ }
+
+ WaitForMessageState waitingForMessage(messageReceiverName, messageName, destinationID, waitForOptions);
+
{
- std::lock_guard<std::mutex> lock(m_waitForMessageMutex);
+ std::lock_guard<Lock> lock(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, nullptr);
+ // We don't support having multiple clients waiting for messages.
+ ASSERT(!m_waitingForMessage);
+
+ m_waitingForMessage = &waitingForMessage;
}
-
+
+ MonotonicTime absoluteTimeout = MonotonicTime::now() + timeout;
+
// Now wait for it to be set.
while (true) {
- std::unique_lock<std::mutex> lock(m_waitForMessageMutex);
-
- auto it = m_waitForMessageMap.find(messageAndDestination);
- if (it->value) {
- std::unique_ptr<MessageDecoder> decoder = std::move(it->value);
- m_waitForMessageMap.remove(it);
+ std::unique_lock<Lock> lock(m_waitForMessageMutex);
+ if (m_waitingForMessage->decoder) {
+ auto decoder = WTFMove(m_waitingForMessage->decoder);
+ m_waitingForMessage = nullptr;
return decoder;
}
// Now we wait.
- if (m_waitForMessageCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
- // We timed out, now remove the pending wait.
- m_waitForMessageMap.remove(messageAndDestination);
-
+ bool didTimeout = !m_waitForMessageCondition.waitUntil(lock, absoluteTimeout);
+ // We timed out, lost our connection, or a sync message came in with InterruptWaitingIfSyncMessageArrives, so stop waiting.
+ if (didTimeout || m_waitingForMessage->messageWaitingInterrupted) {
+ m_waitingForMessage = nullptr;
break;
}
}
@@ -429,13 +501,9 @@ std::unique_ptr<MessageDecoder> Connection::waitForMessage(StringReference messa
return nullptr;
}
-std::unique_ptr<MessageDecoder> Connection::sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<MessageEncoder> encoder, std::chrono::milliseconds timeout, unsigned syncSendFlags)
+std::unique_ptr<Decoder> Connection::sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<Encoder> encoder, Seconds timeout, OptionSet<SendSyncOption> sendSyncOptions)
{
- if (RunLoop::current() != m_clientRunLoop) {
- // No flags are supported for synchronous messages sent from secondary threads.
- ASSERT(!syncSendFlags);
- return sendSyncMessageFromSecondaryThread(syncRequestID, std::move(encoder), timeout);
- }
+ ASSERT(RunLoop::isMain());
if (!isValid()) {
didFailToSendSyncMessage();
@@ -444,7 +512,7 @@ std::unique_ptr<MessageDecoder> Connection::sendSyncMessage(uint64_t syncRequest
// Push the pending sync reply information on our stack.
{
- MutexLocker locker(m_syncReplyStateMutex);
+ LockHolder locker(m_syncReplyStateMutex);
if (!m_shouldWaitForSyncReplies) {
didFailToSendSyncMessage();
return nullptr;
@@ -456,18 +524,18 @@ std::unique_ptr<MessageDecoder> Connection::sendSyncMessage(uint64_t syncRequest
++m_inSendSyncCount;
// First send the message.
- sendMessage(std::move(encoder), DispatchMessageEvenWhenWaitingForSyncReply);
+ sendMessage(WTFMove(encoder), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
// 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.
Ref<Connection> protect(*this);
- std::unique_ptr<MessageDecoder> reply = waitForSyncReply(syncRequestID, timeout, syncSendFlags);
+ std::unique_ptr<Decoder> reply = waitForSyncReply(syncRequestID, timeout, sendSyncOptions);
--m_inSendSyncCount;
// Finally, pop the pending sync reply information.
{
- MutexLocker locker(m_syncReplyStateMutex);
+ LockHolder locker(m_syncReplyStateMutex);
ASSERT(m_pendingSyncReplies.last().syncRequestID == syncRequestID);
m_pendingSyncReplies.removeLast();
}
@@ -478,50 +546,20 @@ std::unique_ptr<MessageDecoder> Connection::sendSyncMessage(uint64_t syncRequest
return reply;
}
-std::unique_ptr<MessageDecoder> Connection::sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr<MessageEncoder> encoder, std::chrono::milliseconds timeout)
-{
- ASSERT(RunLoop::current() != m_clientRunLoop);
-
- if (!isValid())
- return nullptr;
-
- SecondaryThreadPendingSyncReply pendingReply;
-
- // Push the pending sync reply information on our stack.
- {
- MutexLocker locker(m_syncReplyStateMutex);
- if (!m_shouldWaitForSyncReplies)
- return nullptr;
-
- ASSERT(!m_secondaryThreadPendingSyncReplyMap.contains(syncRequestID));
- m_secondaryThreadPendingSyncReplyMap.add(syncRequestID, &pendingReply);
- }
-
- sendMessage(std::move(encoder), 0);
-
- pendingReply.semaphore.wait(currentTime() + (timeout.count() / 1000.0));
-
- // Finally, pop the pending sync reply information.
- {
- MutexLocker locker(m_syncReplyStateMutex);
- ASSERT(m_secondaryThreadPendingSyncReplyMap.contains(syncRequestID));
- m_secondaryThreadPendingSyncReplyMap.remove(syncRequestID);
- }
-
- return std::move(pendingReply.replyDecoder);
-}
-
-std::unique_ptr<MessageDecoder> Connection::waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags)
+std::unique_ptr<Decoder> Connection::waitForSyncReply(uint64_t syncRequestID, Seconds timeout, OptionSet<SendSyncOption> sendSyncOptions)
{
- double absoluteTime = currentTime() + (timeout.count() / 1000.0);
+ timeout = timeoutRespectingIgnoreTimeoutsForTesting(timeout);
+ WallTime absoluteTime = WallTime::now() + timeout;
+ willSendSyncMessage(sendSyncOptions);
+
bool timedOut = false;
while (!timedOut) {
// First, check if we have any messages that we need to process.
- m_syncMessageState->dispatchMessages(0);
+ SyncMessageState::singleton().dispatchMessages(nullptr);
{
- MutexLocker locker(m_syncReplyStateMutex);
+ LockHolder locker(m_syncReplyStateMutex);
// Second, check if there is a sync reply at the top of the stack.
ASSERT(!m_pendingSyncReplies.isEmpty());
@@ -530,129 +568,192 @@ std::unique_ptr<MessageDecoder> Connection::waitForSyncReply(uint64_t syncReques
ASSERT_UNUSED(syncRequestID, pendingSyncReply.syncRequestID == syncRequestID);
// We found the sync reply, or the connection was closed.
- if (pendingSyncReply.didReceiveReply || !m_shouldWaitForSyncReplies)
- return std::move(pendingSyncReply.replyDecoder);
+ if (pendingSyncReply.didReceiveReply || !m_shouldWaitForSyncReplies) {
+ didReceiveSyncReply(sendSyncOptions);
+ return WTFMove(pendingSyncReply.replyDecoder);
+ }
}
// Processing a sync message could cause the connection to be invalidated.
// (If the handler ends up calling Connection::invalidate).
// If that happens, we need to stop waiting, or we'll hang since we won't get
// any more incoming messages.
- if (!isValid())
+ if (!isValid()) {
+ RELEASE_LOG_ERROR(IPC, "Connection::waitForSyncReply: Connection no longer valid, id = %" PRIu64, syncRequestID);
+ didReceiveSyncReply(sendSyncOptions);
return nullptr;
+ }
// We didn't find a sync reply yet, keep waiting.
// This allows the WebProcess to still serve clients while waiting for the message to return.
// Notably, it can continue to process accessibility requests, which are on the main thread.
- if (syncSendFlags & SpinRunLoopWhileWaitingForReply) {
-#if PLATFORM(MAC)
- // FIXME: Although we run forever, any events incoming will cause us to drop out and exit out. This however doesn't
- // account for a timeout value passed in. Timeout is always NoTimeout in these cases, but that could change.
- RunLoop::current()->runForDuration(1e10);
- timedOut = currentTime() >= absoluteTime;
-#endif
- } else
- timedOut = !m_syncMessageState->wait(absoluteTime);
-
+ timedOut = !SyncMessageState::singleton().wait(absoluteTime);
}
+ RELEASE_LOG_ERROR(IPC, "Connection::waitForSyncReply: Timed-out while waiting for reply, id = %" PRIu64, syncRequestID);
+ didReceiveSyncReply(sendSyncOptions);
+
return nullptr;
}
-void Connection::processIncomingSyncReply(std::unique_ptr<MessageDecoder> decoder)
+void Connection::processIncomingSyncReply(std::unique_ptr<Decoder> decoder)
{
- MutexLocker locker(m_syncReplyStateMutex);
+ {
+ LockHolder locker(m_syncReplyStateMutex);
- // Go through the stack of sync requests that have pending replies and see which one
- // this reply is for.
- for (size_t i = m_pendingSyncReplies.size(); i > 0; --i) {
- PendingSyncReply& pendingSyncReply = m_pendingSyncReplies[i - 1];
+ // Go through the stack of sync requests that have pending replies and see which one
+ // this reply is for.
+ for (size_t i = m_pendingSyncReplies.size(); i > 0; --i) {
+ PendingSyncReply& pendingSyncReply = m_pendingSyncReplies[i - 1];
- if (pendingSyncReply.syncRequestID != decoder->destinationID())
- continue;
+ if (pendingSyncReply.syncRequestID != decoder->destinationID())
+ continue;
- ASSERT(!pendingSyncReply.replyDecoder);
+ ASSERT(!pendingSyncReply.replyDecoder);
- pendingSyncReply.replyDecoder = std::move(decoder);
- pendingSyncReply.didReceiveReply = true;
+ pendingSyncReply.replyDecoder = WTFMove(decoder);
+ pendingSyncReply.didReceiveReply = true;
- // We got a reply to the last send message, wake up the client run loop so it can be processed.
- if (i == m_pendingSyncReplies.size())
- m_syncMessageState->wakeUpClientRunLoop();
+ // We got a reply to the last send message, wake up the client run loop so it can be processed.
+ if (i == m_pendingSyncReplies.size())
+ SyncMessageState::singleton().wakeUpClientRunLoop();
- return;
+ return;
+ }
}
- // If it's not a reply to any primary thread message, check if it is a reply to a secondary thread one.
- SecondaryThreadPendingSyncReplyMap::iterator secondaryThreadReplyMapItem = m_secondaryThreadPendingSyncReplyMap.find(decoder->destinationID());
- if (secondaryThreadReplyMapItem != m_secondaryThreadPendingSyncReplyMap.end()) {
- SecondaryThreadPendingSyncReply* reply = secondaryThreadReplyMapItem->value;
- ASSERT(!reply->replyDecoder);
- reply->replyDecoder = std::move(decoder);
- reply->semaphore.signal();
+ {
+ LockHolder locker(m_replyHandlersLock);
+
+ auto replyHandler = m_replyHandlers.take(decoder->destinationID());
+ if (replyHandler.dispatcher) {
+ replyHandler.dispatcher->dispatch([protectedThis = makeRef(*this), handler = WTFMove(replyHandler.handler), decoder = WTFMove(decoder)] () mutable {
+ if (!protectedThis->isValid()) {
+ handler(nullptr);
+ return;
+ }
+
+ handler(WTFMove(decoder));
+ });
+ }
}
// If we get here, it means we got a reply for a message that wasn't in the sync request stack or map.
// This can happen if the send timed out, so it's fine to ignore.
}
-void Connection::processIncomingMessage(std::unique_ptr<MessageDecoder> message)
+void Connection::processIncomingMessage(std::unique_ptr<Decoder> message)
{
ASSERT(!message->messageReceiverName().isEmpty());
ASSERT(!message->messageName().isEmpty());
if (message->messageReceiverName() == "IPC" && message->messageName() == "SyncMessageReply") {
- processIncomingSyncReply(std::move(message));
+ processIncomingSyncReply(WTFMove(message));
return;
}
if (!m_workQueueMessageReceivers.isValidKey(message->messageReceiverName())) {
- if (message->messageReceiverName().isEmpty() && message->messageName().isEmpty()) {
- // Something went wrong when decoding the message. Encode the message length so we can figure out if this
- // happens for certain message lengths.
- CString messageReceiverName = "<unknown message>";
- CString messageName = String::format("<message length: %zu bytes>", message->length()).utf8();
-
- m_clientRunLoop->dispatch(bind(&Connection::dispatchDidReceiveInvalidMessage, this, messageReceiverName, messageName));
- return;
- }
-
- m_clientRunLoop->dispatch(bind(&Connection::dispatchDidReceiveInvalidMessage, this, message->messageReceiverName().toString(), message->messageName().toString()));
+ RefPtr<Connection> protectedThis(this);
+ StringReference messageReceiverNameReference = message->messageReceiverName();
+ String messageReceiverName(messageReceiverNameReference.isEmpty() ? "<unknown message receiver>" : String(messageReceiverNameReference.data(), messageReceiverNameReference.size()));
+ StringReference messageNameReference = message->messageName();
+ String messageName(messageNameReference.isEmpty() ? "<unknown message>" : String(messageNameReference.data(), messageNameReference.size()));
+
+ RunLoop::main().dispatch([protectedThis = makeRef(*this), messageReceiverName = WTFMove(messageReceiverName), messageName = WTFMove(messageName)]() mutable {
+ protectedThis->dispatchDidReceiveInvalidMessage(messageReceiverName.utf8(), messageName.utf8());
+ });
return;
}
auto it = m_workQueueMessageReceivers.find(message->messageReceiverName());
if (it != m_workQueueMessageReceivers.end()) {
- it->value.first->dispatch(bind(&Connection::dispatchWorkQueueMessageReceiverMessage, this, it->value.second, message.release()));
+ it->value.first->dispatch([protectedThis = makeRef(*this), workQueueMessageReceiver = it->value.second, decoder = WTFMove(message)]() mutable {
+ protectedThis->dispatchWorkQueueMessageReceiverMessage(*workQueueMessageReceiver, *decoder);
+ });
return;
}
+#if HAVE(QOS_CLASSES)
+ if (message->isSyncMessage() && m_shouldBoostMainThreadOnSyncMessage) {
+ pthread_override_t override = pthread_override_qos_class_start_np(m_mainThread, adjustedQOSClass(QOS_CLASS_USER_INTERACTIVE), 0);
+ message->setQOSClassOverride(override);
+ }
+#endif
+
+ if (message->isSyncMessage()) {
+ std::lock_guard<Lock> lock(m_incomingSyncMessageCallbackMutex);
+
+ for (auto& callback : m_incomingSyncMessageCallbacks.values())
+ m_incomingSyncMessageCallbackQueue->dispatch(WTFMove(callback));
+
+ m_incomingSyncMessageCallbacks.clear();
+ }
+
// Check if this is a sync message or if it's a message that should be dispatched even when waiting for
// a sync reply. 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 (m_syncMessageState->processIncomingMessage(this, message))
+ if (SyncMessageState::singleton().processIncomingMessage(*this, message))
return;
// Check if we're waiting for this message.
{
- std::lock_guard<std::mutex> lock(m_waitForMessageMutex);
+ std::lock_guard<Lock> lock(m_waitForMessageMutex);
+
+ if (m_waitingForMessage && !m_waitingForMessage->decoder) {
+ if (m_waitingForMessage->messageReceiverName == message->messageReceiverName() && m_waitingForMessage->messageName == message->messageName() && m_waitingForMessage->destinationID == message->destinationID()) {
+ m_waitingForMessage->decoder = WTFMove(message);
+ ASSERT(m_waitingForMessage->decoder);
+ m_waitForMessageCondition.notifyOne();
+ return;
+ }
- auto it = m_waitForMessageMap.find(std::make_pair(std::make_pair(message->messageReceiverName(), message->messageName()), message->destinationID()));
- if (it != m_waitForMessageMap.end()) {
- it->value = std::move(message);
- ASSERT(it->value);
-
- m_waitForMessageCondition.notify_one();
- return;
+ if (m_waitingForMessage->waitForOptions.contains(WaitForOption::InterruptWaitingIfSyncMessageArrives) && message->isSyncMessage()) {
+ m_waitingForMessage->messageWaitingInterrupted = true;
+ m_waitForMessageCondition.notifyOne();
+ }
}
}
- enqueueIncomingMessage(std::move(message));
+ enqueueIncomingMessage(WTFMove(message));
+}
+
+uint64_t Connection::installIncomingSyncMessageCallback(std::function<void ()> callback)
+{
+ std::lock_guard<Lock> lock(m_incomingSyncMessageCallbackMutex);
+
+ m_nextIncomingSyncMessageCallbackID++;
+
+ if (!m_incomingSyncMessageCallbackQueue)
+ m_incomingSyncMessageCallbackQueue = WorkQueue::create("com.apple.WebKit.IPC.IncomingSyncMessageCallbackQueue");
+
+ m_incomingSyncMessageCallbacks.add(m_nextIncomingSyncMessageCallbackID, callback);
+
+ return m_nextIncomingSyncMessageCallbackID;
+}
+
+void Connection::uninstallIncomingSyncMessageCallback(uint64_t callbackID)
+{
+ std::lock_guard<Lock> lock(m_incomingSyncMessageCallbackMutex);
+ m_incomingSyncMessageCallbacks.remove(callbackID);
+}
+
+bool Connection::hasIncomingSyncMessage()
+{
+ std::lock_guard<Lock> lock(m_incomingMessagesMutex);
+
+ for (auto& message : m_incomingMessages) {
+ if (message->isSyncMessage())
+ return true;
+ }
+
+ return false;
}
void Connection::postConnectionDidCloseOnConnectionWorkQueue()
{
- m_connectionQueue->dispatch(WTF::bind(&Connection::connectionDidClose, this));
+ m_connectionQueue->dispatch([protectedThis = makeRef(*this)]() mutable {
+ protectedThis->connectionDidClose();
+ });
}
void Connection::connectionDidClose()
@@ -661,38 +762,48 @@ void Connection::connectionDidClose()
platformInvalidate();
{
- MutexLocker locker(m_syncReplyStateMutex);
+ LockHolder locker(m_replyHandlersLock);
+ for (auto& replyHandler : m_replyHandlers.values()) {
+ replyHandler.dispatcher->dispatch([handler = WTFMove(replyHandler.handler)] {
+ handler(nullptr);
+ });
+ }
+
+ m_replyHandlers.clear();
+ }
+
+ {
+ LockHolder locker(m_syncReplyStateMutex);
ASSERT(m_shouldWaitForSyncReplies);
m_shouldWaitForSyncReplies = false;
if (!m_pendingSyncReplies.isEmpty())
- m_syncMessageState->wakeUpClientRunLoop();
+ SyncMessageState::singleton().wakeUpClientRunLoop();
+ }
- for (SecondaryThreadPendingSyncReplyMap::iterator iter = m_secondaryThreadPendingSyncReplyMap.begin(); iter != m_secondaryThreadPendingSyncReplyMap.end(); ++iter)
- iter->value->semaphore.signal();
+ {
+ std::lock_guard<Lock> lock(m_waitForMessageMutex);
+ if (m_waitingForMessage)
+ m_waitingForMessage->messageWaitingInterrupted = true;
}
+ m_waitForMessageCondition.notifyAll();
if (m_didCloseOnConnectionWorkQueueCallback)
m_didCloseOnConnectionWorkQueueCallback(this);
- m_clientRunLoop->dispatch(WTF::bind(&Connection::dispatchConnectionDidClose, this));
-}
+ RunLoop::main().dispatch([protectedThis = makeRef(*this)]() mutable {
+ // If the connection has been explicitly invalidated before dispatchConnectionDidClose was called,
+ // then the the connection will be invalid here.
+ if (!protectedThis->isValid())
+ return;
-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;
+ // Set m_isValid to false before calling didClose, otherwise, sendSync will try to send a message
+ // to the connection and will then wait indefinitely for a reply.
+ protectedThis->m_isValid = false;
- // 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);
+ protectedThis->m_client.didClose(protectedThis.get());
+ });
}
bool Connection::canSendOutgoingMessages() const
@@ -706,21 +817,21 @@ void Connection::sendOutgoingMessages()
return;
while (true) {
- std::unique_ptr<MessageEncoder> message;
+ std::unique_ptr<Encoder> message;
{
- MutexLocker locker(m_outgoingMessagesLock);
+ std::lock_guard<Lock> lock(m_outgoingMessagesMutex);
if (m_outgoingMessages.isEmpty())
break;
message = m_outgoingMessages.takeFirst();
}
- if (!sendOutgoingMessage(std::move(message)))
+ if (!sendOutgoingMessage(WTFMove(message)))
break;
}
}
-void Connection::dispatchSyncMessage(MessageDecoder& decoder)
+void Connection::dispatchSyncMessage(Decoder& decoder)
{
ASSERT(decoder.isSyncMessage());
@@ -731,26 +842,38 @@ void Connection::dispatchSyncMessage(MessageDecoder& decoder)
return;
}
- auto replyEncoder = std::make_unique<MessageEncoder>("IPC", "SyncMessageReply", syncRequestID);
+ auto replyEncoder = std::make_unique<Encoder>("IPC", "SyncMessageReply", syncRequestID);
- // Hand off both the decoder and encoder to the client.
- m_client->didReceiveSyncMessage(this, decoder, replyEncoder);
+ if (decoder.messageReceiverName() == "IPC" && decoder.messageName() == "WrappedAsyncMessageForTesting") {
+ if (!m_fullySynchronousModeIsAllowedForTesting) {
+ decoder.markInvalid();
+ return;
+ }
+ std::unique_ptr<Decoder> unwrappedDecoder = Decoder::unwrapForTesting(decoder);
+ RELEASE_ASSERT(unwrappedDecoder);
+ processIncomingMessage(WTFMove(unwrappedDecoder));
+
+ SyncMessageState::singleton().dispatchMessages(nullptr);
+ } else {
+ // Hand off both the decoder and encoder to the client.
+ m_client.didReceiveSyncMessage(*this, decoder, replyEncoder);
+ }
// FIXME: If the message was invalid, we should send back a SyncMessageError.
ASSERT(!decoder.isInvalid());
if (replyEncoder)
- sendSyncReply(std::move(replyEncoder));
+ sendSyncReply(WTFMove(replyEncoder));
}
void Connection::dispatchDidReceiveInvalidMessage(const CString& messageReceiverNameString, const CString& messageNameString)
{
- ASSERT(RunLoop::current() == m_clientRunLoop);
+ ASSERT(RunLoop::isMain());
- if (!m_client)
+ if (!isValid())
return;
- m_client->didReceiveInvalidMessage(this, StringReference(messageReceiverNameString.data(), messageReceiverNameString.length()), StringReference(messageNameString.data(), messageNameString.length()));
+ m_client.didReceiveInvalidMessage(*this, StringReference(messageReceiverNameString.data(), messageReceiverNameString.length()), StringReference(messageNameString.data(), messageNameString.length()));
}
void Connection::didFailToSendSyncMessage()
@@ -761,28 +884,36 @@ void Connection::didFailToSendSyncMessage()
exit(0);
}
-void Connection::enqueueIncomingMessage(std::unique_ptr<MessageDecoder> incomingMessage)
+void Connection::enqueueIncomingMessage(std::unique_ptr<Decoder> incomingMessage)
{
{
- MutexLocker locker(m_incomingMessagesLock);
- m_incomingMessages.append(std::move(incomingMessage));
+ std::lock_guard<Lock> lock(m_incomingMessagesMutex);
+ m_incomingMessages.append(WTFMove(incomingMessage));
}
- m_clientRunLoop->dispatch(WTF::bind(&Connection::dispatchOneMessage, this));
+ RunLoop::main().dispatch([protectedThis = makeRef(*this)]() mutable {
+ protectedThis->dispatchOneMessage();
+ });
}
-void Connection::dispatchMessage(MessageDecoder& decoder)
+void Connection::dispatchMessage(Decoder& decoder)
{
- m_client->didReceiveMessage(this, decoder);
+ m_client.didReceiveMessage(*this, decoder);
}
-void Connection::dispatchMessage(std::unique_ptr<MessageDecoder> message)
+void Connection::dispatchMessage(std::unique_ptr<Decoder> message)
{
- // If there's no client, return. We do this after calling releaseArguments so that
- // the ArgumentDecoder message will be freed.
- if (!m_client)
+ if (!isValid())
return;
+ if (message->shouldUseFullySynchronousModeForTesting()) {
+ if (!m_fullySynchronousModeIsAllowedForTesting) {
+ m_client.didReceiveInvalidMessage(*this, message->messageReceiverName(), message->messageName());
+ return;
+ }
+ m_inDispatchMessageMarkedToUseFullySynchronousModeForTesting++;
+ }
+
m_inDispatchMessageCount++;
if (message->shouldDispatchMessageWhenWaitingForSyncReply())
@@ -799,33 +930,38 @@ void Connection::dispatchMessage(std::unique_ptr<MessageDecoder> message)
m_didReceiveInvalidMessage |= message->isInvalid();
m_inDispatchMessageCount--;
+ // FIXME: For Delayed synchronous messages, we should not decrement the counter until we send a response.
+ // Otherwise, we would deadlock if processing the message results in a sync message back after we exit this function.
if (message->shouldDispatchMessageWhenWaitingForSyncReply())
m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount--;
- if (m_didReceiveInvalidMessage && m_client)
- m_client->didReceiveInvalidMessage(this, message->messageReceiverName(), message->messageName());
+ if (message->shouldUseFullySynchronousModeForTesting())
+ m_inDispatchMessageMarkedToUseFullySynchronousModeForTesting--;
+
+ if (m_didReceiveInvalidMessage && isValid())
+ m_client.didReceiveInvalidMessage(*this, message->messageReceiverName(), message->messageName());
m_didReceiveInvalidMessage = oldDidReceiveInvalidMessage;
}
void Connection::dispatchOneMessage()
{
- std::unique_ptr<MessageDecoder> message;
+ std::unique_ptr<Decoder> message;
{
- MutexLocker locker(m_incomingMessagesLock);
+ std::lock_guard<Lock> lock(m_incomingMessagesMutex);
if (m_incomingMessages.isEmpty())
return;
message = m_incomingMessages.takeFirst();
}
- dispatchMessage(std::move(message));
+ dispatchMessage(WTFMove(message));
}
void Connection::wakeUpRunLoop()
{
- m_clientRunLoop->wakeUp();
+ RunLoop::main().wakeUp();
}
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/Connection.h b/Source/WebKit2/Platform/IPC/Connection.h
index 92df2689c..a5a8ad7b4 100644
--- a/Source/WebKit2/Platform/IPC/Connection.h
+++ b/Source/WebKit2/Platform/IPC/Connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2016 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.
*
@@ -25,48 +25,51 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef Connection_h
-#define Connection_h
+#pragma once
-#include "Arguments.h"
-#include "MessageDecoder.h"
-#include "MessageEncoder.h"
+#include "Decoder.h"
+#include "Encoder.h"
+#include "HandleMessage.h"
#include "MessageReceiver.h"
-#include "WorkQueue.h"
#include <atomic>
-#include <condition_variable>
+#include <wtf/Condition.h>
#include <wtf/Deque.h>
#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/OwnPtr.h>
+#include <wtf/HashMap.h>
+#include <wtf/Lock.h>
+#include <wtf/OptionSet.h>
+#include <wtf/WorkQueue.h>
#include <wtf/text/CString.h>
-#if OS(DARWIN)
+#if OS(DARWIN) && !USE(UNIX_DOMAIN_SOCKETS)
#include <mach/mach_port.h>
-#include <xpc/xpc.h>
+#include <wtf/OSObjectPtr.h>
+#include <wtf/spi/darwin/XPCSPI.h>
#endif
-#if PLATFORM(GTK) || PLATFORM(EFL)
-#include "PlatformProcessIdentifier.h"
+#if PLATFORM(GTK)
+#include "GSocketMonitor.h"
#endif
-namespace WTF {
-class RunLoop;
-}
-
namespace IPC {
-enum MessageSendFlags {
+enum class SendOption {
// Whether this message should be dispatched when waiting for a sync reply.
// This is the default for synchronous messages.
DispatchMessageEvenWhenWaitingForSyncReply = 1 << 0,
};
-enum SyncMessageSendFlags {
- // Will allow events to continue being handled while waiting for the sync reply.
- SpinRunLoopWhileWaitingForReply = 1 << 0,
+enum class SendSyncOption {
+ // Use this to inform that this sync call will suspend this process until the user responds with input.
+ InformPlatformProcessWillSuspend = 1 << 0,
+ UseFullySynchronousModeForTesting = 1 << 1,
};
-
+
+enum class WaitForOption {
+ // Use this to make waitForMessage be interrupted immediately by any incoming sync messages.
+ InterruptWaitingIfSyncMessageArrives = 1 << 0,
+};
+
#define MESSAGE_CHECK_BASE(assertion, connection) do \
if (!(assertion)) { \
ASSERT(assertion); \
@@ -75,12 +78,15 @@ enum SyncMessageSendFlags {
} \
while (0)
+class MachMessage;
+class UnixMessage;
+
class Connection : public ThreadSafeRefCounted<Connection> {
public:
class Client : public MessageReceiver {
public:
- virtual void didClose(Connection*) = 0;
- virtual void didReceiveInvalidMessage(Connection*, StringReference messageReceiverName, StringReference messageName) = 0;
+ virtual void didClose(Connection&) = 0;
+ virtual void didReceiveInvalidMessage(Connection&, StringReference messageReceiverName, StringReference messageName) = 0;
protected:
virtual ~Client() { }
@@ -89,54 +95,55 @@ public:
class WorkQueueMessageReceiver : public MessageReceiver, public ThreadSafeRefCounted<WorkQueueMessageReceiver> {
};
-#if OS(DARWIN)
+#if USE(UNIX_DOMAIN_SOCKETS)
+ typedef int Identifier;
+ static bool identifierIsNull(Identifier identifier) { return identifier == -1; }
+
+ struct SocketPair {
+ int client;
+ int server;
+ };
+
+ enum ConnectionOptions {
+ SetCloexecOnClient = 1 << 0,
+ SetCloexecOnServer = 1 << 1,
+ };
+
+ static Connection::SocketPair createPlatformConnection(unsigned options = SetCloexecOnClient | SetCloexecOnServer);
+#elif OS(DARWIN)
struct Identifier {
Identifier()
: port(MACH_PORT_NULL)
- , xpcConnection(0)
{
}
Identifier(mach_port_t port)
: port(port)
- , xpcConnection(0)
{
}
- Identifier(mach_port_t port, xpc_connection_t xpcConnection)
+ Identifier(mach_port_t port, OSObjectPtr<xpc_connection_t> xpcConnection)
: port(port)
- , xpcConnection(xpcConnection)
+ , xpcConnection(WTFMove(xpcConnection))
{
}
mach_port_t port;
- xpc_connection_t xpcConnection;
+ OSObjectPtr<xpc_connection_t> xpcConnection;
};
static bool identifierIsNull(Identifier identifier) { return identifier.port == MACH_PORT_NULL; }
-#elif USE(UNIX_DOMAIN_SOCKETS)
- typedef int Identifier;
- static bool identifierIsNull(Identifier identifier) { return !identifier; }
-
- struct SocketPair {
- int client;
- int server;
- };
-
- enum ConnectionOptions {
- SetCloexecOnClient = 1 << 0,
- SetCloexecOnServer = 1 << 1,
- };
-
- static Connection::SocketPair createPlatformConnection(unsigned options = SetCloexecOnClient | SetCloexecOnServer);
+ xpc_connection_t xpcConnection() const { return m_xpcConnection.get(); }
+ bool getAuditToken(audit_token_t&);
+ pid_t remoteProcessID() const;
#endif
- static PassRefPtr<Connection> createServerConnection(Identifier, Client*, WTF::RunLoop* clientRunLoop);
- static PassRefPtr<Connection> createClientConnection(Identifier, Client*, WTF::RunLoop* clientRunLoop);
+ static Ref<Connection> createServerConnection(Identifier, Client&);
+ static Ref<Connection> createClientConnection(Identifier, Client&);
~Connection();
- Client* client() const { return m_client; }
+ Client& client() const { return m_client; }
-#if OS(DARWIN)
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
void setShouldCloseConnectionOnMachExceptions();
#endif
@@ -151,7 +158,7 @@ public:
typedef void (*DidCloseOnConnectionWorkQueueCallback)(Connection*);
void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback);
- void addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue*, WorkQueueMessageReceiver*);
+ void addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue&, WorkQueueMessageReceiver*);
void removeWorkQueueMessageReceiver(StringReference messageReceiverName);
bool open();
@@ -160,15 +167,16 @@ public:
void postConnectionDidCloseOnConnectionWorkQueue();
- template<typename T> bool send(T&& message, uint64_t destinationID, unsigned messageSendFlags = 0);
- template<typename T> bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout = std::chrono::milliseconds::max(), unsigned syncSendFlags = 0);
- template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout);
+ template<typename T> bool send(T&& message, uint64_t destinationID, OptionSet<SendOption> sendOptions = { });
+ template<typename T> void sendWithReply(T&& message, uint64_t destinationID, FunctionDispatcher& replyDispatcher, Function<void (std::optional<typename CodingType<typename T::Reply>::Type>)>&& replyHandler);
+ template<typename T> bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, Seconds timeout = Seconds::infinity(), OptionSet<SendSyncOption> sendSyncOptions = { });
+ template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, Seconds timeout, OptionSet<WaitForOption> waitForOptions = { });
- std::unique_ptr<MessageEncoder> createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID);
- bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags = 0);
- std::unique_ptr<MessageDecoder> sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout, unsigned syncSendFlags = 0);
- std::unique_ptr<MessageDecoder> sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout);
- bool sendSyncReply(std::unique_ptr<MessageEncoder>);
+ bool sendMessage(std::unique_ptr<Encoder>, OptionSet<SendOption> sendOptions);
+ void sendMessageWithReply(uint64_t requestID, std::unique_ptr<Encoder>, FunctionDispatcher& replyDispatcher, Function<void (std::unique_ptr<Decoder>)>&& replyHandler);
+ std::unique_ptr<Encoder> createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID);
+ std::unique_ptr<Decoder> sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<Encoder>, Seconds timeout, OptionSet<SendSyncOption> sendSyncOptions);
+ bool sendSyncReply(std::unique_ptr<Encoder>);
void wakeUpRunLoop();
@@ -177,45 +185,71 @@ public:
bool inSendSync() const { return m_inSendSyncCount; }
+ Identifier identifier() const;
+
+#if PLATFORM(COCOA)
+ bool kill();
+ void terminateSoon(double intervalInSeconds);
+#endif
+
+ bool isValid() const { return m_isValid; }
+
+#if HAVE(QOS_CLASSES)
+ void setShouldBoostMainThreadOnSyncMessage(bool b) { m_shouldBoostMainThreadOnSyncMessage = b; }
+#endif
+
+ uint64_t installIncomingSyncMessageCallback(std::function<void ()>);
+ void uninstallIncomingSyncMessageCallback(uint64_t);
+ bool hasIncomingSyncMessage();
+
+ void allowFullySynchronousModeForTesting() { m_fullySynchronousModeIsAllowedForTesting = true; }
+
+ void ignoreTimeoutsForTesting() { m_ignoreTimeoutsForTesting = true; }
+
private:
- Connection(Identifier, bool isServer, Client*, WTF::RunLoop* clientRunLoop);
+ Connection(Identifier, bool isServer, Client&);
void platformInitialize(Identifier);
void platformInvalidate();
- bool isValid() const { return m_client; }
+ std::unique_ptr<Decoder> waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, Seconds timeout, OptionSet<WaitForOption>);
- std::unique_ptr<MessageDecoder> waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout);
-
- std::unique_ptr<MessageDecoder> waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags);
+ std::unique_ptr<Decoder> waitForSyncReply(uint64_t syncRequestID, Seconds timeout, OptionSet<SendSyncOption>);
// Called on the connection work queue.
- void processIncomingMessage(std::unique_ptr<MessageDecoder>);
- void processIncomingSyncReply(std::unique_ptr<MessageDecoder>);
+ void processIncomingMessage(std::unique_ptr<Decoder>);
+ void processIncomingSyncReply(std::unique_ptr<Decoder>);
- void addWorkQueueMessageReceiverOnConnectionWorkQueue(StringReference messageReceiverName, WorkQueue*, WorkQueueMessageReceiver*);
- void removeWorkQueueMessageReceiverOnConnectionWorkQueue(StringReference messageReceiverName);
- void dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver*, MessageDecoder*);
+ void dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver&, Decoder&);
bool canSendOutgoingMessages() const;
bool platformCanSendOutgoingMessages() const;
void sendOutgoingMessages();
- bool sendOutgoingMessage(std::unique_ptr<MessageEncoder>);
+ bool sendOutgoingMessage(std::unique_ptr<Encoder>);
void connectionDidClose();
// Called on the listener thread.
- void dispatchConnectionDidClose();
void dispatchOneMessage();
- void dispatchMessage(std::unique_ptr<MessageDecoder>);
- void dispatchMessage(MessageDecoder&);
- void dispatchSyncMessage(MessageDecoder&);
+ void dispatchMessage(std::unique_ptr<Decoder>);
+ void dispatchMessage(Decoder&);
+ void dispatchSyncMessage(Decoder&);
void dispatchDidReceiveInvalidMessage(const CString& messageReceiverNameString, const CString& messageNameString);
void didFailToSendSyncMessage();
// Can be called on any thread.
- void enqueueIncomingMessage(std::unique_ptr<MessageDecoder>);
+ void enqueueIncomingMessage(std::unique_ptr<Decoder>);
+
+ void willSendSyncMessage(OptionSet<SendSyncOption>);
+ void didReceiveSyncReply(OptionSet<SendSyncOption>);
- Client* m_client;
+ Seconds timeoutRespectingIgnoreTimeoutsForTesting(Seconds) const;
+
+#if PLATFORM(COCOA)
+ bool sendMessage(std::unique_ptr<MachMessage>);
+#endif
+
+ Client& m_client;
bool m_isServer;
+ std::atomic<bool> m_isValid { true };
std::atomic<uint64_t> m_syncRequestID;
bool m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage;
@@ -223,119 +257,143 @@ private:
DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback;
bool m_isConnected;
- RefPtr<WorkQueue> m_connectionQueue;
- WTF::RunLoop* m_clientRunLoop;
+ Ref<WorkQueue> m_connectionQueue;
HashMap<StringReference, std::pair<RefPtr<WorkQueue>, RefPtr<WorkQueueMessageReceiver>>> m_workQueueMessageReceivers;
unsigned m_inSendSyncCount;
unsigned m_inDispatchMessageCount;
unsigned m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount;
+ unsigned m_inDispatchMessageMarkedToUseFullySynchronousModeForTesting { 0 };
+ bool m_fullySynchronousModeIsAllowedForTesting { false };
+ bool m_ignoreTimeoutsForTesting { false };
bool m_didReceiveInvalidMessage;
// Incoming messages.
- Mutex m_incomingMessagesLock;
- Deque<std::unique_ptr<MessageDecoder>> m_incomingMessages;
+ Lock m_incomingMessagesMutex;
+ Deque<std::unique_ptr<Decoder>> m_incomingMessages;
// Outgoing messages.
- Mutex m_outgoingMessagesLock;
- Deque<std::unique_ptr<MessageEncoder>> m_outgoingMessages;
+ Lock m_outgoingMessagesMutex;
+ Deque<std::unique_ptr<Encoder>> m_outgoingMessages;
- std::condition_variable m_waitForMessageCondition;
- std::mutex m_waitForMessageMutex;
- HashMap<std::pair<std::pair<StringReference, StringReference>, uint64_t>, std::unique_ptr<MessageDecoder>> m_waitForMessageMap;
+ Condition m_waitForMessageCondition;
+ Lock m_waitForMessageMutex;
- // Represents a sync request for which we're waiting on a reply.
- struct PendingSyncReply {
- // The request ID.
- uint64_t syncRequestID;
+ struct ReplyHandler;
- // The reply decoder, will be null if there was an error processing the sync
- // message on the other side.
- std::unique_ptr<MessageDecoder> replyDecoder;
+ Lock m_replyHandlersLock;
+ HashMap<uint64_t, ReplyHandler> m_replyHandlers;
- // Will be set to true once a reply has been received.
- bool didReceiveReply;
-
- PendingSyncReply()
- : syncRequestID(0)
- , didReceiveReply(false)
- {
- }
-
- explicit PendingSyncReply(uint64_t syncRequestID)
- : syncRequestID(syncRequestID)
- , didReceiveReply(0)
- {
- }
- };
+ struct WaitForMessageState;
+ WaitForMessageState* m_waitingForMessage;
class SyncMessageState;
- friend class SyncMessageState;
- RefPtr<SyncMessageState> m_syncMessageState;
- Mutex m_syncReplyStateMutex;
+ Lock m_syncReplyStateMutex;
bool m_shouldWaitForSyncReplies;
+ struct PendingSyncReply;
Vector<PendingSyncReply> m_pendingSyncReplies;
- class SecondaryThreadPendingSyncReply;
- typedef HashMap<uint64_t, SecondaryThreadPendingSyncReply*> SecondaryThreadPendingSyncReplyMap;
- SecondaryThreadPendingSyncReplyMap m_secondaryThreadPendingSyncReplyMap;
+ Lock m_incomingSyncMessageCallbackMutex;
+ HashMap<uint64_t, std::function<void ()>> m_incomingSyncMessageCallbacks;
+ RefPtr<WorkQueue> m_incomingSyncMessageCallbackQueue;
+ uint64_t m_nextIncomingSyncMessageCallbackID { 0 };
+
+#if HAVE(QOS_CLASSES)
+ pthread_t m_mainThread { 0 };
+ bool m_shouldBoostMainThreadOnSyncMessage { false };
+#endif
-#if OS(DARWIN)
+#if USE(UNIX_DOMAIN_SOCKETS)
+ // Called on the connection queue.
+ void readyReadHandler();
+ bool processMessage();
+ bool sendOutputMessage(UnixMessage&);
+
+ Vector<uint8_t> m_readBuffer;
+ Vector<int> m_fileDescriptors;
+ int m_socketDescriptor;
+ std::unique_ptr<UnixMessage> m_pendingOutputMessage;
+#if PLATFORM(GTK)
+ GRefPtr<GSocket> m_socket;
+ GSocketMonitor m_readSocketMonitor;
+ GSocketMonitor m_writeSocketMonitor;
+#endif
+#elif OS(DARWIN)
// Called on the connection queue.
void receiveSourceEventHandler();
- void initializeDeadNameSource();
- void exceptionSourceEventHandler();
+ void initializeSendSource();
mach_port_t m_sendPort;
- dispatch_source_t m_deadNameSource;
+ dispatch_source_t m_sendSource;
mach_port_t m_receivePort;
- dispatch_source_t m_receivePortDataAvailableSource;
+ dispatch_source_t m_receiveSource;
+
+ std::unique_ptr<MachMessage> m_pendingOutgoingMachMessage;
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
+ void exceptionSourceEventHandler();
// 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;
dispatch_source_t m_exceptionPortDataAvailableSource;
+#endif
- xpc_connection_t m_xpcConnection;
-
-#elif USE(UNIX_DOMAIN_SOCKETS)
- // Called on the connection queue.
- void readyReadHandler();
- bool processMessage();
-
- Vector<uint8_t> m_readBuffer;
- size_t m_readBufferSize;
- Vector<int> m_fileDescriptors;
- size_t m_fileDescriptorsSize;
- int m_socketDescriptor;
+ OSObjectPtr<xpc_connection_t> m_xpcConnection;
#endif
};
-template<typename T> bool Connection::send(T&& message, uint64_t destinationID, unsigned messageSendFlags)
+template<typename T>
+bool Connection::send(T&& message, uint64_t destinationID, OptionSet<SendOption> sendOptions)
{
COMPILE_ASSERT(!T::isSync, AsyncMessageExpected);
- auto encoder = std::make_unique<MessageEncoder>(T::receiverName(), T::name(), destinationID);
+ auto encoder = std::make_unique<Encoder>(T::receiverName(), T::name(), destinationID);
encoder->encode(message.arguments());
- return sendMessage(std::move(encoder), messageSendFlags);
+ return sendMessage(WTFMove(encoder), sendOptions);
+}
+
+template<typename T>
+void Connection::sendWithReply(T&& message, uint64_t destinationID, FunctionDispatcher& replyDispatcher, Function<void (std::optional<typename CodingType<typename T::Reply>::Type>)>&& replyHandler)
+{
+ uint64_t requestID = 0;
+ std::unique_ptr<Encoder> encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, requestID);
+
+ encoder->encode(message.arguments());
+
+ sendMessageWithReply(requestID, WTFMove(encoder), replyDispatcher, [replyHandler = WTFMove(replyHandler)](std::unique_ptr<Decoder> decoder) {
+ if (decoder) {
+ typename CodingType<typename T::Reply>::Type reply;
+ if (decoder->decode(reply)) {
+ replyHandler(WTFMove(reply));
+ return;
+ }
+ }
+
+ replyHandler(std::nullopt);
+ });
}
-template<typename T> bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned syncSendFlags)
+template<typename T> bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, Seconds timeout, OptionSet<SendSyncOption> sendSyncOptions)
{
COMPILE_ASSERT(T::isSync, SyncMessageExpected);
uint64_t syncRequestID = 0;
- std::unique_ptr<MessageEncoder> encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, syncRequestID);
-
+ std::unique_ptr<Encoder> encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, syncRequestID);
+
+ if (sendSyncOptions.contains(SendSyncOption::UseFullySynchronousModeForTesting)) {
+ encoder->setFullySynchronousModeForTesting();
+ m_fullySynchronousModeIsAllowedForTesting = true;
+ }
+
// Encode the rest of the input arguments.
encoder->encode(message.arguments());
// Now send the message and wait for a reply.
- std::unique_ptr<MessageDecoder> replyDecoder = sendSyncMessage(syncRequestID, std::move(encoder), timeout, syncSendFlags);
+ std::unique_ptr<Decoder> replyDecoder = sendSyncMessage(syncRequestID, WTFMove(encoder), timeout, sendSyncOptions);
if (!replyDecoder)
return false;
@@ -343,17 +401,15 @@ template<typename T> bool Connection::sendSync(T&& message, typename T::Reply&&
return replyDecoder->decode(reply);
}
-template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout)
+template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, Seconds timeout, OptionSet<WaitForOption> waitForOptions)
{
- std::unique_ptr<MessageDecoder> decoder = waitForMessage(T::receiverName(), T::name(), destinationID, timeout);
+ std::unique_ptr<Decoder> decoder = waitForMessage(T::receiverName(), T::name(), destinationID, timeout, waitForOptions);
if (!decoder)
return false;
ASSERT(decoder->destinationID() == destinationID);
- m_client->didReceiveMessage(this, *decoder);
+ m_client.didReceiveMessage(*this, *decoder);
return true;
}
} // namespace IPC
-
-#endif // Connection_h
diff --git a/Source/WebKit2/Platform/IPC/DataReference.cpp b/Source/WebKit2/Platform/IPC/DataReference.cpp
index 0047022e9..9bdec4ff4 100644
--- a/Source/WebKit2/Platform/IPC/DataReference.cpp
+++ b/Source/WebKit2/Platform/IPC/DataReference.cpp
@@ -26,19 +26,34 @@
#include "config.h"
#include "DataReference.h"
-#include "ArgumentDecoder.h"
-#include "ArgumentEncoder.h"
+#include "Decoder.h"
+#include "Encoder.h"
namespace IPC {
-void DataReference::encode(ArgumentEncoder& encoder) const
+void DataReference::encode(Encoder& encoder) const
{
encoder.encodeVariableLengthByteArray(*this);
}
-bool DataReference::decode(ArgumentDecoder& decoder, DataReference& dataReference)
+bool DataReference::decode(Decoder& decoder, DataReference& dataReference)
{
return decoder.decodeVariableLengthByteArray(dataReference);
}
+void SharedBufferDataReference::encode(Encoder& encoder) const
+{
+ uint64_t bufferSize = static_cast<uint64_t>(m_buffer->size());
+ encoder.reserve(bufferSize + sizeof(uint64_t));
+ encoder << bufferSize;
+
+ const char* partialData;
+ unsigned position = 0;
+ while (position < bufferSize) {
+ unsigned bytesToWrite = m_buffer->getSomeData(partialData, position);
+ encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(partialData), bytesToWrite, 1);
+ position += bytesToWrite;
+ }
+}
+
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/DataReference.h b/Source/WebKit2/Platform/IPC/DataReference.h
index 66c3761e4..fb57591db 100644
--- a/Source/WebKit2/Platform/IPC/DataReference.h
+++ b/Source/WebKit2/Platform/IPC/DataReference.h
@@ -26,12 +26,13 @@
#ifndef DataReference_h
#define DataReference_h
+#include <WebCore/SharedBuffer.h>
#include <wtf/Vector.h>
namespace IPC {
-class ArgumentDecoder;
-class ArgumentEncoder;
+class Decoder;
+class Encoder;
class DataReference {
public:
@@ -72,14 +73,40 @@ public:
return result;
}
- void encode(ArgumentEncoder&) const;
- static bool decode(ArgumentDecoder&, DataReference&);
+ virtual void encode(Encoder&) const;
+ static bool decode(Decoder&, DataReference&);
+
+ virtual ~DataReference() { }
private:
const uint8_t* m_data;
size_t m_size;
};
+class SharedBufferDataReference : public DataReference {
+public:
+ // FIXME: This class doesn't handle null, so the argument should be a reference or PassRef.
+ SharedBufferDataReference(WebCore::SharedBuffer* buffer)
+ : m_buffer(buffer)
+ {
+ }
+
+private:
+ // FIXME: It is a bad idea to violate the Liskov Substitution Principle as we do here.
+ // Since we are using DataReference as a polymoprhic base class in this fashion,
+ // then we need it to be a base class that does not have functions such as isEmpty,
+ // size, data, and vector, all of which will do the wrong thing if they are called.
+ // Deleting these functions here does not prevent them from being called.
+ bool isEmpty() const = delete;
+ size_t size() const = delete;
+ const uint8_t* data() const = delete;
+ Vector<uint8_t> vector() const = delete;
+
+ void encode(Encoder&) const override;
+
+ RefPtr<WebCore::SharedBuffer> m_buffer;
+};
+
} // namespace IPC
#endif // DataReference_h
diff --git a/Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp b/Source/WebKit2/Platform/IPC/Decoder.cpp
index 6d396beee..740a0cced 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp
+++ b/Source/WebKit2/Platform/IPC/Decoder.cpp
@@ -24,56 +24,111 @@
*/
#include "config.h"
-#include "ArgumentDecoder.h"
+#include "Decoder.h"
#include "DataReference.h"
+#include "MessageFlags.h"
#include <stdio.h>
+#if PLATFORM(MAC)
+#include "ImportanceAssertion.h"
+#endif
+
namespace IPC {
-ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize)
+static const uint8_t* copyBuffer(const uint8_t* buffer, size_t bufferSize)
{
- initialize(buffer, bufferSize);
+ auto bufferCopy = static_cast<uint8_t*>(fastMalloc(bufferSize));
+ memcpy(bufferCopy, buffer, bufferSize);
+
+ return bufferCopy;
}
-ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Vector<Attachment> attachments)
+Decoder::Decoder(const uint8_t* buffer, size_t bufferSize, void (*bufferDeallocator)(const uint8_t*, size_t), Vector<Attachment> attachments)
+ : m_buffer { bufferDeallocator ? buffer : copyBuffer(buffer, bufferSize) }
+ , m_bufferPos { m_buffer }
+ , m_bufferEnd { m_buffer + bufferSize }
+ , m_bufferDeallocator { bufferDeallocator }
+ , m_attachments { WTFMove(attachments) }
{
- initialize(buffer, bufferSize);
+ ASSERT(!(reinterpret_cast<uintptr_t>(m_buffer) % alignof(uint64_t)));
+
+ if (!decode(m_messageFlags))
+ return;
- m_attachments = std::move(attachments);
+ if (!decode(m_messageReceiverName))
+ return;
+
+ if (!decode(m_messageName))
+ return;
+
+ if (!decode(m_destinationID))
+ return;
}
-ArgumentDecoder::~ArgumentDecoder()
+Decoder::~Decoder()
{
ASSERT(m_buffer);
- free(m_buffer);
-#if !USE(UNIX_DOMAIN_SOCKETS)
+
+ if (m_bufferDeallocator)
+ m_bufferDeallocator(m_buffer, m_bufferEnd - m_buffer);
+ else
+ fastFree(const_cast<uint8_t*>(m_buffer));
+
// FIXME: We need to dispose of the mach ports in cases of failure.
-#else
- Vector<Attachment>::iterator end = m_attachments.end();
- for (Vector<Attachment>::iterator it = m_attachments.begin(); it != end; ++it)
- it->dispose();
+
+#if HAVE(QOS_CLASSES)
+ if (m_qosClassOverride)
+ pthread_override_qos_class_end_np(m_qosClassOverride);
#endif
}
-static inline uint8_t* roundUpToAlignment(uint8_t* ptr, unsigned alignment)
+bool Decoder::isSyncMessage() const
{
- // Assert that the alignment is a power of 2.
- ASSERT(alignment && !(alignment & (alignment - 1)));
+ return m_messageFlags & SyncMessage;
+}
- uintptr_t alignmentMask = alignment - 1;
- return reinterpret_cast<uint8_t*>((reinterpret_cast<uintptr_t>(ptr) + alignmentMask) & ~alignmentMask);
+bool Decoder::shouldDispatchMessageWhenWaitingForSyncReply() const
+{
+ return m_messageFlags & DispatchMessageWhenWaitingForSyncReply;
}
-void ArgumentDecoder::initialize(const uint8_t* buffer, size_t bufferSize)
+bool Decoder::shouldUseFullySynchronousModeForTesting() const
{
- m_buffer = static_cast<uint8_t*>(malloc(bufferSize));
+ return m_messageFlags & UseFullySynchronousModeForTesting;
+}
- ASSERT(!(reinterpret_cast<uintptr_t>(m_buffer) % alignof(uint64_t)));
+#if PLATFORM(MAC)
+void Decoder::setImportanceAssertion(std::unique_ptr<ImportanceAssertion> assertion)
+{
+ m_importanceAssertion = WTFMove(assertion);
+}
+#endif
+
+std::unique_ptr<Decoder> Decoder::unwrapForTesting(Decoder& decoder)
+{
+ ASSERT(decoder.isSyncMessage());
+
+ Vector<Attachment> attachments;
+ Attachment attachment;
+ while (decoder.removeAttachment(attachment))
+ attachments.append(WTFMove(attachment));
+ attachments.reverse();
+
+ DataReference wrappedMessage;
+ if (!decoder.decode(wrappedMessage))
+ return nullptr;
- m_bufferPos = m_buffer;
- m_bufferEnd = m_buffer + bufferSize;
- memcpy(m_buffer, buffer, bufferSize);
+ return std::make_unique<Decoder>(wrappedMessage.data(), wrappedMessage.size(), nullptr, WTFMove(attachments));
+}
+
+static inline const uint8_t* roundUpToAlignment(const uint8_t* ptr, unsigned alignment)
+{
+ // Assert that the alignment is a power of 2.
+ ASSERT(alignment && !(alignment & (alignment - 1)));
+
+ uintptr_t alignmentMask = alignment - 1;
+ return reinterpret_cast<uint8_t*>((reinterpret_cast<uintptr_t>(ptr) + alignmentMask) & ~alignmentMask);
}
static inline bool alignedBufferIsLargeEnoughToContain(const uint8_t* alignedPosition, const uint8_t* bufferEnd, size_t size)
@@ -81,9 +136,9 @@ static inline bool alignedBufferIsLargeEnoughToContain(const uint8_t* alignedPos
return bufferEnd >= alignedPosition && static_cast<size_t>(bufferEnd - alignedPosition) >= size;
}
-bool ArgumentDecoder::alignBufferPosition(unsigned alignment, size_t size)
+bool Decoder::alignBufferPosition(unsigned alignment, size_t size)
{
- uint8_t* alignedPosition = roundUpToAlignment(m_bufferPos, alignment);
+ const uint8_t* alignedPosition = roundUpToAlignment(m_bufferPos, alignment);
if (!alignedBufferIsLargeEnoughToContain(alignedPosition, m_bufferEnd, size)) {
// We've walked off the end of this buffer.
markInvalid();
@@ -94,12 +149,12 @@ bool ArgumentDecoder::alignBufferPosition(unsigned alignment, size_t size)
return true;
}
-bool ArgumentDecoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const
+bool Decoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const
{
return alignedBufferIsLargeEnoughToContain(roundUpToAlignment(m_bufferPos, alignment), m_bufferEnd, size);
}
-bool ArgumentDecoder::decodeFixedLengthData(uint8_t* data, size_t size, unsigned alignment)
+bool Decoder::decodeFixedLengthData(uint8_t* data, size_t size, unsigned alignment)
{
if (!alignBufferPosition(alignment, size))
return false;
@@ -110,7 +165,7 @@ bool ArgumentDecoder::decodeFixedLengthData(uint8_t* data, size_t size, unsigned
return true;
}
-bool ArgumentDecoder::decodeVariableLengthByteArray(DataReference& dataReference)
+bool Decoder::decodeVariableLengthByteArray(DataReference& dataReference)
{
uint64_t size;
if (!decode(size))
@@ -119,7 +174,7 @@ bool ArgumentDecoder::decodeVariableLengthByteArray(DataReference& dataReference
if (!alignBufferPosition(1, size))
return false;
- uint8_t* data = m_bufferPos;
+ const uint8_t* data = m_bufferPos;
m_bufferPos += size;
dataReference = DataReference(data, size);
@@ -127,13 +182,13 @@ bool ArgumentDecoder::decodeVariableLengthByteArray(DataReference& dataReference
}
template<typename Type>
-static void decodeValueFromBuffer(Type& value, uint8_t*& bufferPosition)
+static void decodeValueFromBuffer(Type& value, const uint8_t*& bufferPosition)
{
memcpy(&value, bufferPosition, sizeof(value));
bufferPosition += sizeof(Type);
}
-bool ArgumentDecoder::decode(bool& result)
+bool Decoder::decode(bool& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -142,7 +197,7 @@ bool ArgumentDecoder::decode(bool& result)
return true;
}
-bool ArgumentDecoder::decode(uint8_t& result)
+bool Decoder::decode(uint8_t& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -151,7 +206,7 @@ bool ArgumentDecoder::decode(uint8_t& result)
return true;
}
-bool ArgumentDecoder::decode(uint16_t& result)
+bool Decoder::decode(uint16_t& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -160,7 +215,7 @@ bool ArgumentDecoder::decode(uint16_t& result)
return true;
}
-bool ArgumentDecoder::decode(uint32_t& result)
+bool Decoder::decode(uint32_t& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -169,7 +224,7 @@ bool ArgumentDecoder::decode(uint32_t& result)
return true;
}
-bool ArgumentDecoder::decode(uint64_t& result)
+bool Decoder::decode(uint64_t& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -178,7 +233,7 @@ bool ArgumentDecoder::decode(uint64_t& result)
return true;
}
-bool ArgumentDecoder::decode(int32_t& result)
+bool Decoder::decode(int32_t& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -187,7 +242,7 @@ bool ArgumentDecoder::decode(int32_t& result)
return true;
}
-bool ArgumentDecoder::decode(int64_t& result)
+bool Decoder::decode(int64_t& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -196,7 +251,7 @@ bool ArgumentDecoder::decode(int64_t& result)
return true;
}
-bool ArgumentDecoder::decode(float& result)
+bool Decoder::decode(float& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -205,7 +260,7 @@ bool ArgumentDecoder::decode(float& result)
return true;
}
-bool ArgumentDecoder::decode(double& result)
+bool Decoder::decode(double& result)
{
if (!alignBufferPosition(sizeof(result), sizeof(result)))
return false;
@@ -214,13 +269,12 @@ bool ArgumentDecoder::decode(double& result)
return true;
}
-bool ArgumentDecoder::removeAttachment(Attachment& attachment)
+bool Decoder::removeAttachment(Attachment& attachment)
{
if (m_attachments.isEmpty())
return false;
- attachment = m_attachments.last();
- m_attachments.removeLast();
+ attachment = m_attachments.takeLast();
return true;
}
diff --git a/Source/WebKit2/Platform/IPC/ArgumentDecoder.h b/Source/WebKit2/Platform/IPC/Decoder.h
index b35ce3f9c..5a30c4258 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentDecoder.h
+++ b/Source/WebKit2/Platform/IPC/Decoder.h
@@ -23,21 +23,49 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ArgumentDecoder_h
-#define ArgumentDecoder_h
+#pragma once
#include "ArgumentCoder.h"
#include "Attachment.h"
+#include "StringReference.h"
+#include <wtf/EnumTraits.h>
#include <wtf/Vector.h>
+#if HAVE(QOS_CLASSES)
+#include <pthread/qos.h>
+#endif
+
namespace IPC {
class DataReference;
-
-class ArgumentDecoder {
+class ImportanceAssertion;
+
+class Decoder {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- ArgumentDecoder(const uint8_t* buffer, size_t bufferSize);
- virtual ~ArgumentDecoder();
+ Decoder(const uint8_t* buffer, size_t bufferSize, void (*bufferDeallocator)(const uint8_t*, size_t), Vector<Attachment>);
+ ~Decoder();
+
+ Decoder(const Decoder&) = delete;
+ Decoder(Decoder&&) = delete;
+
+ StringReference messageReceiverName() const { return m_messageReceiverName; }
+ StringReference messageName() const { return m_messageName; }
+ uint64_t destinationID() const { return m_destinationID; }
+
+ bool isSyncMessage() const;
+ bool shouldDispatchMessageWhenWaitingForSyncReply() const;
+ bool shouldUseFullySynchronousModeForTesting() const;
+
+#if PLATFORM(MAC)
+ void setImportanceAssertion(std::unique_ptr<ImportanceAssertion>);
+#endif
+
+#if HAVE(QOS_CLASSES)
+ void setQOSClassOverride(pthread_override_t override) { m_qosClassOverride = override; }
+#endif
+
+ static std::unique_ptr<Decoder> unwrapForTesting(Decoder&);
size_t length() const { return m_bufferEnd - m_buffer; }
@@ -59,6 +87,19 @@ public:
bool decode(float&);
bool decode(double&);
+ template<typename E>
+ auto decode(E& e) -> std::enable_if_t<std::is_enum<E>::value, bool>
+ {
+ uint64_t value;
+ if (!decode(value))
+ return false;
+ if (!isValidEnum<E>(value))
+ return false;
+
+ e = static_cast<E>(value);
+ return true;
+ }
+
template<typename T> bool decodeEnum(T& result)
{
static_assert(sizeof(T) <= 8, "Enum type T must not be larger than 64 bits!");
@@ -82,30 +123,40 @@ public:
return bufferIsLargeEnoughToContain(alignof(T), numElements * sizeof(T));
}
- // Generic type decode function.
- template<typename T> bool decode(T& t)
+ template<typename T>
+ auto decode(T& t) -> std::enable_if_t<!std::is_enum<T>::value, bool>
{
return ArgumentCoder<T>::decode(*this, t);
}
bool removeAttachment(Attachment&);
-protected:
- ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Vector<Attachment>);
-
- void initialize(const uint8_t* buffer, size_t bufferSize);
-
- bool alignBufferPosition(unsigned alignment, size_t size);
- bool bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const;
+ static const bool isIPCDecoder = true;
private:
- uint8_t* m_buffer;
- uint8_t* m_bufferPos;
- uint8_t* m_bufferEnd;
+ bool alignBufferPosition(unsigned alignment, size_t);
+ bool bufferIsLargeEnoughToContain(unsigned alignment, size_t) const;
+
+ const uint8_t* m_buffer;
+ const uint8_t* m_bufferPos;
+ const uint8_t* m_bufferEnd;
+ void (*m_bufferDeallocator)(const uint8_t*, size_t);
Vector<Attachment> m_attachments;
+
+ uint8_t m_messageFlags;
+ StringReference m_messageReceiverName;
+ StringReference m_messageName;
+
+ uint64_t m_destinationID;
+
+#if PLATFORM(MAC)
+ std::unique_ptr<ImportanceAssertion> m_importanceAssertion;
+#endif
+
+#if HAVE(QOS_CLASSES)
+ pthread_override_t m_qosClassOverride { nullptr };
+#endif
};
} // namespace IPC
-
-#endif // ArgumentDecoder_h
diff --git a/Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp b/Source/WebKit2/Platform/IPC/Encoder.cpp
index ee8563034..6cd7471d1 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp
+++ b/Source/WebKit2/Platform/IPC/Encoder.cpp
@@ -24,9 +24,10 @@
*/
#include "config.h"
-#include "ArgumentEncoder.h"
+#include "Encoder.h"
#include "DataReference.h"
+#include "MessageFlags.h"
#include <algorithm>
#include <stdio.h>
@@ -36,12 +37,17 @@
namespace IPC {
-static inline void* allocBuffer(size_t size)
+static const uint8_t defaultMessageFlags = 0;
+
+template <typename T>
+static inline bool allocBuffer(T*& buffer, size_t size)
{
#if OS(DARWIN)
- return mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ buffer = static_cast<T*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0));
+ return buffer != MAP_FAILED;
#else
- return fastMalloc(size);
+ buffer = static_cast<T*>(fastMalloc(size));
+ return !!buffer;
#endif
}
@@ -55,25 +61,69 @@ static inline void freeBuffer(void* addr, size_t size)
#endif
}
-ArgumentEncoder::ArgumentEncoder()
- : m_buffer(m_inlineBuffer)
+Encoder::Encoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID)
+ : m_messageReceiverName(messageReceiverName)
+ , m_messageName(messageName)
+ , m_destinationID(destinationID)
+ , m_buffer(m_inlineBuffer)
, m_bufferPointer(m_inlineBuffer)
, m_bufferSize(0)
, m_bufferCapacity(sizeof(m_inlineBuffer))
{
+ encodeHeader();
}
-ArgumentEncoder::~ArgumentEncoder()
+Encoder::~Encoder()
{
if (m_buffer != m_inlineBuffer)
freeBuffer(m_buffer, m_bufferCapacity);
-
-#if !USE(UNIX_DOMAIN_SOCKETS)
// FIXME: We need to dispose of the attachments in cases of failure.
-#else
- for (size_t i = 0; i < m_attachments.size(); ++i)
- m_attachments[i].dispose();
-#endif
+}
+
+bool Encoder::isSyncMessage() const
+{
+ return *buffer() & SyncMessage;
+}
+
+bool Encoder::shouldDispatchMessageWhenWaitingForSyncReply() const
+{
+ return *buffer() & DispatchMessageWhenWaitingForSyncReply;
+}
+
+void Encoder::setIsSyncMessage(bool isSyncMessage)
+{
+ if (isSyncMessage)
+ *buffer() |= SyncMessage;
+ else
+ *buffer() &= ~SyncMessage;
+}
+
+void Encoder::setShouldDispatchMessageWhenWaitingForSyncReply(bool shouldDispatchMessageWhenWaitingForSyncReply)
+{
+ if (shouldDispatchMessageWhenWaitingForSyncReply)
+ *buffer() |= DispatchMessageWhenWaitingForSyncReply;
+ else
+ *buffer() &= ~DispatchMessageWhenWaitingForSyncReply;
+}
+
+void Encoder::setFullySynchronousModeForTesting()
+{
+ *buffer() |= UseFullySynchronousModeForTesting;
+}
+
+void Encoder::wrapForTesting(std::unique_ptr<Encoder> original)
+{
+ ASSERT(isSyncMessage());
+ ASSERT(!original->isSyncMessage());
+
+ original->setShouldDispatchMessageWhenWaitingForSyncReply(true);
+
+ encodeVariableLengthByteArray(DataReference(original->buffer(), original->bufferSize()));
+
+ Vector<Attachment> attachments = original->releaseAttachments();
+ reserve(attachments.size());
+ for (Attachment& attachment : attachments)
+ addAttachment(WTFMove(attachment));
}
static inline size_t roundUpToAlignment(size_t value, unsigned alignment)
@@ -81,27 +131,42 @@ 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)
+void Encoder::reserve(size_t size)
{
- size_t alignedSize = roundUpToAlignment(m_bufferSize, alignment);
-
- if (alignedSize + size > m_bufferCapacity) {
- size_t newCapacity = roundUpToAlignment(m_bufferCapacity * 2, 4096);
- while (newCapacity < alignedSize + size)
- newCapacity *= 2;
+ if (size <= m_bufferCapacity)
+ return;
- uint8_t* newBuffer = static_cast<uint8_t*>(allocBuffer(newCapacity));
- if (!newBuffer)
- CRASH();
+ size_t newCapacity = roundUpToAlignment(m_bufferCapacity * 2, 4096);
+ while (newCapacity < size)
+ newCapacity *= 2;
- memcpy(newBuffer, m_buffer, m_bufferSize);
+ uint8_t* newBuffer;
+ if (!allocBuffer(newBuffer, newCapacity))
+ CRASH();
- if (m_buffer != m_inlineBuffer)
- freeBuffer(m_buffer, m_bufferCapacity);
+ memcpy(newBuffer, m_buffer, m_bufferSize);
- m_buffer = newBuffer;
- m_bufferCapacity = newCapacity;
- }
+ if (m_buffer != m_inlineBuffer)
+ freeBuffer(m_buffer, m_bufferCapacity);
+
+ m_buffer = newBuffer;
+ m_bufferCapacity = newCapacity;
+}
+
+void Encoder::encodeHeader()
+{
+ ASSERT(!m_messageReceiverName.isEmpty());
+
+ *this << defaultMessageFlags;
+ *this << m_messageReceiverName;
+ *this << m_messageName;
+ *this << m_destinationID;
+}
+
+uint8_t* Encoder::grow(unsigned alignment, size_t size)
+{
+ size_t alignedSize = roundUpToAlignment(m_bufferSize, alignment);
+ reserve(alignedSize + size);
m_bufferSize = alignedSize + size;
m_bufferPointer = m_buffer + alignedSize + size;
@@ -109,7 +174,7 @@ uint8_t* ArgumentEncoder::grow(unsigned alignment, size_t size)
return m_buffer + alignedSize;
}
-void ArgumentEncoder::encodeFixedLengthData(const uint8_t* data, size_t size, unsigned alignment)
+void Encoder::encodeFixedLengthData(const uint8_t* data, size_t size, unsigned alignment)
{
ASSERT(!(reinterpret_cast<uintptr_t>(data) % alignment));
@@ -117,7 +182,7 @@ void ArgumentEncoder::encodeFixedLengthData(const uint8_t* data, size_t size, un
memcpy(buffer, data, size);
}
-void ArgumentEncoder::encodeVariableLengthByteArray(const DataReference& dataReference)
+void Encoder::encodeVariableLengthByteArray(const DataReference& dataReference)
{
encode(static_cast<uint64_t>(dataReference.size()));
encodeFixedLengthData(dataReference.data(), dataReference.size(), 1);
@@ -129,70 +194,68 @@ static void copyValueToBuffer(Type value, uint8_t* bufferPosition)
memcpy(bufferPosition, &value, sizeof(Type));
}
-void ArgumentEncoder::encode(bool n)
+void Encoder::encode(bool n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(uint8_t n)
+void Encoder::encode(uint8_t n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(uint16_t n)
+void Encoder::encode(uint16_t n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(uint32_t n)
+void Encoder::encode(uint32_t n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(uint64_t n)
+void Encoder::encode(uint64_t n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(int32_t n)
+void Encoder::encode(int32_t n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(int64_t n)
+void Encoder::encode(int64_t n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(float n)
+void Encoder::encode(float n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::encode(double n)
+void Encoder::encode(double n)
{
uint8_t* buffer = grow(sizeof(n), sizeof(n));
copyValueToBuffer(n, buffer);
}
-void ArgumentEncoder::addAttachment(const Attachment& attachment)
+void Encoder::addAttachment(Attachment&& attachment)
{
- m_attachments.append(attachment);
+ m_attachments.append(WTFMove(attachment));
}
-Vector<Attachment> ArgumentEncoder::releaseAttachments()
+Vector<Attachment> Encoder::releaseAttachments()
{
- Vector<Attachment> newList;
- newList.swap(m_attachments);
- return newList;
+ return WTFMove(m_attachments);
}
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/ArgumentEncoder.h b/Source/WebKit2/Platform/IPC/Encoder.h
index 424291570..92f9ba256 100644
--- a/Source/WebKit2/Platform/IPC/ArgumentEncoder.h
+++ b/Source/WebKit2/Platform/IPC/Encoder.h
@@ -23,22 +23,37 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ArgumentEncoder_h
-#define ArgumentEncoder_h
+#pragma once
#include "ArgumentCoder.h"
#include "Attachment.h"
+#include "StringReference.h"
+#include <wtf/EnumTraits.h>
#include <wtf/Vector.h>
namespace IPC {
-class ArgumentEncoder;
class DataReference;
-class ArgumentEncoder {
+class Encoder final {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- ArgumentEncoder();
- virtual ~ArgumentEncoder();
+ Encoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID);
+ ~Encoder();
+
+ StringReference messageReceiverName() const { return m_messageReceiverName; }
+ StringReference messageName() const { return m_messageName; }
+ uint64_t destinationID() const { return m_destinationID; }
+
+ void setIsSyncMessage(bool);
+ bool isSyncMessage() const;
+
+ void setShouldDispatchMessageWhenWaitingForSyncReply(bool);
+ bool shouldDispatchMessageWhenWaitingForSyncReply() const;
+
+ void setFullySynchronousModeForTesting();
+
+ void wrapForTesting(std::unique_ptr<Encoder>);
void encodeFixedLengthData(const uint8_t*, size_t, unsigned alignment);
void encodeVariableLengthByteArray(const DataReference&);
@@ -50,24 +65,30 @@ public:
encode(static_cast<uint64_t>(t));
}
- template<typename T> void encode(const T& t)
+ template<typename T>
+ auto encode(T&& t) -> std::enable_if_t<!std::is_enum<typename std::remove_const_t<std::remove_reference_t<T>>>::value>
{
- ArgumentCoder<T>::encode(*this, t);
+ ArgumentCoder<typename std::remove_const<typename std::remove_reference<T>::type>::type>::encode(*this, std::forward<T>(t));
}
- template<typename T> ArgumentEncoder& operator<<(const T& t)
+ template<typename T> Encoder& operator<<(T&& t)
{
- encode(t);
+ encode(std::forward<T>(t));
return *this;
}
uint8_t* buffer() const { return m_buffer; }
size_t bufferSize() const { return m_bufferSize; }
- void addAttachment(const Attachment&);
+ void addAttachment(Attachment&&);
Vector<Attachment> releaseAttachments();
+ void reserve(size_t);
+
+ static const bool isIPCEncoder = true;
private:
+ uint8_t* grow(unsigned alignment, size_t);
+
void encode(bool);
void encode(uint8_t);
void encode(uint16_t);
@@ -78,7 +99,20 @@ private:
void encode(float);
void encode(double);
- uint8_t* grow(unsigned alignment, size_t size);
+ template<typename E>
+ auto encode(E value) -> std::enable_if_t<std::is_enum<E>::value>
+ {
+ static_assert(sizeof(E) <= sizeof(uint64_t), "Enum type must not be larger than 64 bits.");
+
+ ASSERT(isValidEnum<E>(static_cast<uint64_t>(value)));
+ encode(static_cast<uint64_t>(value));
+ }
+
+ void encodeHeader();
+
+ StringReference m_messageReceiverName;
+ StringReference m_messageName;
+ uint64_t m_destinationID;
uint8_t m_inlineBuffer[512];
@@ -92,5 +126,3 @@ private:
};
} // namespace IPC
-
-#endif // ArgumentEncoder_h
diff --git a/Source/WebKit2/Platform/IPC/HandleMessage.h b/Source/WebKit2/Platform/IPC/HandleMessage.h
index 7f32bf38f..13b94413a 100644
--- a/Source/WebKit2/Platform/IPC/HandleMessage.h
+++ b/Source/WebKit2/Platform/IPC/HandleMessage.h
@@ -1,19 +1,43 @@
-#ifndef HandleMessage_h
-#define HandleMessage_h
-
-#include "Arguments.h"
-#include "MessageDecoder.h"
-#include "MessageEncoder.h"
+/*
+ * Copyright (C) 2010-2016 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.
+ */
+
+#pragma once
+
+#include "ArgumentCoders.h"
#include <wtf/StdLibExtras.h>
namespace IPC {
+class Connection;
+
// Dispatch functions with no reply arguments.
template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
void callMemberFunctionImpl(C* object, MF function, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
{
- (object->*function)(std::get<ArgsIndex>(args)...);
+ (object->*function)(std::get<ArgsIndex>(std::forward<ArgsTuple>(args))...);
}
template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
@@ -39,27 +63,27 @@ void callMemberFunction(ArgsTuple&& args, ReplyArgsTuple& replyArgs, C* object,
// Dispatch functions with delayed reply arguments.
template <typename C, typename MF, typename R, typename ArgsTuple, size_t... ArgsIndex>
-void callMemberFunctionImpl(C* object, MF function, PassRefPtr<R> delayedReply, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
+void callMemberFunctionImpl(C* object, MF function, Ref<R>&& delayedReply, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
{
- (object->*function)(std::get<ArgsIndex>(args)..., delayedReply);
+ (object->*function)(std::get<ArgsIndex>(args)..., WTFMove(delayedReply));
}
template<typename C, typename MF, typename R, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
-void callMemberFunction(ArgsTuple&& args, PassRefPtr<R> delayedReply, C* object, MF function)
+void callMemberFunction(ArgsTuple&& args, Ref<R>&& delayedReply, C* object, MF function)
{
- callMemberFunctionImpl(object, function, delayedReply, std::forward<ArgsTuple>(args), ArgsIndicies());
+ callMemberFunctionImpl(object, function, WTFMove(delayedReply), std::forward<ArgsTuple>(args), ArgsIndicies());
}
// Dispatch functions with connection parameter with no reply arguments.
template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
-void callMemberFunctionImpl(C* object, MF function, Connection* connection, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
+void callMemberFunctionImpl(C* object, MF function, Connection& connection, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
{
- (object->*function)(connection, std::get<ArgsIndex>(args)...);
+ (object->*function)(connection, std::get<ArgsIndex>(std::forward<ArgsTuple>(args))...);
}
template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
-void callMemberFunction(Connection* connection, ArgsTuple&& args, C* object, MF function)
+void callMemberFunction(Connection& connection, ArgsTuple&& args, C* object, MF function)
{
callMemberFunctionImpl(object, function, connection, std::forward<ArgsTuple>(args), ArgsIndicies());
}
@@ -67,121 +91,91 @@ void callMemberFunction(Connection* connection, ArgsTuple&& args, C* object, MF
// Dispatch functions with connection parameter with reply arguments.
template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex, typename ReplyArgsTuple, size_t... ReplyArgsIndex>
-void callMemberFunctionImpl(C* object, MF function, Connection* connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence<ArgsIndex...>, std::index_sequence<ReplyArgsIndex...>)
+void callMemberFunctionImpl(C* object, MF function, Connection& connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence<ArgsIndex...>, std::index_sequence<ReplyArgsIndex...>)
{
(object->*function)(connection, std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., std::get<ReplyArgsIndex>(replyArgs)...);
}
template <typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence<std::tuple_size<ReplyArgsTuple>::value>>
-void callMemberFunction(Connection* connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, C* object, MF function)
+void callMemberFunction(Connection& connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, C* object, MF function)
{
callMemberFunctionImpl(object, function, connection, std::forward<ArgsTuple>(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies());
}
-// Variadic dispatch functions.
-
-template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
-void callMemberFunctionImpl(C* object, MF function, MessageDecoder& decoder, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
-{
- (object->*function)(std::get<ArgsIndex>(args)..., decoder);
-}
-
-template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
-void callMemberFunction(ArgsTuple&& args, MessageDecoder& decoder, C* object, MF function)
-{
- callMemberFunctionImpl(object, function, decoder, std::forward<ArgsTuple>(args), ArgsIndicies());
-}
-
-// Variadic dispatch functions with non-variadic reply arguments.
-
-template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex, typename ReplyArgsTuple, size_t... ReplyArgsIndex>
-void callMemberFunctionImpl(C* object, MF function, MessageDecoder& decoder, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence<ArgsIndex...>, std::index_sequence<ReplyArgsIndex...>)
-{
- (object->*function)(std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., decoder, std::get<ReplyArgsIndex>(replyArgs)...);
-}
-
-template <typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence<std::tuple_size<ReplyArgsTuple>::value>>
-void callMemberFunction(ArgsTuple&& args, MessageDecoder& decoder, ReplyArgsTuple& replyArgs, C* object, MF function)
-{
- callMemberFunctionImpl(object, function, decoder, std::forward<ArgsTuple>(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies());
-}
-
// Main dispatch functions
-template<typename T, typename C, typename MF>
-void handleMessage(MessageDecoder& decoder, C* object, MF function)
-{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
- return;
- callMemberFunction(std::move(arguments), object, function);
-}
+template<typename T>
+struct CodingType {
+ typedef std::remove_const_t<std::remove_reference_t<T>> Type;
+};
+
+template<typename... Ts>
+struct CodingType<std::tuple<Ts...>> {
+ typedef std::tuple<typename CodingType<Ts>::Type...> Type;
+};
template<typename T, typename C, typename MF>
-void handleMessage(MessageDecoder& decoder, MessageEncoder& replyEncoder, C* object, MF function)
+void handleMessage(Decoder& decoder, C* object, MF function)
{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
+ typename CodingType<typename T::Arguments>::Type arguments;
+ if (!decoder.decode(arguments)) {
+ ASSERT(decoder.isInvalid());
return;
+ }
- typename T::Reply::ValueType replyArguments;
- callMemberFunction(std::move(arguments), replyArguments, object, function);
- replyEncoder << replyArguments;
+ callMemberFunction(WTFMove(arguments), object, function);
}
template<typename T, typename C, typename MF>
-void handleMessage(Connection* connection, MessageDecoder& decoder, MessageEncoder& replyEncoder, C* object, MF function)
+void handleMessage(Decoder& decoder, Encoder& replyEncoder, C* object, MF function)
{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
+ typename CodingType<typename T::Arguments>::Type arguments;
+ if (!decoder.decode(arguments)) {
+ ASSERT(decoder.isInvalid());
return;
+ }
- typename T::Reply::ValueType replyArguments;
- callMemberFunction(connection, std::move(arguments), replyArguments, object, function);
+ typename CodingType<typename T::Reply>::Type replyArguments;
+ callMemberFunction(WTFMove(arguments), replyArguments, object, function);
replyEncoder << replyArguments;
}
template<typename T, typename C, typename MF>
-void handleMessage(Connection* connection, MessageDecoder& decoder, C* object, MF function)
+void handleMessage(Connection& connection, Decoder& decoder, Encoder& replyEncoder, C* object, MF function)
{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
+ typename CodingType<typename T::Arguments>::Type arguments;
+ if (!decoder.decode(arguments)) {
+ ASSERT(decoder.isInvalid());
return;
- callMemberFunction(connection, std::move(arguments), object, function);
-}
+ }
-template<typename T, typename C, typename MF>
-void handleMessageVariadic(MessageDecoder& decoder, C* object, MF function)
-{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
- return;
- callMemberFunction(std::move(arguments), decoder, object, function);
+ typename CodingType<typename T::Reply>::Type replyArguments;
+ callMemberFunction(connection, WTFMove(arguments), replyArguments, object, function);
+ replyEncoder << replyArguments;
}
template<typename T, typename C, typename MF>
-void handleMessageVariadic(MessageDecoder& decoder, MessageEncoder& replyEncoder, C* object, MF function)
+void handleMessage(Connection& connection, Decoder& decoder, C* object, MF function)
{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
+ typename CodingType<typename T::Arguments>::Type arguments;
+ if (!decoder.decode(arguments)) {
+ ASSERT(decoder.isInvalid());
return;
-
- typename T::Reply::ValueType replyArguments;
- callMemberFunction(std::move(arguments), decoder, replyArguments, object, function);
- replyEncoder << replyArguments;
+ }
+ callMemberFunction(connection, WTFMove(arguments), object, function);
}
template<typename T, typename C, typename MF>
-void handleMessageDelayed(Connection* connection, MessageDecoder& decoder, std::unique_ptr<MessageEncoder>& replyEncoder, C* object, MF function)
+void handleMessageDelayed(Connection& connection, Decoder& decoder, std::unique_ptr<Encoder>& replyEncoder, C* object, MF function)
{
- typename T::DecodeType arguments;
- if (!decoder.decode(arguments))
+ typename CodingType<typename T::Arguments>::Type arguments;
+ if (!decoder.decode(arguments)) {
+ ASSERT(decoder.isInvalid());
return;
+ }
- RefPtr<typename T::DelayedReply> delayedReply = adoptRef(new typename T::DelayedReply(connection, std::move(replyEncoder)));
- callMemberFunction(std::move(arguments), delayedReply.release(), object, function);
+ Ref<typename T::DelayedReply> delayedReply = adoptRef(*new typename T::DelayedReply(connection, WTFMove(replyEncoder)));
+ callMemberFunction(WTFMove(arguments), WTFMove(delayedReply), object, function);
}
} // namespace IPC
-
-#endif // HandleMessage_h
diff --git a/Source/WebKit2/Platform/IPC/MessageDecoder.h b/Source/WebKit2/Platform/IPC/MessageDecoder.h
deleted file mode 100644
index 0b09baad7..000000000
--- a/Source/WebKit2/Platform/IPC/MessageDecoder.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 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 MessageDecoder_h
-#define MessageDecoder_h
-
-#include "ArgumentDecoder.h"
-#include "StringReference.h"
-
-namespace IPC {
-
-class DataReference;
-class ImportanceAssertion;
-
-class MessageDecoder : public ArgumentDecoder {
-public:
- MessageDecoder(const DataReference& buffer, Vector<Attachment>);
- virtual ~MessageDecoder();
-
- StringReference messageReceiverName() const { return m_messageReceiverName; }
- StringReference messageName() const { return m_messageName; }
- uint64_t destinationID() const { return m_destinationID; }
-
- bool isSyncMessage() const;
- bool shouldDispatchMessageWhenWaitingForSyncReply() const;
-
-#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
- void setImportanceAssertion(std::unique_ptr<ImportanceAssertion>);
-#endif
-
-private:
- uint8_t m_messageFlags;
- StringReference m_messageReceiverName;
- StringReference m_messageName;
-
- uint64_t m_destinationID;
-
-#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
- std::unique_ptr<ImportanceAssertion> m_importanceAssertion;
-#endif
-};
-
-} // namespace IPC
-
-#endif // MessageDecoder_h
diff --git a/Source/WebKit2/Platform/IPC/MessageEncoder.cpp b/Source/WebKit2/Platform/IPC/MessageEncoder.cpp
deleted file mode 100644
index d2e4efe9a..000000000
--- a/Source/WebKit2/Platform/IPC/MessageEncoder.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 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 "config.h"
-#include "MessageEncoder.h"
-
-#include "ArgumentCoders.h"
-#include "MessageFlags.h"
-#include "StringReference.h"
-
-namespace IPC {
-
-static uint8_t defaultMessageFlags = 0;
-
-MessageEncoder::MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID)
-{
- ASSERT(!messageReceiverName.isEmpty());
-
- *this << defaultMessageFlags;
- *this << messageReceiverName;
- *this << messageName;
- *this << destinationID;
-}
-
-MessageEncoder::~MessageEncoder()
-{
-}
-
-void MessageEncoder::setIsSyncMessage(bool isSyncMessage)
-{
- if (isSyncMessage)
- *buffer() |= SyncMessage;
- else
- *buffer() &= ~SyncMessage;
-}
-
-void MessageEncoder::setShouldDispatchMessageWhenWaitingForSyncReply(bool shouldDispatchMessageWhenWaitingForSyncReply)
-{
- if (shouldDispatchMessageWhenWaitingForSyncReply)
- *buffer() |= DispatchMessageWhenWaitingForSyncReply;
- else
- *buffer() &= ~DispatchMessageWhenWaitingForSyncReply;
-}
-
-} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/MessageFlags.h b/Source/WebKit2/Platform/IPC/MessageFlags.h
index 187ca981b..e8d3e5e37 100644
--- a/Source/WebKit2/Platform/IPC/MessageFlags.h
+++ b/Source/WebKit2/Platform/IPC/MessageFlags.h
@@ -31,6 +31,7 @@ namespace IPC {
enum MessageFlags {
SyncMessage = 1 << 0,
DispatchMessageWhenWaitingForSyncReply = 1 << 1,
+ UseFullySynchronousModeForTesting = 1 << 2,
};
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/MessageReceiver.h b/Source/WebKit2/Platform/IPC/MessageReceiver.h
index 331b7c33a..ef890c146 100644
--- a/Source/WebKit2/Platform/IPC/MessageReceiver.h
+++ b/Source/WebKit2/Platform/IPC/MessageReceiver.h
@@ -23,29 +23,50 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MessageReceiver_h
-#define MessageReceiver_h
+#pragma once
#include <wtf/Assertions.h>
-#include <wtf/OwnPtr.h>
namespace IPC {
-class MessageDecoder;
-class MessageEncoder;
class Connection;
+class Decoder;
+class Encoder;
class MessageReceiver {
public:
- virtual ~MessageReceiver() { }
+ virtual ~MessageReceiver()
+ {
+ ASSERT(!m_messageReceiverMapCount);
+ }
- virtual void didReceiveMessage(Connection*, MessageDecoder&) = 0;
- virtual void didReceiveSyncMessage(Connection*, MessageDecoder&, std::unique_ptr<MessageEncoder>&)
+ virtual void didReceiveMessage(Connection&, Decoder&) = 0;
+ virtual void didReceiveSyncMessage(Connection&, Decoder&, std::unique_ptr<Encoder>&)
{
ASSERT_NOT_REACHED();
}
+
+private:
+ friend class MessageReceiverMap;
+
+ void willBeAddedToMessageReceiverMap()
+ {
+#if !ASSERT_DISABLED
+ m_messageReceiverMapCount++;
+#endif
+ }
+
+ void willBeRemovedFromMessageReceiverMap()
+ {
+ ASSERT(m_messageReceiverMapCount);
+#if !ASSERT_DISABLED
+ m_messageReceiverMapCount--;
+#endif
+ }
+
+#if !ASSERT_DISABLED
+ unsigned m_messageReceiverMapCount { 0 };
+#endif
};
} // namespace IPC
-
-#endif // MessageReceiver_h
diff --git a/Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp b/Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp
index da6d7c5b3..aa5eba8df 100644
--- a/Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp
+++ b/Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "MessageReceiverMap.h"
-#include "MessageDecoder.h"
+#include "Decoder.h"
#include "MessageReceiver.h"
namespace IPC {
@@ -42,6 +42,8 @@ MessageReceiverMap::~MessageReceiverMap()
void MessageReceiverMap::addMessageReceiver(StringReference messageReceiverName, MessageReceiver& messageReceiver)
{
ASSERT(!m_globalMessageReceivers.contains(messageReceiverName));
+
+ messageReceiver.willBeAddedToMessageReceiverMap();
m_globalMessageReceivers.set(messageReceiverName, &messageReceiver);
}
@@ -51,6 +53,7 @@ void MessageReceiverMap::addMessageReceiver(StringReference messageReceiverName,
ASSERT(!m_messageReceivers.contains(std::make_pair(messageReceiverName, destinationID)));
ASSERT(!m_globalMessageReceivers.contains(messageReceiverName));
+ messageReceiver.willBeAddedToMessageReceiverMap();
m_messageReceivers.set(std::make_pair(messageReceiverName, destinationID), &messageReceiver);
}
@@ -58,23 +61,56 @@ void MessageReceiverMap::removeMessageReceiver(StringReference messageReceiverNa
{
ASSERT(m_globalMessageReceivers.contains(messageReceiverName));
- m_globalMessageReceivers.remove(messageReceiverName);
+ auto it = m_globalMessageReceivers.find(messageReceiverName);
+ it->value->willBeRemovedFromMessageReceiverMap();
+
+ m_globalMessageReceivers.remove(it);
}
void MessageReceiverMap::removeMessageReceiver(StringReference messageReceiverName, uint64_t destinationID)
{
ASSERT(m_messageReceivers.contains(std::make_pair(messageReceiverName, destinationID)));
- m_messageReceivers.remove(std::make_pair(messageReceiverName, destinationID));
+ auto it = m_messageReceivers.find(std::make_pair(messageReceiverName, destinationID));
+ it->value->willBeRemovedFromMessageReceiverMap();
+
+ m_messageReceivers.remove(it);
+}
+
+void MessageReceiverMap::removeMessageReceiver(MessageReceiver& messageReceiver)
+{
+ Vector<StringReference> globalReceiversToRemove;
+ for (auto& nameAndReceiver : m_globalMessageReceivers) {
+ if (nameAndReceiver.value == &messageReceiver)
+ globalReceiversToRemove.append(nameAndReceiver.key);
+ }
+
+ for (auto& globalReceiverToRemove : globalReceiversToRemove)
+ removeMessageReceiver(globalReceiverToRemove);
+
+ Vector<std::pair<StringReference, uint64_t>> receiversToRemove;
+ for (auto& nameAndIdAndReceiver : m_messageReceivers) {
+ if (nameAndIdAndReceiver.value == &messageReceiver)
+ receiversToRemove.append(std::make_pair(nameAndIdAndReceiver.key.first, nameAndIdAndReceiver.key.second));
+ }
+
+ for (auto& receiverToRemove : receiversToRemove)
+ removeMessageReceiver(receiverToRemove.first, receiverToRemove.second);
}
void MessageReceiverMap::invalidate()
{
+ for (auto& messageReceiver : m_globalMessageReceivers.values())
+ messageReceiver->willBeRemovedFromMessageReceiverMap();
m_globalMessageReceivers.clear();
+
+
+ for (auto& messageReceiver : m_messageReceivers.values())
+ messageReceiver->willBeRemovedFromMessageReceiverMap();
m_messageReceivers.clear();
}
-bool MessageReceiverMap::dispatchMessage(Connection* connection, MessageDecoder& decoder)
+bool MessageReceiverMap::dispatchMessage(Connection& connection, Decoder& decoder)
{
if (MessageReceiver* messageReceiver = m_globalMessageReceivers.get(decoder.messageReceiverName())) {
ASSERT(!decoder.destinationID());
@@ -91,7 +127,7 @@ bool MessageReceiverMap::dispatchMessage(Connection* connection, MessageDecoder&
return false;
}
-bool MessageReceiverMap::dispatchSyncMessage(Connection* connection, MessageDecoder& decoder, std::unique_ptr<MessageEncoder>& replyEncoder)
+bool MessageReceiverMap::dispatchSyncMessage(Connection& connection, Decoder& decoder, std::unique_ptr<Encoder>& replyEncoder)
{
if (MessageReceiver* messageReceiver = m_globalMessageReceivers.get(decoder.messageReceiverName())) {
ASSERT(!decoder.destinationID());
diff --git a/Source/WebKit2/Platform/IPC/MessageReceiverMap.h b/Source/WebKit2/Platform/IPC/MessageReceiverMap.h
index b00d3646d..4fc751281 100644
--- a/Source/WebKit2/Platform/IPC/MessageReceiverMap.h
+++ b/Source/WebKit2/Platform/IPC/MessageReceiverMap.h
@@ -33,8 +33,8 @@
namespace IPC {
class Connection;
-class MessageDecoder;
-class MessageEncoder;
+class Encoder;
+class Decoder;
class MessageReceiver;
class MessageReceiverMap {
@@ -47,11 +47,12 @@ public:
void removeMessageReceiver(StringReference messageReceiverName);
void removeMessageReceiver(StringReference messageReceiverName, uint64_t destinationID);
+ void removeMessageReceiver(MessageReceiver&);
void invalidate();
- bool dispatchMessage(Connection*, MessageDecoder&);
- bool dispatchSyncMessage(Connection*, MessageDecoder&, std::unique_ptr<MessageEncoder>&);
+ bool dispatchMessage(Connection&, Decoder&);
+ bool dispatchSyncMessage(Connection&, Decoder&, std::unique_ptr<Encoder>&);
private:
// Message receivers that don't require a destination ID.
diff --git a/Source/WebKit2/Platform/IPC/MessageSender.cpp b/Source/WebKit2/Platform/IPC/MessageSender.cpp
index a3f3ef1ae..da1044aed 100644
--- a/Source/WebKit2/Platform/IPC/MessageSender.cpp
+++ b/Source/WebKit2/Platform/IPC/MessageSender.cpp
@@ -32,11 +32,11 @@ MessageSender::~MessageSender()
{
}
-bool MessageSender::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned messageSendFlags)
+bool MessageSender::sendMessage(std::unique_ptr<Encoder> encoder, OptionSet<SendOption> sendOptions)
{
ASSERT(messageSenderConnection());
- return messageSenderConnection()->sendMessage(std::move(encoder), messageSendFlags);
+ return messageSenderConnection()->sendMessage(WTFMove(encoder), sendOptions);
}
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/MessageSender.h b/Source/WebKit2/Platform/IPC/MessageSender.h
index 638bdeebe..f216229b4 100644
--- a/Source/WebKit2/Platform/IPC/MessageSender.h
+++ b/Source/WebKit2/Platform/IPC/MessageSender.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,8 +23,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MessageSender_h
-#define MessageSender_h
+#pragma once
#include <wtf/Assertions.h>
#include "Connection.h"
@@ -37,36 +36,36 @@ public:
template<typename U> bool send(const U& message)
{
- return send(message, messageSenderDestinationID(), 0);
+ return send(message, messageSenderDestinationID(), { });
}
- template<typename U> bool send(const U& message, uint64_t destinationID, unsigned messageSendFlags = 0)
+ template<typename U> bool send(const U& message, uint64_t destinationID, OptionSet<SendOption> sendOptions = { })
{
static_assert(!U::isSync, "Message is sync!");
- auto encoder = std::make_unique<MessageEncoder>(U::receiverName(), U::name(), destinationID);
+ auto encoder = std::make_unique<Encoder>(U::receiverName(), U::name(), destinationID);
encoder->encode(message.arguments());
- return sendMessage(std::move(encoder), messageSendFlags);
+ return sendMessage(WTFMove(encoder), sendOptions);
}
template<typename T>
- bool sendSync(T&& message, typename T::Reply&& reply, std::chrono::milliseconds timeout = std::chrono::milliseconds::max(), unsigned syncSendFlags = 0)
+ bool sendSync(T&& message, typename T::Reply&& reply, Seconds timeout = Seconds::infinity(), OptionSet<SendSyncOption> sendSyncOptions = { })
{
static_assert(T::isSync, "Message is not sync!");
- return sendSync(std::forward<T>(message), std::move(reply), messageSenderDestinationID(), timeout, syncSendFlags);
+ return sendSync(std::forward<T>(message), WTFMove(reply), messageSenderDestinationID(), timeout, sendSyncOptions);
}
template<typename T>
- bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout = std::chrono::milliseconds::max(), unsigned syncSendFlags = 0)
+ bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, Seconds timeout = Seconds::infinity(), OptionSet<SendSyncOption> sendSyncOptions = { })
{
ASSERT(messageSenderConnection());
- return messageSenderConnection()->sendSync(std::move(message), std::move(reply), destinationID, timeout, syncSendFlags);
+ return messageSenderConnection()->sendSync(WTFMove(message), WTFMove(reply), destinationID, timeout, sendSyncOptions);
}
- virtual bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags);
+ virtual bool sendMessage(std::unique_ptr<Encoder>, OptionSet<SendOption>);
private:
virtual Connection* messageSenderConnection() = 0;
@@ -74,5 +73,3 @@ private:
};
} // namespace IPC
-
-#endif // MessageSender_h
diff --git a/Source/WebKit2/Platform/IPC/StringReference.cpp b/Source/WebKit2/Platform/IPC/StringReference.cpp
index 258b7cdd2..852ef43e0 100644
--- a/Source/WebKit2/Platform/IPC/StringReference.cpp
+++ b/Source/WebKit2/Platform/IPC/StringReference.cpp
@@ -26,10 +26,10 @@
#include "config.h"
#include "StringReference.h"
-#include "ArgumentDecoder.h"
-#include "ArgumentEncoder.h"
#include "DataReference.h"
-#include <wtf/StringHasher.h>
+#include "Decoder.h"
+#include "Encoder.h"
+#include <wtf/Hasher.h>
#include <wtf/text/CString.h>
namespace IPC {
@@ -39,12 +39,12 @@ CString StringReference::toString() const
return WTF::CString(m_data, m_size);
}
-void StringReference::encode(ArgumentEncoder& encoder) const
+void StringReference::encode(Encoder& encoder) const
{
encoder << DataReference(reinterpret_cast<const uint8_t*>(m_data), m_size);
}
-bool StringReference::decode(ArgumentDecoder& decoder, StringReference& result)
+bool StringReference::decode(Decoder& decoder, StringReference& result)
{
DataReference dataReference;
if (!decoder.decode(dataReference))
diff --git a/Source/WebKit2/Platform/IPC/StringReference.h b/Source/WebKit2/Platform/IPC/StringReference.h
index 3403bbc84..e98e91119 100644
--- a/Source/WebKit2/Platform/IPC/StringReference.h
+++ b/Source/WebKit2/Platform/IPC/StringReference.h
@@ -32,8 +32,8 @@
namespace IPC {
-class ArgumentEncoder;
-class ArgumentDecoder;
+class Encoder;
+class Decoder;
class StringReference {
public:
@@ -68,8 +68,8 @@ public:
return a.m_size == b.m_size && !memcmp(a.m_data, b.m_data, a.m_size);
}
- void encode(ArgumentEncoder&) const;
- static bool decode(ArgumentDecoder&, StringReference&);
+ void encode(Encoder&) const;
+ static bool decode(Decoder&, StringReference&);
struct Hash {
static unsigned hash(const StringReference& a);
diff --git a/Source/WebKit2/Platform/IPC/MessageDecoder.cpp b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp
index 5dfda2194..14329b938 100644
--- a/Source/WebKit2/Platform/IPC/MessageDecoder.cpp
+++ b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,53 +24,46 @@
*/
#include "config.h"
-#include "MessageDecoder.h"
+#include "GSocketMonitor.h"
-#include "ArgumentCoders.h"
-#include "DataReference.h"
-#include "MessageFlags.h"
-#include "StringReference.h"
-
-#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
-#include "ImportanceAssertion.h"
-#endif
+#include <gio/gio.h>
namespace IPC {
-MessageDecoder::~MessageDecoder()
+GSocketMonitor::~GSocketMonitor()
{
+ stop();
}
-MessageDecoder::MessageDecoder(const DataReference& buffer, Vector<Attachment> attachments)
- : ArgumentDecoder(buffer.data(), buffer.size(), attachments)
+gboolean GSocketMonitor::socketSourceCallback(GSocket*, GIOCondition condition, GSocketMonitor* monitor)
{
- if (!decode(m_messageFlags))
- return;
-
- if (!decode(m_messageReceiverName))
- return;
-
- if (!decode(m_messageName))
- return;
-
- decode(m_destinationID);
+ if (g_cancellable_is_cancelled(monitor->m_cancellable.get()))
+ return G_SOURCE_REMOVE;
+ return monitor->m_callback(condition);
}
-bool MessageDecoder::isSyncMessage() const
+void GSocketMonitor::start(GSocket* socket, GIOCondition condition, RunLoop& runLoop, Function<gboolean (GIOCondition)>&& callback)
{
- return m_messageFlags & SyncMessage;
-}
+ stop();
-bool MessageDecoder::shouldDispatchMessageWhenWaitingForSyncReply() const
-{
- return m_messageFlags & DispatchMessageWhenWaitingForSyncReply;
+ m_cancellable = adoptGRef(g_cancellable_new());
+ m_source = adoptGRef(g_socket_create_source(socket, condition, m_cancellable.get()));
+ g_source_set_name(m_source.get(), "[WebKit] Socket monitor");
+ m_callback = WTFMove(callback);
+ g_source_set_callback(m_source.get(), reinterpret_cast<GSourceFunc>(socketSourceCallback), this, nullptr);
+ g_source_attach(m_source.get(), runLoop.mainContext());
}
-#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
-void MessageDecoder::setImportanceAssertion(std::unique_ptr<ImportanceAssertion> assertion)
+void GSocketMonitor::stop()
{
- m_importanceAssertion = std::move(assertion);
+ if (!m_source)
+ return;
+
+ g_cancellable_cancel(m_cancellable.get());
+ m_cancellable = nullptr;
+ g_source_destroy(m_source.get());
+ m_source = nullptr;
+ m_callback = nullptr;
}
-#endif
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/MessageEncoder.h b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h
index 524e5e1d4..ff37bf9e5 100644
--- a/Source/WebKit2/Platform/IPC/MessageEncoder.h
+++ b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,25 +23,37 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef MessageEncoder_h
-#define MessageEncoder_h
+#ifndef GSocketMonitor_h
+#define GSocketMonitor_h
-#include "ArgumentEncoder.h"
+#include <functional>
+#include <glib.h>
#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RunLoop.h>
+#include <wtf/glib/GRefPtr.h>
-namespace IPC {
+typedef struct _GSocket GSocket;
-class StringReference;
+namespace IPC {
-class MessageEncoder : public ArgumentEncoder {
+class GSocketMonitor {
+ WTF_MAKE_NONCOPYABLE(GSocketMonitor);
public:
- MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID);
- virtual ~MessageEncoder();
+ GSocketMonitor() = default;
+ ~GSocketMonitor();
+
+ void start(GSocket*, GIOCondition, RunLoop&, Function<gboolean (GIOCondition)>&&);
+ void stop();
+
+private:
+ static gboolean socketSourceCallback(GSocket*, GIOCondition, GSocketMonitor*);
- void setIsSyncMessage(bool);
- void setShouldDispatchMessageWhenWaitingForSyncReply(bool);
+ GRefPtr<GSource> m_source;
+ GRefPtr<GCancellable> m_cancellable;
+ Function<gboolean (GIOCondition)> m_callback;
};
} // namespace IPC
-#endif // MessageEncoder_h
+#endif // GSocketMonitor_h
diff --git a/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp b/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp
index 022c72d41..218711645 100644
--- a/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp
+++ b/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp
@@ -45,7 +45,29 @@ Attachment::Attachment(int fileDescriptor)
{
}
-void Attachment::dispose()
+Attachment::Attachment(Attachment&& attachment)
+ : m_type(attachment.m_type)
+ , m_fileDescriptor(attachment.m_fileDescriptor)
+ , m_size(attachment.m_size)
+{
+ attachment.m_type = Uninitialized;
+ attachment.m_fileDescriptor = -1;
+ attachment.m_size = 0;
+}
+
+Attachment& Attachment::operator=(Attachment&& attachment)
+{
+ m_type = attachment.m_type;
+ attachment.m_type = Uninitialized;
+ m_fileDescriptor = attachment.m_fileDescriptor;
+ attachment.m_fileDescriptor = -1;
+ m_size = attachment.m_size;
+ attachment.m_size = 0;
+
+ return *this;
+}
+
+Attachment::~Attachment()
{
if (m_fileDescriptor != -1)
closeWithRetry(m_fileDescriptor);
diff --git a/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp b/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp
index dbadd26a3..7d564a449 100644
--- a/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp
+++ b/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp
@@ -30,21 +30,23 @@
#include "DataReference.h"
#include "SharedMemory.h"
+#include "UnixMessage.h"
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <wtf/Assertions.h>
-#include <wtf/Functional.h>
#include <wtf/StdLibExtras.h>
#include <wtf/UniStdExtras.h>
#if PLATFORM(GTK)
-#include <glib.h>
+#include <gio/gio.h>
#endif
-#ifdef SOCK_SEQPACKET
+// Although it's available on Darwin, SOCK_SEQPACKET seems to work differently
+// than in traditional Unix so fallback to STREAM on that platform.
+#if defined(SOCK_SEQPACKET) && !OS(DARWIN)
#define SOCKET_TYPE SOCK_SEQPACKET
#else
#if PLATFORM(GTK)
@@ -59,59 +61,20 @@ namespace IPC {
static const size_t messageMaxSize = 4096;
static const size_t attachmentMaxAmount = 255;
-enum {
- MessageBodyIsOutOfLine = 1U << 31
-};
-
-class MessageInfo {
-public:
- MessageInfo() { }
-
- MessageInfo(size_t bodySize, size_t initialAttachmentCount)
- : m_bodySize(bodySize)
- , m_attachmentCount(initialAttachmentCount)
- , m_isMessageBodyOutOfLine(false)
- {
- }
-
- void setMessageBodyIsOutOfLine()
- {
- ASSERT(!isMessageBodyIsOutOfLine());
-
- m_isMessageBodyOutOfLine = true;
- m_attachmentCount++;
- }
-
- bool isMessageBodyIsOutOfLine() const { return m_isMessageBodyOutOfLine; }
-
- size_t bodySize() const { return m_bodySize; }
-
- size_t attachmentCount() const { return m_attachmentCount; }
-
-private:
- size_t m_bodySize;
- size_t m_attachmentCount;
- bool m_isMessageBodyOutOfLine;
-};
-
class AttachmentInfo {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- AttachmentInfo()
- : m_type(Attachment::Uninitialized)
- , m_size(0)
- , m_isNull(false)
- {
- }
+ AttachmentInfo() = default;
void setType(Attachment::Type type) { m_type = type; }
- Attachment::Type getType() { return m_type; }
+ Attachment::Type type() const { return m_type; }
void setSize(size_t size)
{
ASSERT(m_type == Attachment::MappedMemoryType);
m_size = size;
}
- size_t getSize()
+ size_t size() const
{
ASSERT(m_type == Attachment::MappedMemoryType);
return m_size;
@@ -119,27 +82,30 @@ public:
// The attachment is not null unless explicitly set.
void setNull() { m_isNull = true; }
- bool isNull() { return m_isNull; }
+ bool isNull() const { return m_isNull; }
private:
- Attachment::Type m_type;
- size_t m_size;
- bool m_isNull;
+ Attachment::Type m_type { Attachment::Uninitialized };
+ size_t m_size { 0 };
+ bool m_isNull { false };
};
void Connection::platformInitialize(Identifier identifier)
{
m_socketDescriptor = identifier;
- m_readBuffer.resize(messageMaxSize);
- m_readBufferSize = 0;
- m_fileDescriptors.resize(attachmentMaxAmount);
- m_fileDescriptorsSize = 0;
+#if PLATFORM(GTK)
+ m_socket = adoptGRef(g_socket_new_from_fd(m_socketDescriptor, nullptr));
+#endif
+ m_readBuffer.reserveInitialCapacity(messageMaxSize);
+ m_fileDescriptors.reserveInitialCapacity(attachmentMaxAmount);
}
void Connection::platformInvalidate()
{
- // In GTK+ platform the socket is closed by the work queue.
-#if !PLATFORM(GTK)
+#if PLATFORM(GTK)
+ // In GTK+ platform the socket descriptor is owned by GSocket.
+ m_socket = nullptr;
+#else
if (m_socketDescriptor != -1)
closeWithRetry(m_socketDescriptor);
#endif
@@ -147,34 +113,18 @@ void Connection::platformInvalidate()
if (!m_isConnected)
return;
-#if PLATFORM(GTK) || PLATFORM(EFL)
- m_connectionQueue->unregisterSocketEventHandler(m_socketDescriptor);
+#if PLATFORM(GTK)
+ m_readSocketMonitor.stop();
+ m_writeSocketMonitor.stop();
#endif
m_socketDescriptor = -1;
m_isConnected = false;
}
-template<class T, class iterator>
-class AttachmentResourceGuard {
-public:
- AttachmentResourceGuard(T& attachments)
- : m_attachments(attachments)
- {
- }
- ~AttachmentResourceGuard()
- {
- iterator end = m_attachments.end();
- for (iterator i = m_attachments.begin(); i != end; ++i)
- i->dispose();
- }
-private:
- T& m_attachments;
-};
-
bool Connection::processMessage()
{
- if (m_readBufferSize < sizeof(MessageInfo))
+ if (m_readBuffer.size() < sizeof(MessageInfo))
return false;
uint8_t* messageData = m_readBuffer.data();
@@ -182,8 +132,13 @@ bool Connection::processMessage()
memcpy(&messageInfo, messageData, sizeof(messageInfo));
messageData += sizeof(messageInfo);
- size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(AttachmentInfo) + (messageInfo.isMessageBodyIsOutOfLine() ? 0 : messageInfo.bodySize());
- if (m_readBufferSize < messageLength)
+ if (messageInfo.attachmentCount() > attachmentMaxAmount || (!messageInfo.isBodyOutOfLine() && messageInfo.bodySize() > messageMaxSize)) {
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(AttachmentInfo) + (messageInfo.isBodyOutOfLine() ? 0 : messageInfo.bodySize());
+ if (m_readBuffer.size() < messageLength)
return false;
size_t attachmentFileDescriptorCount = 0;
@@ -196,7 +151,7 @@ bool Connection::processMessage()
messageData += sizeof(AttachmentInfo) * attachmentCount;
for (size_t i = 0; i < attachmentCount; ++i) {
- switch (attachmentInfo[i].getType()) {
+ switch (attachmentInfo[i].type()) {
case Attachment::MappedMemoryType:
case Attachment::SocketType:
if (!attachmentInfo[i].isNull())
@@ -204,27 +159,25 @@ bool Connection::processMessage()
break;
case Attachment::Uninitialized:
default:
- ASSERT_NOT_REACHED();
break;
}
}
- if (messageInfo.isMessageBodyIsOutOfLine())
+ if (messageInfo.isBodyOutOfLine())
attachmentCount--;
}
Vector<Attachment> attachments(attachmentCount);
- AttachmentResourceGuard<Vector<Attachment>, Vector<Attachment>::iterator> attachementDisposer(attachments);
RefPtr<WebKit::SharedMemory> oolMessageBody;
size_t fdIndex = 0;
for (size_t i = 0; i < attachmentCount; ++i) {
int fd = -1;
- switch (attachmentInfo[i].getType()) {
+ switch (attachmentInfo[i].type()) {
case Attachment::MappedMemoryType:
if (!attachmentInfo[i].isNull())
fd = m_fileDescriptors[fdIndex++];
- attachments[attachmentCount - i - 1] = Attachment(fd, attachmentInfo[i].getSize());
+ attachments[attachmentCount - i - 1] = Attachment(fd, attachmentInfo[i].size());
break;
case Attachment::SocketType:
if (!attachmentInfo[i].isNull())
@@ -238,54 +191,53 @@ bool Connection::processMessage()
}
}
- if (messageInfo.isMessageBodyIsOutOfLine()) {
+ if (messageInfo.isBodyOutOfLine()) {
ASSERT(messageInfo.bodySize());
- if (attachmentInfo[attachmentCount].isNull()) {
+ if (attachmentInfo[attachmentCount].isNull() || attachmentInfo[attachmentCount].size() != messageInfo.bodySize()) {
ASSERT_NOT_REACHED();
return false;
}
WebKit::SharedMemory::Handle handle;
- handle.adoptFromAttachment(m_fileDescriptors[attachmentFileDescriptorCount - 1], attachmentInfo[attachmentCount].getSize());
+ handle.adoptAttachment(IPC::Attachment(m_fileDescriptors[attachmentFileDescriptorCount - 1], attachmentInfo[attachmentCount].size()));
- oolMessageBody = WebKit::SharedMemory::create(handle, WebKit::SharedMemory::ReadOnly);
+ oolMessageBody = WebKit::SharedMemory::map(handle, WebKit::SharedMemory::Protection::ReadOnly);
if (!oolMessageBody) {
ASSERT_NOT_REACHED();
return false;
}
}
- ASSERT(attachments.size() == (messageInfo.isMessageBodyIsOutOfLine() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount()));
+ ASSERT(attachments.size() == (messageInfo.isBodyOutOfLine() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount()));
uint8_t* messageBody = messageData;
- if (messageInfo.isMessageBodyIsOutOfLine())
+ if (messageInfo.isBodyOutOfLine())
messageBody = reinterpret_cast<uint8_t*>(oolMessageBody->data());
- auto decoder = std::make_unique<MessageDecoder>(DataReference(messageBody, messageInfo.bodySize()), std::move(attachments));
+ auto decoder = std::make_unique<Decoder>(messageBody, messageInfo.bodySize(), nullptr, WTFMove(attachments));
- processIncomingMessage(std::move(decoder));
+ processIncomingMessage(WTFMove(decoder));
- if (m_readBufferSize > messageLength) {
- memmove(m_readBuffer.data(), m_readBuffer.data() + messageLength, m_readBufferSize - messageLength);
- m_readBufferSize -= messageLength;
+ if (m_readBuffer.size() > messageLength) {
+ memmove(m_readBuffer.data(), m_readBuffer.data() + messageLength, m_readBuffer.size() - messageLength);
+ m_readBuffer.shrink(m_readBuffer.size() - messageLength);
} else
- m_readBufferSize = 0;
+ m_readBuffer.shrink(0);
if (attachmentFileDescriptorCount) {
- if (m_fileDescriptorsSize > attachmentFileDescriptorCount) {
- size_t fileDescriptorsLength = attachmentFileDescriptorCount * sizeof(int);
- memmove(m_fileDescriptors.data(), m_fileDescriptors.data() + fileDescriptorsLength, m_fileDescriptorsSize - fileDescriptorsLength);
- m_fileDescriptorsSize -= fileDescriptorsLength;
+ if (m_fileDescriptors.size() > attachmentFileDescriptorCount) {
+ memmove(m_fileDescriptors.data(), m_fileDescriptors.data() + attachmentFileDescriptorCount, (m_fileDescriptors.size() - attachmentFileDescriptorCount) * sizeof(int));
+ m_fileDescriptors.shrink(m_fileDescriptors.size() - attachmentFileDescriptorCount);
} else
- m_fileDescriptorsSize = 0;
+ m_fileDescriptors.shrink(0);
}
return true;
}
-static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int count, int* fileDescriptors, size_t* fileDescriptorsCount)
+static ssize_t readBytesFromSocket(int socketDescriptor, Vector<uint8_t>& buffer, Vector<int>& fileDescriptors)
{
struct msghdr message;
memset(&message, 0, sizeof(message));
@@ -294,12 +246,14 @@ static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int co
memset(&iov, 0, sizeof(iov));
message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentMaxAmount);
- auto attachmentDescriptorBuffer = std::make_unique<char[]>(message.msg_controllen);
- memset(attachmentDescriptorBuffer.get(), 0, message.msg_controllen);
+ MallocPtr<char> attachmentDescriptorBuffer = MallocPtr<char>::malloc(sizeof(char) * message.msg_controllen);
+ memset(attachmentDescriptorBuffer.get(), 0, sizeof(char) * message.msg_controllen);
message.msg_control = attachmentDescriptorBuffer.get();
- iov[0].iov_base = buffer;
- iov[0].iov_len = count;
+ size_t previousBufferSize = buffer.size();
+ buffer.grow(buffer.capacity());
+ iov[0].iov_base = buffer.data() + previousBufferSize;
+ iov[0].iov_len = buffer.size() - previousBufferSize;
message.msg_iov = iov;
message.msg_iovlen = 1;
@@ -311,33 +265,33 @@ static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int co
if (errno == EINTR)
continue;
+ buffer.shrink(previousBufferSize);
return -1;
}
- bool found = false;
struct cmsghdr* controlMessage;
for (controlMessage = CMSG_FIRSTHDR(&message); controlMessage; controlMessage = CMSG_NXTHDR(&message, controlMessage)) {
if (controlMessage->cmsg_level == SOL_SOCKET && controlMessage->cmsg_type == SCM_RIGHTS) {
- *fileDescriptorsCount = (controlMessage->cmsg_len - CMSG_LEN(0)) / sizeof(int);
- memcpy(fileDescriptors, CMSG_DATA(controlMessage), sizeof(int) * *fileDescriptorsCount);
-
- for (size_t i = 0; i < *fileDescriptorsCount; ++i) {
- while (fcntl(fileDescriptors[i], F_SETFD, FD_CLOEXEC) == -1) {
- if (errno != EINTR) {
- ASSERT_NOT_REACHED();
- break;
- }
+ if (controlMessage->cmsg_len < CMSG_LEN(0) || controlMessage->cmsg_len > attachmentMaxAmount) {
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ size_t previousFileDescriptorsSize = fileDescriptors.size();
+ size_t fileDescriptorsCount = (controlMessage->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+ fileDescriptors.grow(fileDescriptors.size() + fileDescriptorsCount);
+ memcpy(fileDescriptors.data() + previousFileDescriptorsSize, CMSG_DATA(controlMessage), sizeof(int) * fileDescriptorsCount);
+
+ for (size_t i = 0; i < fileDescriptorsCount; ++i) {
+ if (!setCloseOnExec(fileDescriptors[previousFileDescriptorsSize + i])) {
+ ASSERT_NOT_REACHED();
+ break;
}
}
-
- found = true;
break;
}
}
- if (!found)
- *fileDescriptorsCount = 0;
-
+ buffer.shrink(previousBufferSize + bytesRead);
return bytesRead;
}
@@ -347,24 +301,20 @@ static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int co
void Connection::readyReadHandler()
{
while (true) {
- size_t fileDescriptorsCount = 0;
- size_t bytesToRead = m_readBuffer.size() - m_readBufferSize;
- ssize_t bytesRead = readBytesFromSocket(m_socketDescriptor, m_readBuffer.data() + m_readBufferSize, bytesToRead,
- m_fileDescriptors.data() + m_fileDescriptorsSize, &fileDescriptorsCount);
+ ssize_t bytesRead = readBytesFromSocket(m_socketDescriptor, m_readBuffer, m_fileDescriptors);
if (bytesRead < 0) {
// EINTR was already handled by readBytesFromSocket.
if (errno == EAGAIN || errno == EWOULDBLOCK)
return;
- WTFLogAlways("Error receiving IPC message on socket %d in process %d: %s", m_socketDescriptor, getpid(), strerror(errno));
- connectionDidClose();
+ if (m_isConnected) {
+ WTFLogAlways("Error receiving IPC message on socket %d in process %d: %s", m_socketDescriptor, getpid(), strerror(errno));
+ connectionDidClose();
+ }
return;
}
- m_readBufferSize += bytesRead;
- m_fileDescriptorsSize += fileDescriptorsCount;
-
if (!bytesRead) {
connectionDidClose();
return;
@@ -388,66 +338,73 @@ bool Connection::open()
}
}
+ RefPtr<Connection> protectedThis(this);
m_isConnected = true;
#if PLATFORM(GTK)
- RefPtr<Connection> protector(this);
- m_connectionQueue->registerSocketEventHandler(m_socketDescriptor,
- [=] {
- protector->readyReadHandler();
- },
- [=] {
- protector->connectionDidClose();
- });
-#elif PLATFORM(EFL)
- RefPtr<Connection> protector(this);
- m_connectionQueue->registerSocketEventHandler(m_socketDescriptor,
- [protector] {
- protector->readyReadHandler();
- });
+ m_readSocketMonitor.start(m_socket.get(), G_IO_IN, m_connectionQueue->runLoop(), [protectedThis] (GIOCondition condition) -> gboolean {
+ if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
+ protectedThis->connectionDidClose();
+ return G_SOURCE_REMOVE;
+ }
+
+ if (condition & G_IO_IN) {
+ protectedThis->readyReadHandler();
+ return G_SOURCE_CONTINUE;
+ }
+
+ ASSERT_NOT_REACHED();
+ return G_SOURCE_REMOVE;
+ });
#endif
- // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal
- // handler.
- m_connectionQueue->dispatch(WTF::bind(&Connection::readyReadHandler, this));
+ // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal handler.
+ m_connectionQueue->dispatch([protectedThis] {
+ protectedThis->readyReadHandler();
+ });
return true;
}
bool Connection::platformCanSendOutgoingMessages() const
{
- return m_isConnected;
+ return !m_pendingOutputMessage;
}
-bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
+bool Connection::sendOutgoingMessage(std::unique_ptr<Encoder> encoder)
{
COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline);
- Vector<Attachment> attachments = encoder->releaseAttachments();
- AttachmentResourceGuard<Vector<Attachment>, Vector<Attachment>::iterator> attachementDisposer(attachments);
-
- if (attachments.size() > (attachmentMaxAmount - 1)) {
+ UnixMessage outputMessage(*encoder);
+ if (outputMessage.attachments().size() > (attachmentMaxAmount - 1)) {
ASSERT_NOT_REACHED();
return false;
}
- MessageInfo messageInfo(encoder->bufferSize(), attachments.size());
- size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder->bufferSize();
- if (messageSizeWithBodyInline > messageMaxSize && encoder->bufferSize()) {
- RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::create(encoder->bufferSize());
+ size_t messageSizeWithBodyInline = sizeof(MessageInfo) + (outputMessage.attachments().size() * sizeof(AttachmentInfo)) + outputMessage.bodySize();
+ if (messageSizeWithBodyInline > messageMaxSize && outputMessage.bodySize()) {
+ RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::allocate(encoder->bufferSize());
if (!oolMessageBody)
return false;
WebKit::SharedMemory::Handle handle;
- if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::ReadOnly))
+ if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::Protection::ReadOnly))
return false;
- messageInfo.setMessageBodyIsOutOfLine();
+ outputMessage.messageInfo().setBodyOutOfLine();
- memcpy(oolMessageBody->data(), encoder->buffer(), encoder->bufferSize());
+ memcpy(oolMessageBody->data(), outputMessage.body(), outputMessage.bodySize());
- attachments.append(handle.releaseToAttachment());
+ outputMessage.appendAttachment(handle.releaseAttachment());
}
+ return sendOutputMessage(outputMessage);
+}
+
+bool Connection::sendOutputMessage(UnixMessage& outputMessage)
+{
+ ASSERT(!m_pendingOutputMessage);
+
+ auto& messageInfo = outputMessage.messageInfo();
struct msghdr message;
memset(&message, 0, sizeof(message));
@@ -460,21 +417,21 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
iov[0].iov_base = reinterpret_cast<void*>(&messageInfo);
iov[0].iov_len = sizeof(messageInfo);
- auto attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size());
-
- size_t attachmentFDBufferLength = 0;
- if (!attachments.isEmpty()) {
- for (size_t i = 0; i < attachments.size(); ++i) {
- if (attachments[i].fileDescriptor() != -1)
- attachmentFDBufferLength++;
- }
- }
- auto attachmentFDBuffer = std::make_unique<char[]>(CMSG_SPACE(sizeof(int) * attachmentFDBufferLength));
+ std::unique_ptr<AttachmentInfo[]> attachmentInfo;
+ MallocPtr<char> attachmentFDBuffer;
+ auto& attachments = outputMessage.attachments();
if (!attachments.isEmpty()) {
int* fdPtr = 0;
+ size_t attachmentFDBufferLength = std::count_if(attachments.begin(), attachments.end(),
+ [](const Attachment& attachment) {
+ return attachment.fileDescriptor() != -1;
+ });
+
if (attachmentFDBufferLength) {
+ attachmentFDBuffer = MallocPtr<char>::malloc(sizeof(char) * CMSG_SPACE(sizeof(int) * attachmentFDBufferLength));
+
message.msg_control = attachmentFDBuffer.get();
message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentFDBufferLength);
memset(message.msg_control, 0, message.msg_controllen);
@@ -487,6 +444,7 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
fdPtr = reinterpret_cast<int*>(CMSG_DATA(cmsg));
}
+ attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size());
int fdIndex = 0;
for (size_t i = 0; i < attachments.size(); ++i) {
attachmentInfo[i].setType(attachments[i].type());
@@ -513,19 +471,37 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
++iovLength;
}
- if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) {
- iov[iovLength].iov_base = reinterpret_cast<void*>(encoder->buffer());
- iov[iovLength].iov_len = encoder->bufferSize();
+ if (!messageInfo.isBodyOutOfLine() && outputMessage.bodySize()) {
+ iov[iovLength].iov_base = reinterpret_cast<void*>(outputMessage.body());
+ iov[iovLength].iov_len = outputMessage.bodySize();
++iovLength;
}
message.msg_iovlen = iovLength;
- int bytesSent = 0;
- while ((bytesSent = sendmsg(m_socketDescriptor, &message, 0)) == -1) {
+ while (sendmsg(m_socketDescriptor, &message, 0) == -1) {
if (errno == EINTR)
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
+#if PLATFORM(GTK)
+ m_pendingOutputMessage = std::make_unique<UnixMessage>(WTFMove(outputMessage));
+ m_writeSocketMonitor.start(m_socket.get(), G_IO_OUT, m_connectionQueue->runLoop(), [this, protectedThis = makeRef(*this)] (GIOCondition condition) -> gboolean {
+ if (condition & G_IO_OUT) {
+ ASSERT(m_pendingOutputMessage);
+ // We can't stop the monitor from this lambda, because stop destroys the lambda.
+ m_connectionQueue->dispatch([this, protectedThis = makeRef(*this)] {
+ m_writeSocketMonitor.stop();
+ auto message = WTFMove(m_pendingOutputMessage);
+ if (m_isConnected) {
+ sendOutputMessage(*message);
+ sendOutgoingMessages();
+ }
+ });
+ }
+ return G_SOURCE_REMOVE;
+ });
+ return false;
+#else
struct pollfd pollfd;
pollfd.fd = m_socketDescriptor;
@@ -533,9 +509,11 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
pollfd.revents = 0;
poll(&pollfd, 1, -1);
continue;
+#endif
}
- WTFLogAlways("Error sending IPC message: %s", strerror(errno));
+ if (m_isConnected)
+ WTFLogAlways("Error sending IPC message: %s", strerror(errno));
return false;
}
return true;
@@ -548,18 +526,26 @@ Connection::SocketPair Connection::createPlatformConnection(unsigned options)
if (options & SetCloexecOnServer) {
// Don't expose the child socket to the parent process.
- while (fcntl(sockets[1], F_SETFD, FD_CLOEXEC) == -1)
- RELEASE_ASSERT(errno != EINTR);
+ if (!setCloseOnExec(sockets[1]))
+ RELEASE_ASSERT_NOT_REACHED();
}
if (options & SetCloexecOnClient) {
// Don't expose the parent socket to potential future children.
- while (fcntl(sockets[0], F_SETFD, FD_CLOEXEC) == -1)
- RELEASE_ASSERT(errno != EINTR);
+ if (!setCloseOnExec(sockets[0]))
+ RELEASE_ASSERT_NOT_REACHED();
}
SocketPair socketPair = { sockets[0], sockets[1] };
return socketPair;
}
+void Connection::willSendSyncMessage(OptionSet<SendSyncOption>)
+{
+}
+
+void Connection::didReceiveSyncReply(OptionSet<SendSyncOption>)
+{
+}
+
} // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/unix/UnixMessage.h b/Source/WebKit2/Platform/IPC/unix/UnixMessage.h
new file mode 100644
index 000000000..6e98a7374
--- /dev/null
+++ b/Source/WebKit2/Platform/IPC/unix/UnixMessage.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011,2017 Igalia S.L.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "Attachment.h"
+#include <wtf/Vector.h>
+
+namespace IPC {
+
+class MessageInfo {
+public:
+ MessageInfo() = default;
+
+ MessageInfo(size_t bodySize, size_t initialAttachmentCount)
+ : m_bodySize(bodySize)
+ , m_attachmentCount(initialAttachmentCount)
+ {
+ }
+
+ void setBodyOutOfLine()
+ {
+ ASSERT(!isBodyOutOfLine());
+
+ m_isBodyOutOfLine = true;
+ m_attachmentCount++;
+ }
+
+ bool isBodyOutOfLine() const { return m_isBodyOutOfLine; }
+ size_t bodySize() const { return m_bodySize; }
+ size_t attachmentCount() const { return m_attachmentCount; }
+
+private:
+ size_t m_bodySize { 0 };
+ size_t m_attachmentCount { 0 };
+ bool m_isBodyOutOfLine { false };
+};
+
+class UnixMessage {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ UnixMessage(Encoder& encoder)
+ : m_attachments(encoder.releaseAttachments())
+ , m_messageInfo(encoder.bufferSize(), m_attachments.size())
+ , m_body(encoder.buffer())
+ {
+ }
+
+ UnixMessage(UnixMessage&& other)
+ {
+ m_attachments = WTFMove(other.m_attachments);
+ m_messageInfo = WTFMove(other.m_messageInfo);
+ if (other.m_bodyOwned) {
+ std::swap(m_body, other.m_body);
+ std::swap(m_bodyOwned, other.m_bodyOwned);
+ } else if (!m_messageInfo.isBodyOutOfLine()) {
+ m_body = static_cast<uint8_t*>(fastMalloc(m_messageInfo.bodySize()));
+ memcpy(m_body, other.m_body, m_messageInfo.bodySize());
+ m_bodyOwned = true;
+ other.m_body = nullptr;
+ other.m_bodyOwned = false;
+ }
+ }
+
+ ~UnixMessage()
+ {
+ if (m_bodyOwned)
+ fastFree(m_body);
+ }
+
+ const Vector<Attachment>& attachments() const { return m_attachments; }
+ MessageInfo& messageInfo() { return m_messageInfo; }
+
+ uint8_t* body() const { return m_body; }
+ size_t bodySize() const { return m_messageInfo.bodySize(); }
+
+ void appendAttachment(Attachment&& attachment)
+ {
+ m_attachments.append(WTFMove(attachment));
+ }
+
+private:
+ Vector<Attachment> m_attachments;
+ MessageInfo m_messageInfo;
+ uint8_t* m_body { nullptr };
+ bool m_bodyOwned { false };
+};
+
+} // namespace IPC
diff --git a/Source/WebKit2/Platform/WorkQueue.cpp b/Source/WebKit2/Platform/LogInitialization.h
index 184825c27..c55b6cae1 100644
--- a/Source/WebKit2/Platform/WorkQueue.cpp
+++ b/Source/WebKit2/Platform/LogInitialization.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,20 +23,17 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "WorkQueue.h"
+#pragma once
-PassRefPtr<WorkQueue> WorkQueue::create(const char* name)
-{
- return adoptRef(new WorkQueue(name));
-}
+#include <wtf/text/WTFString.h>
-WorkQueue::WorkQueue(const char* name)
-{
- platformInitialize(name);
-}
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
-WorkQueue::~WorkQueue()
-{
- platformInvalidate();
-}
+namespace WebKit {
+
+void initializeLogChannelsIfNecessary(void);
+String logLevelString();
+
+} // namespace WebKit
+
+#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
diff --git a/Source/WebKit2/Platform/Logging.cpp b/Source/WebKit2/Platform/Logging.cpp
index a26beadc4..7da0f1f53 100644
--- a/Source/WebKit2/Platform/Logging.cpp
+++ b/Source/WebKit2/Platform/Logging.cpp
@@ -26,31 +26,25 @@
#include "config.h"
#include "Logging.h"
+#include "LogInitialization.h"
#include <wtf/text/CString.h>
-#if !LOG_DISABLED
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
-namespace WebKit {
-
-#define DEFINE_LOG_CHANNEL(name) \
- WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name) = { WTFLogChannelOff, #name };
-WEBKIT2_LOG_CHANNELS(DEFINE_LOG_CHANNEL)
+#define DEFINE_WEBKIT2_LOG_CHANNEL(name) DEFINE_LOG_CHANNEL(name, LOG_CHANNEL_WEBKIT_SUBSYSTEM)
+WEBKIT2_LOG_CHANNELS(DEFINE_WEBKIT2_LOG_CHANNEL)
-#define LOG_CHANNEL_ADDRESS(name) &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name),
static WTFLogChannel* logChannels[] = {
WEBKIT2_LOG_CHANNELS(LOG_CHANNEL_ADDRESS)
};
-const size_t logChannelCount = WTF_ARRAY_LENGTH(logChannels);
+namespace WebKit {
+
+static const size_t logChannelCount = WTF_ARRAY_LENGTH(logChannels);
void initializeLogChannelsIfNecessary()
{
- static bool haveInitializedLogChannels = false;
- if (haveInitializedLogChannels)
- return;
- haveInitializedLogChannels = true;
-
static bool haveInitializedLoggingChannels = false;
if (haveInitializedLoggingChannels)
return;
@@ -59,21 +53,6 @@ void initializeLogChannelsIfNecessary()
WTFInitializeLogChannelStatesFromString(logChannels, logChannelCount, logLevelString().utf8().data());
}
-#if PLATFORM(GTK) || PLATFORM(EFL)
-WTFLogChannel* logChannelByName(const String& name)
-{
- return WTFLogChannelByName(logChannels, logChannelCount, name.utf8().data());
-}
-#endif
-
-#if !PLATFORM(MAC) && !PLATFORM(GTK) && !PLATFORM(EFL)
-String logLevelString()
-{
- // FIXME: Each platform will need to define their own logLevelString();
- return emptyString();
-}
-#endif
-
} // namespace WebKit
-#endif // !LOG_DISABLED
+#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
diff --git a/Source/WebKit2/Platform/Logging.h b/Source/WebKit2/Platform/Logging.h
index 1d0b349f1..3d1e172a3 100644
--- a/Source/WebKit2/Platform/Logging.h
+++ b/Source/WebKit2/Platform/Logging.h
@@ -26,48 +26,60 @@
#ifndef WebKitLogging_h
#define WebKitLogging_h
+#include <WebCore/LogMacros.h>
+#include <functional>
#include <wtf/Assertions.h>
#include <wtf/text/WTFString.h>
-#if !LOG_DISABLED
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
#ifndef LOG_CHANNEL_PREFIX
#define LOG_CHANNEL_PREFIX WebKit2Log
#endif
-namespace WebKit {
+#ifdef __cplusplus
+extern "C" {
+#endif
#define WEBKIT2_LOG_CHANNELS(M) \
M(ContextMenu) \
+ M(Gamepad) \
M(IconDatabase) \
+ M(IDB) \
+ M(IndexedDB) \
M(InspectorServer) \
+ M(IPC) \
M(KeyHandling) \
+ M(Layers) \
M(Network) \
+ M(NetworkCache) \
+ M(NetworkCacheSpeculativePreloading) \
+ M(NetworkCacheStorage) \
M(NetworkScheduling) \
+ M(NetworkSession) \
+ M(PerformanceLogging) \
M(Plugins) \
+ M(Printing) \
+ M(ProcessSuspension) \
M(RemoteLayerTree) \
+ M(Resize) \
+ M(Selection) \
M(SessionState) \
M(StorageAPI) \
M(TextInput) \
- M(View) \
- M(IDB) \
-
-#define DECLARE_LOG_CHANNEL(name) \
- extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name);
+ M(ViewGestures) \
+ M(ViewState) \
+ M(VirtualMemory) \
+ M(VisibleRects) \
WEBKIT2_LOG_CHANNELS(DECLARE_LOG_CHANNEL)
#undef DECLARE_LOG_CHANNEL
-void initializeLogChannelsIfNecessary(void);
-String logLevelString();
-
-#if PLATFORM(GTK) || PLATFORM(EFL)
-WTFLogChannel* logChannelByName(const String&);
+#ifdef __cplusplus
+}
#endif
-} // namespace WebKit
-
-#endif // !LOG_DISABLED
+#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
#endif // Logging_h
diff --git a/Source/WebKit2/Platform/Module.cpp b/Source/WebKit2/Platform/Module.cpp
index 755fc8714..45c244cda 100644
--- a/Source/WebKit2/Platform/Module.cpp
+++ b/Source/WebKit2/Platform/Module.cpp
@@ -30,7 +30,7 @@ namespace WebKit {
Module::Module(const String& path)
: m_path(path)
-#if PLATFORM(MAC) && !defined(__LP64__)
+#if USE(CF) && !defined(__LP64__)
, m_bundleResourceMap(-1)
#endif
{
diff --git a/Source/WebKit2/Platform/Module.h b/Source/WebKit2/Platform/Module.h
index e5de8bc45..53bed92f0 100644
--- a/Source/WebKit2/Platform/Module.h
+++ b/Source/WebKit2/Platform/Module.h
@@ -29,7 +29,7 @@
#include <wtf/Noncopyable.h>
#include <wtf/text/WTFString.h>
-#if PLATFORM(MAC)
+#if USE(CF)
#include <wtf/RetainPtr.h>
#endif
@@ -37,10 +37,6 @@
typedef struct _GModule GModule;
#endif
-#if PLATFORM(EFL)
-#include <Eina.h>
-#endif
-
namespace WebKit {
class Module {
@@ -54,13 +50,13 @@ public:
// live Objective-C objects whose methods come from that bundle.
void unload();
-#if PLATFORM(MAC)
+#if USE(CF)
String bundleIdentifier() const;
#endif
template<typename FunctionType> FunctionType functionPointer(const char* functionName) const;
-#if PLATFORM(MAC) && !defined(__LP64__)
+#if USE(CF) && !defined(__LP64__)
CFBundleRefNum bundleResourceMap();
#endif
@@ -68,15 +64,13 @@ private:
void* platformFunctionPointer(const char* functionName) const;
String m_path;
-#if PLATFORM(MAC)
+#if USE(CF)
RetainPtr<CFBundleRef> m_bundle;
#if !defined(__LP64__)
CFBundleRefNum m_bundleResourceMap;
#endif
#elif PLATFORM(GTK)
GModule* m_handle;
-#elif PLATFORM(EFL)
- OwnPtr<Eina_Module> m_module;
#endif
};
diff --git a/Source/WebKit2/Platform/SharedMemory.h b/Source/WebKit2/Platform/SharedMemory.h
index efa5f0074..08421ae66 100644
--- a/Source/WebKit2/Platform/SharedMemory.h
+++ b/Source/WebKit2/Platform/SharedMemory.h
@@ -26,25 +26,31 @@
#ifndef SharedMemory_h
#define SharedMemory_h
+#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
-#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
-#if PLATFORM(GTK) || PLATFORM(EFL)
+#if USE(UNIX_DOMAIN_SOCKETS)
#include "Attachment.h"
-#include <wtf/text/WTFString.h>
+#include <wtf/Optional.h>
#endif
namespace IPC {
- class ArgumentDecoder;
- class ArgumentEncoder;
+class Decoder;
+class Encoder;
}
+#if OS(DARWIN)
+namespace WebCore {
+class MachSendRight;
+}
+#endif
+
namespace WebKit {
class SharedMemory : public RefCounted<SharedMemory> {
public:
- enum Protection {
+ enum class Protection {
ReadOnly,
ReadWrite
};
@@ -57,55 +63,62 @@ public:
bool isNull() const;
- void encode(IPC::ArgumentEncoder&) const;
- static bool decode(IPC::ArgumentDecoder&, Handle&);
+ void clear();
+
+ void encode(IPC::Encoder&) const;
+ static bool decode(IPC::Decoder&, Handle&);
#if USE(UNIX_DOMAIN_SOCKETS)
- IPC::Attachment releaseToAttachment() const;
- void adoptFromAttachment(int fileDescriptor, size_t);
+ IPC::Attachment releaseAttachment() const;
+ void adoptAttachment(IPC::Attachment&&);
#endif
private:
friend class SharedMemory;
-#if OS(DARWIN)
+#if USE(UNIX_DOMAIN_SOCKETS)
+ mutable IPC::Attachment m_attachment;
+#elif OS(DARWIN)
mutable mach_port_t m_port;
-#elif USE(UNIX_DOMAIN_SOCKETS)
- mutable int m_fileDescriptor;
-#endif
size_t m_size;
+#endif
};
-
- // Create a shared memory object with the given size. Will return 0 on failure.
- static PassRefPtr<SharedMemory> create(size_t);
- // Create a shared memory object from the given handle and the requested protection. Will return 0 on failure.
- static PassRefPtr<SharedMemory> create(const Handle&, Protection);
-
- // Create a shared memory object with the given size by vm_copy'ing the given buffer.
- // Will return 0 on failure.
- static PassRefPtr<SharedMemory> createFromVMBuffer(void*, size_t);
+ static RefPtr<SharedMemory> allocate(size_t);
+ static RefPtr<SharedMemory> create(void*, size_t, Protection);
+ static RefPtr<SharedMemory> map(const Handle&, Protection);
+#if USE(UNIX_DOMAIN_SOCKETS)
+ static RefPtr<SharedMemory> wrapMap(void*, size_t, int fileDescriptor);
+#endif
~SharedMemory();
bool createHandle(Handle&, Protection);
size_t size() const { return m_size; }
- void* data() const { return m_data; }
-
- // Creates a copy-on-write copy of the first |size| bytes.
- PassRefPtr<SharedMemory> createCopyOnWriteCopy(size_t) const;
+ void* data() const
+ {
+ ASSERT(m_data);
+ return m_data;
+ }
// Return the system page size in bytes.
static unsigned systemPageSize();
private:
+#if OS(DARWIN)
+ WebCore::MachSendRight createSendRight(Protection) const;
+#endif
+
size_t m_size;
void* m_data;
- bool m_shouldVMDeallocateData;
+#if PLATFORM(COCOA)
+ Protection m_protection;
+#endif
-#if OS(DARWIN)
+#if USE(UNIX_DOMAIN_SOCKETS)
+ std::optional<int> m_fileDescriptor;
+ bool m_isWrappingMap { false };
+#elif OS(DARWIN)
mach_port_t m_port;
-#elif USE(UNIX_DOMAIN_SOCKETS)
- int m_fileDescriptor;
#endif
};
diff --git a/Source/WebKit2/Platform/WorkQueue.h b/Source/WebKit2/Platform/WorkQueue.h
deleted file mode 100644
index e322f59f1..000000000
--- a/Source/WebKit2/Platform/WorkQueue.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WorkQueue_h
-#define WorkQueue_h
-
-#if OS(DARWIN)
-#include <dispatch/dispatch.h>
-#endif
-
-#include <chrono>
-#include <functional>
-#include <wtf/Forward.h>
-#include <wtf/Functional.h>
-#include <wtf/HashMap.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/Threading.h>
-#include <wtf/Vector.h>
-
-#if PLATFORM(GTK) || PLATFORM(EFL)
-#include "PlatformProcessIdentifier.h"
-#endif
-
-#if PLATFORM(GTK)
-#include <wtf/gobject/GRefPtr.h>
-typedef gboolean (*GSourceFunc) (gpointer data);
-#elif PLATFORM(EFL)
-#include <DispatchQueueEfl.h>
-#endif
-
-class WorkQueue : public ThreadSafeRefCounted<WorkQueue> {
-public:
- static PassRefPtr<WorkQueue> create(const char* name);
- ~WorkQueue();
-
- void dispatch(std::function<void ()>);
- void dispatchAfter(std::chrono::nanoseconds, std::function<void ()>);
-
-#if OS(DARWIN)
- dispatch_queue_t dispatchQueue() const { return m_dispatchQueue; }
-#elif PLATFORM(GTK)
- void registerSocketEventHandler(int, std::function<void ()>, std::function<void ()>);
- void unregisterSocketEventHandler(int);
-#elif PLATFORM(EFL)
- void registerSocketEventHandler(int, std::function<void ()>);
- void unregisterSocketEventHandler(int);
-#endif
-
-private:
- explicit WorkQueue(const char* name);
-
- void platformInitialize(const char* name);
- void platformInvalidate();
-
-#if OS(DARWIN)
- static void executeFunction(void*);
- dispatch_queue_t m_dispatchQueue;
-#elif PLATFORM(GTK)
- class EventSource;
- class SocketEventSource;
-
- static void startWorkQueueThread(WorkQueue*);
- void workQueueThreadBody();
- void dispatchOnSource(GSource*, std::function<void ()>, GSourceFunc);
-
- ThreadIdentifier m_workQueueThread;
- GRefPtr<GMainContext> m_eventContext;
- Mutex m_eventLoopLock;
- GRefPtr<GMainLoop> m_eventLoop;
- Mutex m_eventSourcesLock;
- HashMap<int, Vector<SocketEventSource*>> m_eventSources;
-#elif PLATFORM(EFL)
- RefPtr<DispatchQueue> m_dispatchQueue;
-#endif
-};
-
-#endif // WorkQueue_h
diff --git a/Source/WebKit2/Platform/gtk/ModuleGtk.cpp b/Source/WebKit2/Platform/glib/ModuleGlib.cpp
index ef1ce112a..ef1ce112a 100644
--- a/Source/WebKit2/Platform/gtk/ModuleGtk.cpp
+++ b/Source/WebKit2/Platform/glib/ModuleGlib.cpp
diff --git a/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp b/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp
deleted file mode 100644
index ae03c47dd..000000000
--- a/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2011 Igalia S.L.
- * 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 "config.h"
-#include "WorkQueue.h"
-
-#include <gio/gio.h>
-#include <glib.h>
-#include <wtf/gobject/GRefPtr.h>
-
-// WorkQueue::EventSource
-class WorkQueue::EventSource {
-public:
- EventSource(std::function<void()> function, WorkQueue* workQueue)
- : m_function(std::move(function))
- , m_workQueue(workQueue)
- {
- ASSERT(workQueue);
- }
-
- virtual ~EventSource() { }
-
- void performWork()
- {
- m_function();
- }
-
- static gboolean performWorkOnce(EventSource* eventSource)
- {
- ASSERT(eventSource);
- eventSource->performWork();
- return FALSE;
- }
-
- static void deleteEventSource(EventSource* eventSource)
- {
- ASSERT(eventSource);
- delete eventSource;
- }
-
-private:
- std::function<void ()> m_function;
- RefPtr<WorkQueue> m_workQueue;
-};
-
-class WorkQueue::SocketEventSource : public WorkQueue::EventSource {
-public:
- SocketEventSource(std::function<void ()> function, WorkQueue* workQueue, GCancellable* cancellable, std::function<void ()> closeFunction)
- : EventSource(std::move(function), workQueue)
- , m_cancellable(cancellable)
- , m_closeFunction(std::move(closeFunction))
- {
- ASSERT(cancellable);
- }
-
- void cancel()
- {
- g_cancellable_cancel(m_cancellable);
- }
-
- void didClose()
- {
- m_closeFunction();
- }
-
- bool isCancelled() const
- {
- return g_cancellable_is_cancelled(m_cancellable);
- }
-
- static gboolean eventCallback(GSocket*, GIOCondition condition, SocketEventSource* eventSource)
- {
- ASSERT(eventSource);
-
- if (eventSource->isCancelled()) {
- // EventSource has been cancelled, return FALSE to destroy the source.
- return FALSE;
- }
-
- if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
- eventSource->didClose();
- return FALSE;
- }
-
- if (condition & G_IO_IN) {
- eventSource->performWork();
- return TRUE;
- }
-
- ASSERT_NOT_REACHED();
- return FALSE;
- }
-
-private:
- GCancellable* m_cancellable;
- std::function<void ()> m_closeFunction;
-};
-
-// WorkQueue
-static const size_t kVisualStudioThreadNameLimit = 31;
-
-void WorkQueue::platformInitialize(const char* name)
-{
- m_eventContext = adoptGRef(g_main_context_new());
- ASSERT(m_eventContext);
- m_eventLoop = adoptGRef(g_main_loop_new(m_eventContext.get(), FALSE));
- ASSERT(m_eventLoop);
-
- // This name can be com.apple.WebKit.ProcessLauncher or com.apple.CoreIPC.ReceiveQueue.
- // We are using those names for the thread name, but both are longer than 31 characters,
- // which is the limit of Visual Studio for thread names.
- // When log is enabled createThread() will assert instead of truncate the name, so we need
- // to make sure we don't use a name longer than 31 characters.
- const char* threadName = g_strrstr(name, ".");
- if (threadName)
- threadName++;
- else
- threadName = name;
- if (strlen(threadName) > kVisualStudioThreadNameLimit)
- threadName += strlen(threadName) - kVisualStudioThreadNameLimit;
-
- m_workQueueThread = createThread(reinterpret_cast<WTF::ThreadFunction>(&WorkQueue::startWorkQueueThread), this, threadName);
-}
-
-void WorkQueue::platformInvalidate()
-{
- MutexLocker locker(m_eventLoopLock);
-
- if (m_eventLoop) {
- if (g_main_loop_is_running(m_eventLoop.get()))
- g_main_loop_quit(m_eventLoop.get());
- m_eventLoop.clear();
- }
-
- m_eventContext.clear();
-}
-
-void WorkQueue::startWorkQueueThread(WorkQueue* workQueue)
-{
- workQueue->workQueueThreadBody();
-}
-
-void WorkQueue::workQueueThreadBody()
-{
- g_main_loop_run(m_eventLoop.get());
-}
-
-void WorkQueue::registerSocketEventHandler(int fileDescriptor, std::function<void ()> function, std::function<void ()> closeFunction)
-{
- GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0));
- ASSERT(socket);
- GRefPtr<GCancellable> cancellable = adoptGRef(g_cancellable_new());
- GRefPtr<GSource> dispatchSource = adoptGRef(g_socket_create_source(socket.get(), G_IO_IN, cancellable.get()));
- ASSERT(dispatchSource);
- SocketEventSource* eventSource = new SocketEventSource(std::move(function), this,
- cancellable.get(), std::move(closeFunction));
-
- g_source_set_callback(dispatchSource.get(), reinterpret_cast<GSourceFunc>(&WorkQueue::SocketEventSource::eventCallback),
- eventSource, reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));
-
- // Set up the event sources under the mutex since this is shared across multiple threads.
- {
- MutexLocker locker(m_eventSourcesLock);
- Vector<SocketEventSource*> sources;
- auto it = m_eventSources.find(fileDescriptor);
- if (it != m_eventSources.end())
- sources = it->value;
-
- sources.append(eventSource);
- m_eventSources.set(fileDescriptor, sources);
- }
-
- g_source_attach(dispatchSource.get(), m_eventContext.get());
-}
-
-void WorkQueue::unregisterSocketEventHandler(int fileDescriptor)
-{
- ASSERT(fileDescriptor);
-
- MutexLocker locker(m_eventSourcesLock);
-
- ASSERT(m_eventSources.contains(fileDescriptor));
- auto it = m_eventSources.find(fileDescriptor);
-
- if (it != m_eventSources.end()) {
- Vector<SocketEventSource*> sources = it->value;
- for (unsigned i = 0; i < sources.size(); i++)
- sources[i]->cancel();
-
- m_eventSources.remove(it);
- }
-}
-
-void WorkQueue::dispatchOnSource(GSource* dispatchSource, std::function<void ()> function, GSourceFunc sourceCallback)
-{
- g_source_set_callback(dispatchSource, sourceCallback, new EventSource(std::move(function), this),
- reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource));
-
- g_source_attach(dispatchSource, m_eventContext.get());
-}
-
-void WorkQueue::dispatch(std::function<void ()> function)
-{
- GRefPtr<GSource> dispatchSource = adoptGRef(g_idle_source_new());
- g_source_set_priority(dispatchSource.get(), G_PRIORITY_DEFAULT);
- dispatchOnSource(dispatchSource.get(), std::move(function),
- reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce));
-}
-
-void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function<void ()> function)
-{
- GRefPtr<GSource> dispatchSource = adoptGRef(g_timeout_source_new(
- static_cast<guint>(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count())));
- dispatchOnSource(dispatchSource.get(), std::move(function),
- reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce));
-}
diff --git a/Source/WebKit2/Platform/unix/EnvironmentUtilities.cpp b/Source/WebKit2/Platform/unix/EnvironmentUtilities.cpp
new file mode 100644
index 000000000..0de876715
--- /dev/null
+++ b/Source/WebKit2/Platform/unix/EnvironmentUtilities.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "EnvironmentUtilities.h"
+
+#include <wtf/text/CString.h>
+
+namespace WebKit {
+
+namespace EnvironmentUtilities {
+
+void stripValuesEndingWithString(const char* environmentVariable, const char* searchValue)
+{
+ ASSERT(environmentVariable);
+ ASSERT(searchValue);
+
+ // Grab the current value of the environment variable.
+ char* environmentValue = getenv(environmentVariable);
+
+ if (!environmentValue || environmentValue[0] == '\0')
+ return;
+
+ // Set up the strings we'll be searching for.
+ size_t searchLength = strlen(searchValue);
+ if (!searchLength)
+ return;
+
+ Vector<char> searchValueWithColonVector;
+ searchValueWithColonVector.grow(searchLength + 2);
+ char* searchValueWithColon = searchValueWithColonVector.data();
+ size_t searchLengthWithColon = searchLength + 1;
+
+ memcpy(searchValueWithColon, searchValue, searchLength);
+ searchValueWithColon[searchLength] = ':';
+ searchValueWithColon[searchLengthWithColon] = '\0';
+
+ // Loop over environmentValueBuffer, removing any components that match the search value ending with a colon.
+ char* componentStart = environmentValue;
+ char* match = strstr(componentStart, searchValueWithColon);
+ bool foundAnyMatches = match != NULL;
+ while (match != NULL) {
+ // Update componentStart to point to the colon immediately preceding the match.
+ char* nextColon = strstr(componentStart, ":");
+ while (nextColon && nextColon < match) {
+ componentStart = nextColon;
+ nextColon = strstr(componentStart + 1, ":");
+ }
+
+ // Copy over everything right of the match to the current component start, and search from there again.
+ if (componentStart[0] == ':') {
+ // If componentStart points to a colon, copy the colon over.
+ strcpy(componentStart, match + searchLength);
+ } else {
+ // Otherwise, componentStart still points to the beginning of environmentValueBuffer, so don't copy over the colon.
+ // The edge case is if the colon is the last character in the string, so "match + searchLengthWithoutColon + 1" is the
+ // null terminator of the original input, in which case this is still safe.
+ strcpy(componentStart, match + searchLengthWithColon);
+ }
+
+ match = strstr(componentStart, searchValueWithColon);
+ }
+
+ // Search for the value without a trailing colon, seeing if the original input ends with it.
+ match = strstr(componentStart, searchValue);
+ while (match != NULL) {
+ if (match[searchLength] == '\0')
+ break;
+ match = strstr(match + 1, searchValue);
+ }
+
+ // Since the original input ends with the search, strip out the last component.
+ if (match) {
+ // Update componentStart to point to the colon immediately preceding the match.
+ char* nextColon = strstr(componentStart, ":");
+ while (nextColon && nextColon < match) {
+ componentStart = nextColon;
+ nextColon = strstr(componentStart + 1, ":");
+ }
+
+ // Whether componentStart points to the original string or the last colon, putting the null terminator there will get us the desired result.
+ componentStart[0] = '\0';
+
+ foundAnyMatches = true;
+ }
+
+ // If we found no matches, don't change anything.
+ if (!foundAnyMatches)
+ return;
+
+ // If we have nothing left, just unset the variable
+ if (environmentValue[0] == '\0') {
+ unsetenv(environmentVariable);
+ return;
+ }
+
+ setenv(environmentVariable, environmentValue, 1);
+}
+
+} // namespace EnvironmentUtilities
+
+} // namespace WebKit
diff --git a/Source/WebKit2/Platform/PlatformProcessIdentifier.h b/Source/WebKit2/Platform/unix/EnvironmentUtilities.h
index 1a630487b..fed77bc3f 100644
--- a/Source/WebKit2/Platform/PlatformProcessIdentifier.h
+++ b/Source/WebKit2/Platform/unix/EnvironmentUtilities.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,24 +23,20 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef EnvironmentUtilities_h
+#define EnvironmentUtilities_h
-#ifndef PlatformProcessIdentifier_h
-#define PlatformProcessIdentifier_h
-
-#if PLATFORM(EFL)
-#include <unistd.h>
-#endif
+#include <wtf/text/WTFString.h>
namespace WebKit {
-#if PLATFORM(MAC)
-typedef pid_t PlatformProcessIdentifier;
-#elif PLATFORM(GTK)
-typedef int PlatformProcessIdentifier;
-#elif PLATFORM(EFL)
-typedef pid_t PlatformProcessIdentifier;
-#endif
+namespace EnvironmentUtilities {
+
+void stripValuesEndingWithString(const char* environmentVariable, const char* search);
+
+} // namespace EnvironmentUtilities
+
+} // namespace WebKit
-} // namespace WebKit
+#endif // #define EnvironmentUtilities_h
-#endif // PlatformProcessIdentifier_h
diff --git a/Source/WebKit2/Platform/gtk/LoggingGtk.cpp b/Source/WebKit2/Platform/unix/LoggingUnix.cpp
index 44e5b118d..8014a5dcf 100644
--- a/Source/WebKit2/Platform/gtk/LoggingGtk.cpp
+++ b/Source/WebKit2/Platform/unix/LoggingUnix.cpp
@@ -27,17 +27,15 @@
#include "config.h"
#include "Logging.h"
-#include <glib.h>
-
namespace WebKit {
-#if !LOG_DISABLED
+#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
String logLevelString()
{
- return g_getenv("WEBKIT_DEBUG");
+ return getenv("WEBKIT_DEBUG");
}
-#endif // !LOG_DISABLED
+#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED
}
diff --git a/Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp b/Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp
index 5beba1370..c246312f9 100644
--- a/Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp
+++ b/Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp
@@ -29,8 +29,8 @@
#if USE(UNIX_DOMAIN_SOCKETS)
#include "SharedMemory.h"
-#include "ArgumentDecoder.h"
-#include "ArgumentEncoder.h"
+#include "Decoder.h"
+#include "Encoder.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -43,61 +43,71 @@
#include <wtf/RandomNumber.h>
#include <wtf/UniStdExtras.h>
#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
namespace WebKit {
SharedMemory::Handle::Handle()
- : m_fileDescriptor(-1)
- , m_size(0)
{
}
SharedMemory::Handle::~Handle()
{
- if (!isNull())
- closeWithRetry(m_fileDescriptor);
+}
+
+void SharedMemory::Handle::clear()
+{
+ m_attachment = IPC::Attachment();
}
bool SharedMemory::Handle::isNull() const
{
- return m_fileDescriptor == -1;
+ return m_attachment.fileDescriptor() == -1;
}
-void SharedMemory::Handle::encode(IPC::ArgumentEncoder& encoder) const
+void SharedMemory::Handle::encode(IPC::Encoder& encoder) const
{
- encoder << releaseToAttachment();
+ encoder << releaseAttachment();
}
-bool SharedMemory::Handle::decode(IPC::ArgumentDecoder& decoder, Handle& handle)
+bool SharedMemory::Handle::decode(IPC::Decoder& decoder, Handle& handle)
{
- ASSERT_ARG(handle, !handle.m_size);
ASSERT_ARG(handle, handle.isNull());
IPC::Attachment attachment;
if (!decoder.decode(attachment))
return false;
- handle.adoptFromAttachment(attachment.releaseFileDescriptor(), attachment.size());
+ handle.adoptAttachment(WTFMove(attachment));
return true;
}
-IPC::Attachment SharedMemory::Handle::releaseToAttachment() const
+IPC::Attachment SharedMemory::Handle::releaseAttachment() const
{
- int temp = m_fileDescriptor;
- m_fileDescriptor = -1;
- return IPC::Attachment(temp, m_size);
+ return WTFMove(m_attachment);
}
-void SharedMemory::Handle::adoptFromAttachment(int fileDescriptor, size_t size)
+void SharedMemory::Handle::adoptAttachment(IPC::Attachment&& attachment)
{
- ASSERT(!m_size);
ASSERT(isNull());
- m_fileDescriptor = fileDescriptor;
- m_size = size;
+ m_attachment = WTFMove(attachment);
}
-PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
+static inline int accessModeMMap(SharedMemory::Protection protection)
+{
+ switch (protection) {
+ case SharedMemory::Protection::ReadOnly:
+ return PROT_READ;
+ case SharedMemory::Protection::ReadWrite:
+ return PROT_READ | PROT_WRITE;
+ }
+
+ ASSERT_NOT_REACHED();
+ return PROT_READ | PROT_WRITE;
+}
+
+RefPtr<SharedMemory> SharedMemory::create(void* address, size_t size, Protection protection)
{
CString tempName;
@@ -111,7 +121,7 @@ PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
} while (fileDescriptor == -1 && errno == EINTR);
}
if (fileDescriptor == -1) {
- WTFLogAlways("Failed to create shared memory file %s", tempName.data());
+ WTFLogAlways("Failed to create shared memory file %s: %s", tempName.data(), strerror(errno));
return 0;
}
@@ -123,7 +133,7 @@ PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
}
}
- void* data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileDescriptor, 0);
+ void* data = mmap(address, size, accessModeMMap(protection), MAP_SHARED, fileDescriptor, 0);
if (data == MAP_FAILED) {
closeWithRetry(fileDescriptor);
shm_unlink(tempName.data());
@@ -139,66 +149,61 @@ PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
return instance.release();
}
-static inline int accessModeMMap(SharedMemory::Protection protection)
+RefPtr<SharedMemory> SharedMemory::allocate(size_t size)
{
- switch (protection) {
- case SharedMemory::ReadOnly:
- return PROT_READ;
- case SharedMemory::ReadWrite:
- return PROT_READ | PROT_WRITE;
- }
-
- ASSERT_NOT_REACHED();
- return PROT_READ | PROT_WRITE;
+ return SharedMemory::create(nullptr, size, SharedMemory::Protection::ReadWrite);
}
-PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
+RefPtr<SharedMemory> SharedMemory::map(const Handle& handle, Protection protection)
{
ASSERT(!handle.isNull());
- void* data = mmap(0, handle.m_size, accessModeMMap(protection), MAP_SHARED, handle.m_fileDescriptor, 0);
+ int fd = handle.m_attachment.releaseFileDescriptor();
+ void* data = mmap(0, handle.m_attachment.size(), accessModeMMap(protection), MAP_SHARED, fd, 0);
+ closeWithRetry(fd);
if (data == MAP_FAILED)
- return 0;
+ return nullptr;
+ RefPtr<SharedMemory> instance = wrapMap(data, handle.m_attachment.size(), -1);
+ instance->m_fileDescriptor = std::nullopt;
+ instance->m_isWrappingMap = false;
+ return instance;
+}
+
+RefPtr<SharedMemory> SharedMemory::wrapMap(void* data, size_t size, int fileDescriptor)
+{
RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
instance->m_data = data;
- instance->m_fileDescriptor = handle.m_fileDescriptor;
- instance->m_size = handle.m_size;
- handle.m_fileDescriptor = -1;
+ instance->m_size = size;
+ instance->m_fileDescriptor = fileDescriptor;
+ instance->m_isWrappingMap = true;
return instance;
}
SharedMemory::~SharedMemory()
{
+ if (m_isWrappingMap)
+ return;
+
munmap(m_data, m_size);
- closeWithRetry(m_fileDescriptor);
+ if (m_fileDescriptor)
+ closeWithRetry(m_fileDescriptor.value());
}
bool SharedMemory::createHandle(Handle& handle, Protection)
{
- ASSERT_ARG(handle, !handle.m_size);
ASSERT_ARG(handle, handle.isNull());
+ ASSERT(m_fileDescriptor);
// FIXME: Handle the case where the passed Protection is ReadOnly.
// See https://bugs.webkit.org/show_bug.cgi?id=131542.
- int duplicatedHandle;
- while ((duplicatedHandle = dup(m_fileDescriptor)) == -1) {
- if (errno != EINTR) {
- ASSERT_NOT_REACHED();
- return false;
- }
- }
-
- while (fcntl(duplicatedHandle, F_SETFD, FD_CLOEXEC) == -1) {
- if (errno != EINTR) {
- ASSERT_NOT_REACHED();
- closeWithRetry(duplicatedHandle);
- return false;
- }
+ int duplicatedHandle = dupCloseOnExec(m_fileDescriptor.value());
+ if (duplicatedHandle == -1) {
+ ASSERT_NOT_REACHED();
+ return false;
}
- handle.m_fileDescriptor = duplicatedHandle;
- handle.m_size = m_size;
+ handle.m_attachment = IPC::Attachment(duplicatedHandle, m_size);
return true;
}