diff options
author | Ben Murdoch <benm@google.com> | 2011-06-02 12:07:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-10 10:47:21 +0100 |
commit | 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch) | |
tree | e4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebKit2/Platform | |
parent | 87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff) | |
download | external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2 |
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebKit2/Platform')
20 files changed, 357 insertions, 343 deletions
diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp b/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp index 44f9a9f..b80a9bf 100644 --- a/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp +++ b/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp @@ -47,7 +47,7 @@ ArgumentDecoder::~ArgumentDecoder() { ASSERT(m_buffer); fastFree(m_buffer); -#if !PLATFORM(QT) +#if !PLATFORM(QT) && !PLATFORM(GTK) // FIXME: We need to dispose of the mach ports in cases of failure. #else Deque<Attachment>::iterator end = m_attachments.end(); diff --git a/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp b/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp index fb0b68b..d20dc10 100644 --- a/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp +++ b/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp @@ -50,7 +50,7 @@ ArgumentEncoder::~ArgumentEncoder() { if (m_buffer) fastFree(m_buffer); -#if !PLATFORM(QT) +#if !PLATFORM(QT) && !PLATFORM(GTK) // FIXME: We need to dispose of the attachments in cases of failure. #else for (int i = 0; i < m_attachments.size(); ++i) diff --git a/Source/WebKit2/Platform/CoreIPC/Attachment.h b/Source/WebKit2/Platform/CoreIPC/Attachment.h index c057714..8060c64 100644 --- a/Source/WebKit2/Platform/CoreIPC/Attachment.h +++ b/Source/WebKit2/Platform/CoreIPC/Attachment.h @@ -39,8 +39,8 @@ public: Uninitialized, #if PLATFORM(MAC) MachPortType, - MachOOLMemoryType -#elif PLATFORM(QT) + MachOOLMemoryType, +#elif USE(UNIX_DOMAIN_SOCKETS) MappedMemory #endif }; @@ -48,7 +48,7 @@ public: #if PLATFORM(MAC) Attachment(mach_port_name_t port, mach_msg_type_name_t disposition); Attachment(void* address, mach_msg_size_t size, mach_msg_copy_options_t copyOptions, bool deallocate); -#elif PLATFORM(QT) +#elif USE(UNIX_DOMAIN_SOCKETS) Attachment(int fileDescriptor, size_t); #endif @@ -66,7 +66,7 @@ public: mach_msg_size_t size() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.size; } mach_msg_copy_options_t copyOptions() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.copyOptions; } bool deallocate() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.deallocate; } -#elif PLATFORM(QT) +#elif USE(UNIX_DOMAIN_SOCKETS) size_t size() const { return m_size; } int releaseFileDescriptor() { int temp = m_fileDescriptor; m_fileDescriptor = -1; return temp; } @@ -94,7 +94,7 @@ private: bool deallocate; } m_oolMemory; }; -#elif PLATFORM(QT) +#elif USE(UNIX_DOMAIN_SOCKETS) int m_fileDescriptor; size_t m_size; #endif diff --git a/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h b/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h index 32b5b02..e75ed75 100644 --- a/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h +++ b/Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h @@ -41,6 +41,10 @@ public: void signal(); bool wait(double absoluteTime); +#if PLATFORM(WIN) + HANDLE event() const { return m_event; } +#endif + private: #if PLATFORM(WIN) HANDLE m_event; diff --git a/Source/WebKit2/Platform/CoreIPC/Connection.cpp b/Source/WebKit2/Platform/CoreIPC/Connection.cpp index a65f065..0821ae8 100644 --- a/Source/WebKit2/Platform/CoreIPC/Connection.cpp +++ b/Source/WebKit2/Platform/CoreIPC/Connection.cpp @@ -29,6 +29,7 @@ #include "BinarySemaphore.h" #include "CoreIPCMessageKinds.h" #include "RunLoop.h" +#include "WebProcess.h" #include "WorkItem.h" #include <wtf/CurrentTime.h> @@ -51,6 +52,13 @@ public: return m_waitForSyncReplySemaphore.wait(absoluteTime); } +#if PLATFORM(WIN) + bool waitWhileDispatchingSentWin32Messages(double absoluteTime, const Vector<HWND>& windowsToReceiveMessages) + { + return RunLoop::dispatchSentMessagesUntil(windowsToReceiveMessages, m_waitForSyncReplySemaphore, absoluteTime); + } +#endif + // 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*, IncomingMessage&); @@ -189,6 +197,7 @@ Connection::Connection(Identifier identifier, bool isServer, Client* client, Run , m_isServer(isServer) , m_syncRequestID(0) , m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(false) + , m_shouldExitOnSyncMessageSendFailure(false) , m_didCloseOnConnectionWorkQueueCallback(0) , m_isConnected(false) , m_connectionQueue("com.apple.CoreIPC.ReceiveQueue") @@ -196,6 +205,7 @@ Connection::Connection(Identifier identifier, bool isServer, Client* client, Run , m_inDispatchMessageCount(0) , m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount(0) , m_didReceiveInvalidMessage(false) + , m_defaultSyncMessageTimeout(NoTimeout) , m_syncMessageState(SyncMessageState::getOrCreate(clientRunLoop)) , m_shouldWaitForSyncReplies(true) { @@ -218,6 +228,13 @@ void Connection::setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcess m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage = flag; } +void Connection::setShouldExitOnSyncMessageSendFailure(bool shouldExitOnSyncMessageSendFailure) +{ + ASSERT(!m_isConnected); + + m_shouldExitOnSyncMessageSendFailure = shouldExitOnSyncMessageSendFailure; +} + void Connection::setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback) { ASSERT(!m_isConnected); @@ -246,6 +263,13 @@ void Connection::markCurrentlyDispatchedMessageAsInvalid() m_didReceiveInvalidMessage = true; } +void Connection::setDefaultSyncMessageTimeout(double defaultSyncMessageTimeout) +{ + ASSERT(defaultSyncMessageTimeout != DefaultTimeout); + + m_defaultSyncMessageTimeout = defaultSyncMessageTimeout; +} + PassOwnPtr<ArgumentEncoder> Connection::createSyncMessageArgumentEncoder(uint64_t destinationID, uint64_t& syncRequestID) { OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID); @@ -342,14 +366,16 @@ PassOwnPtr<ArgumentDecoder> Connection::sendSyncMessage(MessageID messageID, uin // We only allow sending sync messages from the client run loop. ASSERT(RunLoop::current() == m_clientRunLoop); - if (!isValid()) + if (!isValid()) { + didFailToSendSyncMessage(); return 0; - + } + // Push the pending sync reply information on our stack. { MutexLocker locker(m_syncReplyStateMutex); if (!m_shouldWaitForSyncReplies) { - m_client->didFailToSendSyncMessage(this); + didFailToSendSyncMessage(); return 0; } @@ -371,14 +397,21 @@ PassOwnPtr<ArgumentDecoder> Connection::sendSyncMessage(MessageID messageID, uin m_pendingSyncReplies.removeLast(); } - if (!reply && m_client) - m_client->didFailToSendSyncMessage(this); + if (!reply) + didFailToSendSyncMessage(); return reply.release(); } PassOwnPtr<ArgumentDecoder> Connection::waitForSyncReply(uint64_t syncRequestID, double timeout) { + if (timeout == DefaultTimeout) + timeout = m_defaultSyncMessageTimeout; + + // Use a really long timeout. + if (timeout == NoTimeout) + timeout = 1e10; + double absoluteTime = currentTime() + timeout; bool timedOut = false; @@ -401,10 +434,17 @@ PassOwnPtr<ArgumentDecoder> Connection::waitForSyncReply(uint64_t syncRequestID, } // We didn't find a sync reply yet, keep waiting. +#if PLATFORM(WIN) + timedOut = !m_syncMessageState->waitWhileDispatchingSentWin32Messages(absoluteTime, m_client->windowsToReceiveSentMessagesWhileWaitingForSyncReply()); +#else timedOut = !m_syncMessageState->wait(absoluteTime); +#endif } // We timed out. + if (m_client) + m_client->syncMessageSendTimedOut(this); + return 0; } @@ -565,6 +605,14 @@ void Connection::dispatchSyncMessage(MessageID messageID, ArgumentDecoder* argum sendSyncReply(replyEncoder); } +void Connection::didFailToSendSyncMessage() +{ + if (!m_shouldExitOnSyncMessageSendFailure) + return; + + exit(0); +} + void Connection::enqueueIncomingMessage(IncomingMessage& incomingMessage) { MutexLocker locker(m_incomingMessagesLock); diff --git a/Source/WebKit2/Platform/CoreIPC/Connection.h b/Source/WebKit2/Platform/CoreIPC/Connection.h index b6a2415..8754034 100644 --- a/Source/WebKit2/Platform/CoreIPC/Connection.h +++ b/Source/WebKit2/Platform/CoreIPC/Connection.h @@ -44,6 +44,9 @@ #include <string> #elif PLATFORM(QT) class QSocketNotifier; +#endif + +#if PLATFORM(QT) || PLATFORM(GTK) #include "PlatformProcessIdentifier.h" #endif @@ -90,7 +93,11 @@ public: public: virtual void didClose(Connection*) = 0; virtual void didReceiveInvalidMessage(Connection*, MessageID) = 0; - virtual void didFailToSendSyncMessage(Connection*) { } + virtual void syncMessageSendTimedOut(Connection*) = 0; + +#if PLATFORM(WIN) + virtual Vector<HWND> windowsToReceiveSentMessagesWhileWaitingForSyncReply() = 0; +#endif }; #if PLATFORM(MAC) @@ -98,9 +105,7 @@ public: #elif PLATFORM(WIN) typedef HANDLE Identifier; static bool createServerAndClientIdentifiers(Identifier& serverIdentifier, Identifier& clientIdentifier); -#elif PLATFORM(QT) - typedef int Identifier; -#elif PLATFORM(GTK) +#elif USE(UNIX_DOMAIN_SOCKETS) typedef int Identifier; #endif @@ -110,11 +115,12 @@ public: #if PLATFORM(MAC) void setShouldCloseConnectionOnMachExceptions(); -#elif PLATFORM(QT) +#elif PLATFORM(QT) || PLATFORM(GTK) void setShouldCloseConnectionOnProcessTermination(WebKit::PlatformProcessIdentifier); #endif void setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(bool); + void setShouldExitOnSyncMessageSendFailure(bool shouldExitOnSyncMessageSendFailure); // The set callback will be called on the connection work queue when the connection is closed, // before didCall is called on the client thread. Must be called before the connection is opened. @@ -128,10 +134,13 @@ public: void invalidate(); void markCurrentlyDispatchedMessageAsInvalid(); - static const unsigned long long NoTimeout = 10000000000ULL; + void setDefaultSyncMessageTimeout(double); + + static const int DefaultTimeout = 0; + static const int NoTimeout = -1; template<typename T> bool send(const T& message, uint64_t destinationID, unsigned messageSendFlags = 0); - template<typename T> bool sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout = NoTimeout); + template<typename T> bool sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout = DefaultTimeout); template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, double timeout); PassOwnPtr<ArgumentEncoder> createSyncMessageArgumentEncoder(uint64_t destinationID, uint64_t& syncRequestID); @@ -208,6 +217,7 @@ private: void dispatchMessage(IncomingMessage&); void dispatchMessages(); void dispatchSyncMessage(MessageID, ArgumentDecoder*); + void didFailToSendSyncMessage(); // Can be called on any thread. void enqueueIncomingMessage(IncomingMessage&); @@ -217,6 +227,7 @@ private: uint64_t m_syncRequestID; bool m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage; + bool m_shouldExitOnSyncMessageSendFailure; DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback; bool m_isConnected; @@ -227,6 +238,8 @@ private: unsigned m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; bool m_didReceiveInvalidMessage; + double m_defaultSyncMessageTimeout; + // Incoming messages. Mutex m_incomingMessagesLock; Vector<IncomingMessage> m_incomingMessages; @@ -305,23 +318,17 @@ private: OwnPtr<ArgumentEncoder> m_pendingWriteArguments; OVERLAPPED m_writeState; HANDLE m_connectionPipe; -#elif PLATFORM(QT) +#elif USE(UNIX_DOMAIN_SOCKETS) // Called on the connection queue. void readyReadHandler(); Vector<uint8_t> m_readBuffer; size_t m_currentMessageSize; - QSocketNotifier* m_socketNotifier; int m_socketDescriptor; -#elif PLATFORM(GTK) - void readEventHandler(); - void processCompletedMessage(); - bool messageProcessingCompleted() { return !m_currentMessageSize; } - int m_socket; - Vector<uint8_t> m_readBuffer; - size_t m_currentMessageSize; - size_t m_pendingBytes; +#if PLATFORM(QT) + QSocketNotifier* m_socketNotifier; +#endif #endif }; diff --git a/Source/WebKit2/Platform/CoreIPC/HandleMessage.h b/Source/WebKit2/Platform/CoreIPC/HandleMessage.h index a99c76e..112503d 100644 --- a/Source/WebKit2/Platform/CoreIPC/HandleMessage.h +++ b/Source/WebKit2/Platform/CoreIPC/HandleMessage.h @@ -141,6 +141,12 @@ void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, Arguments1<R1>& (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, replyArgs.argument1); } +template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename R1> +void callMemberFunction(const Arguments6<P1, P2, P3, P4, P5, P6>& args, Arguments1<R1>& replyArgs, C* object, MF function) +{ + (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, args.argument5, args.argument6, replyArgs.argument1); +} + template<typename C, typename MF, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename R1> void callMemberFunction(const Arguments7<P1, P2, P3, P4, P5, P6, P7>& args, Arguments1<R1>& replyArgs, C* object, MF function) { @@ -171,6 +177,13 @@ void callMemberFunction(const Arguments4<P1, P2, P3, P4>& args, Arguments3<R1, R (object->*function)(args.argument1, args.argument2, args.argument3, args.argument4, replyArgs.argument1, replyArgs.argument2, replyArgs.argument3); } +// Dispatch functions with delayed reply arguments. +template<typename C, typename MF, typename P1, typename R> +void callMemberFunction(const Arguments1<P1>& args, PassRefPtr<R> delayedReply, C* object, MF function) +{ + (object->*function)(args.argument1, delayedReply); +} + // Variadic dispatch functions. template<typename C, typename MF> @@ -286,6 +299,17 @@ void handleMessageVariadic(ArgumentDecoder* argumentDecoder, ArgumentEncoder* re replyEncoder->encode(replyArguments); } +template<typename T, typename C, typename MF> +void handleMessageDelayed(Connection* connection, ArgumentDecoder* argumentDecoder, ArgumentEncoder* replyEncoder, C* object, MF function) +{ + typename T::DecodeType::ValueType arguments; + if (!argumentDecoder->decode(arguments)) + return; + + RefPtr<typename T::DelayedReply> delayedReply = adoptRef(new typename T::DelayedReply(connection, replyEncoder)); + callMemberFunction(arguments, delayedReply.release(), object, function); +} + } // namespace CoreIPC #endif // HandleMessage_h diff --git a/Source/WebKit2/Platform/CoreIPC/MessageID.h b/Source/WebKit2/Platform/CoreIPC/MessageID.h index 2afb168..0b52806 100644 --- a/Source/WebKit2/Platform/CoreIPC/MessageID.h +++ b/Source/WebKit2/Platform/CoreIPC/MessageID.h @@ -69,7 +69,6 @@ enum MessageClass { MessageClassWebMediaCacheManagerProxy, MessageClassWebPageProxy, MessageClassWebProcessProxy, - MessageClassWebProcessProxyLegacy, MessageClassWebResourceCacheManagerProxy, // Messages sent by the UI process to the plug-in process. diff --git a/Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp b/Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp deleted file mode 100644 index 4b140ee..0000000 --- a/Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp +++ /dev/null @@ -1,207 +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. - */ - -#include "config.h" -#include "Connection.h" - -#include "ArgumentEncoder.h" -#include "WorkItem.h" -#include <errno.h> -#include <glib.h> -#include <sys/fcntl.h> - -using namespace std; - -namespace CoreIPC { - -static const size_t initialMessageBufferSize = 4096; - -static int readBytesFromSocket(int fileDescriptor, uint8_t* ptr, size_t length) -{ - ASSERT(fileDescriptor > 0); - ASSERT(ptr); - ASSERT(length > 0); - - ssize_t numberOfBytesRead = 0; - size_t pendingBytesToRead = length; - uint8_t* buffer = ptr; - - while (pendingBytesToRead > 0) { - if ((numberOfBytesRead = read(fileDescriptor, buffer, pendingBytesToRead)) < 0) { - if (errno == EINTR) - numberOfBytesRead = 0; - else if (errno == EAGAIN || errno == EWOULDBLOCK) - break; - else - return 0; - } else if (!numberOfBytesRead) - break; - - buffer += numberOfBytesRead; - pendingBytesToRead -= numberOfBytesRead; - } - - return (length - pendingBytesToRead); -} - -static bool writeBytesToSocket(int fileDescriptor, uint8_t* ptr, size_t length) -{ - ASSERT(fileDescriptor > 0); - ASSERT(ptr); - ASSERT(length > 0); - - ssize_t numberOfBytesWritten = 0; - size_t pendingBytesToWrite = length; - uint8_t* buffer = ptr; - - // Keep writing to the socket till the complete message has been written. - while (pendingBytesToWrite > 0) { - if ((numberOfBytesWritten = write(fileDescriptor, buffer, pendingBytesToWrite)) < 0) { - if (errno == EINTR) - numberOfBytesWritten = 0; - else - return false; - } - buffer += numberOfBytesWritten; - pendingBytesToWrite -= numberOfBytesWritten; - } - - // Write operation failed if complete message is not written. - return !pendingBytesToWrite; -} - -void Connection::platformInitialize(Identifier identifier) -{ - m_currentMessageSize = 0; - m_pendingBytes = 0; - m_readBuffer.resize(initialMessageBufferSize); - m_socket = identifier; -} - -void Connection::platformInvalidate() -{ - if (!m_isConnected) - return; - - m_connectionQueue.unregisterEventSourceHandler(m_socket); - if (m_socket > 0) { - close(m_socket); - m_socket = -1; - } - - m_isConnected = false; -} - -void Connection::processCompletedMessage() -{ - size_t realBufferSize = m_currentMessageSize - sizeof(MessageID); - unsigned messageID = *reinterpret_cast<unsigned*>(m_readBuffer.data() + realBufferSize); - - processIncomingMessage(MessageID::fromInt(messageID), adoptPtr(new ArgumentDecoder(m_readBuffer.data(), realBufferSize))); - - // Prepare for the next message. - m_currentMessageSize = 0; - m_pendingBytes = 0; -} - -void Connection::readEventHandler() -{ - if (m_socket < 0) - return; - - // Handle any previously unprocessed message. - if (!messageProcessingCompleted()) { - if ((m_pendingBytes -= readBytesFromSocket(m_socket, (m_readBuffer.data() + (m_currentMessageSize - m_pendingBytes)), m_pendingBytes)) > 0) - return; - - // Message received completely. Process the message now. - processCompletedMessage(); - } - - // Prepare to read the next message. - uint8_t sizeBuffer[sizeof(size_t)]; - memset(sizeBuffer, 0, sizeof(size_t)); - - while (messageProcessingCompleted()) { - if (readBytesFromSocket(m_socket, sizeBuffer, sizeof(size_t))) - m_currentMessageSize = *reinterpret_cast<size_t*>(sizeBuffer); - - if (!m_currentMessageSize) - break; - - if (m_readBuffer.size() < m_currentMessageSize) - m_readBuffer.grow(m_currentMessageSize); - - m_pendingBytes = m_currentMessageSize - readBytesFromSocket(m_socket, m_readBuffer.data(), m_currentMessageSize); - if (m_pendingBytes > 0) // Message partially received. - break; - - // Message received completely. Process the message now. - processCompletedMessage(); - - memset(sizeBuffer, 0, sizeof(size_t)); - } -} - -bool Connection::open() -{ - int flags = fcntl(m_socket, F_GETFL, 0); - fcntl(m_socket, F_SETFL, flags | O_NONBLOCK); - - m_isConnected = true; - - // Register callbacks for connection termination and input data on the WorkQueue. - m_connectionQueue.registerEventSourceHandler(m_socket, (G_IO_HUP | G_IO_ERR), WorkItem::create(this, &Connection::connectionDidClose)); - m_connectionQueue.registerEventSourceHandler(m_socket, G_IO_IN, WorkItem::create(this, &Connection::readEventHandler)); - return true; -} - -bool Connection::platformCanSendOutgoingMessages() const -{ - return (m_socket > 0); -} - -bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments) -{ - if (m_socket < 0) - return false; - - // We put the message ID last. - arguments->encodeUInt32(messageID.toInt()); - - size_t bufferSize = arguments->bufferSize(); - - // Send the message size first. - if (!writeBytesToSocket(m_socket, reinterpret_cast<uint8_t*>(&bufferSize), sizeof(size_t))) - return false; - - if (!writeBytesToSocket(m_socket, arguments->buffer(), arguments->bufferSize())) - return false; - - return true; -} - -} // namespace CoreIPC diff --git a/Source/WebKit2/Platform/CoreIPC/qt/AttachmentQt.cpp b/Source/WebKit2/Platform/CoreIPC/unix/AttachmentUnix.cpp index 4c0ebc0..2d842da 100644 --- a/Source/WebKit2/Platform/CoreIPC/qt/AttachmentQt.cpp +++ b/Source/WebKit2/Platform/CoreIPC/unix/AttachmentUnix.cpp @@ -27,11 +27,8 @@ #include "config.h" #include "Attachment.h" -#if PLATFORM(QT) #include <unistd.h> #include <errno.h> -#endif - namespace CoreIPC { diff --git a/Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp b/Source/WebKit2/Platform/CoreIPC/unix/ConnectionUnix.cpp index 225d7dc..92ffff3 100644 --- a/Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp +++ b/Source/WebKit2/Platform/CoreIPC/unix/ConnectionUnix.cpp @@ -32,14 +32,19 @@ #include "WorkItem.h" #include "SharedMemory.h" #include "WebProcessProxy.h" -#include <QApplication> -#include <QSocketNotifier> #include <sys/socket.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <wtf/Assertions.h> +#if PLATFORM(QT) +#include <QApplication> +#include <QSocketNotifier> +#elif PLATFORM(GTK) +#include <glib.h> +#endif + using namespace std; namespace CoreIPC { @@ -48,7 +53,7 @@ static const size_t messageMaxSize = 4096; static const size_t attachmentMaxAmount = 255; enum { - MessageBodyIsOOL = 1 << 31 + MessageBodyIsOOL = 1U << 31 }; class MessageInfo { @@ -88,9 +93,12 @@ private: void Connection::platformInitialize(Identifier identifier) { m_socketDescriptor = identifier; - m_socketNotifier = 0; m_readBuffer.resize(messageMaxSize); m_currentMessageSize = 0; + +#if PLATFORM(QT) + m_socketNotifier = 0; +#endif } void Connection::platformInvalidate() @@ -101,12 +109,20 @@ void Connection::platformInvalidate() if (!m_isConnected) return; +#if PLATFORM(GTK) + m_connectionQueue.unregisterEventSourceHandler(m_socketDescriptor); +#endif + +#if PLATFORM(QT) delete m_socketNotifier; m_socketNotifier = 0; +#endif + m_socketDescriptor = -1; m_isConnected = false; } +#if PLATFORM(QT) class SocketNotifierResourceGuard { public: SocketNotifierResourceGuard(QSocketNotifier* socketNotifier) @@ -123,6 +139,7 @@ public: private: QSocketNotifier* const m_socketNotifier; }; +#endif template<class T, class iterator> class AttachmentResourceGuard { @@ -144,17 +161,19 @@ private: void Connection::readyReadHandler() { Deque<Attachment> attachments; +#if PLATFORM(QT) SocketNotifierResourceGuard socketNotifierEnabler(m_socketNotifier); +#endif AttachmentResourceGuard<Deque<Attachment>, Deque<Attachment>::iterator> attachementDisposer(attachments); - char attachmentDescriptorBuffer[CMSG_SPACE(sizeof(int) * (attachmentMaxAmount))]; + OwnArrayPtr<char> attachmentDescriptorBuffer = adoptArrayPtr(new char[CMSG_SPACE(sizeof(int) * (attachmentMaxAmount))]); struct msghdr message; memset(&message, 0, sizeof(message)); struct iovec iov[1]; memset(&iov, 0, sizeof(iov)); - message.msg_control = attachmentDescriptorBuffer; + message.msg_control = attachmentDescriptorBuffer.get(); message.msg_controllen = CMSG_SPACE(sizeof(int) * (attachmentMaxAmount)); iov[0].iov_base = m_readBuffer.data(); @@ -184,13 +203,13 @@ void Connection::readyReadHandler() if (messageInfo.attachmentCount()) { if (controlMessage && controlMessage->cmsg_level == SOL_SOCKET && controlMessage->cmsg_type == SCM_RIGHTS) { - size_t attachmentSizes[messageInfo.attachmentCount()]; - memcpy(attachmentSizes, messageData, sizeof(attachmentSizes)); + OwnArrayPtr<size_t> attachmentSizes = adoptArrayPtr(new size_t[messageInfo.attachmentCount()]); + memcpy(attachmentSizes.get(), messageData, sizeof(size_t) * messageInfo.attachmentCount()); messageData += sizeof(attachmentSizes); - int fileDescriptors[messageInfo.attachmentCount()]; - memcpy(fileDescriptors, CMSG_DATA(controlMessage), sizeof(fileDescriptors)); + OwnArrayPtr<int> fileDescriptors = adoptArrayPtr(new int[messageInfo.attachmentCount()]); + memcpy(fileDescriptors.get(), CMSG_DATA(controlMessage), sizeof(int) * messageInfo.attachmentCount()); int attachmentCount = messageInfo.attachmentCount(); @@ -253,7 +272,10 @@ void Connection::readyReadHandler() bool Connection::open() { +#if PLATFORM(QT) ASSERT(!m_socketNotifier); +#endif + int flags = fcntl(m_socketDescriptor, F_GETFL, 0); while (fcntl(m_socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { if (errno != EINTR) { @@ -263,7 +285,12 @@ bool Connection::open() } m_isConnected = true; +#if PLATFORM(QT) m_socketNotifier = m_connectionQueue.registerSocketEventHandler(m_socketDescriptor, QSocketNotifier::Read, WorkItem::create(this, &Connection::readyReadHandler)); +#elif PLATFORM(GTK) + m_connectionQueue.registerEventSourceHandler(m_socketDescriptor, (G_IO_HUP | G_IO_ERR), WorkItem::create(this, &Connection::connectionDidClose)); + m_connectionQueue.registerEventSourceHandler(m_socketDescriptor, G_IO_IN, WorkItem::create(this, &Connection::readyReadHandler)); +#endif // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal // handler. @@ -274,12 +301,15 @@ bool Connection::open() bool Connection::platformCanSendOutgoingMessages() const { - return m_socketNotifier; + return m_isConnected; } bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments) { +#if PLATFORM(QT) ASSERT(m_socketNotifier); +#endif + COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline); Vector<Attachment> attachments = arguments->releaseAttachments(); @@ -320,12 +350,12 @@ bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEnc iov[0].iov_base = reinterpret_cast<void*>(&messageInfo); iov[0].iov_len = sizeof(messageInfo); - char attachmentFDBuffer[CMSG_SPACE(sizeof(int) * (attachments.size()))]; - size_t attachmentSizes[attachments.size()]; + OwnArrayPtr<char> attachmentFDBuffer = adoptArrayPtr(new char[CMSG_SPACE(sizeof(int) * attachments.size())]); + OwnArrayPtr<size_t> attachmentSizes = adoptArrayPtr(new size_t[attachments.size()]); if (!attachments.isEmpty()) { - message.msg_control = attachmentFDBuffer; - message.msg_controllen = sizeof(attachmentFDBuffer); + message.msg_control = attachmentFDBuffer.get(); + message.msg_controllen = sizeof(char) * CMSG_SPACE(sizeof(int) * attachments.size()); struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message); cmsg->cmsg_level = SOL_SOCKET; @@ -333,15 +363,15 @@ bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEnc cmsg->cmsg_len = CMSG_LEN(sizeof(int) * attachments.size()); int* fdptr = reinterpret_cast<int*>(CMSG_DATA(cmsg)); - for (int i = 0; i < attachments.size(); ++i) { + for (size_t i = 0; i < attachments.size(); ++i) { attachmentSizes[i] = attachments[i].size(); fdptr[i] = attachments[i].fileDescriptor(); } message.msg_controllen = cmsg->cmsg_len; - iov[iovLength].iov_base = attachmentSizes; - iov[iovLength].iov_len = sizeof(attachmentSizes); + iov[iovLength].iov_base = attachmentSizes.get(); + iov[iovLength].iov_len = sizeof(size_t) * attachments.size(); ++iovLength; } @@ -361,9 +391,11 @@ bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEnc return true; } +#if PLATFORM(QT) || PLATFORM(GTK) void Connection::setShouldCloseConnectionOnProcessTermination(WebKit::PlatformProcessIdentifier process) { m_connectionQueue.scheduleWorkOnTermination(process, WorkItem::create(this, &Connection::connectionDidClose)); } +#endif } // namespace CoreIPC diff --git a/Source/WebKit2/Platform/PlatformProcessIdentifier.h b/Source/WebKit2/Platform/PlatformProcessIdentifier.h index 0363692..5022da7 100644 --- a/Source/WebKit2/Platform/PlatformProcessIdentifier.h +++ b/Source/WebKit2/Platform/PlatformProcessIdentifier.h @@ -40,7 +40,12 @@ typedef HANDLE PlatformProcessIdentifier; #elif PLATFORM(QT) typedef QProcess* PlatformProcessIdentifier; #elif PLATFORM(GTK) -typedef pid_t PlatformProcessIdentifier; +#ifdef G_OS_WIN32 +typedef void* GPid; +#else +typedef int GPid; +#endif +typedef GPid PlatformProcessIdentifier; #endif } // namespace WebKit diff --git a/Source/WebKit2/Platform/RunLoop.h b/Source/WebKit2/Platform/RunLoop.h index aa87506..b2f1411 100644 --- a/Source/WebKit2/Platform/RunLoop.h +++ b/Source/WebKit2/Platform/RunLoop.h @@ -34,6 +34,7 @@ #include <wtf/Threading.h> #include <wtf/Vector.h> #if PLATFORM(GTK) +#include <wtf/gobject/GRefPtr.h> typedef struct _GSource GSource; typedef struct _GMainLoop GMainLoop; typedef struct _GMainContext GMainContext; @@ -42,6 +43,10 @@ typedef int gboolean; class WorkItem; +namespace CoreIPC { + class BinarySemaphore; +} + class RunLoop { public: // Must be called from the main thread. @@ -52,6 +57,14 @@ public: void scheduleWork(PassOwnPtr<WorkItem>); +#if PLATFORM(WIN) + // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the + // same time zone as WTF::currentTime(). Dispatches sent (not posted) messages to the passed-in + // set of HWNDs until the semaphore is signaled or absoluteTime is reached. Returns true if the + // semaphore is signaled, false otherwise. + static bool dispatchSentMessagesUntil(const Vector<HWND>& windows, CoreIPC::BinarySemaphore&, double absoluteTime); +#endif + static void run(); void stop(); @@ -86,10 +99,12 @@ public: int m_ID; bool m_isRepeating; #elif PLATFORM(GTK) - static gboolean oneShotTimerFired(RunLoop::TimerBase*); - static gboolean repeatingTimerFired(RunLoop::TimerBase*); - void resetTimerSource(); - GSource* m_timerSource; + static gboolean timerFiredCallback(RunLoop::TimerBase*); + static void destroyNotifyCallback(RunLoop::TimerBase*); + gboolean isRepeating() const { return m_isRepeating; } + void clearTimerSource(); + GRefPtr<GSource> m_timerSource; + gboolean m_isRepeating; #endif }; diff --git a/Source/WebKit2/Platform/SharedMemory.h b/Source/WebKit2/Platform/SharedMemory.h index a4b95bf..b242b9b 100644 --- a/Source/WebKit2/Platform/SharedMemory.h +++ b/Source/WebKit2/Platform/SharedMemory.h @@ -30,7 +30,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#if PLATFORM(QT) +#if PLATFORM(QT) || PLATFORM(GTK) #include "Attachment.h" #include <wtf/text/WTFString.h> #endif @@ -60,7 +60,7 @@ public: void encode(CoreIPC::ArgumentEncoder*) const; static bool decode(CoreIPC::ArgumentDecoder*, Handle&); -#if PLATFORM(QT) +#if USE(UNIX_DOMAIN_SOCKETS) CoreIPC::Attachment releaseToAttachment() const; void adoptFromAttachment(int fileDescriptor, size_t); #endif @@ -70,7 +70,7 @@ public: mutable mach_port_t m_port; #elif PLATFORM(WIN) mutable HANDLE m_handle; -#elif PLATFORM(QT) +#elif USE(UNIX_DOMAIN_SOCKETS) mutable int m_fileDescriptor; #endif size_t m_size; @@ -82,6 +82,10 @@ public: // Create a shared memory object from the given handle and the requested protection. Will return 0 on failure. static PassRefPtr<SharedMemory> create(const Handle&, Protection); +#if PLATFORM(WIN) + static PassRefPtr<SharedMemory> adopt(HANDLE, size_t, Protection); +#endif + ~SharedMemory(); bool createHandle(Handle&, Protection); @@ -99,7 +103,7 @@ private: mach_port_t m_port; #elif PLATFORM(WIN) HANDLE m_handle; -#elif PLATFORM(QT) +#elif USE(UNIX_DOMAIN_SOCKETS) int m_fileDescriptor; #endif }; diff --git a/Source/WebKit2/Platform/WorkQueue.h b/Source/WebKit2/Platform/WorkQueue.h index 99f77ae..74d6055 100644 --- a/Source/WebKit2/Platform/WorkQueue.h +++ b/Source/WebKit2/Platform/WorkQueue.h @@ -46,8 +46,10 @@ class QObject; class QThread; #elif PLATFORM(GTK) +#include "PlatformProcessIdentifier.h" typedef struct _GMainContext GMainContext; typedef struct _GMainLoop GMainLoop; +typedef gboolean (*GSourceFunc) (gpointer data); #endif class WorkQueue { @@ -87,6 +89,7 @@ public: #elif PLATFORM(GTK) void registerEventSourceHandler(int, int, PassOwnPtr<WorkItem>); void unregisterEventSourceHandler(int); + void scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier, PassOwnPtr<WorkItem>); #endif private: @@ -165,6 +168,7 @@ private: #elif PLATFORM(GTK) static void* startWorkQueueThread(WorkQueue*); void workQueueThreadBody(); + void scheduleWorkOnSource(GSource*, PassOwnPtr<WorkItem>, GSourceFunc); ThreadIdentifier m_workQueueThread; GMainContext* m_eventContext; diff --git a/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp b/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp index 70b0552..0f4ab68 100644 --- a/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp +++ b/Source/WebKit2/Platform/gtk/RunLoopGtk.cpp @@ -41,7 +41,8 @@ RunLoop::RunLoop() RunLoop::~RunLoop() { if (m_runLoopMain) { - g_main_loop_quit(m_runLoopMain); + if (g_main_loop_is_running(m_runLoopMain)) + g_main_loop_quit(m_runLoopMain); g_main_loop_unref(m_runLoopMain); } @@ -72,9 +73,10 @@ gboolean RunLoop::queueWork(RunLoop* runLoop) void RunLoop::wakeUp() { - GSource* source = g_timeout_source_new(0); - g_source_set_callback(source, reinterpret_cast<GSourceFunc>(&RunLoop::queueWork), this, 0); - g_source_attach(source, m_runLoopContext); + GRefPtr<GSource> source = adoptGRef(g_idle_source_new()); + g_source_set_priority(source.get(), G_PRIORITY_DEFAULT); + g_source_set_callback(source.get(), reinterpret_cast<GSourceFunc>(&RunLoop::queueWork), this, 0); + g_source_attach(source.get(), m_runLoopContext); g_main_context_wakeup(m_runLoopContext); } @@ -90,22 +92,20 @@ RunLoop::TimerBase::~TimerBase() stop(); } -void RunLoop::TimerBase::resetTimerSource() +void RunLoop::TimerBase::clearTimerSource() { m_timerSource = 0; } -gboolean RunLoop::TimerBase::oneShotTimerFired(RunLoop::TimerBase* timer) +void RunLoop::TimerBase::destroyNotifyCallback(RunLoop::TimerBase* timer) { - timer->fired(); - timer->resetTimerSource(); - return FALSE; + timer->clearTimerSource(); } -gboolean RunLoop::TimerBase::repeatingTimerFired(RunLoop::TimerBase* timer) +gboolean RunLoop::TimerBase::timerFiredCallback(RunLoop::TimerBase* timer) { timer->fired(); - return TRUE; + return timer->isRepeating(); } void RunLoop::TimerBase::start(double fireInterval, bool repeat) @@ -113,12 +113,11 @@ void RunLoop::TimerBase::start(double fireInterval, bool repeat) if (m_timerSource) stop(); - m_timerSource = g_timeout_source_new(static_cast<guint>(fireInterval)); - if (repeat) - g_source_set_callback(m_timerSource, reinterpret_cast<GSourceFunc>(&RunLoop::TimerBase::repeatingTimerFired), this, 0); - else - g_source_set_callback(m_timerSource, reinterpret_cast<GSourceFunc>(&RunLoop::TimerBase::oneShotTimerFired), this, 0); - g_source_attach(m_timerSource, m_runLoop->m_runLoopContext); + m_timerSource = adoptGRef(g_timeout_source_new(static_cast<guint>(fireInterval * 1000))); + m_isRepeating = repeat; + g_source_set_callback(m_timerSource.get(), reinterpret_cast<GSourceFunc>(&RunLoop::TimerBase::timerFiredCallback), this, + reinterpret_cast<GDestroyNotify>(&RunLoop::TimerBase::destroyNotifyCallback)); + g_source_attach(m_timerSource.get(), m_runLoop->m_runLoopContext); } void RunLoop::TimerBase::stop() @@ -126,8 +125,8 @@ void RunLoop::TimerBase::stop() if (!m_timerSource) return; - g_source_destroy(m_timerSource); - m_timerSource = 0; + g_source_destroy(m_timerSource.get()); + clearTimerSource(); } bool RunLoop::TimerBase::isActive() const diff --git a/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp b/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp index dbe38bd..0cdb92f 100644 --- a/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp +++ b/Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2011 Igalia S.L. * Copyright (C) 2010 Apple Inc. All rights reserved. * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. * @@ -29,56 +30,63 @@ #include "WKBase.h" #include <WebCore/NotImplemented.h> +#include <gio/gio.h> #include <glib.h> +#include <wtf/gobject/GRefPtr.h> // WorkQueue::EventSource class WorkQueue::EventSource { public: - EventSource(GSource* dispatchSource, PassOwnPtr<WorkItem> workItem, WorkQueue* workQueue) - : m_dispatchSource(dispatchSource) - , m_workItem(workItem) + EventSource(PassOwnPtr<WorkItem> workItem, WorkQueue* workQueue, GCancellable* cancellable) + : m_workItem(workItem) , m_workQueue(workQueue) + , m_cancellable(cancellable) { } - GSource* dispatchSource() { return m_dispatchSource; } + void cancel() + { + if (!m_cancellable) + return; + g_cancellable_cancel(m_cancellable); + } - static gboolean performWorkOnce(EventSource* eventSource) + static void executeEventSource(EventSource* eventSource) { ASSERT(eventSource); WorkQueue* queue = eventSource->m_workQueue; { MutexLocker locker(queue->m_isValidMutex); if (!queue->m_isValid) - return FALSE; + return; } eventSource->m_workItem->execute(); - return FALSE; } - static gboolean performWork(GIOChannel* channel, GIOCondition condition, EventSource* eventSource) + static gboolean performWorkOnce(EventSource* eventSource) { - ASSERT(eventSource); + executeEventSource(eventSource); + return FALSE; + } - if (!(condition & G_IO_IN) && !(condition & G_IO_HUP) && !(condition & G_IO_ERR)) + static gboolean performWork(GSocket* socket, GIOCondition condition, EventSource* eventSource) + { + if (!(condition & G_IO_IN) && !(condition & G_IO_HUP) && !(condition & G_IO_ERR)) { + // EventSource has been cancelled, return FALSE to destroy the source. return FALSE; - - WorkQueue* queue = eventSource->m_workQueue; - { - MutexLocker locker(queue->m_isValidMutex); - if (!queue->m_isValid) - return FALSE; } - eventSource->m_workItem->execute(); - - if ((condition & G_IO_HUP) || (condition & G_IO_ERR)) - return FALSE; - + executeEventSource(eventSource); return TRUE; } - + + static gboolean performWorkOnTermination(GPid, gint, EventSource* eventSource) + { + executeEventSource(eventSource); + return FALSE; + } + static void deleteEventSource(EventSource* eventSource) { ASSERT(eventSource); @@ -86,9 +94,9 @@ public: } public: - GSource* m_dispatchSource; PassOwnPtr<WorkItem> m_workItem; WorkQueue* m_workQueue; + GCancellable* m_cancellable; }; // WorkQueue @@ -132,14 +140,15 @@ void WorkQueue::workQueueThreadBody() void WorkQueue::registerEventSourceHandler(int fileDescriptor, int condition, PassOwnPtr<WorkItem> item) { - GIOChannel* channel = g_io_channel_unix_new(fileDescriptor); - ASSERT(channel); - GSource* dispatchSource = g_io_create_watch(channel, static_cast<GIOCondition>(condition)); + GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0)); + ASSERT(socket); + GRefPtr<GCancellable> cancellable = adoptGRef(g_cancellable_new()); + GRefPtr<GSource> dispatchSource = adoptGRef(g_socket_create_source(socket.get(), static_cast<GIOCondition>(condition), cancellable.get())); ASSERT(dispatchSource); - EventSource* eventSource = new EventSource(dispatchSource, item, this); + EventSource* eventSource = new EventSource(item, this, cancellable.get()); ASSERT(eventSource); - g_source_set_callback(dispatchSource, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWork), + g_source_set_callback(dispatchSource.get(), reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWork), eventSource, reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource)); // Set up the event sources under the mutex since this is shared across multiple threads. @@ -154,11 +163,7 @@ void WorkQueue::registerEventSourceHandler(int fileDescriptor, int condition, Pa m_eventSources.set(fileDescriptor, sources); } - // Attach the event source to the GMainContext under the mutex since this is shared across multiple threads. - { - MutexLocker locker(m_eventLoopLock); - g_source_attach(dispatchSource, m_eventContext); - } + g_source_attach(dispatchSource.get(), m_eventContext); } void WorkQueue::unregisterEventSourceHandler(int fileDescriptor) @@ -174,29 +179,43 @@ void WorkQueue::unregisterEventSourceHandler(int fileDescriptor) if (it != m_eventSources.end()) { Vector<EventSource*> sources = it->second; for (unsigned i = 0; i < sources.size(); i++) - g_source_destroy(sources[i]->dispatchSource()); + sources[i]->cancel(); m_eventSources.remove(it); } } +void WorkQueue::scheduleWorkOnSource(GSource* dispatchSource, PassOwnPtr<WorkItem> item, GSourceFunc sourceCallback) +{ + EventSource* eventSource = new EventSource(item, this, 0); + + g_source_set_callback(dispatchSource, sourceCallback, eventSource, + reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource)); + + g_source_attach(dispatchSource, m_eventContext); +} + void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item) { - GSource* dispatchSource = g_timeout_source_new(0); + GRefPtr<GSource> dispatchSource = adoptGRef(g_idle_source_new()); ASSERT(dispatchSource); - EventSource* eventSource = new EventSource(dispatchSource, item, this); - - g_source_set_callback(dispatchSource, - reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce), - eventSource, - reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource)); - { - MutexLocker locker(m_eventLoopLock); - g_source_attach(dispatchSource, m_eventContext); - } + g_source_set_priority(dispatchSource.get(), G_PRIORITY_DEFAULT); + + scheduleWorkOnSource(dispatchSource.get(), item, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce)); } -void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem>, double) +void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem> item, double delay) { - notImplemented(); + GRefPtr<GSource> dispatchSource = adoptGRef(g_timeout_source_new(static_cast<guint>(delay * 1000))); + ASSERT(dispatchSource); + + scheduleWorkOnSource(dispatchSource.get(), item, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnce)); +} + +void WorkQueue::scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier process, PassOwnPtr<WorkItem> item) +{ + GRefPtr<GSource> dispatchSource = adoptGRef(g_child_watch_source_new(process)); + ASSERT(dispatchSource); + + scheduleWorkOnSource(dispatchSource.get(), item, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnTermination)); } diff --git a/Source/WebKit2/Platform/qt/SharedMemoryQt.cpp b/Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp index 8d5d70f..7acf132 100644 --- a/Source/WebKit2/Platform/qt/SharedMemoryQt.cpp +++ b/Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp @@ -31,7 +31,6 @@ #include "ArgumentDecoder.h" #include "ArgumentEncoder.h" #include "WebCoreArgumentCoders.h" -#include <QDir> #include <errno.h> #include <fcntl.h> #include <stdlib.h> @@ -42,6 +41,12 @@ #include <wtf/Assertions.h> #include <wtf/CurrentTime.h> +#if PLATFORM(QT) +#include <QDir> +#elif PLATFORM(GTK) +#include <wtf/gobject/GOwnPtr.h> +#endif + namespace WebKit { SharedMemory::Handle::Handle() @@ -101,9 +106,14 @@ void SharedMemory::Handle::adoptFromAttachment(int fileDescriptor, size_t size) PassRefPtr<SharedMemory> SharedMemory::create(size_t size) { +#if PLATFORM(QT) QString tempName = QDir::temp().filePath(QLatin1String("qwkshm.XXXXXX")); QByteArray tempNameCSTR = tempName.toLocal8Bit(); char* tempNameC = tempNameCSTR.data(); +#elif PLATFORM(GTK) + GOwnPtr<gchar> tempName(g_build_filename(g_get_tmp_dir(), "WK2SharedMemoryXXXXXX", NULL)); + gchar* tempNameC = tempName.get(); +#endif int fileDescriptor; while ((fileDescriptor = mkstemp(tempNameC)) == -1) { diff --git a/Source/WebKit2/Platform/win/RunLoopWin.cpp b/Source/WebKit2/Platform/win/RunLoopWin.cpp index 0ca7d9b..21bc2e0 100644 --- a/Source/WebKit2/Platform/win/RunLoopWin.cpp +++ b/Source/WebKit2/Platform/win/RunLoopWin.cpp @@ -26,7 +26,12 @@ #include "config.h" #include "RunLoop.h" +#include "BinarySemaphore.h" #include "WorkItem.h" +#include <wtf/CurrentTime.h> + +using namespace CoreIPC; +using namespace std; static const UINT PerformWorkMessage = WM_USER + 1; static const LPWSTR kRunLoopMessageWindowClassName = L"RunLoopMessageWindow"; @@ -74,6 +79,47 @@ void RunLoop::run() } } +bool RunLoop::dispatchSentMessagesUntil(const Vector<HWND>& windows, CoreIPC::BinarySemaphore& semaphore, double absoluteTime) +{ + if (windows.isEmpty()) + return semaphore.wait(absoluteTime); + + HANDLE handle = semaphore.event(); + DWORD handleCount = 1; + + while (true) { + DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime); + if (!interval) { + // Consider the wait to have timed out, even if the semaphore is currently signaled. + // This matches the WTF::ThreadCondition implementation of BinarySemaphore::wait. + return false; + } + + DWORD result = ::MsgWaitForMultipleObjectsEx(handleCount, &handle, interval, QS_SENDMESSAGE, 0); + if (result == WAIT_OBJECT_0) { + // The semaphore was signaled. + return true; + } + if (result == WAIT_TIMEOUT) { + // absoluteTime was reached. + return false; + } + if (result == WAIT_OBJECT_0 + handleCount) { + // One or more sent messages are available. Process sent messages for all the windows + // we were given, since we don't have a way of knowing which window has available sent + // messages. + for (size_t i = 0; i < windows.size(); ++i) { + MSG message; + ::PeekMessageW(&message, windows[i], 0, 0, PM_NOREMOVE | PM_QS_SENDMESSAGE); + } + continue; + } + ASSERT_WITH_MESSAGE(result != WAIT_FAILED, "::MsgWaitForMultipleObjectsEx failed with error %lu", ::GetLastError()); + ASSERT_WITH_MESSAGE(false, "::MsgWaitForMultipleObjectsEx returned unexpected result %lu", result); + return false; + } +} + void RunLoop::stop() { ::PostQuitMessage(0); diff --git a/Source/WebKit2/Platform/win/SharedMemoryWin.cpp b/Source/WebKit2/Platform/win/SharedMemoryWin.cpp index ef83de7..50985e7 100644 --- a/Source/WebKit2/Platform/win/SharedMemoryWin.cpp +++ b/Source/WebKit2/Platform/win/SharedMemoryWin.cpp @@ -136,8 +136,7 @@ static DWORD accessRights(SharedMemory::Protection protection) case SharedMemory::ReadOnly: return FILE_MAP_READ; case SharedMemory::ReadWrite: - // FILE_MAP_WRITE implies read access, too. - return FILE_MAP_WRITE; + return FILE_MAP_READ | FILE_MAP_WRITE; } ASSERT_NOT_REACHED(); @@ -146,23 +145,32 @@ static DWORD accessRights(SharedMemory::Protection protection) PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection) { - if (handle.isNull()) + RefPtr<SharedMemory> memory = adopt(handle.m_handle, handle.m_size, protection); + if (!memory) + return 0; + + // The SharedMemory object now owns the HANDLE. + handle.m_handle = 0; + + return memory.release(); +} + +PassRefPtr<SharedMemory> SharedMemory::adopt(HANDLE handle, size_t size, Protection protection) +{ + if (!handle) return 0; DWORD desiredAccess = accessRights(protection); - void* baseAddress = ::MapViewOfFile(handle.m_handle, desiredAccess, 0, 0, handle.m_size); + void* baseAddress = ::MapViewOfFile(handle, desiredAccess, 0, 0, size); ASSERT_WITH_MESSAGE(baseAddress, "::MapViewOfFile failed with error %lu", ::GetLastError()); if (!baseAddress) return 0; RefPtr<SharedMemory> memory = adoptRef(new SharedMemory); - memory->m_size = handle.m_size; + memory->m_size = size; memory->m_data = baseAddress; - - // Adopt the HANDLE. - memory->m_handle = handle.m_handle; - handle.m_handle = 0; + memory->m_handle = handle; return memory.release(); } |