Add a WebKitMessageRecorder DTrace provider, exposing IPC details to DTrace
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Jan 2015 02:32:24 +0000 (02:32 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Jan 2015 02:32:24 +0000 (02:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140673

Reviewed by Sam Weinig.

* Platform/IPC/ArgumentCoders.cpp:
(IPC::ArgumentCoder<uuid_t>::encode):
(IPC::ArgumentCoder<uuid_t>::decode):
* Platform/IPC/ArgumentCoders.h:
Add a uuid_t (simple) argument coder.
Fix a mis-named header-guard #ifdef.

* Platform/IPC/Connection.cpp:
(IPC::Connection::dispatchWorkQueueMessageReceiverMessage):
(IPC::Connection::dispatchSyncMessage):
Sync message replies inherit the message UUID from the incoming sync message.

(IPC::Connection::sendMessage):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::sendSyncMessageFromSecondaryThread):
Record outgoing messages. Because sendSyncMessage calls sendMessage,
we have to explicitly avoid recording the message twice.

(IPC::Connection::dispatchMessage):
Record the incoming message.

(IPC::Connection::remoteProcessID):
Add remoteProcessID(), which tries to determine the pid of the remote process.

* Platform/IPC/Connection.h:
(IPC::Connection::xpcConnection):
This can be const.

(IPC::Connection::isValid):
Make this public.

* Platform/IPC/MessageDecoder.cpp:
(IPC::MessageDecoder::MessageDecoder):
* Platform/IPC/MessageDecoder.h:
(IPC::MessageDecoder::setMessageProcessingToken):
(IPC::MessageDecoder::UUID):
Decode and store the message UUID.
Store a MessageProcessingToken for the lifetime of the MessageDecoder;
this ensures that all time spent processing the incoming message will be
counted against that message.

* Platform/IPC/MessageEncoder.cpp:
(IPC::MessageEncoder::MessageEncoder):
By default, create a new UUID for the message. Alternatively, allow clients
to pass the message UUID in (used for sync message replies).
Store the messageReceiverName and messageName.

(IPC::MessageEncoder::encodeHeader):
Factor encodeHeader() out of the constructors so most of their code can be shared.

(IPC::MessageEncoder::isSyncMessage):
(IPC::MessageEncoder::shouldDispatchMessageWhenWaitingForSyncReply):
Add getters for these flags.

* Platform/IPC/MessageEncoder.h:
(IPC::MessageEncoder::messageReceiverName):
(IPC::MessageEncoder::messageName):
(IPC::MessageEncoder::destinationID):
(IPC::MessageEncoder::UUID):

* Platform/IPC/MessageRecorder.h: Added.
* Platform/IPC/MessageRecorder.cpp: Added.
(MessageRecorder::MessageRecorder):
Add a class that interfaces with a custom DTrace provider to log incoming and outgoing messages.

(MessageRecorder::shared):
(MessageRecorder::isEnabled):
Determine if either of the message probes are enabled. If not, we'll avoid most of the
work associated with MessageRecorder.

(MessageRecorder::recordOutgoingMessage):
(MessageRecorder::recordIncomingMessage):
Build a WebKitMessageRecord and MessageProcessingToken from the Message(De|En)coder.
Once the MessageProcessingToken is deallocated, the probe will be invoked with the WebKitMessageRecord.

(MessageRecorder::MessageProcessingToken::MessageProcessingToken):
(MessageRecorder::MessageProcessingToken::~MessageProcessingToken):
Keep track of when the token is created and destroyed; these are considered the beginning
and ending "processing" times of the message (and as such the token should be kept alive for
exactly as long as the message is being processed).

* Platform/IPC/MessageRecorderProbes.d: Added.
Add a DTrace provider source file with two probes, message_sent and message_received.
The struct must match the struct in MessageRecorder.h.

* Platform/IPC/ProcessType.h: Added.
Add an enum of process types.

* WebKit2.xcodeproj/project.pbxproj:

* DatabaseProcess/DatabaseProcess.h:
* DatabaseProcess/DatabaseToWebProcessConnection.h:
* NetworkProcess/NetworkConnectionToWebProcess.h:
* NetworkProcess/NetworkProcess.h:
* WebProcess/Databases/WebToDatabaseProcessConnection.h:
* WebProcess/Network/NetworkProcessConnection.h:
* WebProcess/Plugins/PluginProcessConnection.h:
* WebProcess/WebPage/WebInspector.h:
* WebProcess/WebPage/WebInspectorUI.h:
* WebProcess/WebProcess.h:
* UIProcess/Databases/DatabaseProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Plugins/PluginProcessProxy.h:
* UIProcess/WebProcessProxy.h:
* PluginProcess/PluginProcess.h:
* PluginProcess/WebProcessConnection.h:
Annotate Connection::Clients with process types.

* Scripts/dtrace/trace-webkit2-messages.d: Added.
Add a DTrace script that outputs a small blob of JSON per message.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179326 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/DatabaseProcess/DatabaseProcess.h
Source/WebKit2/DatabaseProcess/DatabaseToWebProcessConnection.h
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h
Source/WebKit2/NetworkProcess/NetworkProcess.h
Source/WebKit2/Platform/IPC/ArgumentCoders.cpp
Source/WebKit2/Platform/IPC/ArgumentCoders.h
Source/WebKit2/Platform/IPC/Connection.cpp
Source/WebKit2/Platform/IPC/Connection.h
Source/WebKit2/Platform/IPC/MessageDecoder.cpp
Source/WebKit2/Platform/IPC/MessageDecoder.h
Source/WebKit2/Platform/IPC/MessageEncoder.cpp
Source/WebKit2/Platform/IPC/MessageEncoder.h
Source/WebKit2/Platform/IPC/MessageRecorder.cpp [new file with mode: 0644]
Source/WebKit2/Platform/IPC/MessageRecorder.h [new file with mode: 0644]
Source/WebKit2/Platform/IPC/MessageRecorderProbes.d [new file with mode: 0644]
Source/WebKit2/Platform/IPC/ProcessType.h [new file with mode: 0644]
Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm
Source/WebKit2/PluginProcess/PluginProcess.h
Source/WebKit2/PluginProcess/WebProcessConnection.h
Source/WebKit2/UIProcess/Databases/DatabaseProcessProxy.h
Source/WebKit2/UIProcess/Network/NetworkProcessProxy.h
Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h
Source/WebKit2/UIProcess/WebProcessProxy.h
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/Databases/WebToDatabaseProcessConnection.h
Source/WebKit2/WebProcess/Network/NetworkProcessConnection.h
Source/WebKit2/WebProcess/Plugins/PluginProcessConnection.h
Source/WebKit2/WebProcess/WebPage/WebInspector.h
Source/WebKit2/WebProcess/WebPage/WebInspectorUI.h
Source/WebKit2/WebProcess/WebProcess.h
Tools/ChangeLog
Tools/Scripts/dtrace/trace-webkit2-messages.d [new file with mode: 0755]

index c04c9a3..f00f0d7 100644 (file)
@@ -1,3 +1,119 @@
+2015-01-28  Timothy Horton  <timothy_horton@apple.com>
+
+        Add a WebKitMessageRecorder DTrace provider, exposing IPC details to DTrace
+        https://bugs.webkit.org/show_bug.cgi?id=140673
+
+        Reviewed by Sam Weinig.
+
+        * Platform/IPC/ArgumentCoders.cpp:
+        (IPC::ArgumentCoder<uuid_t>::encode):
+        (IPC::ArgumentCoder<uuid_t>::decode):
+        * Platform/IPC/ArgumentCoders.h:
+        Add a uuid_t (simple) argument coder.
+        Fix a mis-named header-guard #ifdef.
+
+        * Platform/IPC/Connection.cpp:
+        (IPC::Connection::dispatchWorkQueueMessageReceiverMessage):
+        (IPC::Connection::dispatchSyncMessage):
+        Sync message replies inherit the message UUID from the incoming sync message.
+
+        (IPC::Connection::sendMessage):
+        (IPC::Connection::waitForMessage):
+        (IPC::Connection::sendSyncMessage):
+        (IPC::Connection::sendSyncMessageFromSecondaryThread):
+        Record outgoing messages. Because sendSyncMessage calls sendMessage,
+        we have to explicitly avoid recording the message twice.
+
+        (IPC::Connection::dispatchMessage):
+        Record the incoming message.
+
+        (IPC::Connection::remoteProcessID):
+        Add remoteProcessID(), which tries to determine the pid of the remote process.
+
+        * Platform/IPC/Connection.h:
+        (IPC::Connection::xpcConnection):
+        This can be const.
+
+        (IPC::Connection::isValid):
+        Make this public.
+
+        * Platform/IPC/MessageDecoder.cpp:
+        (IPC::MessageDecoder::MessageDecoder):
+        * Platform/IPC/MessageDecoder.h:
+        (IPC::MessageDecoder::setMessageProcessingToken):
+        (IPC::MessageDecoder::UUID):
+        Decode and store the message UUID.
+        Store a MessageProcessingToken for the lifetime of the MessageDecoder;
+        this ensures that all time spent processing the incoming message will be
+        counted against that message.
+
+        * Platform/IPC/MessageEncoder.cpp:
+        (IPC::MessageEncoder::MessageEncoder):
+        By default, create a new UUID for the message. Alternatively, allow clients
+        to pass the message UUID in (used for sync message replies).
+        Store the messageReceiverName and messageName.
+
+        (IPC::MessageEncoder::encodeHeader):
+        Factor encodeHeader() out of the constructors so most of their code can be shared.
+
+        (IPC::MessageEncoder::isSyncMessage):
+        (IPC::MessageEncoder::shouldDispatchMessageWhenWaitingForSyncReply):
+        Add getters for these flags.
+
+        * Platform/IPC/MessageEncoder.h:
+        (IPC::MessageEncoder::messageReceiverName):
+        (IPC::MessageEncoder::messageName):
+        (IPC::MessageEncoder::destinationID):
+        (IPC::MessageEncoder::UUID):
+
+        * Platform/IPC/MessageRecorder.h: Added.
+        * Platform/IPC/MessageRecorder.cpp: Added.
+        (MessageRecorder::MessageRecorder):
+        Add a class that interfaces with a custom DTrace provider to log incoming and outgoing messages.
+
+        (MessageRecorder::shared):
+        (MessageRecorder::isEnabled):
+        Determine if either of the message probes are enabled. If not, we'll avoid most of the
+        work associated with MessageRecorder.
+
+        (MessageRecorder::recordOutgoingMessage):
+        (MessageRecorder::recordIncomingMessage):
+        Build a WebKitMessageRecord and MessageProcessingToken from the Message(De|En)coder.
+        Once the MessageProcessingToken is deallocated, the probe will be invoked with the WebKitMessageRecord.
+
+        (MessageRecorder::MessageProcessingToken::MessageProcessingToken):
+        (MessageRecorder::MessageProcessingToken::~MessageProcessingToken):
+        Keep track of when the token is created and destroyed; these are considered the beginning
+        and ending "processing" times of the message (and as such the token should be kept alive for
+        exactly as long as the message is being processed).
+
+        * Platform/IPC/MessageRecorderProbes.d: Added.
+        Add a DTrace provider source file with two probes, message_sent and message_received.
+        The struct must match the struct in MessageRecorder.h.
+        
+        * Platform/IPC/ProcessType.h: Added.
+        Add an enum of process types.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+
+        * DatabaseProcess/DatabaseProcess.h:
+        * DatabaseProcess/DatabaseToWebProcessConnection.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        * NetworkProcess/NetworkProcess.h:
+        * WebProcess/Databases/WebToDatabaseProcessConnection.h:
+        * WebProcess/Network/NetworkProcessConnection.h:
+        * WebProcess/Plugins/PluginProcessConnection.h:
+        * WebProcess/WebPage/WebInspector.h:
+        * WebProcess/WebPage/WebInspectorUI.h:
+        * WebProcess/WebProcess.h:
+        * UIProcess/Databases/DatabaseProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Plugins/PluginProcessProxy.h:
+        * UIProcess/WebProcessProxy.h:
+        * PluginProcess/PluginProcess.h:
+        * PluginProcess/WebProcessConnection.h:
+        Annotate Connection::Clients with process types.
+        
 2015-01-28  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Crash closing inspected page with frequent activity
index b3aff28..b2b24ee 100644 (file)
@@ -82,6 +82,8 @@ private:
     virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Database; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::UI; }
     void didReceiveDatabaseProcessMessage(IPC::Connection&, IPC::MessageDecoder&);
 
     // Message Handlers
