summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/Platform
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-06-02 12:07:03 +0100
committerBen Murdoch <benm@google.com>2011-06-10 10:47:21 +0100
commit2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch)
treee4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebKit2/Platform
parent87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff)
downloadexternal_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')
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp2
-rw-r--r--Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp2
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Attachment.h10
-rw-r--r--Source/WebKit2/Platform/CoreIPC/BinarySemaphore.h4
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Connection.cpp58
-rw-r--r--Source/WebKit2/Platform/CoreIPC/Connection.h41
-rw-r--r--Source/WebKit2/Platform/CoreIPC/HandleMessage.h24
-rw-r--r--Source/WebKit2/Platform/CoreIPC/MessageID.h1
-rw-r--r--Source/WebKit2/Platform/CoreIPC/gtk/ConnectionGtk.cpp207
-rw-r--r--Source/WebKit2/Platform/CoreIPC/unix/AttachmentUnix.cpp (renamed from Source/WebKit2/Platform/CoreIPC/qt/AttachmentQt.cpp)3
-rw-r--r--Source/WebKit2/Platform/CoreIPC/unix/ConnectionUnix.cpp (renamed from Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp)68
-rw-r--r--Source/WebKit2/Platform/PlatformProcessIdentifier.h7
-rw-r--r--Source/WebKit2/Platform/RunLoop.h23
-rw-r--r--Source/WebKit2/Platform/SharedMemory.h12
-rw-r--r--Source/WebKit2/Platform/WorkQueue.h4
-rw-r--r--Source/WebKit2/Platform/gtk/RunLoopGtk.cpp37
-rw-r--r--Source/WebKit2/Platform/gtk/WorkQueueGtk.cpp113
-rw-r--r--Source/WebKit2/Platform/unix/SharedMemoryUnix.cpp (renamed from Source/WebKit2/Platform/qt/SharedMemoryQt.cpp)12
-rw-r--r--Source/WebKit2/Platform/win/RunLoopWin.cpp46
-rw-r--r--Source/WebKit2/Platform/win/SharedMemoryWin.cpp26
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();
}