From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- Source/WebKit2/Platform/IPC/ArgumentCoder.h | 8 +- Source/WebKit2/Platform/IPC/ArgumentCoders.cpp | 40 +- Source/WebKit2/Platform/IPC/ArgumentCoders.h | 259 ++++++- Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp | 227 ------- Source/WebKit2/Platform/IPC/ArgumentDecoder.h | 111 --- Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp | 198 ------ Source/WebKit2/Platform/IPC/ArgumentEncoder.h | 96 --- Source/WebKit2/Platform/IPC/Arguments.h | 391 ----------- Source/WebKit2/Platform/IPC/Attachment.cpp | 12 +- Source/WebKit2/Platform/IPC/Attachment.h | 50 +- Source/WebKit2/Platform/IPC/Connection.cpp | 748 ++++++++++++--------- Source/WebKit2/Platform/IPC/Connection.h | 340 ++++++---- Source/WebKit2/Platform/IPC/DataReference.cpp | 23 +- Source/WebKit2/Platform/IPC/DataReference.h | 35 +- Source/WebKit2/Platform/IPC/Decoder.cpp | 281 ++++++++ Source/WebKit2/Platform/IPC/Decoder.h | 162 +++++ Source/WebKit2/Platform/IPC/Encoder.cpp | 261 +++++++ Source/WebKit2/Platform/IPC/Encoder.h | 128 ++++ Source/WebKit2/Platform/IPC/HandleMessage.h | 172 +++-- Source/WebKit2/Platform/IPC/MessageDecoder.cpp | 76 --- Source/WebKit2/Platform/IPC/MessageDecoder.h | 67 -- Source/WebKit2/Platform/IPC/MessageEncoder.cpp | 67 -- Source/WebKit2/Platform/IPC/MessageEncoder.h | 47 -- Source/WebKit2/Platform/IPC/MessageFlags.h | 1 + Source/WebKit2/Platform/IPC/MessageReceiver.h | 41 +- Source/WebKit2/Platform/IPC/MessageReceiverMap.cpp | 46 +- Source/WebKit2/Platform/IPC/MessageReceiverMap.h | 9 +- Source/WebKit2/Platform/IPC/MessageSender.cpp | 4 +- Source/WebKit2/Platform/IPC/MessageSender.h | 25 +- Source/WebKit2/Platform/IPC/StringReference.cpp | 10 +- Source/WebKit2/Platform/IPC/StringReference.h | 8 +- .../WebKit2/Platform/IPC/glib/GSocketMonitor.cpp | 69 ++ Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h | 59 ++ .../WebKit2/Platform/IPC/unix/AttachmentUnix.cpp | 24 +- .../WebKit2/Platform/IPC/unix/ConnectionUnix.cpp | 348 +++++----- Source/WebKit2/Platform/IPC/unix/UnixMessage.h | 113 ++++ Source/WebKit2/Platform/LogInitialization.h | 39 ++ Source/WebKit2/Platform/Logging.cpp | 37 +- Source/WebKit2/Platform/Logging.h | 42 +- Source/WebKit2/Platform/Module.cpp | 2 +- Source/WebKit2/Platform/Module.h | 14 +- .../WebKit2/Platform/PlatformProcessIdentifier.h | 46 -- Source/WebKit2/Platform/SharedMemory.h | 75 ++- Source/WebKit2/Platform/WorkQueue.cpp | 42 -- Source/WebKit2/Platform/WorkQueue.h | 101 --- Source/WebKit2/Platform/glib/ModuleGlib.cpp | 57 ++ Source/WebKit2/Platform/gtk/LoggingGtk.cpp | 43 -- Source/WebKit2/Platform/gtk/ModuleGtk.cpp | 57 -- Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp | 240 ------- .../WebKit2/Platform/unix/EnvironmentUtilities.cpp | 124 ++++ .../WebKit2/Platform/unix/EnvironmentUtilities.h | 42 ++ Source/WebKit2/Platform/unix/LoggingUnix.cpp | 41 ++ Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp | 119 ++-- 53 files changed, 2880 insertions(+), 2797 deletions(-) delete mode 100644 Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp delete mode 100644 Source/WebKit2/Platform/IPC/ArgumentDecoder.h delete mode 100644 Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp delete mode 100644 Source/WebKit2/Platform/IPC/ArgumentEncoder.h delete mode 100644 Source/WebKit2/Platform/IPC/Arguments.h create mode 100644 Source/WebKit2/Platform/IPC/Decoder.cpp create mode 100644 Source/WebKit2/Platform/IPC/Decoder.h create mode 100644 Source/WebKit2/Platform/IPC/Encoder.cpp create mode 100644 Source/WebKit2/Platform/IPC/Encoder.h delete mode 100644 Source/WebKit2/Platform/IPC/MessageDecoder.cpp delete mode 100644 Source/WebKit2/Platform/IPC/MessageDecoder.h delete mode 100644 Source/WebKit2/Platform/IPC/MessageEncoder.cpp delete mode 100644 Source/WebKit2/Platform/IPC/MessageEncoder.h create mode 100644 Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp create mode 100644 Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h create mode 100644 Source/WebKit2/Platform/IPC/unix/UnixMessage.h create mode 100644 Source/WebKit2/Platform/LogInitialization.h delete mode 100644 Source/WebKit2/Platform/PlatformProcessIdentifier.h delete mode 100644 Source/WebKit2/Platform/WorkQueue.cpp delete mode 100644 Source/WebKit2/Platform/WorkQueue.h create mode 100644 Source/WebKit2/Platform/glib/ModuleGlib.cpp delete mode 100644 Source/WebKit2/Platform/gtk/LoggingGtk.cpp delete mode 100644 Source/WebKit2/Platform/gtk/ModuleGtk.cpp delete mode 100644 Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp create mode 100644 Source/WebKit2/Platform/unix/EnvironmentUtilities.cpp create mode 100644 Source/WebKit2/Platform/unix/EnvironmentUtilities.h create mode 100644 Source/WebKit2/Platform/unix/LoggingUnix.cpp (limited to 'Source/WebKit2/Platform') 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 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::encode(ArgumentEncoder& encoder, const AtomicString& atomicString) +void ArgumentCoder::encode(IPC::Encoder& encoder, const std::chrono::system_clock::time_point& timePoint) +{ + encoder << static_cast(timePoint.time_since_epoch().count()); +} + +bool ArgumentCoder::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(time))); + return true; +} + +void ArgumentCoder::encode(Encoder& encoder, const AtomicString& atomicString) { encoder << atomicString.string(); } -bool ArgumentCoder::decode(ArgumentDecoder& decoder, AtomicString& atomicString) +bool ArgumentCoder::decode(Decoder& decoder, AtomicString& atomicString) { String string; if (!decoder.decode(string)) @@ -47,7 +62,7 @@ bool ArgumentCoder::decode(ArgumentDecoder& decoder, AtomicString& return true; } -void ArgumentCoder::encode(ArgumentEncoder& encoder, const CString& string) +void ArgumentCoder::encode(Encoder& encoder, const CString& string) { // Special case the null string. if (string.isNull()) { @@ -60,7 +75,7 @@ void ArgumentCoder::encode(ArgumentEncoder& encoder, const CString& str encoder.encodeFixedLengthData(reinterpret_cast(string.data()), length, 1); } -bool ArgumentCoder::decode(ArgumentDecoder& decoder, CString& result) +bool ArgumentCoder::decode(Decoder& decoder, CString& result) { uint32_t length; if (!decoder.decode(length)) @@ -88,7 +103,7 @@ bool ArgumentCoder::decode(ArgumentDecoder& decoder, CString& result) } -void ArgumentCoder::encode(ArgumentEncoder& encoder, const String& string) +void ArgumentCoder::encode(Encoder& encoder, const String& string) { // Special case the null string. if (string.isNull()) { @@ -108,7 +123,7 @@ void ArgumentCoder::encode(ArgumentEncoder& encoder, const String& strin } template -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(length)) { @@ -125,7 +140,7 @@ static inline bool decodeStringText(ArgumentDecoder& decoder, uint32_t length, S return true; } -bool ArgumentCoder::decode(ArgumentDecoder& decoder, String& result) +bool ArgumentCoder::decode(Decoder& decoder, String& result) { uint32_t length; if (!decoder.decode(length)) @@ -147,4 +162,15 @@ bool ArgumentCoder::decode(ArgumentDecoder& decoder, String& result) return decodeStringText(decoder, length, result); } + +void ArgumentCoder::encode(Encoder& encoder, const SHA1::Digest& digest) +{ + encoder.encodeFixedLengthData(digest.data(), sizeof(digest), 1); +} + +bool ArgumentCoder::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 #include +#include #include +#include +#include +#include +#include +#include #include namespace IPC { // An argument coder works on POD types template struct SimpleArgumentCoder { - static void encode(ArgumentEncoder& encoder, const T& t) + static void encode(Encoder& encoder, const T& t) { encoder.encodeFixedLengthData(reinterpret_cast(&t), sizeof(T), alignof(T)); } - static bool decode(ArgumentDecoder& decoder, T& t) + static bool decode(Decoder& decoder, T& t) { return decoder.decodeFixedLengthData(reinterpret_cast(&t), sizeof(T), alignof(T)); } }; +template struct ArgumentCoder> { + static void encode(Encoder& encoder, const OptionSet& optionSet) + { + encoder << (static_cast(optionSet.toRaw())); + } + + static bool decode(Decoder& decoder, OptionSet& optionSet) + { + uint64_t value; + if (!decoder.decode(value)) + return false; + + optionSet = OptionSet::fromRaw(value); + return true; + } +}; + +template struct ArgumentCoder> { + static void encode(Encoder& encoder, const std::optional& optional) + { + if (!optional) { + encoder << false; + return; + } + + encoder << true; + encoder << optional.value(); + } + + static bool decode(Decoder& decoder, std::optional& 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 struct ArgumentCoder> { - static void encode(ArgumentEncoder& encoder, const std::pair& pair) + static void encode(Encoder& encoder, const std::pair& pair) { encoder << pair.first << pair.second; } - static bool decode(ArgumentDecoder& decoder, std::pair& pair) + static bool decode(Decoder& decoder, std::pair& pair) { T first; if (!decoder.decode(first)) @@ -70,13 +124,71 @@ template struct ArgumentCoder> { } }; +template +struct TupleCoder { + static void encode(Encoder& encoder, const std::tuple& tuple) + { + encoder << std::get(tuple); + TupleCoder::encode(encoder, tuple); + } + + static bool decode(Decoder& decoder, std::tuple& tuple) + { + if (!decoder.decode(std::get(tuple))) + return false; + return TupleCoder::decode(decoder, tuple); + } +}; + +template +struct TupleCoder<0, Elements...> { + static void encode(Encoder&, const std::tuple&) + { + } + + static bool decode(Decoder&, std::tuple&) + { + return true; + } +}; + +template struct ArgumentCoder> { + static void encode(Encoder& encoder, const std::tuple& tuple) + { + TupleCoder::encode(encoder, tuple); + } + + static bool decode(Decoder& decoder, std::tuple& tuple) + { + return TupleCoder::decode(decoder, tuple); + } +}; + + +template struct ArgumentCoder> { + static void encode(Encoder& encoder, const std::chrono::duration& duration) + { + static_assert(std::is_integral::value && std::is_signed::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(duration.count()); + } + + static bool decode(Decoder& decoder, std::chrono::duration& result) + { + int64_t count; + if (!decoder.decode(count)) + return false; + result = std::chrono::duration(static_cast(count)); + return true; + } +}; + template struct ArgumentCoder> { - static void encode(ArgumentEncoder& encoder, const WTF::KeyValuePair& pair) + static void encode(Encoder& encoder, const WTF::KeyValuePair& pair) { encoder << pair.key << pair.value; } - static bool decode(ArgumentDecoder& decoder, WTF::KeyValuePair& pair) + static bool decode(Decoder& decoder, WTF::KeyValuePair& pair) { KeyType key; if (!decoder.decode(key)) @@ -92,29 +204,29 @@ template struct ArgumentCoder struct VectorArgumentCoder; +template struct VectorArgumentCoder; -template struct VectorArgumentCoder { - static void encode(ArgumentEncoder& encoder, const Vector& vector) +template struct VectorArgumentCoder { + static void encode(Encoder& encoder, const Vector& vector) { encoder << static_cast(vector.size()); for (size_t i = 0; i < vector.size(); ++i) encoder << vector[i]; } - static bool decode(ArgumentDecoder& decoder, Vector& vector) + static bool decode(Decoder& decoder, Vector& vector) { uint64_t size; if (!decoder.decode(size)) return false; - Vector tmp; + Vector 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 struct VectorArgumentCoder { } }; -template struct VectorArgumentCoder { - static void encode(ArgumentEncoder& encoder, const Vector& vector) +template struct VectorArgumentCoder { + static void encode(Encoder& encoder, const Vector& vector) { encoder << static_cast(vector.size()); encoder.encodeFixedLengthData(reinterpret_cast(vector.data()), vector.size() * sizeof(T), alignof(T)); } - static bool decode(ArgumentDecoder& decoder, Vector& vector) + static bool decode(Decoder& decoder, Vector& vector) { uint64_t size; if (!decoder.decode(size)) @@ -144,7 +256,7 @@ template struct VectorArgumentCoder { return false; } - Vector temp; + Vector temp; temp.resize(size); decoder.decodeFixedLengthData(reinterpret_cast(temp.data()), size * sizeof(T), alignof(T)); @@ -154,19 +266,19 @@ template struct VectorArgumentCoder { } }; -template struct ArgumentCoder> : VectorArgumentCoder::value, T> { }; +template struct ArgumentCoder> : VectorArgumentCoder::value, T, inlineCapacity> { }; template struct ArgumentCoder> { typedef HashMap HashMapType; - static void encode(ArgumentEncoder& encoder, const HashMapType& hashMap) + static void encode(Encoder& encoder, const HashMapType& hashMap) { encoder << static_cast(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 struct ArgumentCoder> { + typedef HashSet HashSetType; + + static void encode(Encoder& encoder, const HashSetType& hashSet) + { + encoder << static_cast(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 struct ArgumentCoder> { + typedef HashCountedSet HashCountedSetType; + + static void encode(Encoder& encoder, const HashCountedSetType& hashCountedSet) + { + encoder << static_cast(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 { + static void encode(Encoder&, const std::chrono::system_clock::time_point&); + static bool decode(Decoder&, std::chrono::system_clock::time_point&); +}; + template<> struct ArgumentCoder { - 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 { - 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 { - 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 { + 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/ArgumentDecoder.cpp b/Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp deleted file mode 100644 index 6d396beee..000000000 --- a/Source/WebKit2/Platform/IPC/ArgumentDecoder.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ArgumentDecoder.h" - -#include "DataReference.h" -#include - -namespace IPC { - -ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize) -{ - initialize(buffer, bufferSize); -} - -ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Vector attachments) -{ - initialize(buffer, bufferSize); - - m_attachments = std::move(attachments); -} - -ArgumentDecoder::~ArgumentDecoder() -{ - ASSERT(m_buffer); - free(m_buffer); -#if !USE(UNIX_DOMAIN_SOCKETS) - // FIXME: We need to dispose of the mach ports in cases of failure. -#else - Vector::iterator end = m_attachments.end(); - for (Vector::iterator it = m_attachments.begin(); it != end; ++it) - it->dispose(); -#endif -} - -static inline uint8_t* roundUpToAlignment(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((reinterpret_cast(ptr) + alignmentMask) & ~alignmentMask); -} - -void ArgumentDecoder::initialize(const uint8_t* buffer, size_t bufferSize) -{ - m_buffer = static_cast(malloc(bufferSize)); - - ASSERT(!(reinterpret_cast(m_buffer) % alignof(uint64_t))); - - m_bufferPos = m_buffer; - m_bufferEnd = m_buffer + bufferSize; - memcpy(m_buffer, buffer, bufferSize); -} - -static inline bool alignedBufferIsLargeEnoughToContain(const uint8_t* alignedPosition, const uint8_t* bufferEnd, size_t size) -{ - return bufferEnd >= alignedPosition && static_cast(bufferEnd - alignedPosition) >= size; -} - -bool ArgumentDecoder::alignBufferPosition(unsigned alignment, size_t size) -{ - uint8_t* alignedPosition = roundUpToAlignment(m_bufferPos, alignment); - if (!alignedBufferIsLargeEnoughToContain(alignedPosition, m_bufferEnd, size)) { - // We've walked off the end of this buffer. - markInvalid(); - return false; - } - - m_bufferPos = alignedPosition; - return true; -} - -bool ArgumentDecoder::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) -{ - if (!alignBufferPosition(alignment, size)) - return false; - - memcpy(data, m_bufferPos, size); - m_bufferPos += size; - - return true; -} - -bool ArgumentDecoder::decodeVariableLengthByteArray(DataReference& dataReference) -{ - uint64_t size; - if (!decode(size)) - return false; - - if (!alignBufferPosition(1, size)) - return false; - - uint8_t* data = m_bufferPos; - m_bufferPos += size; - - dataReference = DataReference(data, size); - return true; -} - -template -static void decodeValueFromBuffer(Type& value, uint8_t*& bufferPosition) -{ - memcpy(&value, bufferPosition, sizeof(value)); - bufferPosition += sizeof(Type); -} - -bool ArgumentDecoder::decode(bool& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(uint8_t& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(uint16_t& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(uint32_t& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(uint64_t& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(int32_t& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(int64_t& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(float& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::decode(double& result) -{ - if (!alignBufferPosition(sizeof(result), sizeof(result))) - return false; - - decodeValueFromBuffer(result, m_bufferPos); - return true; -} - -bool ArgumentDecoder::removeAttachment(Attachment& attachment) -{ - if (m_attachments.isEmpty()) - return false; - - attachment = m_attachments.last(); - m_attachments.removeLast(); - return true; -} - -} // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/ArgumentDecoder.h b/Source/WebKit2/Platform/IPC/ArgumentDecoder.h deleted file mode 100644 index b35ce3f9c..000000000 --- a/Source/WebKit2/Platform/IPC/ArgumentDecoder.h +++ /dev/null @@ -1,111 +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 ArgumentDecoder_h -#define ArgumentDecoder_h - -#include "ArgumentCoder.h" -#include "Attachment.h" -#include - -namespace IPC { - -class DataReference; - -class ArgumentDecoder { -public: - ArgumentDecoder(const uint8_t* buffer, size_t bufferSize); - virtual ~ArgumentDecoder(); - - size_t length() const { return m_bufferEnd - m_buffer; } - - bool isInvalid() const { return m_bufferPos > m_bufferEnd; } - void markInvalid() { m_bufferPos = m_bufferEnd + 1; } - - bool decodeFixedLengthData(uint8_t*, size_t, unsigned alignment); - - // The data in the data reference here will only be valid for the lifetime of the ArgumentDecoder object. - bool decodeVariableLengthByteArray(DataReference&); - - bool decode(bool&); - bool decode(uint8_t&); - bool decode(uint16_t&); - bool decode(uint32_t&); - bool decode(uint64_t&); - bool decode(int32_t&); - bool decode(int64_t&); - bool decode(float&); - bool decode(double&); - - template bool decodeEnum(T& result) - { - static_assert(sizeof(T) <= 8, "Enum type T must not be larger than 64 bits!"); - - uint64_t value; - if (!decode(value)) - return false; - - result = static_cast(value); - return true; - } - - template - bool bufferIsLargeEnoughToContain(size_t numElements) const - { - static_assert(std::is_arithmetic::value, "Type T must have a fixed, known encoded size!"); - - if (numElements > std::numeric_limits::max() / sizeof(T)) - return false; - - return bufferIsLargeEnoughToContain(alignof(T), numElements * sizeof(T)); - } - - // Generic type decode function. - template bool decode(T& t) - { - return ArgumentCoder::decode(*this, t); - } - - bool removeAttachment(Attachment&); - -protected: - ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Vector); - - void initialize(const uint8_t* buffer, size_t bufferSize); - - bool alignBufferPosition(unsigned alignment, size_t size); - bool bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const; - -private: - uint8_t* m_buffer; - uint8_t* m_bufferPos; - uint8_t* m_bufferEnd; - - Vector m_attachments; -}; - -} // namespace IPC - -#endif // ArgumentDecoder_h diff --git a/Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp b/Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp deleted file mode 100644 index ee8563034..000000000 --- a/Source/WebKit2/Platform/IPC/ArgumentEncoder.cpp +++ /dev/null @@ -1,198 +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. - */ - -#include "config.h" -#include "ArgumentEncoder.h" - -#include "DataReference.h" -#include -#include - -#if OS(DARWIN) -#include -#endif - -namespace IPC { - -static inline void* allocBuffer(size_t size) -{ -#if OS(DARWIN) - return mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); -#else - return fastMalloc(size); -#endif -} - -static inline void freeBuffer(void* addr, size_t size) -{ -#if OS(DARWIN) - munmap(addr, size); -#else - UNUSED_PARAM(size); - fastFree(addr); -#endif -} - -ArgumentEncoder::ArgumentEncoder() - : m_buffer(m_inlineBuffer) - , m_bufferPointer(m_inlineBuffer) - , m_bufferSize(0) - , m_bufferCapacity(sizeof(m_inlineBuffer)) -{ -} - -ArgumentEncoder::~ArgumentEncoder() -{ - 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 -} - -static inline size_t roundUpToAlignment(size_t value, unsigned alignment) -{ - return ((value + alignment - 1) / alignment) * alignment; -} - -uint8_t* ArgumentEncoder::grow(unsigned alignment, size_t size) -{ - size_t alignedSize = roundUpToAlignment(m_bufferSize, alignment); - - if (alignedSize + size > m_bufferCapacity) { - size_t newCapacity = roundUpToAlignment(m_bufferCapacity * 2, 4096); - while (newCapacity < alignedSize + size) - newCapacity *= 2; - - uint8_t* newBuffer = static_cast(allocBuffer(newCapacity)); - if (!newBuffer) - CRASH(); - - memcpy(newBuffer, m_buffer, m_bufferSize); - - if (m_buffer != m_inlineBuffer) - freeBuffer(m_buffer, m_bufferCapacity); - - m_buffer = newBuffer; - m_bufferCapacity = newCapacity; - } - - m_bufferSize = alignedSize + size; - m_bufferPointer = m_buffer + alignedSize + size; - - return m_buffer + alignedSize; -} - -void ArgumentEncoder::encodeFixedLengthData(const uint8_t* data, size_t size, unsigned alignment) -{ - ASSERT(!(reinterpret_cast(data) % alignment)); - - uint8_t* buffer = grow(alignment, size); - memcpy(buffer, data, size); -} - -void ArgumentEncoder::encodeVariableLengthByteArray(const DataReference& dataReference) -{ - encode(static_cast(dataReference.size())); - encodeFixedLengthData(dataReference.data(), dataReference.size(), 1); -} - -template -static void copyValueToBuffer(Type value, uint8_t* bufferPosition) -{ - memcpy(bufferPosition, &value, sizeof(Type)); -} - -void ArgumentEncoder::encode(bool n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(uint8_t n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(uint16_t n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(uint32_t n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(uint64_t n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(int32_t n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(int64_t n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(float n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::encode(double n) -{ - uint8_t* buffer = grow(sizeof(n), sizeof(n)); - copyValueToBuffer(n, buffer); -} - -void ArgumentEncoder::addAttachment(const Attachment& attachment) -{ - m_attachments.append(attachment); -} - -Vector ArgumentEncoder::releaseAttachments() -{ - Vector newList; - newList.swap(m_attachments); - return newList; -} - -} // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/ArgumentEncoder.h b/Source/WebKit2/Platform/IPC/ArgumentEncoder.h deleted file mode 100644 index 424291570..000000000 --- a/Source/WebKit2/Platform/IPC/ArgumentEncoder.h +++ /dev/null @@ -1,96 +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 ArgumentEncoder_h -#define ArgumentEncoder_h - -#include "ArgumentCoder.h" -#include "Attachment.h" -#include - -namespace IPC { - -class ArgumentEncoder; -class DataReference; - -class ArgumentEncoder { -public: - ArgumentEncoder(); - virtual ~ArgumentEncoder(); - - void encodeFixedLengthData(const uint8_t*, size_t, unsigned alignment); - void encodeVariableLengthByteArray(const DataReference&); - - template void encodeEnum(T t) - { - COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits); - - encode(static_cast(t)); - } - - template void encode(const T& t) - { - ArgumentCoder::encode(*this, t); - } - - template ArgumentEncoder& operator<<(const T& t) - { - encode(t); - return *this; - } - - uint8_t* buffer() const { return m_buffer; } - size_t bufferSize() const { return m_bufferSize; } - - void addAttachment(const Attachment&); - Vector releaseAttachments(); - -private: - void encode(bool); - void encode(uint8_t); - void encode(uint16_t); - void encode(uint32_t); - void encode(uint64_t); - void encode(int32_t); - void encode(int64_t); - void encode(float); - void encode(double); - - uint8_t* grow(unsigned alignment, size_t size); - - uint8_t m_inlineBuffer[512]; - - uint8_t* m_buffer; - uint8_t* m_bufferPointer; - - size_t m_bufferSize; - size_t m_bufferCapacity; - - Vector m_attachments; -}; - -} // namespace IPC - -#endif // ArgumentEncoder_h 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 -struct TupleCoder { - static void encode(ArgumentEncoder& encoder, const std::tuple& tuple) - { - encoder << std::get(tuple); - TupleCoder::encode(encoder, tuple); - } - - static bool decode(ArgumentDecoder& decoder, std::tuple& tuple) - { - if (!decoder.decode(std::get(tuple))) - return false; - return TupleCoder::decode(decoder, tuple); - } -}; - -template -struct TupleCoder<0, Elements...> { - static void encode(ArgumentEncoder&, const std::tuple&) - { - } - - static bool decode(ArgumentDecoder&, std::tuple&) - { - return true; - } -}; - -template struct ArgumentCoder> { - static void encode(ArgumentEncoder& encoder, const std::tuple& tuple) - { - TupleCoder::encode(encoder, tuple); - } - - static bool decode(ArgumentDecoder& decoder, std::tuple& tuple) - { - return TupleCoder::decode(decoder, tuple); - } -}; - -struct Arguments0 { - typedef std::tuple<> ValueType; - - void encode(ArgumentEncoder&) const - { - } - - static bool decode(ArgumentDecoder&, Arguments0&) - { - return true; - } -}; - -template struct Arguments1 { - typedef std::tuple::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 struct Arguments2 : Arguments1 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type> ValueType; - - Arguments2() - { - } - - Arguments2(T1 t1, T2 t2) - : Arguments1(t1) - , argument2(t2) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments1::encode(encoder); - encoder << argument2; - } - - static bool decode(ArgumentDecoder& decoder, Arguments2& result) - { - if (!Arguments1::decode(decoder, result)) - return false; - - return decoder.decode(result.argument2); - } - - T2 argument2; -}; - -template struct Arguments3 : Arguments2 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type> ValueType; - - Arguments3() - { - } - - Arguments3(T1 t1, T2 t2, T3 t3) - : Arguments2(t1, t2) - , argument3(t3) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments2::encode(encoder); - encoder << argument3; - } - - static bool decode(ArgumentDecoder& decoder, Arguments3& result) - { - if (!Arguments2::decode(decoder, result)) - return false; - - return decoder.decode(result.argument3); - } - - T3 argument3; -}; - -template struct Arguments4 : Arguments3 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type> ValueType; - - Arguments4() - { - } - - Arguments4(T1 t1, T2 t2, T3 t3, T4 t4) - : Arguments3(t1, t2, t3) - , argument4(t4) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments3::encode(encoder); - encoder << argument4; - } - - static bool decode(ArgumentDecoder& decoder, Arguments4& result) - { - if (!Arguments3::decode(decoder, result)) - return false; - - return decoder.decode(result.argument4); - } - - T4 argument4; -}; - -template struct Arguments5 : Arguments4 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type> ValueType; - - Arguments5() - { - } - - Arguments5(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) - : Arguments4(t1, t2, t3, t4) - , argument5(t5) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments4::encode(encoder); - encoder << argument5; - } - - static bool decode(ArgumentDecoder& decoder, Arguments5& result) - { - if (!Arguments4::decode(decoder, result)) - return false; - - return decoder.decode(result.argument5); - } - - T5 argument5; -}; - -template struct Arguments6 : Arguments5 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type> ValueType; - - Arguments6() - { - } - - Arguments6(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) - : Arguments5(t1, t2, t3, t4, t5) - , argument6(t6) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments5::encode(encoder); - encoder << argument6; - } - - static bool decode(ArgumentDecoder& decoder, Arguments6& result) - { - if (!Arguments5::decode(decoder, result)) - return false; - - return decoder.decode(result.argument6); - } - - T6 argument6; -}; - -template struct Arguments7 : Arguments6 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::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) - , argument7(t7) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments6::encode(encoder); - encoder << argument7; - } - - static bool decode(ArgumentDecoder& decoder, Arguments7& result) - { - if (!Arguments6::decode(decoder, result)) - return false; - - return decoder.decode(result.argument7); - } - - T7 argument7; -}; - -template struct Arguments8 : Arguments7 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::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) - , argument8(t8) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments7::encode(encoder); - encoder << argument8; - } - - static bool decode(ArgumentDecoder& decoder, Arguments8& result) - { - if (!Arguments7::decode(decoder, result)) - return false; - - return decoder.decode(result.argument8); - } - - T8 argument8; -}; - -template struct Arguments10 : Arguments8 { - typedef std::tuple::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::type>::type, - typename std::remove_const::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) - , argument9(t9) - , argument10(t10) - { - } - - void encode(ArgumentEncoder& encoder) const - { - Arguments8::encode(encoder); - encoder << argument9; - encoder << argument10; - } - - static bool decode(ArgumentDecoder& decoder, Arguments10& result) - { - if (!Arguments8::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(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 #include #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 #include #include #include @@ -33,121 +35,116 @@ #include #include +#if PLATFORM(COCOA) +#include "MachMessage.h" +#endif + +#if USE(UNIX_DOMAIN_SOCKETS) +#include "UnixMessage.h" +#endif + namespace IPC { -class Connection::SyncMessageState : public ThreadSafeRefCounted { +struct Connection::ReplyHandler { + RefPtr dispatcher; + Function)> handler; +}; + +struct Connection::WaitForMessageState { + WaitForMessageState(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, OptionSet waitForOptions) + : messageReceiverName(messageReceiverName) + , messageName(messageName) + , destinationID(destinationID) + , waitForOptions(waitForOptions) + { + } + + StringReference messageReceiverName; + StringReference messageName; + uint64_t destinationID; + + OptionSet waitForOptions; + bool messageWaitingInterrupted = false; + + std::unique_ptr decoder; +}; + +class Connection::SyncMessageState { public: - static PassRefPtr 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&); + bool processIncomingMessage(Connection&, std::unique_ptr&); // 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 SyncMessageStateMap; - static SyncMessageStateMap& syncMessageStateMap() - { - static NeverDestroyed syncMessageStateMap; - return syncMessageStateMap; - } + void dispatchMessageAndResetDidScheduleDispatchMessagesForConnection(Connection&); - static Mutex& syncMessageStateMapMutex() - { - static NeverDestroyed 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> m_didScheduleDispatchMessagesWorkSet; struct ConnectionAndIncomingMessage { - RefPtr connection; - std::unique_ptr message; + Ref connection; + std::unique_ptr message; }; Vector 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 replyDecoder; - - BinarySemaphore semaphore; -}; - - -PassRefPtr 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 = adoptRef(new SyncMessageState(runLoop)); - result.iterator->value = syncMessageState.get(); + static std::once_flag onceFlag; + static LazyNeverDestroyed 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& message) +bool Connection::SyncMessageState::processIncomingMessage(Connection& connection, std::unique_ptr& 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(m_mutex); - if (m_didScheduleDispatchMessagesWorkSet.add(connection).isNewEntry) - m_runLoop->dispatch(bind(&SyncMessageState::dispatchMessageAndResetDidScheduleDispatchMessagesForConnection, this, RefPtr(connection))); + if (m_didScheduleDispatchMessagesWorkSet.add(&connection).isNewEntry) { + RunLoop::main().dispatch([this, protectedConnection = Ref(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 messagesToDispatchWhileWaitingForSyncReply; { - MutexLocker locker(m_mutex); + std::lock_guard 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(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(m_mutex); + ASSERT(m_didScheduleDispatchMessagesWorkSet.contains(&connection)); + m_didScheduleDispatchMessagesWorkSet.remove(&connection); } - dispatchMessages(connection); + dispatchMessages(&connection); } -PassRefPtr 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 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::createServerConnection(Identifier identifier, Client& client) { - return adoptRef(new Connection(identifier, true, client, clientRunLoop)); + return adoptRef(*new Connection(identifier, true, client)); } -PassRefPtr Connection::createClientConnection(Identifier identifier, Client* client, RunLoop* clientRunLoop) +Ref 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), RefPtr(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 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("IPC", "SyncMessageReply", syncRequestID); + auto replyEncoder = std::make_unique("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(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 Connection::createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID) +std::unique_ptr Connection::createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID) { - auto encoder = std::make_unique(messageReceiverName, messageName, destinationID); + auto encoder = std::make_unique(messageReceiverName, messageName, destinationID); encoder->setIsSyncMessage(true); // Encode the sync request ID. @@ -350,78 +374,126 @@ std::unique_ptr Connection::createSyncMessageEncoder(StringRefer return encoder; } -bool Connection::sendMessage(std::unique_ptr encoder, unsigned messageSendFlags) +bool Connection::sendMessage(std::unique_ptr encoder, OptionSet 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(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(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 encoder) +void Connection::sendMessageWithReply(uint64_t requestID, std::unique_ptr encoder, FunctionDispatcher& replyDispatcher, Function)>&& replyHandler) { - return sendMessage(std::move(encoder)); + { + std::lock_guard 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) +{ + return sendMessage(WTFMove(encoder), { }); } -std::unique_ptr 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 Connection::waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, Seconds timeout, OptionSet 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(m_incomingMessagesMutex); for (auto it = m_incomingMessages.begin(), end = m_incomingMessages.end(); it != end; ++it) { - std::unique_ptr& message = *it; + std::unique_ptr& message = *it; if (message->messageReceiverName() == messageReceiverName && message->messageName() == messageName && message->destinationID() == destinationID) { - std::unique_ptr returnedMessage = std::move(message); + std::unique_ptr returnedMessage = WTFMove(message); m_incomingMessages.remove(it); return returnedMessage; } + + if (message->isSyncMessage()) + hasIncomingSynchronousMessage = true; } } - std::pair, 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 lock(m_waitForMessageMutex); + std::lock_guard 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 lock(m_waitForMessageMutex); - - auto it = m_waitForMessageMap.find(messageAndDestination); - if (it->value) { - std::unique_ptr decoder = std::move(it->value); - m_waitForMessageMap.remove(it); + std::unique_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 Connection::waitForMessage(StringReference messa return nullptr; } -std::unique_ptr Connection::sendSyncMessage(uint64_t syncRequestID, std::unique_ptr encoder, std::chrono::milliseconds timeout, unsigned syncSendFlags) +std::unique_ptr Connection::sendSyncMessage(uint64_t syncRequestID, std::unique_ptr encoder, Seconds timeout, OptionSet 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 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 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 protect(*this); - std::unique_ptr reply = waitForSyncReply(syncRequestID, timeout, syncSendFlags); + std::unique_ptr 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 Connection::sendSyncMessage(uint64_t syncRequest return reply; } -std::unique_ptr Connection::sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr 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 Connection::waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags) +std::unique_ptr Connection::waitForSyncReply(uint64_t syncRequestID, Seconds timeout, OptionSet 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 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 decoder) +void Connection::processIncomingSyncReply(std::unique_ptr 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 message) +void Connection::processIncomingMessage(std::unique_ptr 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 = ""; - CString messageName = String::format("", 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 protectedThis(this); + StringReference messageReceiverNameReference = message->messageReceiverName(); + String messageReceiverName(messageReceiverNameReference.isEmpty() ? "" : String(messageReceiverNameReference.data(), messageReceiverNameReference.size())); + StringReference messageNameReference = message->messageName(); + String messageName(messageNameReference.isEmpty() ? "" : 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(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 lock(m_waitForMessageMutex); + std::lock_guard 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 callback) +{ + std::lock_guard 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(m_incomingSyncMessageCallbackMutex); + m_incomingSyncMessageCallbacks.remove(callbackID); +} + +bool Connection::hasIncomingSyncMessage() +{ + std::lock_guard 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(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 message; + std::unique_ptr message; { - MutexLocker locker(m_outgoingMessagesLock); + std::lock_guard 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("IPC", "SyncMessageReply", syncRequestID); + auto replyEncoder = std::make_unique("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 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 incomingMessage) +void Connection::enqueueIncomingMessage(std::unique_ptr incomingMessage) { { - MutexLocker locker(m_incomingMessagesLock); - m_incomingMessages.append(std::move(incomingMessage)); + std::lock_guard 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 message) +void Connection::dispatchMessage(std::unique_ptr 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 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 message; + std::unique_ptr message; { - MutexLocker locker(m_incomingMessagesLock); + std::lock_guard 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 -#include +#include #include #include -#include -#include +#include +#include +#include +#include #include -#if OS(DARWIN) +#if OS(DARWIN) && !USE(UNIX_DOMAIN_SOCKETS) #include -#include +#include +#include #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 { 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 { }; -#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 xpcConnection) : port(port) - , xpcConnection(xpcConnection) + , xpcConnection(WTFMove(xpcConnection)) { } mach_port_t port; - xpc_connection_t xpcConnection; + OSObjectPtr 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 createServerConnection(Identifier, Client*, WTF::RunLoop* clientRunLoop); - static PassRefPtr createClientConnection(Identifier, Client*, WTF::RunLoop* clientRunLoop); + static Ref createServerConnection(Identifier, Client&); + static Ref 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 bool send(T&& message, uint64_t destinationID, unsigned messageSendFlags = 0); - template bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout = std::chrono::milliseconds::max(), unsigned syncSendFlags = 0); - template bool waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout); + template bool send(T&& message, uint64_t destinationID, OptionSet sendOptions = { }); + template void sendWithReply(T&& message, uint64_t destinationID, FunctionDispatcher& replyDispatcher, Function::Type>)>&& replyHandler); + template bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, Seconds timeout = Seconds::infinity(), OptionSet sendSyncOptions = { }); + template bool waitForAndDispatchImmediately(uint64_t destinationID, Seconds timeout, OptionSet waitForOptions = { }); - std::unique_ptr createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID); - bool sendMessage(std::unique_ptr, unsigned messageSendFlags = 0); - std::unique_ptr sendSyncMessage(uint64_t syncRequestID, std::unique_ptr, std::chrono::milliseconds timeout, unsigned syncSendFlags = 0); - std::unique_ptr sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr, std::chrono::milliseconds timeout); - bool sendSyncReply(std::unique_ptr); + bool sendMessage(std::unique_ptr, OptionSet sendOptions); + void sendMessageWithReply(uint64_t requestID, std::unique_ptr, FunctionDispatcher& replyDispatcher, Function)>&& replyHandler); + std::unique_ptr createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID); + std::unique_ptr sendSyncMessage(uint64_t syncRequestID, std::unique_ptr, Seconds timeout, OptionSet sendSyncOptions); + bool sendSyncReply(std::unique_ptr); 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 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 waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, Seconds timeout, OptionSet); - std::unique_ptr waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout); - - std::unique_ptr waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags); + std::unique_ptr waitForSyncReply(uint64_t syncRequestID, Seconds timeout, OptionSet); // Called on the connection work queue. - void processIncomingMessage(std::unique_ptr); - void processIncomingSyncReply(std::unique_ptr); + void processIncomingMessage(std::unique_ptr); + void processIncomingSyncReply(std::unique_ptr); - 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); + bool sendOutgoingMessage(std::unique_ptr); void connectionDidClose(); // Called on the listener thread. - void dispatchConnectionDidClose(); void dispatchOneMessage(); - void dispatchMessage(std::unique_ptr); - void dispatchMessage(MessageDecoder&); - void dispatchSyncMessage(MessageDecoder&); + void dispatchMessage(std::unique_ptr); + 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); + void enqueueIncomingMessage(std::unique_ptr); + + void willSendSyncMessage(OptionSet); + void didReceiveSyncReply(OptionSet); - Client* m_client; + Seconds timeoutRespectingIgnoreTimeoutsForTesting(Seconds) const; + +#if PLATFORM(COCOA) + bool sendMessage(std::unique_ptr); +#endif + + Client& m_client; bool m_isServer; + std::atomic m_isValid { true }; std::atomic m_syncRequestID; bool m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage; @@ -223,119 +257,143 @@ private: DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback; bool m_isConnected; - RefPtr m_connectionQueue; - WTF::RunLoop* m_clientRunLoop; + Ref m_connectionQueue; HashMap, RefPtr>> 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> m_incomingMessages; + Lock m_incomingMessagesMutex; + Deque> m_incomingMessages; // Outgoing messages. - Mutex m_outgoingMessagesLock; - Deque> m_outgoingMessages; + Lock m_outgoingMessagesMutex; + Deque> m_outgoingMessages; - std::condition_variable m_waitForMessageCondition; - std::mutex m_waitForMessageMutex; - HashMap, uint64_t>, std::unique_ptr> 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 replyDecoder; + Lock m_replyHandlersLock; + HashMap 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 m_syncMessageState; - Mutex m_syncReplyStateMutex; + Lock m_syncReplyStateMutex; bool m_shouldWaitForSyncReplies; + struct PendingSyncReply; Vector m_pendingSyncReplies; - class SecondaryThreadPendingSyncReply; - typedef HashMap SecondaryThreadPendingSyncReplyMap; - SecondaryThreadPendingSyncReplyMap m_secondaryThreadPendingSyncReplyMap; + Lock m_incomingSyncMessageCallbackMutex; + HashMap> m_incomingSyncMessageCallbacks; + RefPtr 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 m_readBuffer; + Vector m_fileDescriptors; + int m_socketDescriptor; + std::unique_ptr m_pendingOutputMessage; +#if PLATFORM(GTK) + GRefPtr 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 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 m_readBuffer; - size_t m_readBufferSize; - Vector m_fileDescriptors; - size_t m_fileDescriptorsSize; - int m_socketDescriptor; + OSObjectPtr m_xpcConnection; #endif }; -template bool Connection::send(T&& message, uint64_t destinationID, unsigned messageSendFlags) +template +bool Connection::send(T&& message, uint64_t destinationID, OptionSet sendOptions) { COMPILE_ASSERT(!T::isSync, AsyncMessageExpected); - auto encoder = std::make_unique(T::receiverName(), T::name(), destinationID); + auto encoder = std::make_unique(T::receiverName(), T::name(), destinationID); encoder->encode(message.arguments()); - return sendMessage(std::move(encoder), messageSendFlags); + return sendMessage(WTFMove(encoder), sendOptions); +} + +template +void Connection::sendWithReply(T&& message, uint64_t destinationID, FunctionDispatcher& replyDispatcher, Function::Type>)>&& replyHandler) +{ + uint64_t requestID = 0; + std::unique_ptr encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, requestID); + + encoder->encode(message.arguments()); + + sendMessageWithReply(requestID, WTFMove(encoder), replyDispatcher, [replyHandler = WTFMove(replyHandler)](std::unique_ptr decoder) { + if (decoder) { + typename CodingType::Type reply; + if (decoder->decode(reply)) { + replyHandler(WTFMove(reply)); + return; + } + } + + replyHandler(std::nullopt); + }); } -template bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned syncSendFlags) +template bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, Seconds timeout, OptionSet sendSyncOptions) { COMPILE_ASSERT(T::isSync, SyncMessageExpected); uint64_t syncRequestID = 0; - std::unique_ptr encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, syncRequestID); - + std::unique_ptr 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 replyDecoder = sendSyncMessage(syncRequestID, std::move(encoder), timeout, syncSendFlags); + std::unique_ptr replyDecoder = sendSyncMessage(syncRequestID, WTFMove(encoder), timeout, sendSyncOptions); if (!replyDecoder) return false; @@ -343,17 +401,15 @@ template bool Connection::sendSync(T&& message, typename T::Reply&& return replyDecoder->decode(reply); } -template bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout) +template bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, Seconds timeout, OptionSet waitForOptions) { - std::unique_ptr decoder = waitForMessage(T::receiverName(), T::name(), destinationID, timeout); + std::unique_ptr 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(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(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 #include 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 vector() const = delete; + + void encode(Encoder&) const override; + + RefPtr m_buffer; +}; + } // namespace IPC #endif // DataReference_h diff --git a/Source/WebKit2/Platform/IPC/Decoder.cpp b/Source/WebKit2/Platform/IPC/Decoder.cpp new file mode 100644 index 000000000..740a0cced --- /dev/null +++ b/Source/WebKit2/Platform/IPC/Decoder.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Decoder.h" + +#include "DataReference.h" +#include "MessageFlags.h" +#include + +#if PLATFORM(MAC) +#include "ImportanceAssertion.h" +#endif + +namespace IPC { + +static const uint8_t* copyBuffer(const uint8_t* buffer, size_t bufferSize) +{ + auto bufferCopy = static_cast(fastMalloc(bufferSize)); + memcpy(bufferCopy, buffer, bufferSize); + + return bufferCopy; +} + +Decoder::Decoder(const uint8_t* buffer, size_t bufferSize, void (*bufferDeallocator)(const uint8_t*, size_t), Vector attachments) + : m_buffer { bufferDeallocator ? buffer : copyBuffer(buffer, bufferSize) } + , m_bufferPos { m_buffer } + , m_bufferEnd { m_buffer + bufferSize } + , m_bufferDeallocator { bufferDeallocator } + , m_attachments { WTFMove(attachments) } +{ + ASSERT(!(reinterpret_cast(m_buffer) % alignof(uint64_t))); + + if (!decode(m_messageFlags)) + return; + + if (!decode(m_messageReceiverName)) + return; + + if (!decode(m_messageName)) + return; + + if (!decode(m_destinationID)) + return; +} + +Decoder::~Decoder() +{ + ASSERT(m_buffer); + + if (m_bufferDeallocator) + m_bufferDeallocator(m_buffer, m_bufferEnd - m_buffer); + else + fastFree(const_cast(m_buffer)); + + // FIXME: We need to dispose of the mach ports in cases of failure. + +#if HAVE(QOS_CLASSES) + if (m_qosClassOverride) + pthread_override_qos_class_end_np(m_qosClassOverride); +#endif +} + +bool Decoder::isSyncMessage() const +{ + return m_messageFlags & SyncMessage; +} + +bool Decoder::shouldDispatchMessageWhenWaitingForSyncReply() const +{ + return m_messageFlags & DispatchMessageWhenWaitingForSyncReply; +} + +bool Decoder::shouldUseFullySynchronousModeForTesting() const +{ + return m_messageFlags & UseFullySynchronousModeForTesting; +} + +#if PLATFORM(MAC) +void Decoder::setImportanceAssertion(std::unique_ptr assertion) +{ + m_importanceAssertion = WTFMove(assertion); +} +#endif + +std::unique_ptr Decoder::unwrapForTesting(Decoder& decoder) +{ + ASSERT(decoder.isSyncMessage()); + + Vector attachments; + Attachment attachment; + while (decoder.removeAttachment(attachment)) + attachments.append(WTFMove(attachment)); + attachments.reverse(); + + DataReference wrappedMessage; + if (!decoder.decode(wrappedMessage)) + return nullptr; + + return std::make_unique(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((reinterpret_cast(ptr) + alignmentMask) & ~alignmentMask); +} + +static inline bool alignedBufferIsLargeEnoughToContain(const uint8_t* alignedPosition, const uint8_t* bufferEnd, size_t size) +{ + return bufferEnd >= alignedPosition && static_cast(bufferEnd - alignedPosition) >= size; +} + +bool Decoder::alignBufferPosition(unsigned alignment, size_t size) +{ + const uint8_t* alignedPosition = roundUpToAlignment(m_bufferPos, alignment); + if (!alignedBufferIsLargeEnoughToContain(alignedPosition, m_bufferEnd, size)) { + // We've walked off the end of this buffer. + markInvalid(); + return false; + } + + m_bufferPos = alignedPosition; + return true; +} + +bool Decoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const +{ + return alignedBufferIsLargeEnoughToContain(roundUpToAlignment(m_bufferPos, alignment), m_bufferEnd, size); +} + +bool Decoder::decodeFixedLengthData(uint8_t* data, size_t size, unsigned alignment) +{ + if (!alignBufferPosition(alignment, size)) + return false; + + memcpy(data, m_bufferPos, size); + m_bufferPos += size; + + return true; +} + +bool Decoder::decodeVariableLengthByteArray(DataReference& dataReference) +{ + uint64_t size; + if (!decode(size)) + return false; + + if (!alignBufferPosition(1, size)) + return false; + + const uint8_t* data = m_bufferPos; + m_bufferPos += size; + + dataReference = DataReference(data, size); + return true; +} + +template +static void decodeValueFromBuffer(Type& value, const uint8_t*& bufferPosition) +{ + memcpy(&value, bufferPosition, sizeof(value)); + bufferPosition += sizeof(Type); +} + +bool Decoder::decode(bool& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(uint8_t& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(uint16_t& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(uint32_t& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(uint64_t& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(int32_t& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(int64_t& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(float& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::decode(double& result) +{ + if (!alignBufferPosition(sizeof(result), sizeof(result))) + return false; + + decodeValueFromBuffer(result, m_bufferPos); + return true; +} + +bool Decoder::removeAttachment(Attachment& attachment) +{ + if (m_attachments.isEmpty()) + return false; + + attachment = m_attachments.takeLast(); + return true; +} + +} // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/Decoder.h b/Source/WebKit2/Platform/IPC/Decoder.h new file mode 100644 index 000000000..5a30c4258 --- /dev/null +++ b/Source/WebKit2/Platform/IPC/Decoder.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "ArgumentCoder.h" +#include "Attachment.h" +#include "StringReference.h" +#include +#include + +#if HAVE(QOS_CLASSES) +#include +#endif + +namespace IPC { + +class DataReference; +class ImportanceAssertion; + +class Decoder { + WTF_MAKE_FAST_ALLOCATED; +public: + Decoder(const uint8_t* buffer, size_t bufferSize, void (*bufferDeallocator)(const uint8_t*, size_t), Vector); + ~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); +#endif + +#if HAVE(QOS_CLASSES) + void setQOSClassOverride(pthread_override_t override) { m_qosClassOverride = override; } +#endif + + static std::unique_ptr unwrapForTesting(Decoder&); + + size_t length() const { return m_bufferEnd - m_buffer; } + + bool isInvalid() const { return m_bufferPos > m_bufferEnd; } + void markInvalid() { m_bufferPos = m_bufferEnd + 1; } + + bool decodeFixedLengthData(uint8_t*, size_t, unsigned alignment); + + // The data in the data reference here will only be valid for the lifetime of the ArgumentDecoder object. + bool decodeVariableLengthByteArray(DataReference&); + + bool decode(bool&); + bool decode(uint8_t&); + bool decode(uint16_t&); + bool decode(uint32_t&); + bool decode(uint64_t&); + bool decode(int32_t&); + bool decode(int64_t&); + bool decode(float&); + bool decode(double&); + + template + auto decode(E& e) -> std::enable_if_t::value, bool> + { + uint64_t value; + if (!decode(value)) + return false; + if (!isValidEnum(value)) + return false; + + e = static_cast(value); + return true; + } + + template bool decodeEnum(T& result) + { + static_assert(sizeof(T) <= 8, "Enum type T must not be larger than 64 bits!"); + + uint64_t value; + if (!decode(value)) + return false; + + result = static_cast(value); + return true; + } + + template + bool bufferIsLargeEnoughToContain(size_t numElements) const + { + static_assert(std::is_arithmetic::value, "Type T must have a fixed, known encoded size!"); + + if (numElements > std::numeric_limits::max() / sizeof(T)) + return false; + + return bufferIsLargeEnoughToContain(alignof(T), numElements * sizeof(T)); + } + + template + auto decode(T& t) -> std::enable_if_t::value, bool> + { + return ArgumentCoder::decode(*this, t); + } + + bool removeAttachment(Attachment&); + + static const bool isIPCDecoder = true; + +private: + 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 m_attachments; + + uint8_t m_messageFlags; + StringReference m_messageReceiverName; + StringReference m_messageName; + + uint64_t m_destinationID; + +#if PLATFORM(MAC) + std::unique_ptr m_importanceAssertion; +#endif + +#if HAVE(QOS_CLASSES) + pthread_override_t m_qosClassOverride { nullptr }; +#endif +}; + +} // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/Encoder.cpp b/Source/WebKit2/Platform/IPC/Encoder.cpp new file mode 100644 index 000000000..6cd7471d1 --- /dev/null +++ b/Source/WebKit2/Platform/IPC/Encoder.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Encoder.h" + +#include "DataReference.h" +#include "MessageFlags.h" +#include +#include + +#if OS(DARWIN) +#include +#endif + +namespace IPC { + +static const uint8_t defaultMessageFlags = 0; + +template +static inline bool allocBuffer(T*& buffer, size_t size) +{ +#if OS(DARWIN) + buffer = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0)); + return buffer != MAP_FAILED; +#else + buffer = static_cast(fastMalloc(size)); + return !!buffer; +#endif +} + +static inline void freeBuffer(void* addr, size_t size) +{ +#if OS(DARWIN) + munmap(addr, size); +#else + UNUSED_PARAM(size); + fastFree(addr); +#endif +} + +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(); +} + +Encoder::~Encoder() +{ + if (m_buffer != m_inlineBuffer) + freeBuffer(m_buffer, m_bufferCapacity); + // FIXME: We need to dispose of the attachments in cases of failure. +} + +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 original) +{ + ASSERT(isSyncMessage()); + ASSERT(!original->isSyncMessage()); + + original->setShouldDispatchMessageWhenWaitingForSyncReply(true); + + encodeVariableLengthByteArray(DataReference(original->buffer(), original->bufferSize())); + + Vector attachments = original->releaseAttachments(); + reserve(attachments.size()); + for (Attachment& attachment : attachments) + addAttachment(WTFMove(attachment)); +} + +static inline size_t roundUpToAlignment(size_t value, unsigned alignment) +{ + return ((value + alignment - 1) / alignment) * alignment; +} + +void Encoder::reserve(size_t size) +{ + if (size <= m_bufferCapacity) + return; + + size_t newCapacity = roundUpToAlignment(m_bufferCapacity * 2, 4096); + while (newCapacity < size) + newCapacity *= 2; + + uint8_t* newBuffer; + if (!allocBuffer(newBuffer, newCapacity)) + CRASH(); + + memcpy(newBuffer, m_buffer, m_bufferSize); + + 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; + + return m_buffer + alignedSize; +} + +void Encoder::encodeFixedLengthData(const uint8_t* data, size_t size, unsigned alignment) +{ + ASSERT(!(reinterpret_cast(data) % alignment)); + + uint8_t* buffer = grow(alignment, size); + memcpy(buffer, data, size); +} + +void Encoder::encodeVariableLengthByteArray(const DataReference& dataReference) +{ + encode(static_cast(dataReference.size())); + encodeFixedLengthData(dataReference.data(), dataReference.size(), 1); +} + +template +static void copyValueToBuffer(Type value, uint8_t* bufferPosition) +{ + memcpy(bufferPosition, &value, sizeof(Type)); +} + +void Encoder::encode(bool n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(uint8_t n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(uint16_t n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(uint32_t n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(uint64_t n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(int32_t n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(int64_t n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(float n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::encode(double n) +{ + uint8_t* buffer = grow(sizeof(n), sizeof(n)); + copyValueToBuffer(n, buffer); +} + +void Encoder::addAttachment(Attachment&& attachment) +{ + m_attachments.append(WTFMove(attachment)); +} + +Vector Encoder::releaseAttachments() +{ + return WTFMove(m_attachments); +} + +} // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/Encoder.h b/Source/WebKit2/Platform/IPC/Encoder.h new file mode 100644 index 000000000..92f9ba256 --- /dev/null +++ b/Source/WebKit2/Platform/IPC/Encoder.h @@ -0,0 +1,128 @@ +/* + * 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. + */ + +#pragma once + +#include "ArgumentCoder.h" +#include "Attachment.h" +#include "StringReference.h" +#include +#include + +namespace IPC { + +class DataReference; + +class Encoder final { + WTF_MAKE_FAST_ALLOCATED; +public: + 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); + + void encodeFixedLengthData(const uint8_t*, size_t, unsigned alignment); + void encodeVariableLengthByteArray(const DataReference&); + + template void encodeEnum(T t) + { + COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits); + + encode(static_cast(t)); + } + + template + auto encode(T&& t) -> std::enable_if_t>>::value> + { + ArgumentCoder::type>::type>::encode(*this, std::forward(t)); + } + + template Encoder& operator<<(T&& t) + { + encode(std::forward(t)); + return *this; + } + + uint8_t* buffer() const { return m_buffer; } + size_t bufferSize() const { return m_bufferSize; } + + void addAttachment(Attachment&&); + Vector 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); + void encode(uint32_t); + void encode(uint64_t); + void encode(int32_t); + void encode(int64_t); + void encode(float); + void encode(double); + + template + auto encode(E value) -> std::enable_if_t::value> + { + static_assert(sizeof(E) <= sizeof(uint64_t), "Enum type must not be larger than 64 bits."); + + ASSERT(isValidEnum(static_cast(value))); + encode(static_cast(value)); + } + + void encodeHeader(); + + StringReference m_messageReceiverName; + StringReference m_messageName; + uint64_t m_destinationID; + + uint8_t m_inlineBuffer[512]; + + uint8_t* m_buffer; + uint8_t* m_bufferPointer; + + size_t m_bufferSize; + size_t m_bufferCapacity; + + Vector m_attachments; +}; + +} // namespace IPC 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 namespace IPC { +class Connection; + // Dispatch functions with no reply arguments. template void callMemberFunctionImpl(C* object, MF function, ArgsTuple&& args, std::index_sequence) { - (object->*function)(std::get(args)...); + (object->*function)(std::get(std::forward(args))...); } template::value>> @@ -39,27 +63,27 @@ void callMemberFunction(ArgsTuple&& args, ReplyArgsTuple& replyArgs, C* object, // Dispatch functions with delayed reply arguments. template -void callMemberFunctionImpl(C* object, MF function, PassRefPtr delayedReply, ArgsTuple&& args, std::index_sequence) +void callMemberFunctionImpl(C* object, MF function, Ref&& delayedReply, ArgsTuple&& args, std::index_sequence) { - (object->*function)(std::get(args)..., delayedReply); + (object->*function)(std::get(args)..., WTFMove(delayedReply)); } template::value>> -void callMemberFunction(ArgsTuple&& args, PassRefPtr delayedReply, C* object, MF function) +void callMemberFunction(ArgsTuple&& args, Ref&& delayedReply, C* object, MF function) { - callMemberFunctionImpl(object, function, delayedReply, std::forward(args), ArgsIndicies()); + callMemberFunctionImpl(object, function, WTFMove(delayedReply), std::forward(args), ArgsIndicies()); } // Dispatch functions with connection parameter with no reply arguments. template -void callMemberFunctionImpl(C* object, MF function, Connection* connection, ArgsTuple&& args, std::index_sequence) +void callMemberFunctionImpl(C* object, MF function, Connection& connection, ArgsTuple&& args, std::index_sequence) { - (object->*function)(connection, std::get(args)...); + (object->*function)(connection, std::get(std::forward(args))...); } template::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(args), ArgsIndicies()); } @@ -67,121 +91,91 @@ void callMemberFunction(Connection* connection, ArgsTuple&& args, C* object, MF // Dispatch functions with connection parameter with reply arguments. template -void callMemberFunctionImpl(C* object, MF function, Connection* connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence, std::index_sequence) +void callMemberFunctionImpl(C* object, MF function, Connection& connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence, std::index_sequence) { (object->*function)(connection, std::get(std::forward(args))..., std::get(replyArgs)...); } template ::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence::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(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies()); } -// Variadic dispatch functions. - -template -void callMemberFunctionImpl(C* object, MF function, MessageDecoder& decoder, ArgsTuple&& args, std::index_sequence) -{ - (object->*function)(std::get(args)..., decoder); -} - -template::value>> -void callMemberFunction(ArgsTuple&& args, MessageDecoder& decoder, C* object, MF function) -{ - callMemberFunctionImpl(object, function, decoder, std::forward(args), ArgsIndicies()); -} - -// Variadic dispatch functions with non-variadic reply arguments. - -template -void callMemberFunctionImpl(C* object, MF function, MessageDecoder& decoder, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence, std::index_sequence) -{ - (object->*function)(std::get(std::forward(args))..., decoder, std::get(replyArgs)...); -} - -template ::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence::value>> -void callMemberFunction(ArgsTuple&& args, MessageDecoder& decoder, ReplyArgsTuple& replyArgs, C* object, MF function) -{ - callMemberFunctionImpl(object, function, decoder, std::forward(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies()); -} - // Main dispatch functions -template -void handleMessage(MessageDecoder& decoder, C* object, MF function) -{ - typename T::DecodeType arguments; - if (!decoder.decode(arguments)) - return; - callMemberFunction(std::move(arguments), object, function); -} +template +struct CodingType { + typedef std::remove_const_t> Type; +}; + +template +struct CodingType> { + typedef std::tuple::Type...> Type; +}; template -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::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 -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::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::Type replyArguments; + callMemberFunction(WTFMove(arguments), replyArguments, object, function); replyEncoder << replyArguments; } template -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::Type arguments; + if (!decoder.decode(arguments)) { + ASSERT(decoder.isInvalid()); return; - callMemberFunction(connection, std::move(arguments), object, function); -} + } -template -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::Type replyArguments; + callMemberFunction(connection, WTFMove(arguments), replyArguments, object, function); + replyEncoder << replyArguments; } template -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::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 -void handleMessageDelayed(Connection* connection, MessageDecoder& decoder, std::unique_ptr& replyEncoder, C* object, MF function) +void handleMessageDelayed(Connection& connection, Decoder& decoder, std::unique_ptr& replyEncoder, C* object, MF function) { - typename T::DecodeType arguments; - if (!decoder.decode(arguments)) + typename CodingType::Type arguments; + if (!decoder.decode(arguments)) { + ASSERT(decoder.isInvalid()); return; + } - RefPtr delayedReply = adoptRef(new typename T::DelayedReply(connection, std::move(replyEncoder))); - callMemberFunction(std::move(arguments), delayedReply.release(), object, function); + Ref 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.cpp b/Source/WebKit2/Platform/IPC/MessageDecoder.cpp deleted file mode 100644 index 5dfda2194..000000000 --- a/Source/WebKit2/Platform/IPC/MessageDecoder.cpp +++ /dev/null @@ -1,76 +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 "MessageDecoder.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 - -namespace IPC { - -MessageDecoder::~MessageDecoder() -{ -} - -MessageDecoder::MessageDecoder(const DataReference& buffer, Vector attachments) - : ArgumentDecoder(buffer.data(), buffer.size(), attachments) -{ - if (!decode(m_messageFlags)) - return; - - if (!decode(m_messageReceiverName)) - return; - - if (!decode(m_messageName)) - return; - - decode(m_destinationID); -} - -bool MessageDecoder::isSyncMessage() const -{ - return m_messageFlags & SyncMessage; -} - -bool MessageDecoder::shouldDispatchMessageWhenWaitingForSyncReply() const -{ - return m_messageFlags & DispatchMessageWhenWaitingForSyncReply; -} - -#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 -void MessageDecoder::setImportanceAssertion(std::unique_ptr assertion) -{ - m_importanceAssertion = std::move(assertion); -} -#endif - -} // namespace IPC 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); - 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); -#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 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/MessageEncoder.h b/Source/WebKit2/Platform/IPC/MessageEncoder.h deleted file mode 100644 index 524e5e1d4..000000000 --- a/Source/WebKit2/Platform/IPC/MessageEncoder.h +++ /dev/null @@ -1,47 +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 MessageEncoder_h -#define MessageEncoder_h - -#include "ArgumentEncoder.h" -#include - -namespace IPC { - -class StringReference; - -class MessageEncoder : public ArgumentEncoder { -public: - MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID); - virtual ~MessageEncoder(); - - void setIsSyncMessage(bool); - void setShouldDispatchMessageWhenWaitingForSyncReply(bool); -}; - -} // namespace IPC - -#endif // MessageEncoder_h 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 -#include 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&) + virtual void didReceiveMessage(Connection&, Decoder&) = 0; + virtual void didReceiveSyncMessage(Connection&, Decoder&, std::unique_ptr&) { 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 globalReceiversToRemove; + for (auto& nameAndReceiver : m_globalMessageReceivers) { + if (nameAndReceiver.value == &messageReceiver) + globalReceiversToRemove.append(nameAndReceiver.key); + } + + for (auto& globalReceiverToRemove : globalReceiversToRemove) + removeMessageReceiver(globalReceiverToRemove); + + Vector> 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& replyEncoder) +bool MessageReceiverMap::dispatchSyncMessage(Connection& connection, Decoder& decoder, std::unique_ptr& 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&); + bool dispatchMessage(Connection&, Decoder&); + bool dispatchSyncMessage(Connection&, Decoder&, std::unique_ptr&); 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 encoder, unsigned messageSendFlags) +bool MessageSender::sendMessage(std::unique_ptr encoder, OptionSet 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 #include "Connection.h" @@ -37,36 +36,36 @@ public: template bool send(const U& message) { - return send(message, messageSenderDestinationID(), 0); + return send(message, messageSenderDestinationID(), { }); } - template bool send(const U& message, uint64_t destinationID, unsigned messageSendFlags = 0) + template bool send(const U& message, uint64_t destinationID, OptionSet sendOptions = { }) { static_assert(!U::isSync, "Message is sync!"); - auto encoder = std::make_unique(U::receiverName(), U::name(), destinationID); + auto encoder = std::make_unique(U::receiverName(), U::name(), destinationID); encoder->encode(message.arguments()); - return sendMessage(std::move(encoder), messageSendFlags); + return sendMessage(WTFMove(encoder), sendOptions); } template - 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 sendSyncOptions = { }) { static_assert(T::isSync, "Message is not sync!"); - return sendSync(std::forward(message), std::move(reply), messageSenderDestinationID(), timeout, syncSendFlags); + return sendSync(std::forward(message), WTFMove(reply), messageSenderDestinationID(), timeout, sendSyncOptions); } template - 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 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, unsigned messageSendFlags); + virtual bool sendMessage(std::unique_ptr, OptionSet); 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 +#include "Decoder.h" +#include "Encoder.h" +#include #include 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(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/glib/GSocketMonitor.cpp b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp new file mode 100644 index 000000000..14329b938 --- /dev/null +++ b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp @@ -0,0 +1,69 @@ +/* + * 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 + * 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 "GSocketMonitor.h" + +#include + +namespace IPC { + +GSocketMonitor::~GSocketMonitor() +{ + stop(); +} + +gboolean GSocketMonitor::socketSourceCallback(GSocket*, GIOCondition condition, GSocketMonitor* monitor) +{ + if (g_cancellable_is_cancelled(monitor->m_cancellable.get())) + return G_SOURCE_REMOVE; + return monitor->m_callback(condition); +} + +void GSocketMonitor::start(GSocket* socket, GIOCondition condition, RunLoop& runLoop, Function&& callback) +{ + stop(); + + 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(socketSourceCallback), this, nullptr); + g_source_attach(m_source.get(), runLoop.mainContext()); +} + +void GSocketMonitor::stop() +{ + 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; +} + +} // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h new file mode 100644 index 000000000..ff37bf9e5 --- /dev/null +++ b/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h @@ -0,0 +1,59 @@ +/* + * 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 + * 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 GSocketMonitor_h +#define GSocketMonitor_h + +#include +#include +#include +#include +#include +#include + +typedef struct _GSocket GSocket; + +namespace IPC { + +class GSocketMonitor { + WTF_MAKE_NONCOPYABLE(GSocketMonitor); +public: + GSocketMonitor() = default; + ~GSocketMonitor(); + + void start(GSocket*, GIOCondition, RunLoop&, Function&&); + void stop(); + +private: + static gboolean socketSourceCallback(GSocket*, GIOCondition, GSocketMonitor*); + + GRefPtr m_source; + GRefPtr m_cancellable; + Function m_callback; +}; + +} // namespace IPC + +#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 #include #include #include #include #include -#include #include #include #if PLATFORM(GTK) -#include +#include #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 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 attachments(attachmentCount); - AttachmentResourceGuard, Vector::iterator> attachementDisposer(attachments); RefPtr 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(oolMessageBody->data()); - auto decoder = std::make_unique(DataReference(messageBody, messageInfo.bodySize()), std::move(attachments)); + auto decoder = std::make_unique(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& buffer, Vector& 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(message.msg_controllen); - memset(attachmentDescriptorBuffer.get(), 0, message.msg_controllen); + MallocPtr attachmentDescriptorBuffer = MallocPtr::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 protectedThis(this); m_isConnected = true; #if PLATFORM(GTK) - RefPtr protector(this); - m_connectionQueue->registerSocketEventHandler(m_socketDescriptor, - [=] { - protector->readyReadHandler(); - }, - [=] { - protector->connectionDidClose(); - }); -#elif PLATFORM(EFL) - RefPtr 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 encoder) +bool Connection::sendOutgoingMessage(std::unique_ptr encoder) { COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline); - Vector attachments = encoder->releaseAttachments(); - AttachmentResourceGuard, Vector::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 oolMessageBody = WebKit::SharedMemory::create(encoder->bufferSize()); + size_t messageSizeWithBodyInline = sizeof(MessageInfo) + (outputMessage.attachments().size() * sizeof(AttachmentInfo)) + outputMessage.bodySize(); + if (messageSizeWithBodyInline > messageMaxSize && outputMessage.bodySize()) { + RefPtr 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 encoder) iov[0].iov_base = reinterpret_cast(&messageInfo); iov[0].iov_len = sizeof(messageInfo); - auto attachmentInfo = std::make_unique(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(CMSG_SPACE(sizeof(int) * attachmentFDBufferLength)); + std::unique_ptr attachmentInfo; + MallocPtr 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::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 encoder) fdPtr = reinterpret_cast(CMSG_DATA(cmsg)); } + attachmentInfo = std::make_unique(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 encoder) ++iovLength; } - if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) { - iov[iovLength].iov_base = reinterpret_cast(encoder->buffer()); - iov[iovLength].iov_len = encoder->bufferSize(); + if (!messageInfo.isBodyOutOfLine() && outputMessage.bodySize()) { + iov[iovLength].iov_base = reinterpret_cast(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(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 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) +{ +} + +void Connection::didReceiveSyncReply(OptionSet) +{ +} + } // 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 + +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(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& 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 m_attachments; + MessageInfo m_messageInfo; + uint8_t* m_body { nullptr }; + bool m_bodyOwned { false }; +}; + +} // namespace IPC diff --git a/Source/WebKit2/Platform/LogInitialization.h b/Source/WebKit2/Platform/LogInitialization.h new file mode 100644 index 000000000..c55b6cae1 --- /dev/null +++ b/Source/WebKit2/Platform/LogInitialization.h @@ -0,0 +1,39 @@ +/* + * 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 + * 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 + +#if !LOG_DISABLED || !RELEASE_LOG_DISABLED + +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 -#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 +#include #include #include -#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 #include -#if PLATFORM(MAC) +#if USE(CF) #include #endif @@ -37,10 +37,6 @@ typedef struct _GModule GModule; #endif -#if PLATFORM(EFL) -#include -#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 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 m_bundle; #if !defined(__LP64__) CFBundleRefNum m_bundleResourceMap; #endif #elif PLATFORM(GTK) GModule* m_handle; -#elif PLATFORM(EFL) - OwnPtr m_module; #endif }; diff --git a/Source/WebKit2/Platform/PlatformProcessIdentifier.h b/Source/WebKit2/Platform/PlatformProcessIdentifier.h deleted file mode 100644 index 1a630487b..000000000 --- a/Source/WebKit2/Platform/PlatformProcessIdentifier.h +++ /dev/null @@ -1,46 +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 PlatformProcessIdentifier_h -#define PlatformProcessIdentifier_h - -#if PLATFORM(EFL) -#include -#endif - -namespace WebKit { - -#if PLATFORM(MAC) -typedef pid_t PlatformProcessIdentifier; -#elif PLATFORM(GTK) -typedef int PlatformProcessIdentifier; -#elif PLATFORM(EFL) -typedef pid_t PlatformProcessIdentifier; -#endif - -} // namespace WebKit - -#endif // PlatformProcessIdentifier_h 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 #include -#include #include -#if PLATFORM(GTK) || PLATFORM(EFL) +#if USE(UNIX_DOMAIN_SOCKETS) #include "Attachment.h" -#include +#include #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 { 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 create(size_t); - // Create a shared memory object from the given handle and the requested protection. Will return 0 on failure. - static PassRefPtr 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 createFromVMBuffer(void*, size_t); + static RefPtr allocate(size_t); + static RefPtr create(void*, size_t, Protection); + static RefPtr map(const Handle&, Protection); +#if USE(UNIX_DOMAIN_SOCKETS) + static RefPtr 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 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 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.cpp b/Source/WebKit2/Platform/WorkQueue.cpp deleted file mode 100644 index 184825c27..000000000 --- a/Source/WebKit2/Platform/WorkQueue.cpp +++ /dev/null @@ -1,42 +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. - */ - -#include "config.h" -#include "WorkQueue.h" - -PassRefPtr WorkQueue::create(const char* name) -{ - return adoptRef(new WorkQueue(name)); -} - -WorkQueue::WorkQueue(const char* name) -{ - platformInitialize(name); -} - -WorkQueue::~WorkQueue() -{ - platformInvalidate(); -} 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if PLATFORM(GTK) || PLATFORM(EFL) -#include "PlatformProcessIdentifier.h" -#endif - -#if PLATFORM(GTK) -#include -typedef gboolean (*GSourceFunc) (gpointer data); -#elif PLATFORM(EFL) -#include -#endif - -class WorkQueue : public ThreadSafeRefCounted { -public: - static PassRefPtr create(const char* name); - ~WorkQueue(); - - void dispatch(std::function); - void dispatchAfter(std::chrono::nanoseconds, std::function); - -#if OS(DARWIN) - dispatch_queue_t dispatchQueue() const { return m_dispatchQueue; } -#elif PLATFORM(GTK) - void registerSocketEventHandler(int, std::function, std::function); - void unregisterSocketEventHandler(int); -#elif PLATFORM(EFL) - void registerSocketEventHandler(int, std::function); - 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, GSourceFunc); - - ThreadIdentifier m_workQueueThread; - GRefPtr m_eventContext; - Mutex m_eventLoopLock; - GRefPtr m_eventLoop; - Mutex m_eventSourcesLock; - HashMap> m_eventSources; -#elif PLATFORM(EFL) - RefPtr m_dispatchQueue; -#endif -}; - -#endif // WorkQueue_h diff --git a/Source/WebKit2/Platform/glib/ModuleGlib.cpp b/Source/WebKit2/Platform/glib/ModuleGlib.cpp new file mode 100644 index 000000000..ef1ce112a --- /dev/null +++ b/Source/WebKit2/Platform/glib/ModuleGlib.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * Copyright (C) 2011 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. + */ + +#include "config.h" +#include "Module.h" + +#include +#include + +namespace WebKit { + +bool Module::load() +{ + m_handle = g_module_open(m_path.utf8().data(), G_MODULE_BIND_LAZY); + if (!m_handle) + WTFLogAlways("Error loading module '%s': %s", m_path.utf8().data(), g_module_error()); + return m_handle; +} + +void Module::unload() +{ + if (m_handle) + g_module_close(m_handle); +} + +void* Module::platformFunctionPointer(const char* functionName) const +{ + gpointer symbol = 0; + g_module_symbol(m_handle, functionName, &symbol); + return symbol; +} + +} diff --git a/Source/WebKit2/Platform/gtk/LoggingGtk.cpp b/Source/WebKit2/Platform/gtk/LoggingGtk.cpp deleted file mode 100644 index 44e5b118d..000000000 --- a/Source/WebKit2/Platform/gtk/LoggingGtk.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * Copyright (C) 2013 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 "Logging.h" - -#include - -namespace WebKit { - -#if !LOG_DISABLED - -String logLevelString() -{ - return g_getenv("WEBKIT_DEBUG"); -} - -#endif // !LOG_DISABLED - -} diff --git a/Source/WebKit2/Platform/gtk/ModuleGtk.cpp b/Source/WebKit2/Platform/gtk/ModuleGtk.cpp deleted file mode 100644 index ef1ce112a..000000000 --- a/Source/WebKit2/Platform/gtk/ModuleGtk.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. - * Copyright (C) 2011 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. - */ - -#include "config.h" -#include "Module.h" - -#include -#include - -namespace WebKit { - -bool Module::load() -{ - m_handle = g_module_open(m_path.utf8().data(), G_MODULE_BIND_LAZY); - if (!m_handle) - WTFLogAlways("Error loading module '%s': %s", m_path.utf8().data(), g_module_error()); - return m_handle; -} - -void Module::unload() -{ - if (m_handle) - g_module_close(m_handle); -} - -void* Module::platformFunctionPointer(const char* functionName) const -{ - gpointer symbol = 0; - g_module_symbol(m_handle, functionName, &symbol); - return symbol; -} - -} 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 -#include -#include - -// WorkQueue::EventSource -class WorkQueue::EventSource { -public: - EventSource(std::function 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 m_function; - RefPtr m_workQueue; -}; - -class WorkQueue::SocketEventSource : public WorkQueue::EventSource { -public: - SocketEventSource(std::function function, WorkQueue* workQueue, GCancellable* cancellable, std::function 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 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(&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 function, std::function closeFunction) -{ - GRefPtr socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0)); - ASSERT(socket); - GRefPtr cancellable = adoptGRef(g_cancellable_new()); - GRefPtr 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(&WorkQueue::SocketEventSource::eventCallback), - eventSource, reinterpret_cast(&WorkQueue::EventSource::deleteEventSource)); - - // Set up the event sources under the mutex since this is shared across multiple threads. - { - MutexLocker locker(m_eventSourcesLock); - Vector 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 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 function, GSourceFunc sourceCallback) -{ - g_source_set_callback(dispatchSource, sourceCallback, new EventSource(std::move(function), this), - reinterpret_cast(&WorkQueue::EventSource::deleteEventSource)); - - g_source_attach(dispatchSource, m_eventContext.get()); -} - -void WorkQueue::dispatch(std::function function) -{ - GRefPtr dispatchSource = adoptGRef(g_idle_source_new()); - g_source_set_priority(dispatchSource.get(), G_PRIORITY_DEFAULT); - dispatchOnSource(dispatchSource.get(), std::move(function), - reinterpret_cast(&WorkQueue::EventSource::performWorkOnce)); -} - -void WorkQueue::dispatchAfter(std::chrono::nanoseconds duration, std::function function) -{ - GRefPtr dispatchSource = adoptGRef(g_timeout_source_new( - static_cast(std::chrono::duration_cast(duration).count()))); - dispatchOnSource(dispatchSource.get(), std::move(function), - reinterpret_cast(&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 + +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 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/unix/EnvironmentUtilities.h b/Source/WebKit2/Platform/unix/EnvironmentUtilities.h new file mode 100644 index 000000000..fed77bc3f --- /dev/null +++ b/Source/WebKit2/Platform/unix/EnvironmentUtilities.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EnvironmentUtilities_h +#define EnvironmentUtilities_h + +#include + +namespace WebKit { + +namespace EnvironmentUtilities { + +void stripValuesEndingWithString(const char* environmentVariable, const char* search); + +} // namespace EnvironmentUtilities + +} // namespace WebKit + +#endif // #define EnvironmentUtilities_h + diff --git a/Source/WebKit2/Platform/unix/LoggingUnix.cpp b/Source/WebKit2/Platform/unix/LoggingUnix.cpp new file mode 100644 index 000000000..8014a5dcf --- /dev/null +++ b/Source/WebKit2/Platform/unix/LoggingUnix.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * Copyright (C) 2013 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 "Logging.h" + +namespace WebKit { + +#if !LOG_DISABLED || !RELEASE_LOG_DISABLED + +String logLevelString() +{ + return getenv("WEBKIT_DEBUG"); +} + +#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 #include #include @@ -43,61 +43,71 @@ #include #include #include +#include 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::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::create(void* address, size_t size, Protection protection) { CString tempName; @@ -111,7 +121,7 @@ PassRefPtr 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::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::create(size_t size) return instance.release(); } -static inline int accessModeMMap(SharedMemory::Protection protection) +RefPtr 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::create(const Handle& handle, Protection protection) +RefPtr 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 instance = wrapMap(data, handle.m_attachment.size(), -1); + instance->m_fileDescriptor = std::nullopt; + instance->m_isWrappingMap = false; + return instance; +} + +RefPtr SharedMemory::wrapMap(void* data, size_t size, int fileDescriptor) +{ RefPtr 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; } -- cgit v1.2.1