index 06f85bf..59c40d3 100644 (file)
@@ -51,6 +51,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Database; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Web; }
     void didReceiveDatabaseToWebProcessConnectionMessage(IPC::Connection&, IPC::MessageDecoder&);
 
     // IPC::MessageSender
index 06cc88e..946d2ea 100644 (file)
@@ -65,6 +65,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&);
     virtual void didClose(IPC::Connection&);
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName);
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Network; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Web; }
 
     // Message handlers.
     void didReceiveNetworkConnectionToWebProcessMessage(IPC::Connection&, IPC::MessageDecoder&);
index b9dcc6b..d57f751 100644 (file)
@@ -99,6 +99,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Network; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::UI; }
 
     // DownloadManager::Client
     virtual void didCreateDownload() override;
index 39f3e07..f72eac2 100644 (file)
@@ -162,4 +162,14 @@ bool ArgumentCoder<String>::decode(ArgumentDecoder& decoder, String& result)
     return decodeStringText<UChar>(decoder, length, result);
 }
 
+void ArgumentCoder<uuid_t>::encode(ArgumentEncoder& encoder, const uuid_t& uuid)
+{
+    SimpleArgumentCoder<uuid_t>::encode(encoder, uuid);
+}
+
+bool ArgumentCoder<uuid_t>::decode(ArgumentDecoder& decoder, uuid_t& uuid)
+{
+    return SimpleArgumentCoder<uuid_t>::decode(decoder, uuid);
+}
+
 } // namespace IPC
index 462ce37..62da344 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SimpleArgumentCoder_h
-#define SimpleArgumentCoder_h
+#ifndef ArgumentCoders_h
+#define ArgumentCoders_h
 
 #include "ArgumentDecoder.h"
 #include "ArgumentEncoder.h"
 #include <utility>
+#include <uuid/uuid.h>
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -298,6 +299,11 @@ template<> struct ArgumentCoder<String> {
     static bool decode(ArgumentDecoder&, String&);
 };
 
+template<> struct ArgumentCoder<uuid_t> {
+    static void encode(ArgumentEncoder&, const uuid_t&);
+    static bool decode(ArgumentDecoder&, uuid_t&);
+};
+
 } // namespace IPC
 
 #endif // ArgumentCoders_h
index 7b8ab20..aca77bd 100644 (file)
@@ -317,7 +317,7 @@ void Connection::dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceive
         return;
     }
 
-    auto replyEncoder = std::make_unique<MessageEncoder>("IPC", "SyncMessageReply", syncRequestID);
+    auto replyEncoder = std::make_unique<MessageEncoder>("IPC", "SyncMessageReply", syncRequestID, incomingMessageDecoder->UUID());
 
     // Hand off both the decoder and encoder to the work queue message receiver.
     workQueueMessageReceiver->didReceiveSyncMessage(*this, *decoder, replyEncoder);
@@ -369,7 +369,7 @@ std::unique_ptr<MessageEncoder> Connection::createSyncMessageEncoder(StringRefer
     return encoder;
 }
 
-bool Connection::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned messageSendFlags)
+bool Connection::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned messageSendFlags, bool alreadyRecordedMessage)
 {
     if (!isValid())
         return false;
@@ -379,6 +379,10 @@ bool Connection::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned m
             || m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount))
         encoder->setShouldDispatchMessageWhenWaitingForSyncReply(true);
 
+    std::unique_ptr<MessageRecorder::MessageProcessingToken> token;
+    if (!alreadyRecordedMessage)
+        token = MessageRecorder::recordOutgoingMessage(*this, *encoder);
+
     {
         std::lock_guard<std::mutex> lock(m_outgoingMessagesMutex);
         m_outgoingMessages.append(WTF::move(encoder));
@@ -473,8 +477,10 @@ std::unique_ptr<MessageDecoder> Connection::sendSyncMessage(uint64_t syncRequest
 
     ++m_inSendSyncCount;
 
+    auto token = MessageRecorder::recordOutgoingMessage(*this, *encoder);
+
     // First send the message.
-    sendMessage(WTF::move(encoder), DispatchMessageEvenWhenWaitingForSyncReply);
+    sendMessage(WTF::move(encoder), DispatchMessageEvenWhenWaitingForSyncReply, true);
 
     // Then wait for a reply. Waiting for a reply could involve dispatching incoming sync messages, so
     // keep an extra reference to the connection here in case it's invalidated.
@@ -515,7 +521,9 @@ std::unique_ptr<MessageDecoder> Connection::sendSyncMessageFromSecondaryThread(u
         m_secondaryThreadPendingSyncReplyMap.add(syncRequestID, &pendingReply);
     }
 
-    sendMessage(WTF::move(encoder), 0);
+    auto token = MessageRecorder::recordOutgoingMessage(*this, *encoder);
+
+    sendMessage(WTF::move(encoder), 0, true);
 
     pendingReply.semaphore.wait(currentTime() + (timeout.count() / 1000.0));
 
@@ -768,7 +776,7 @@ void Connection::dispatchSyncMessage(MessageDecoder& decoder)
         return;
     }
 
-    auto replyEncoder = std::make_unique<MessageEncoder>("IPC", "SyncMessageReply", syncRequestID);
+    auto replyEncoder = std::make_unique<MessageEncoder>("IPC", "SyncMessageReply", syncRequestID, decoder.UUID());
 
     // Hand off both the decoder and encoder to the client.
     m_client->didReceiveSyncMessage(*this, decoder, replyEncoder);
@@ -815,6 +823,8 @@ void Connection::dispatchMessage(MessageDecoder& decoder)
 
 void Connection::dispatchMessage(std::unique_ptr<MessageDecoder> message)
 {
+    MessageRecorder::recordIncomingMessage(*this, *message);
+
     if (!m_client)
         return;
 
index 156fff6..2b6fd09 100644 (file)
@@ -32,6 +32,7 @@
 #include "MessageDecoder.h"
 #include "MessageEncoder.h"
 #include "MessageReceiver.h"
+#include "ProcessType.h"
 #include "WorkQueue.h"
 #include <atomic>
 #include <condition_variable>
@@ -90,6 +91,8 @@ public:
     public:
         virtual void didClose(Connection&) = 0;
         virtual void didReceiveInvalidMessage(Connection&, StringReference messageReceiverName, StringReference messageName) = 0;
+        virtual IPC::ProcessType localProcessType() = 0;
+        virtual IPC::ProcessType remoteProcessType() = 0;
 
     protected:
         virtual ~Client() { }
@@ -120,8 +123,9 @@ public:
         OSObjectPtr<xpc_connection_t> xpcConnection;
     };
     static bool identifierIsNull(Identifier identifier) { return identifier.port == MACH_PORT_NULL; }
-    xpc_connection_t xpcConnection() { return m_xpcConnection.get(); }
+    xpc_connection_t xpcConnection() const { return m_xpcConnection.get(); }
     bool getAuditToken(audit_token_t&);
+    pid_t remoteProcessID() const;
 #elif USE(UNIX_DOMAIN_SOCKETS)
     typedef int Identifier;
     static bool identifierIsNull(Identifier identifier) { return !identifier; }
@@ -174,7 +178,7 @@ public:
     template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags = 0);
 
     std::unique_ptr<MessageEncoder> createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID);
-    bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags = 0);
+    bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags = 0, bool alreadyRecordedMessage = false);
     std::unique_ptr<MessageDecoder> sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout, unsigned syncSendFlags = 0);
     std::unique_ptr<MessageDecoder> sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout);
     bool sendSyncReply(std::unique_ptr<MessageEncoder>);
@@ -193,13 +197,13 @@ public:
     void terminateSoon(double intervalInSeconds);
 #endif
 
+    bool isValid() const { return m_client; }
+
 private:
     Connection(Identifier, bool isServer, Client&, WTF::RunLoop& clientRunLoop);
     void platformInitialize(Identifier);
     void platformInvalidate();
     
-    bool isValid() const { return m_client; }
-    
     std::unique_ptr<MessageDecoder> waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags);
     
     std::unique_ptr<MessageDecoder> waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags);
index 29a054e..ff521c3 100644 (file)
@@ -53,7 +53,10 @@ MessageDecoder::MessageDecoder(const DataReference& buffer, Vector<Attachment> a
     if (!decode(m_messageName))
         return;
 
-    decode(m_destinationID);
+    if (!decode(m_destinationID))
+        return;
+
+    decode(m_UUID);
 }
 
 bool MessageDecoder::isSyncMessage() const
index eaa9b5e..3fafad1 100644 (file)
@@ -27,7 +27,9 @@
 #define MessageDecoder_h
 
 #include "ArgumentDecoder.h"
+#include "MessageRecorder.h"
 #include "StringReference.h"
+#include <uuid/uuid.h>
 
 namespace IPC {
 
@@ -50,6 +52,10 @@ public:
     void setImportanceAssertion(std::unique_ptr<ImportanceAssertion>);
 #endif
 
+    void setMessageProcessingToken(std::unique_ptr<MessageRecorder::MessageProcessingToken> token) { m_processingToken = WTF::move(token); }
+
+    const uuid_t& UUID() const { return m_UUID; }
+
 private:
     uint8_t m_messageFlags;
     StringReference m_messageReceiverName;
@@ -57,9 +63,13 @@ private:
 
     uint64_t m_destinationID;
 
+    uuid_t m_UUID;
+
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
     std::unique_ptr<ImportanceAssertion> m_importanceAssertion;
 #endif
+
+    std::unique_ptr<MessageRecorder::MessageProcessingToken> m_processingToken;
 };
 
 } // namespace IPC
index d2e4efe..bf7c367 100644 (file)
 
 #include "ArgumentCoders.h"
 #include "MessageFlags.h"
+#include "MessageRecorder.h"
 #include "StringReference.h"
 
 namespace IPC {
 
 static uint8_t defaultMessageFlags = 0;
 
+MessageEncoder::MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, const uuid_t& UUID)
+    : m_messageReceiverName(messageReceiverName)
+    , m_messageName(messageName)
+    , m_destinationID(destinationID)
+{
+    uuid_copy(m_UUID, UUID);
+    encodeHeader();
+}
+
 MessageEncoder::MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID)
+    : m_messageReceiverName(messageReceiverName)
+    , m_messageName(messageName)
+    , m_destinationID(destinationID)
+{
+    uuid_generate(m_UUID);
+    encodeHeader();
+}
+
+MessageEncoder::~MessageEncoder()
 {
-    ASSERT(!messageReceiverName.isEmpty());
+}
+
+void MessageEncoder::encodeHeader()
+{
+    ASSERT(!m_messageReceiverName.isEmpty());
 
     *this << defaultMessageFlags;
-    *this << messageReceiverName;
-    *this << messageName;
-    *this << destinationID;
+    *this << m_messageReceiverName;
+    *this << m_messageName;
+    *this << m_destinationID;
+    *this << m_UUID;
 }
 
-MessageEncoder::~MessageEncoder()
+bool MessageEncoder::isSyncMessage() const
+{
+    return *buffer() & SyncMessage;
+}
+
+bool MessageEncoder::shouldDispatchMessageWhenWaitingForSyncReply() const
 {
+    return *buffer() & DispatchMessageWhenWaitingForSyncReply;
 }
 
 void MessageEncoder::setIsSyncMessage(bool isSyncMessage)
index 524e5e1..872f264 100644 (file)
@@ -27,6 +27,8 @@
 #define MessageEncoder_h
 
 #include "ArgumentEncoder.h"
+#include "StringReference.h"
+#include <uuid/uuid.h>
 #include <wtf/Forward.h>
 
 namespace IPC {
@@ -36,10 +38,28 @@ class StringReference;
 class MessageEncoder : public ArgumentEncoder {
 public:
     MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID);
+    MessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, const uuid_t&);
     virtual ~MessageEncoder();
 
+    StringReference messageReceiverName() const { return m_messageReceiverName; }
+    StringReference messageName() const { return m_messageName; }
+    uint64_t destinationID() const { return m_destinationID; }
+
     void setIsSyncMessage(bool);
+    bool isSyncMessage() const;
+
     void setShouldDispatchMessageWhenWaitingForSyncReply(bool);
+    bool shouldDispatchMessageWhenWaitingForSyncReply() const;
+
+    const uuid_t& UUID() const { return m_UUID; }
+
+private:
+    void encodeHeader();
+
+    StringReference m_messageReceiverName;
+    StringReference m_messageName;
+    uint64_t m_destinationID;
+    uuid_t m_UUID;
 };
 
 } // namespace IPC
diff --git a/Source/WebKit2/Platform/IPC/MessageRecorder.cpp b/Source/WebKit2/Platform/IPC/MessageRecorder.cpp
new file mode 100644 (file)
index 0000000..1b2e9c3
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MessageRecorder.h"
+
+#include "Connection.h"
+#include "MessageDecoder.h"
+#include "MessageEncoder.h"
+#include "MessageRecorderProbes.h"
+#include <wtf/CurrentTime.h>
+
+namespace IPC {
+
+bool MessageRecorder::isEnabled()
+{
+    return WEBKITMESSAGERECORDER_MESSAGE_RECEIVED_ENABLED() || WEBKITMESSAGERECORDER_MESSAGE_SENT_ENABLED();
+}
+
+std::unique_ptr<MessageRecorder::MessageProcessingToken> MessageRecorder::recordOutgoingMessage(Connection& connection, MessageEncoder& encoder)
+{
+    if (!isEnabled() || !connection.isValid())
+        return nullptr;
+
+    WebKitMessageRecord record;
+    record.sourceProcessType = static_cast<uint64_t>(connection.client()->localProcessType());
+    record.destinationProcessType = static_cast<uint64_t>(connection.client()->remoteProcessType());
+    record.destinationID = encoder.destinationID();
+    record.isSyncMessage = encoder.isSyncMessage();
+    record.shouldDispatchMessageWhenWaitingForSyncReply = encoder.shouldDispatchMessageWhenWaitingForSyncReply();
+    record.sourceProcessID = getpid();
+    record.destinationProcessID = connection.remoteProcessID();
+    record.isIncoming = false;
+
+    record.messageReceiverName = MallocPtr<char>::malloc(sizeof(char) * (encoder.messageReceiverName().size() + 1));
+    strncpy(record.messageReceiverName.get(), encoder.messageReceiverName().data(), encoder.messageReceiverName().size());
+    record.messageReceiverName.get()[encoder.messageReceiverName().size()] = 0;
+
+    record.messageName = MallocPtr<char>::malloc(sizeof(char) * (encoder.messageName().size() + 1));
+    strncpy(record.messageName.get(), encoder.messageName().data(), encoder.messageName().size());
+    record.messageName.get()[encoder.messageName().size()] = 0;
+
+    uuid_copy(record.UUID, encoder.UUID());
+
+    return std::make_unique<MessageProcessingToken>(WTF::move(record));
+}
+
+void MessageRecorder::recordIncomingMessage(Connection& connection, MessageDecoder& decoder)
+{
+    if (!isEnabled() || !connection.isValid())
+        return;
+
+    WebKitMessageRecord record;
+    record.sourceProcessType = static_cast<uint64_t>(connection.client()->remoteProcessType());
+    record.destinationProcessType = static_cast<uint64_t>(connection.client()->localProcessType());
+    record.destinationID = decoder.destinationID();
+    record.isSyncMessage = decoder.isSyncMessage();
+    record.shouldDispatchMessageWhenWaitingForSyncReply = decoder.shouldDispatchMessageWhenWaitingForSyncReply();
+    record.sourceProcessID = connection.remoteProcessID();
+    record.destinationProcessID = getpid();
+    record.isIncoming = true;
+
+    record.messageReceiverName = MallocPtr<char>::malloc(sizeof(char) * (decoder.messageReceiverName().size() + 1));
+    strncpy(record.messageReceiverName.get(), decoder.messageReceiverName().data(), decoder.messageReceiverName().size());
+    record.messageReceiverName.get()[decoder.messageReceiverName().size()] = 0;
+
+    record.messageName = MallocPtr<char>::malloc(sizeof(char) * (decoder.messageName().size() + 1));
+    strncpy(record.messageName.get(), decoder.messageName().data(), decoder.messageName().size());
+    record.messageName.get()[decoder.messageName().size()] = 0;
+
+    uuid_copy(record.UUID, decoder.UUID());
+
+    decoder.setMessageProcessingToken(std::make_unique<MessageProcessingToken>(WTF::move(record)));
+}
+
+#pragma mark MessageProcessingToken
+
+MessageRecorder::MessageProcessingToken::MessageProcessingToken(WebKitMessageRecord record)
+    : m_record(WTF::move(record))
+{
+    m_record.startTime = monotonicallyIncreasingTime();
+}
+
+MessageRecorder::MessageProcessingToken::~MessageProcessingToken()
+{
+    m_record.endTime = monotonicallyIncreasingTime();
+
+    if (m_record.isIncoming)
+        WEBKITMESSAGERECORDER_MESSAGE_RECEIVED(&m_record);
+    else
+        WEBKITMESSAGERECORDER_MESSAGE_SENT(&m_record);
+}
+
+}
diff --git a/Source/WebKit2/Platform/IPC/MessageRecorder.h b/Source/WebKit2/Platform/IPC/MessageRecorder.h
new file mode 100644 (file)
index 0000000..a25b39c
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MessageRecorder_h
+#define MessageRecorder_h
+
+#include "ProcessType.h"
+#include <uuid/uuid.h>
+#include <wtf/Forward.h>
+#include <wtf/MallocPtr.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+struct WebKitMessageRecord {
+    uint8_t sourceProcessType; // IPC::ProcessType
+    pid_t sourceProcessID;
+
+    uint8_t destinationProcessType; // IPC::ProcessType
+    pid_t destinationProcessID;
+
+    MallocPtr<char> messageReceiverName;
+    MallocPtr<char> messageName;
+    uint64_t destinationID;
+
+    uuid_t UUID;
+
+    double startTime;
+    double endTime;
+
+    bool isSyncMessage;
+    bool shouldDispatchMessageWhenWaitingForSyncReply;
+    bool isIncoming;
+};
+
+namespace IPC {
+
+class Connection;
+class MessageDecoder;
+class MessageEncoder;
+
+class MessageRecorder {
+public:
+    static bool isEnabled();
+
+    class MessageProcessingToken {
+        WTF_MAKE_NONCOPYABLE(MessageProcessingToken);
+    public:
+        explicit MessageProcessingToken(WebKitMessageRecord);
+        ~MessageProcessingToken();
+
+    private:
+        WebKitMessageRecord m_record;
+    };
+
+    static std::unique_ptr<MessageRecorder::MessageProcessingToken> recordOutgoingMessage(IPC::Connection&, IPC::MessageEncoder&);
+    static void recordIncomingMessage(IPC::Connection&, IPC::MessageDecoder&);
+
+private:
+    explicit MessageRecorder() { }
+};
+
+};
+
+#endif // MessageRecorder_h
diff --git a/Source/WebKit2/Platform/IPC/MessageRecorderProbes.d b/Source/WebKit2/Platform/IPC/MessageRecorderProbes.d
new file mode 100644 (file)
index 0000000..f57e293
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct WebKitMessageRecord;
+
+provider WebKitMessageRecorder {
+    probe message_sent(struct WebKitMessageRecord*);
+    probe message_received(struct WebKitMessageRecord*);
+};
diff --git a/Source/WebKit2/Platform/IPC/ProcessType.h b/Source/WebKit2/Platform/IPC/ProcessType.h
new file mode 100644 (file)
index 0000000..237c267
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProcessType_h
+#define ProcessType_h
+
+namespace IPC {
+
+enum class ProcessType : uint8_t {
+    UI,
+    Web,
+    Network,
+    Database,
+    Plugin
+};
+
+};
+
+#endif
index 57c9f20..b83168f 100644 (file)
@@ -609,6 +609,14 @@ void Connection::didReceiveSyncReply(unsigned flags)
     if ((flags & InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
         _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatusRunning);
 #endif
-}    
+}
+
+pid_t Connection::remoteProcessID() const
+{
+    if (!m_xpcConnection)
+        return 0;
+
+    return xpc_connection_get_pid(m_xpcConnection.get());
+}
     
 } // namespace IPC
index 3df2d82..3568d09 100644 (file)
@@ -91,6 +91,8 @@ private:
     virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Plugin; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::UI; }
 
     // Message handlers.
     void didReceivePluginProcessMessage(IPC::Connection&, IPC::MessageDecoder&);
index 6d550ee..1221f95 100644 (file)
@@ -69,6 +69,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Plugin; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Web; }
 
     // Message handlers.
     void didReceiveWebProcessConnectionMessage(IPC::Connection&, IPC::MessageDecoder&);
index a7b9810..be66ade 100644 (file)
@@ -54,6 +54,8 @@ private:
     virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::UI; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Database; }
 
     void didReceiveDatabaseProcessProxyMessage(IPC::Connection&, IPC::MessageDecoder&);
 
index 35f264a..cd996d1 100644 (file)
@@ -83,6 +83,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::UI; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Network; }
 
     // Message handlers
     void didReceiveNetworkProcessProxyMessage(IPC::Connection&, IPC::MessageDecoder&);
index d6f700a..45feedd 100644 (file)
@@ -120,6 +120,8 @@ private:
 
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::UI; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Plugin; }
 
     // ProcessLauncher::Client
     virtual void didFinishLaunching(ProcessLauncher*, IPC::Connection::Identifier) override;
index 1b65b28..5760ddd 100644 (file)
@@ -184,6 +184,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::UI; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Web; }
 
     // ResponsivenessTimer::Client
     void didBecomeUnresponsive(ResponsivenessTimer*) override;
index 01236f8..6c4cef6 100644 (file)
                2D429BFD1721E2C700EC681F /* PDFPluginPasswordField.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */; };
                2D47B56C1810714E003A3AEE /* RemoteLayerBackingStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D47B56A1810714E003A3AEE /* RemoteLayerBackingStore.mm */; };
                2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D47B56B1810714E003A3AEE /* RemoteLayerBackingStore.h */; };
+               2D5AB62E1A69D6FB0014A9CB /* MessageRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D5AB62B1A69D6FB0014A9CB /* MessageRecorder.h */; };
+               2D5AB62F1A69D6FB0014A9CB /* MessageRecorder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D5AB62C1A69D6FB0014A9CB /* MessageRecorder.cpp */; };
+               2D5AB6301A69D6FB0014A9CB /* MessageRecorderProbes.d in Sources */ = {isa = PBXBuildFile; fileRef = 2D5AB62D1A69D6FB0014A9CB /* MessageRecorderProbes.d */; };
                2D5C9D0519C81D8F00B3C5C1 /* WebPageOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D5C9D0319C81D8F00B3C5C1 /* WebPageOverlay.cpp */; };
                2D5C9D0619C81D8F00B3C5C1 /* WebPageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D5C9D0419C81D8F00B3C5C1 /* WebPageOverlay.h */; };
                2D6AB541192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6AB53F192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h */; };
                2D6CD11A189058A500E5A4A0 /* ViewSnapshotStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D6CD118189058A500E5A4A0 /* ViewSnapshotStore.mm */; };
                2D7AAFD318C8640600A7ACD4 /* WKWebViewContentProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D7AAFD218C8640600A7ACD4 /* WKWebViewContentProvider.h */; };
                2D7AAFD618C956AF00A7ACD4 /* WKWebViewConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D7AAFD518C956AF00A7ACD4 /* WKWebViewConfigurationInternal.h */; };
+               2D7F13101A702FBA009A6FBD /* ProcessType.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D7F130F1A702FBA009A6FBD /* ProcessType.h */; };
                2D819B9E18627EE9001F03D1 /* ViewGestureGeometryCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */; };
                2D819BA11862800E001F03D1 /* ViewGestureGeometryCollectorMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D819B9F1862800E001F03D1 /* ViewGestureGeometryCollectorMessageReceiver.cpp */; };
                2D819BA21862800E001F03D1 /* ViewGestureGeometryCollectorMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D819BA01862800E001F03D1 /* ViewGestureGeometryCollectorMessages.h */; };
                2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPluginPasswordField.mm; path = PDF/PDFPluginPasswordField.mm; sourceTree = "<group>"; };
                2D47B56A1810714E003A3AEE /* RemoteLayerBackingStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteLayerBackingStore.mm; sourceTree = "<group>"; };
                2D47B56B1810714E003A3AEE /* RemoteLayerBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteLayerBackingStore.h; sourceTree = "<group>"; };
+               2D5AB62B1A69D6FB0014A9CB /* MessageRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageRecorder.h; sourceTree = "<group>"; };
+               2D5AB62C1A69D6FB0014A9CB /* MessageRecorder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageRecorder.cpp; sourceTree = "<group>"; };
+               2D5AB62D1A69D6FB0014A9CB /* MessageRecorderProbes.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = MessageRecorderProbes.d; sourceTree = "<group>"; };
                2D5C9D0319C81D8F00B3C5C1 /* WebPageOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageOverlay.cpp; sourceTree = "<group>"; };
                2D5C9D0419C81D8F00B3C5C1 /* WebPageOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageOverlay.h; sourceTree = "<group>"; };
                2D6AB53F192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WKPDFPageNumberIndicator.h; path = ios/WKPDFPageNumberIndicator.h; sourceTree = "<group>"; };
                2D70AB1418A1D57C00026D6E /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
                2D7AAFD218C8640600A7ACD4 /* WKWebViewContentProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewContentProvider.h; sourceTree = "<group>"; };
                2D7AAFD518C956AF00A7ACD4 /* WKWebViewConfigurationInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewConfigurationInternal.h; sourceTree = "<group>"; };
+               2D7F130F1A702FBA009A6FBD /* ProcessType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessType.h; sourceTree = "<group>"; };
                2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewGestureGeometryCollector.cpp; sourceTree = "<group>"; };
                2D819B9A186275B3001F03D1 /* ViewGestureGeometryCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewGestureGeometryCollector.h; sourceTree = "<group>"; };
                2D819B9B186275B3001F03D1 /* ViewGestureGeometryCollector.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ViewGestureGeometryCollector.messages.in; sourceTree = "<group>"; };
                                1A3EED11161A53D600AEB4F5 /* MessageReceiver.h */,
                                1A3EED0C161A535300AEB4F5 /* MessageReceiverMap.cpp */,
                                1A3EED0D161A535300AEB4F5 /* MessageReceiverMap.h */,
+                               2D5AB62B1A69D6FB0014A9CB /* MessageRecorder.h */,
+                               2D5AB62C1A69D6FB0014A9CB /* MessageRecorder.cpp */,
+                               2D5AB62D1A69D6FB0014A9CB /* MessageRecorderProbes.d */,
                                1AAB0377185A7C6A00EDF501 /* MessageSender.cpp */,
                                1AAB0378185A7C6A00EDF501 /* MessageSender.h */,
+                               2D7F130F1A702FBA009A6FBD /* ProcessType.h */,
                                1AE00D6918327C1200087DD7 /* StringReference.cpp */,
                                1AE00D6A18327C1200087DD7 /* StringReference.h */,
                        );
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               2D7F13101A702FBA009A6FBD /* ProcessType.h in Headers */,
                                37A5E01418BBF93F000A081E /* _WKActivatedElementInfo.h in Headers */,
                                379A873618BBFA4300588AF2 /* _WKActivatedElementInfoInternal.h in Headers */,
                                A1A4FE5A18DCE9FA00B5EA8A /* _WKDownload.h in Headers */,
                                1AA56F2911E92BC80061B882 /* PluginController.h in Headers */,
                                1A8EF4CB1252403700F7067F /* PluginControllerProxy.h in Headers */,
                                1A8EF96F1252AF6B00F7067F /* PluginControllerProxyMessages.h in Headers */,
+                               2D5AB62E1A69D6FB0014A9CB /* MessageRecorder.h in Headers */,
                                1A179780137EE82C00F97D45 /* PluginCreationParameters.h in Headers */,
                                7C3F8C91173AF52D007B7F39 /* PluginInformation.h in Headers */,
                                7C89D2B41A6B068C003A5FDE /* APIUserContentFilter.h in Headers */,
                                1AFDE6591954A42B00C48FFA /* SessionState.cpp in Sources */,
                                1A002D48196B345D00B9AD44 /* SessionStateCoding.mm in Sources */,
                                1A7284481959F8040007BCE5 /* SessionStateConversion.cpp in Sources */,
+                               2D5AB6301A69D6FB0014A9CB /* MessageRecorderProbes.d in Sources */,
                                753E3E0D1887398500188496 /* SessionTracker.cpp in Sources */,
                                1A6420E412DCE2FF00CAAE2C /* ShareableBitmap.cpp in Sources */,
                                C01A260112662F2100C9ED55 /* ShareableBitmapCG.cpp in Sources */,
                                BC111B5E112F629800337BAB /* WebEventFactory.mm in Sources */,
                                1A3DD1FD125E59F3004515E6 /* WebFindClient.cpp in Sources */,
                                BCE469531214E6CB000B98EB /* WebFormClient.cpp in Sources */,
+                               2D5AB62F1A69D6FB0014A9CB /* MessageRecorder.cpp in Sources */,
                                BCE469551214E6CB000B98EB /* WebFormSubmissionListenerProxy.cpp in Sources */,
                                BC111ADD112F5B9300337BAB /* WebFrame.cpp in Sources */,
                                BCE469791214F2B4000B98EB /* WebFrameListenerProxy.cpp in Sources */,
index df23166..ef5bfc9 100644 (file)
@@ -58,6 +58,8 @@ private:
     virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Web; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Database; }
 
     // IPC::MessageSender
     virtual IPC::Connection* messageSenderConnection() override { return m_connection.get(); }
index 1602705..803e801 100644 (file)
@@ -68,6 +68,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Web; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Network; }
 
 #if ENABLE(SHAREABLE_RESOURCE)
     // Message handlers.
index 15aced6..4361030 100644 (file)
@@ -68,6 +68,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Web; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Plugin; }
 
     // Message handlers.
     void didReceivePluginProcessConnectionMessage(IPC::Connection&, IPC::MessageDecoder&);
index 155d671..ed85c90 100644 (file)
@@ -53,6 +53,8 @@ public:
     // IPC::Connection::Client
     void didClose(IPC::Connection&) override { close(); }
     void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference) override { close(); }
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Web; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::UI; }
 
     // Called by WebInspector messages
     void connectionEstablished();
index 8bef177..f835fca 100644 (file)
@@ -48,6 +48,8 @@ public:
     // IPC::Connection::Client
     void didClose(IPC::Connection&) override { closeWindow(); }
     void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference) override { closeWindow(); }
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Web; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Web; }
 
     // Called by WebInspectorUI messages
     void establishConnection(IPC::Attachment connectionIdentifier, uint64_t inspectedPageIdentifier, bool underTest);
index f2e721f..df94ee7 100644 (file)
@@ -290,6 +290,8 @@ private:
     virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override;
     virtual void didClose(IPC::Connection&) override;
     virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
+    virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Web; }
+    virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::UI; }
 
     // Implemented in generated WebProcessMessageReceiver.cpp
     void didReceiveWebProcessMessage(IPC::Connection&, IPC::MessageDecoder&);
index dbed956..72df1ce 100644 (file)
@@ -1,3 +1,13 @@
+2015-01-28  Timothy Horton  <timothy_horton@apple.com>
+
+        Add a WebKitMessageRecorder DTrace provider, exposing IPC details to DTrace
+        https://bugs.webkit.org/show_bug.cgi?id=140673
+
+        Reviewed by Sam Weinig.
+
+        * Scripts/dtrace/trace-webkit2-messages.d: Added.
+        Add a DTrace script that outputs a small blob of JSON per message.
+
 2015-01-28  Geoffrey Garen  <ggaren@apple.com>
 
         Removed fastMallocForbid / fastMallocAllow
diff --git a/Tools/Scripts/dtrace/trace-webkit2-messages.d b/Tools/Scripts/dtrace/trace-webkit2-messages.d
new file mode 100755 (executable)
index 0000000..4e8911d
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/sbin/dtrace -qZs
+
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct WebKitMessageRecord {
+    uint8_t sourceProcessType;
+    pid_t sourceProcessID;
+
+    uint8_t destinationProcessType;
+    pid_t destinationProcessID;
+
+    char* messageReceiverName;
+    char* messageName;
+    uint64_t destinationID;
+
+    char UUID[16];
+
+    double startTime;
+    double endTime;
+
+    bool isSyncMessage;
+    bool shouldDispatchMessageWhenWaitingForSyncReply;
+    bool isIncoming;
+};
+
+WebKitMessageRecorder*:::message_*
+{
+    this->record = (struct WebKitMessageRecord*)copyin(arg0, sizeof(struct WebKitMessageRecord));
+    printf("{");
+
+    printf("\"sourceProcessType\": %d, ", this->record->sourceProcessType);
+    printf("\"sourceProcessID\": %d, ", this->record->sourceProcessID);
+
+    printf("\"destinationProcessType\": %d, ", this->record->destinationProcessType);
+    printf("\"destinationProcessID\": %d, ", this->record->destinationProcessID);
+
+    printf("\"messageReceiverName\": \"%s\", ", copyinstr((user_addr_t)this->record->messageReceiverName));
+    printf("\"messageName\": \"%s\", ", copyinstr((user_addr_t)this->record->messageName));
+
+    printf("\"destinationID\": %d, ", this->record->destinationID);
+
+    printf("\"UUID\": \"");
+    printf("%02x", this->record->UUID[0]);
+    printf("%02x", this->record->UUID[1]);
+    printf("%02x", this->record->UUID[2]);
+    printf("%02x", this->record->UUID[3]);
+    printf("-");
+    printf("%02x", this->record->UUID[4]);
+    printf("%02x", this->record->UUID[5]);
+    printf("-");
+    printf("%02x", this->record->UUID[6]);
+    printf("%02x", this->record->UUID[7]);
+    printf("-");
+    printf("%02x", this->record->UUID[8]);
+    printf("%02x", this->record->UUID[9]);
+    printf("-");
+    printf("%02x", this->record->UUID[10]);
+    printf("%02x", this->record->UUID[11]);
+    printf("%02x", this->record->UUID[12]);
+    printf("%02x", this->record->UUID[13]);
+    printf("%02x", this->record->UUID[14]);
+    printf("%02x", this->record->UUID[15]);
+    printf("\", ");
+
+    printf("\"startTime\": %f, ", this->record->startTime);
+    printf("\"endTime\": %f, ", this->record->endTime);
+
+    printf("\"isSyncMessage\": %d, ", this->record->isSyncMessage);
+    printf("\"shouldDispatchMessageWhenWaitingForSyncReply\": %d, ", this->record->shouldDispatchMessageWhenWaitingForSyncReply);
+    printf("\"isIncoming\": %d", this->record->isIncoming);
+
+    printf("}\n");
+}