Revert "libmojo: Uprev the library to r456626 from Chromium"
This reverts commit 8ac9103e05b66812c25348943383f9365d1ce3e0.
Reason for revert: Broke the mac_sdk
Exempt-From-Owner-Approval: Fixing mac_sdk
Change-Id: I0b74d1abaa66933a93fd6f82ff018e8948c1204e
diff --git a/ipc/attachment_broker.h b/ipc/attachment_broker.h
new file mode 100644
index 0000000..a106e29
--- /dev/null
+++ b/ipc/attachment_broker.h
@@ -0,0 +1,176 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IPC_ATTACHMENT_BROKER_H_
+#define IPC_ATTACHMENT_BROKER_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/process/process_handle.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_listener.h"
+
+// If the platform has no attachments that need brokering, then it shouldn't
+// compile any code that calls member functions of AttachmentBroker. This
+// prevents symbols only used by AttachmentBroker and its subclasses from
+// making it into the binary.
+#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#define USE_ATTACHMENT_BROKER 1
+#else
+#define USE_ATTACHMENT_BROKER 0
+#endif // defined(OS_WIN)
+
+namespace base {
+class SequencedTaskRunner;
+class SingleThreadTaskRunner;
+};
+
+namespace IPC {
+
+class AttachmentBroker;
+class Endpoint;
+
+// Classes that inherit from this abstract base class are capable of
+// communicating with a broker to send and receive attachments to Chrome IPC
+// messages.
+class IPC_EXPORT SupportsAttachmentBrokering {
+ public:
+ // Returns an AttachmentBroker used to broker attachments of IPC messages to
+ // other processes. There must be exactly one AttachmentBroker per process.
+ virtual AttachmentBroker* GetAttachmentBroker() = 0;
+};
+
+// Responsible for brokering attachments to Chrome IPC messages. On platforms
+// that support attachment brokering, every IPC channel should have a reference
+// to a AttachmentBroker.
+// This class is not thread safe. The implementation of this class assumes that
+// it is only ever used on the same thread as its consumers.
+class IPC_EXPORT AttachmentBroker : public Listener {
+ public:
+ // A standard observer interface that allows consumers of the AttachmentBroker
+ // to be notified when a new attachment has been received.
+ class Observer {
+ public:
+ virtual void ReceivedBrokerableAttachmentWithId(
+ const BrokerableAttachment::AttachmentId& id) = 0;
+ };
+
+ // Each process has at most one attachment broker. The process is responsible
+ // for ensuring that |broker| stays alive for as long as the process is
+ // sending/receiving ipc messages.
+ static void SetGlobal(AttachmentBroker* broker);
+ static AttachmentBroker* GetGlobal();
+
+ AttachmentBroker();
+ ~AttachmentBroker() override;
+
+ // Sends |attachment| to |destination_process|. The implementation uses an
+ // IPC::Channel to communicate with the broker process. This may be the same
+ // IPC::Channel that is requesting the brokering of an attachment.
+ // Returns true on success and false otherwise.
+ virtual bool SendAttachmentToProcess(
+ const scoped_refptr<BrokerableAttachment>& attachment,
+ base::ProcessId destination_process) = 0;
+
+ // Returns whether the attachment was available. If the attachment was
+ // available, populates the output parameter |attachment|.
+ bool GetAttachmentWithId(BrokerableAttachment::AttachmentId id,
+ scoped_refptr<BrokerableAttachment>* attachment);
+
+ // Any given observer should only ever add itself once to the observer list.
+ // Notifications to |observer| will be posted to |runner|.
+ // The |observer| is expected to call RemoveObserver() before being destroyed.
+ void AddObserver(Observer* observer,
+ const scoped_refptr<base::SequencedTaskRunner>& runner);
+ void RemoveObserver(Observer* observer);
+
+ // These two methods should only be called by the broker process.
+ //
+ // Each unprivileged process should have one IPC channel on which it
+ // communicates attachment information with the broker process. In the broker
+ // process, these channels must be registered and deregistered with the
+ // Attachment Broker as they are created and destroyed.
+ //
+ // Invocations of Send() on |endpoint| will occur on thread bound to |runner|.
+ virtual void RegisterCommunicationChannel(
+ Endpoint* endpoint,
+ scoped_refptr<base::SingleThreadTaskRunner> runner);
+ virtual void DeregisterCommunicationChannel(Endpoint* endpoint);
+
+ // In each unprivileged process, exactly one channel should be used to
+ // communicate brokerable attachments with the broker process.
+ virtual void RegisterBrokerCommunicationChannel(Endpoint* endpoint);
+ virtual void DeregisterBrokerCommunicationChannel(Endpoint* endpoint);
+
+ // Informs the attachment broker that a channel endpoint has received its
+ // peer's PID.
+ virtual void ReceivedPeerPid(base::ProcessId peer_pid);
+
+ // True if and only if this broker is privileged.
+ virtual bool IsPrivilegedBroker();
+
+ protected:
+ using AttachmentVector = std::vector<scoped_refptr<BrokerableAttachment>>;
+
+ // Adds |attachment| to |attachments_|, and notifies the observers.
+ void HandleReceivedAttachment(
+ const scoped_refptr<BrokerableAttachment>& attachment);
+
+ // Informs the observers that a new BrokerableAttachment has been received.
+ void NotifyObservers(const BrokerableAttachment::AttachmentId& id);
+
+ // Informs the observer identified by |unique_id| that a new
+ // BrokerableAttachment has been received.
+ void NotifyObserver(int unique_id,
+ const BrokerableAttachment::AttachmentId& id);
+
+ // This method is exposed for testing only.
+ AttachmentVector* get_attachments() { return &attachments_; }
+
+ base::Lock* get_lock() { return &lock_; }
+
+ private:
+#if defined(OS_WIN)
+ FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerUnprivilegedWinTest,
+ ReceiveValidMessage);
+ FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerUnprivilegedWinTest,
+ ReceiveInvalidMessage);
+#endif // defined(OS_WIN)
+
+ // A vector of BrokerableAttachments that have been received, but not yet
+ // consumed.
+ // A std::vector is used instead of a std::map because this container is
+ // expected to have few elements, for which a std::vector is expected to have
+ // better performance.
+ AttachmentVector attachments_;
+
+ struct ObserverInfo {
+ ObserverInfo();
+ ObserverInfo(const ObserverInfo& other);
+ ~ObserverInfo();
+
+ Observer* observer;
+ int unique_id;
+
+ // Notifications must be dispatched onto |runner|.
+ scoped_refptr<base::SequencedTaskRunner> runner;
+ };
+ std::vector<ObserverInfo> observers_;
+
+ // This member holds the last id given to an ObserverInfo.
+ int last_unique_id_;
+
+ // The AttachmentBroker can be accessed from any thread, so modifications to
+ // internal state must be guarded by a lock.
+ base::Lock lock_;
+ DISALLOW_COPY_AND_ASSIGN(AttachmentBroker);
+};
+
+} // namespace IPC
+
+#endif // IPC_ATTACHMENT_BROKER_H_
diff --git a/ipc/brokerable_attachment.cc b/ipc/brokerable_attachment.cc
new file mode 100644
index 0000000..96ce5bb
--- /dev/null
+++ b/ipc/brokerable_attachment.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ipc/brokerable_attachment.h"
+
+#include <stddef.h>
+
+#include "build/build_config.h"
+#include "ipc/attachment_broker.h"
+
+namespace IPC {
+
+// BrokerableAttachment::AttachmentId ------------------------------------------
+#if !USE_ATTACHMENT_BROKER
+// static
+BrokerableAttachment::AttachmentId
+BrokerableAttachment::AttachmentId::CreateIdWithRandomNonce() {
+ CHECK(false) << "Platforms that don't support attachment brokering shouldn't "
+ "be trying to generating a random nonce.";
+ return AttachmentId();
+}
+#endif
+
+BrokerableAttachment::AttachmentId::AttachmentId() {
+ for (size_t i = 0; i < BrokerableAttachment::kNonceSize; ++i)
+ nonce[i] = 0;
+}
+
+BrokerableAttachment::AttachmentId::AttachmentId(const char* start_address,
+ size_t size) {
+ DCHECK(size == BrokerableAttachment::kNonceSize);
+ for (size_t i = 0; i < BrokerableAttachment::kNonceSize; ++i)
+ nonce[i] = start_address[i];
+}
+
+void BrokerableAttachment::AttachmentId::SerializeToBuffer(char* start_address,
+ size_t size) {
+ DCHECK(size == BrokerableAttachment::kNonceSize);
+ for (size_t i = 0; i < BrokerableAttachment::kNonceSize; ++i)
+ start_address[i] = nonce[i];
+}
+
+// BrokerableAttachment::BrokerableAttachment ----------------------------------
+
+BrokerableAttachment::BrokerableAttachment()
+ : id_(AttachmentId::CreateIdWithRandomNonce()) {}
+
+BrokerableAttachment::BrokerableAttachment(const AttachmentId& id) : id_(id) {}
+
+BrokerableAttachment::~BrokerableAttachment() {}
+
+BrokerableAttachment::AttachmentId BrokerableAttachment::GetIdentifier() const {
+ return id_;
+}
+
+bool BrokerableAttachment::NeedsBrokering() const {
+ return GetBrokerableType() == PLACEHOLDER;
+}
+
+BrokerableAttachment::Type BrokerableAttachment::GetType() const {
+ return TYPE_BROKERABLE_ATTACHMENT;
+}
+
+#if defined(OS_POSIX)
+base::PlatformFile BrokerableAttachment::TakePlatformFile() {
+ NOTREACHED();
+ return base::PlatformFile();
+}
+#endif // OS_POSIX
+
+} // namespace IPC
diff --git a/ipc/brokerable_attachment.h b/ipc/brokerable_attachment.h
new file mode 100644
index 0000000..50e7fd2
--- /dev/null
+++ b/ipc/brokerable_attachment.h
@@ -0,0 +1,91 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IPC_BROKERABLE_ATTACHMENT_H_
+#define IPC_BROKERABLE_ATTACHMENT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_message_attachment.h"
+
+namespace IPC {
+
+// This subclass of MessageAttachment requires an AttachmentBroker to be
+// attached to a Chrome IPC message.
+class IPC_EXPORT BrokerableAttachment : public MessageAttachment {
+ public:
+ static const size_t kNonceSize = 16;
+ // An id uniquely identifies an attachment sent via a broker.
+ struct IPC_EXPORT AttachmentId {
+ uint8_t nonce[kNonceSize];
+
+ // Generates an AttachmentId with an unguessable, random nonce.
+ static AttachmentId CreateIdWithRandomNonce();
+
+ // Creates an AttachmentId with a zeroed nonce. This should only be used by
+ // the IPC translation system, which requires that classes have a default
+ // constructor.
+ AttachmentId();
+
+ // Constructs an AttachmentId from a buffer.
+ AttachmentId(const char* start_address, size_t size);
+
+ // Writes the nonce into a buffer.
+ void SerializeToBuffer(char* start_address, size_t size);
+
+ bool operator==(const AttachmentId& rhs) const {
+ return std::equal(nonce, nonce + kNonceSize, rhs.nonce);
+ }
+
+ bool operator<(const AttachmentId& rhs) const {
+ return std::lexicographical_compare(nonce, nonce + kNonceSize, rhs.nonce,
+ rhs.nonce + kNonceSize);
+ }
+ };
+
+ enum BrokerableType {
+ PLACEHOLDER,
+ WIN_HANDLE,
+ MACH_PORT,
+ };
+
+ // The identifier is unique across all Chrome processes.
+ AttachmentId GetIdentifier() const;
+
+ // Whether the attachment still needs information from the broker before it
+ // can be used.
+ bool NeedsBrokering() const;
+
+ // Returns TYPE_BROKERABLE_ATTACHMENT
+ Type GetType() const override;
+
+ virtual BrokerableType GetBrokerableType() const = 0;
+
+// MessageAttachment override.
+#if defined(OS_POSIX)
+ base::PlatformFile TakePlatformFile() override;
+#endif // OS_POSIX
+
+ protected:
+ BrokerableAttachment();
+ BrokerableAttachment(const AttachmentId& id);
+ ~BrokerableAttachment() override;
+
+ private:
+ // This member uniquely identifies a BrokerableAttachment across all Chrome
+ // processes.
+ const AttachmentId id_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrokerableAttachment);
+};
+
+} // namespace IPC
+
+#endif // IPC_BROKERABLE_ATTACHMENT_H_
diff --git a/ipc/ipc.mojom b/ipc/ipc.mojom
deleted file mode 100644
index 0a4fcfa..0000000
--- a/ipc/ipc.mojom
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module IPC.mojom;
-
-// NOTE: This MUST match the value of MSG_ROUTING_NONE in src/ipc/ipc_message.h.
-const int32 kRoutingIdNone = -2;
-
-struct SerializedHandle {
- handle the_handle;
-
- enum Type {
- MOJO_HANDLE,
- PLATFORM_FILE,
- WIN_HANDLE,
- MACH_PORT,
- };
-
- Type type;
-};
-
-// A placeholder interface type since we don't yet support generic associated
-// message pipe handles.
-interface GenericInterface {};
-
-interface Channel {
- // Informs the remote end of this client's PID. Must be called exactly once,
- // before any calls to Receive() below.
- SetPeerPid(int32 pid);
-
- // Transmits a classical Chrome IPC message.
- Receive(array<uint8> data, array<SerializedHandle>? handles);
-
- // Requests a Channel-associated interface.
- GetAssociatedInterface(string name, associated GenericInterface& request);
-};
-
-// A strictly nominal interface used to identify Channel bootstrap requests.
-interface ChannelBootstrap {};
diff --git a/ipc/ipc_channel_handle.h b/ipc/ipc_channel_handle.h
index ef31b84..2e9dc3e 100644
--- a/ipc/ipc_channel_handle.h
+++ b/ipc/ipc_channel_handle.h
@@ -10,31 +10,60 @@
#include "build/build_config.h"
#include "mojo/public/cpp/system/message_pipe.h"
-#if defined(OS_NACL_SFI)
+#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
-#endif // defined (OS_NACL_SFI)
+#elif defined(OS_WIN)
+#include <windows.h>
+#endif // defined (OS_WIN)
+
+// On Windows, any process can create an IPC channel and others can fetch
+// it by name. We pass around the channel names over IPC.
+// On Windows the initialization of ChannelHandle with an existing pipe
+// handle is provided for convenience.
+// NOTE: A ChannelHandle with a pipe handle Will NOT be marshalled over IPC.
+
+// On POSIX, we instead pass around handles to channel endpoints via IPC.
+// When it's time to IPC a new channel endpoint around, we send both the
+// channel name as well as a base::FileDescriptor, which is itself a special
+// type that knows how to copy a socket endpoint over IPC.
+//
+// In sum, this data structure can be used to pass channel information by name
+// in both Windows and Posix. When passing a handle to a channel over IPC,
+// use this data structure only for POSIX.
namespace IPC {
-// Note that serialization for this object is defined in the ParamTraits
-// template specialization in ipc_message_utils.h.
-#if defined(OS_NACL_SFI)
struct ChannelHandle {
+ // Note that serialization for this object is defined in the ParamTraits
+ // template specialization in ipc_message_utils.h.
ChannelHandle() {}
- explicit ChannelHandle(const base::FileDescriptor& s) : socket(s) {}
-
- base::FileDescriptor socket;
-};
-#else
-struct ChannelHandle {
- ChannelHandle() {}
+ // The name that is passed in should be an absolute path for Posix.
+ // Otherwise there may be a problem in IPC communication between
+ // processes with different working directories.
+ ChannelHandle(const std::string& n) : name(n) {}
+ ChannelHandle(const char* n) : name(n) {}
+#if defined(OS_WIN)
+ explicit ChannelHandle(HANDLE h) : pipe(h) {}
+#elif defined(OS_POSIX)
+ ChannelHandle(const std::string& n, const base::FileDescriptor& s)
+ : name(n), socket(s) {}
+#endif // defined(OS_POSIX)
ChannelHandle(mojo::MessagePipeHandle h) : mojo_handle(h) {}
- bool is_mojo_channel_handle() const { return mojo_handle.is_valid(); }
-
+ std::string name;
+#if defined(OS_POSIX)
+ base::FileDescriptor socket;
+#elif defined(OS_WIN)
+ // A simple container to automatically initialize pipe handle
+ struct PipeHandle {
+ PipeHandle() : handle(NULL) {}
+ PipeHandle(HANDLE h) : handle(h) {}
+ HANDLE handle;
+ };
+ PipeHandle pipe;
+#endif // defined (OS_WIN)
mojo::MessagePipeHandle mojo_handle;
};
-#endif // defined(OS_NACL_SFI)
} // namespace IPC
diff --git a/ipc/ipc_listener.h b/ipc/ipc_listener.h
index d7ad75c..0277086 100644
--- a/ipc/ipc_listener.h
+++ b/ipc/ipc_listener.h
@@ -7,11 +7,8 @@
#include <stdint.h>
-#include <string>
-
#include "build/build_config.h"
#include "ipc/ipc_export.h"
-#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
namespace IPC {
@@ -35,12 +32,6 @@
// Called when a message's deserialization failed.
virtual void OnBadMessageReceived(const Message& message) {}
- // Called when an associated interface request is received on a Channel and
- // the Channel has no registered handler for it.
- virtual void OnAssociatedInterfaceRequest(
- const std::string& interface_name,
- mojo::ScopedInterfaceEndpointHandle handle) {}
-
#if defined(OS_POSIX)
// Called on the server side when a channel that listens for connections
// denies an attempt to connect.
diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc
index f5e9ac7..83ee495 100644
--- a/ipc/ipc_message.cc
+++ b/ipc/ipc_message.cc
@@ -11,8 +11,10 @@
#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "build/build_config.h"
+#include "ipc/attachment_broker.h"
#include "ipc/ipc_message_attachment.h"
#include "ipc/ipc_message_attachment_set.h"
+#include "ipc/placeholder_brokerable_attachment.h"
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
@@ -50,6 +52,9 @@
Message::Message() : base::Pickle(sizeof(Header)) {
header()->routing = header()->type = 0;
header()->flags = GetRefNumUpper24();
+#if USE_ATTACHMENT_BROKER
+ header()->num_brokered_attachments = 0;
+#endif
#if defined(OS_POSIX)
header()->num_fds = 0;
header()->pad = 0;
@@ -63,6 +68,9 @@
header()->type = type;
DCHECK((priority & 0xffffff00) == 0);
header()->flags = priority | GetRefNumUpper24();
+#if USE_ATTACHMENT_BROKER
+ header()->num_brokered_attachments = 0;
+#endif
#if defined(OS_POSIX)
header()->num_fds = 0;
header()->pad = 0;
@@ -78,10 +86,12 @@
Message::Message(const Message& other) : base::Pickle(other) {
Init();
attachment_set_ = other.attachment_set_;
+ sender_pid_ = other.sender_pid_;
}
void Message::Init() {
dispatch_error_ = false;
+ sender_pid_ = base::kNullProcessId;
#ifdef IPC_MESSAGE_LOG_ENABLED
received_time_ = 0;
dont_log_ = false;
@@ -92,6 +102,7 @@
Message& Message::operator=(const Message& other) {
*static_cast<base::Pickle*>(this) = other;
attachment_set_ = other.attachment_set_;
+ sender_pid_ = other.sender_pid_;
return *this;
}
@@ -135,6 +146,26 @@
message_end(nullptr) {}
Message::NextMessageInfo::~NextMessageInfo() {}
+Message::SerializedAttachmentIds
+Message::SerializedIdsOfBrokerableAttachments() {
+ DCHECK(HasBrokerableAttachments());
+ std::vector<scoped_refptr<IPC::BrokerableAttachment>> attachments(
+ attachment_set_->GetBrokerableAttachments());
+ CHECK_LE(attachments.size(), std::numeric_limits<size_t>::max() /
+ BrokerableAttachment::kNonceSize);
+ size_t size = attachments.size() * BrokerableAttachment::kNonceSize;
+ char* buffer = static_cast<char*>(malloc(size));
+ for (size_t i = 0; i < attachments.size(); ++i) {
+ char* start_range = buffer + i * BrokerableAttachment::kNonceSize;
+ BrokerableAttachment::AttachmentId id = attachments[i]->GetIdentifier();
+ id.SerializeToBuffer(start_range, BrokerableAttachment::kNonceSize);
+ }
+ SerializedAttachmentIds ids;
+ ids.buffer = buffer;
+ ids.size = size;
+ return ids;
+}
+
// static
void Message::FindNext(const char* range_start,
const char* range_end,
@@ -151,6 +182,43 @@
bool have_entire_pickle =
static_cast<size_t>(range_end - range_start) >= pickle_size;
+#if USE_ATTACHMENT_BROKER
+ // TODO(dskiba): determine message_size when entire pickle is not available
+
+ if (!have_entire_pickle)
+ return;
+
+ const char* pickle_end = range_start + pickle_size;
+
+ // The data is not copied.
+ Message message(range_start, static_cast<int>(pickle_size));
+ size_t num_attachments = message.header()->num_brokered_attachments;
+
+ // Check for possible overflows.
+ size_t max_size_t = std::numeric_limits<size_t>::max();
+ if (num_attachments >= max_size_t / BrokerableAttachment::kNonceSize)
+ return;
+
+ size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize;
+ if (pickle_size > max_size_t - attachment_length)
+ return;
+
+ // Check whether the range includes the attachments.
+ size_t buffer_length = static_cast<size_t>(range_end - range_start);
+ if (buffer_length < attachment_length + pickle_size)
+ return;
+
+ for (size_t i = 0; i < num_attachments; ++i) {
+ const char* attachment_start =
+ pickle_end + i * BrokerableAttachment::kNonceSize;
+ BrokerableAttachment::AttachmentId id(attachment_start,
+ BrokerableAttachment::kNonceSize);
+ info->attachment_ids.push_back(id);
+ }
+ info->message_end =
+ pickle_end + num_attachments * BrokerableAttachment::kNonceSize;
+ info->message_size = info->message_end - range_start;
+#else
info->message_size = pickle_size;
if (!have_entire_pickle)
@@ -159,32 +227,53 @@
const char* pickle_end = range_start + pickle_size;
info->message_end = pickle_end;
+#endif // USE_ATTACHMENT_BROKER
info->pickle_end = pickle_end;
info->message_found = true;
}
+bool Message::AddPlaceholderBrokerableAttachmentWithId(
+ BrokerableAttachment::AttachmentId id) {
+ scoped_refptr<PlaceholderBrokerableAttachment> attachment(
+ new PlaceholderBrokerableAttachment(id));
+ return attachment_set()->AddAttachment(attachment);
+}
+
bool Message::WriteAttachment(
scoped_refptr<base::Pickle::Attachment> attachment) {
+ bool brokerable;
size_t index;
bool success = attachment_set()->AddAttachment(
make_scoped_refptr(static_cast<MessageAttachment*>(attachment.get())),
- &index);
+ &index, &brokerable);
DCHECK(success);
// NOTE: If you add more data to the pickle, make sure to update
// PickleSizer::AddAttachment.
+ // Write the type of descriptor.
+ WriteBool(brokerable);
+
// Write the index of the descriptor so that we don't have to
// keep the current descriptor as extra decoding state when deserialising.
WriteInt(static_cast<int>(index));
+#if USE_ATTACHMENT_BROKER
+ if (brokerable)
+ header()->num_brokered_attachments++;
+#endif
+
return success;
}
bool Message::ReadAttachment(
base::PickleIterator* iter,
scoped_refptr<base::Pickle::Attachment>* attachment) const {
+ bool brokerable;
+ if (!iter->ReadBool(&brokerable))
+ return false;
+
int index;
if (!iter->ReadInt(&index))
return false;
@@ -193,7 +282,9 @@
if (!attachment_set)
return false;
- *attachment = attachment_set->GetAttachmentAt(index);
+ *attachment = brokerable
+ ? attachment_set->GetBrokerableAttachmentAt(index)
+ : attachment_set->GetNonBrokerableAttachmentAt(index);
return nullptr != attachment->get();
}
@@ -202,4 +293,13 @@
return attachment_set_.get() && !attachment_set_->empty();
}
+bool Message::HasMojoHandles() const {
+ return attachment_set_.get() && attachment_set_->num_mojo_handles() > 0;
+}
+
+bool Message::HasBrokerableAttachments() const {
+ return attachment_set_.get() &&
+ attachment_set_->num_brokerable_attachments() > 0;
+}
+
} // namespace IPC
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
index 43e9ae3..56c3a46 100644
--- a/ipc/ipc_message.h
+++ b/ipc/ipc_message.h
@@ -15,6 +15,8 @@
#include "base/pickle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "ipc/attachment_broker.h"
+#include "ipc/brokerable_attachment.h"
#include "ipc/ipc_export.h"
#if !defined(NDEBUG)
@@ -30,6 +32,7 @@
//------------------------------------------------------------------------------
struct LogData;
+class MessageAttachment;
class MessageAttachmentSet;
class IPC_EXPORT Message : public base::Pickle {
@@ -188,13 +191,34 @@
// The end address of the message should be used to determine the start
// address of the next message.
const char* message_end;
+ // If the message has brokerable attachments, this vector will contain the
+ // ids of the brokerable attachments. The caller of FindNext() is
+ // responsible for adding the attachments to the message.
+ std::vector<BrokerableAttachment::AttachmentId> attachment_ids;
};
+ struct SerializedAttachmentIds {
+ void* buffer;
+ size_t size;
+ };
+ // Creates a buffer that contains a serialization of the ids of the brokerable
+ // attachments of the message. This buffer is intended to be sent over the IPC
+ // channel immediately after the pickled message. The caller takes ownership
+ // of the buffer.
+ // This method should only be called if the message has brokerable
+ // attachments.
+ SerializedAttachmentIds SerializedIdsOfBrokerableAttachments();
+
// |info| is an output parameter and must not be nullptr.
static void FindNext(const char* range_start,
const char* range_end,
NextMessageInfo* info);
+ // Adds a placeholder brokerable attachment that must be replaced before the
+ // message can be dispatched.
+ bool AddPlaceholderBrokerableAttachmentWithId(
+ BrokerableAttachment::AttachmentId id);
+
// WriteAttachment appends |attachment| to the end of the set. It returns
// false iff the set is full.
bool WriteAttachment(
@@ -206,6 +230,13 @@
scoped_refptr<base::Pickle::Attachment>* attachment) const override;
// Returns true if there are any attachment in this message.
bool HasAttachments() const override;
+ // Returns true if there are any MojoHandleAttachments in this message.
+ bool HasMojoHandles() const;
+ // Whether the message has any brokerable attachments.
+ bool HasBrokerableAttachments() const;
+
+ void set_sender_pid(base::ProcessId id) { sender_pid_ = id; }
+ base::ProcessId get_sender_pid() const { return sender_pid_; }
#ifdef IPC_MESSAGE_LOG_ENABLED
// Adds the outgoing time from Time::Now() at the end of the message and sets
@@ -242,6 +273,12 @@
int32_t routing; // ID of the view that this message is destined for
uint32_t type; // specifies the user-defined message type
uint32_t flags; // specifies control flags for the message
+#if USE_ATTACHMENT_BROKER
+ // The number of brokered attachments included with this message. The
+ // ids of the brokered attachment ids are sent immediately after the pickled
+ // message, before the next pickled message is sent.
+ uint32_t num_brokered_attachments;
+#endif
#if defined(OS_POSIX)
uint16_t num_fds; // the number of descriptors included with this message
uint16_t pad; // explicitly initialize this to appease valgrind
@@ -275,6 +312,10 @@
return attachment_set_.get();
}
+ // The process id of the sender of the message. This member is populated with
+ // a valid value for every message dispatched to listeners.
+ base::ProcessId sender_pid_;
+
#ifdef IPC_MESSAGE_LOG_ENABLED
// Used for logging.
mutable int64_t received_time_;
diff --git a/ipc/ipc_message_attachment.h b/ipc/ipc_message_attachment.h
index 9ff1de8..7f7137d 100644
--- a/ipc/ipc_message_attachment.h
+++ b/ipc/ipc_message_attachment.h
@@ -10,7 +10,6 @@
#include "base/memory/ref_counted.h"
#include "base/pickle.h"
#include "build/build_config.h"
-#include "ipc/ipc.mojom.h"
#include "ipc/ipc_export.h"
namespace IPC {
@@ -19,10 +18,18 @@
// or a mojo |MessagePipe|. |GetType()| returns the type of the subclass.
class IPC_EXPORT MessageAttachment : public base::Pickle::Attachment {
public:
- using Type = mojom::SerializedHandle::Type;
+ enum Type {
+ TYPE_PLATFORM_FILE, // The instance is |PlatformFileAttachment|.
+ TYPE_MOJO_HANDLE, // The instance is |MojoHandleAttachment|.
+ TYPE_BROKERABLE_ATTACHMENT, // The instance is |BrokerableAttachment|.
+ };
virtual Type GetType() const = 0;
+#if defined(OS_POSIX)
+ virtual base::PlatformFile TakePlatformFile() = 0;
+#endif // OS_POSIX
+
protected:
friend class base::RefCountedThreadSafe<MessageAttachment>;
MessageAttachment();
diff --git a/ipc/ipc_message_attachment_set.cc b/ipc/ipc_message_attachment_set.cc
index b9a990d..3b7eefb 100644
--- a/ipc/ipc_message_attachment_set.cc
+++ b/ipc/ipc_message_attachment_set.cc
@@ -11,8 +11,16 @@
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
+#include "ipc/brokerable_attachment.h"
#include "ipc/ipc_message_attachment.h"
+#if defined(OS_POSIX)
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "ipc/ipc_platform_file_attachment_posix.h"
+#endif // OS_POSIX
+
namespace IPC {
namespace {
@@ -35,7 +43,7 @@
}
MessageAttachmentSet::~MessageAttachmentSet() {
- if (consumed_descriptor_highwater_ == size())
+ if (consumed_descriptor_highwater_ == num_non_brokerable_attachments())
return;
// We close all the owning descriptors. If this message should have
@@ -46,24 +54,39 @@
// (which could a DOS against the browser by a rogue renderer) then all
// the descriptors have their close flag set and we free all the extra
// kernel resources.
- LOG(WARNING) << "MessageAttachmentSet destroyed with unconsumed attachments: "
- << consumed_descriptor_highwater_ << "/" << size();
+ LOG(WARNING) << "MessageAttachmentSet destroyed with unconsumed descriptors: "
+ << consumed_descriptor_highwater_ << "/" << num_descriptors();
}
unsigned MessageAttachmentSet::num_descriptors() const {
return count_attachments_of_type(attachments_,
- MessageAttachment::Type::PLATFORM_FILE);
+ MessageAttachment::TYPE_PLATFORM_FILE);
+}
+
+unsigned MessageAttachmentSet::num_mojo_handles() const {
+ return count_attachments_of_type(attachments_,
+ MessageAttachment::TYPE_MOJO_HANDLE);
+}
+
+unsigned MessageAttachmentSet::num_brokerable_attachments() const {
+ return static_cast<unsigned>(brokerable_attachments_.size());
+}
+
+unsigned MessageAttachmentSet::num_non_brokerable_attachments() const {
+ return static_cast<unsigned>(attachments_.size());
}
unsigned MessageAttachmentSet::size() const {
- return static_cast<unsigned>(attachments_.size());
+ return static_cast<unsigned>(attachments_.size() +
+ brokerable_attachments_.size());
}
bool MessageAttachmentSet::AddAttachment(
scoped_refptr<MessageAttachment> attachment,
- size_t* index) {
+ size_t* index,
+ bool* brokerable) {
#if defined(OS_POSIX)
- if (attachment->GetType() == MessageAttachment::Type::PLATFORM_FILE &&
+ if (attachment->GetType() == MessageAttachment::TYPE_PLATFORM_FILE &&
num_descriptors() == kMaxDescriptorsPerMessage) {
DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full.";
return false;
@@ -71,12 +94,19 @@
#endif
switch (attachment->GetType()) {
- case MessageAttachment::Type::PLATFORM_FILE:
- case MessageAttachment::Type::MOJO_HANDLE:
- case MessageAttachment::Type::WIN_HANDLE:
- case MessageAttachment::Type::MACH_PORT:
+ case MessageAttachment::TYPE_PLATFORM_FILE:
+ case MessageAttachment::TYPE_MOJO_HANDLE:
attachments_.push_back(attachment);
*index = attachments_.size() - 1;
+ *brokerable = false;
+ return true;
+ case MessageAttachment::TYPE_BROKERABLE_ATTACHMENT:
+ BrokerableAttachment* brokerable_attachment =
+ static_cast<BrokerableAttachment*>(attachment.get());
+ scoped_refptr<BrokerableAttachment> a(brokerable_attachment);
+ brokerable_attachments_.push_back(a);
+ *index = brokerable_attachments_.size() - 1;
+ *brokerable = true;
return true;
}
return false;
@@ -84,14 +114,16 @@
bool MessageAttachmentSet::AddAttachment(
scoped_refptr<MessageAttachment> attachment) {
+ bool brokerable;
size_t index;
- return AddAttachment(attachment, &index);
+ return AddAttachment(attachment, &index, &brokerable);
}
-scoped_refptr<MessageAttachment> MessageAttachmentSet::GetAttachmentAt(
- unsigned index) {
- if (index >= size()) {
- DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size();
+scoped_refptr<MessageAttachment>
+MessageAttachmentSet::GetNonBrokerableAttachmentAt(unsigned index) {
+ if (index >= num_non_brokerable_attachments()) {
+ DLOG(WARNING) << "Accessing out of bound index:" << index << "/"
+ << num_non_brokerable_attachments();
return scoped_refptr<MessageAttachment>();
}
@@ -116,7 +148,8 @@
// end of the array and index 0 is requested, we reset the highwater value.
// TODO(morrita): This is absurd. This "wringle" disallow to introduce clearer
// ownership model. Only client is NaclIPCAdapter. See crbug.com/415294
- if (index == 0 && consumed_descriptor_highwater_ == size()) {
+ if (index == 0 &&
+ consumed_descriptor_highwater_ == num_non_brokerable_attachments()) {
consumed_descriptor_highwater_ = 0;
}
@@ -128,9 +161,90 @@
return attachments_[index];
}
+scoped_refptr<MessageAttachment>
+MessageAttachmentSet::GetBrokerableAttachmentAt(unsigned index) {
+ if (index >= num_brokerable_attachments()) {
+ DLOG(WARNING) << "Accessing out of bound index:" << index << "/"
+ << num_brokerable_attachments();
+ return scoped_refptr<MessageAttachment>();
+ }
+
+ scoped_refptr<BrokerableAttachment> brokerable_attachment(
+ brokerable_attachments_[index]);
+ return scoped_refptr<MessageAttachment>(brokerable_attachment.get());
+}
+
void MessageAttachmentSet::CommitAllDescriptors() {
attachments_.clear();
consumed_descriptor_highwater_ = 0;
}
+std::vector<scoped_refptr<IPC::BrokerableAttachment>>
+MessageAttachmentSet::GetBrokerableAttachments() const {
+ return brokerable_attachments_;
+}
+
+void MessageAttachmentSet::ReplacePlaceholderWithAttachment(
+ const scoped_refptr<BrokerableAttachment>& attachment) {
+ DCHECK_NE(BrokerableAttachment::PLACEHOLDER, attachment->GetBrokerableType());
+ for (auto it = brokerable_attachments_.begin();
+ it != brokerable_attachments_.end(); ++it) {
+ if ((*it)->GetBrokerableType() == BrokerableAttachment::PLACEHOLDER &&
+ (*it)->GetIdentifier() == attachment->GetIdentifier()) {
+ *it = attachment;
+ return;
+ }
+ }
+
+ // This function should only be called if there is a placeholder ready to be
+ // replaced.
+ NOTREACHED();
+}
+
+#if defined(OS_POSIX)
+
+void MessageAttachmentSet::PeekDescriptors(base::PlatformFile* buffer) const {
+ for (size_t i = 0; i != attachments_.size(); ++i)
+ buffer[i] = internal::GetPlatformFile(attachments_[i]);
+}
+
+bool MessageAttachmentSet::ContainsDirectoryDescriptor() const {
+ struct stat st;
+
+ for (auto i = attachments_.begin(); i != attachments_.end(); ++i) {
+ if (fstat(internal::GetPlatformFile(*i), &st) == 0 && S_ISDIR(st.st_mode))
+ return true;
+ }
+
+ return false;
+}
+
+void MessageAttachmentSet::ReleaseFDsToClose(
+ std::vector<base::PlatformFile>* fds) {
+ for (size_t i = 0; i < attachments_.size(); ++i) {
+ internal::PlatformFileAttachment* file =
+ static_cast<internal::PlatformFileAttachment*>(attachments_[i].get());
+ if (file->Owns())
+ fds->push_back(file->TakePlatformFile());
+ }
+
+ CommitAllDescriptors();
+}
+
+void MessageAttachmentSet::AddDescriptorsToOwn(const base::PlatformFile* buffer,
+ unsigned count) {
+ DCHECK(count <= kMaxDescriptorsPerMessage);
+ DCHECK_EQ(num_descriptors(), 0u);
+ DCHECK_EQ(consumed_descriptor_highwater_, 0u);
+
+ attachments_.reserve(count);
+ for (unsigned i = 0; i < count; ++i)
+ AddAttachment(
+ new internal::PlatformFileAttachment(base::ScopedFD(buffer[i])));
+}
+
+#endif // OS_POSIX
+
} // namespace IPC
+
+
diff --git a/ipc/ipc_message_attachment_set.h b/ipc/ipc_message_attachment_set.h
index de37211..764c818 100644
--- a/ipc/ipc_message_attachment_set.h
+++ b/ipc/ipc_message_attachment_set.h
@@ -14,17 +14,31 @@
#include "build/build_config.h"
#include "ipc/ipc_export.h"
+#if defined(OS_POSIX)
+#include "base/files/file.h"
+#endif
+
namespace IPC {
+class BrokerableAttachment;
class MessageAttachment;
// -----------------------------------------------------------------------------
// A MessageAttachmentSet is an ordered set of MessageAttachment objects
-// associated with an IPC message. All attachments are wrapped in a mojo handle
-// if necessary and sent over the mojo message pipe.
+// associated with an IPC message. There are three types of MessageAttachments:
+// 1) TYPE_PLATFORM_FILE is transmitted over the Channel's underlying
+// UNIX domain socket
+// 2) TYPE_MOJO_HANDLE is transmitted over the Mojo MessagePipe.
+// 3) TYPE_BROKERABLE_ATTACHMENT is transmitted by the Attachment Broker.
+// Any given IPC Message can have attachments of type (1) or (2), but not both.
+// These are stored in |attachments_|. Attachments of type (3) are stored in
+// |brokerable_attachments_|.
//
-// For ChannelNacl under SFI NaCl, only Type::PLATFORM_FILE is supported. In
-// that case, the FD is sent over socket.
+// To produce a deterministic ordering, all attachments in |attachments_| are
+// considered to come before those in |brokerable_attachments_|. These
+// attachments are transmitted across different communication channels, and
+// multiplexed by the receiver, so ordering between them cannot be guaranteed.
+//
// -----------------------------------------------------------------------------
class IPC_EXPORT MessageAttachmentSet
: public base::RefCountedThreadSafe<MessageAttachmentSet> {
@@ -33,31 +47,57 @@
// Return the number of attachments
unsigned size() const;
+ // Return the number of file descriptors
+ unsigned num_descriptors() const;
+ // Return the number of mojo handles in the attachment set
+ unsigned num_mojo_handles() const;
+ // Return the number of brokerable attachments in the attachment set.
+ unsigned num_brokerable_attachments() const;
+ // Return the number of non-brokerable attachments in the attachment set.
+ unsigned num_non_brokerable_attachments() const;
// Return true if no unconsumed descriptors remain
- bool empty() const { return attachments_.empty(); }
+ bool empty() const { return 0 == size(); }
// Returns whether the attachment was successfully added.
// |index| is an output variable. On success, it contains the index of the
// newly added attachment.
+ // |brokerable| is an output variable. On success, it describes which vector
+ // the attachment was added to.
bool AddAttachment(scoped_refptr<MessageAttachment> attachment,
- size_t* index);
+ size_t* index,
+ bool* brokerable);
// Similar to the above method, but without output variables.
bool AddAttachment(scoped_refptr<MessageAttachment> attachment);
- // Take the nth from the beginning of the vector, Code using this /must/
- // access the attachments in order, and must do it at most once.
+ // Take the nth non-brokerable attachment from the beginning of the vector,
+ // Code using this /must/ access the attachments in order, and must do it at
+ // most once.
//
// This interface is designed for the deserialising code as it doesn't
// support close flags.
// returns: an attachment, or nullptr on error
- scoped_refptr<MessageAttachment> GetAttachmentAt(unsigned index);
+ scoped_refptr<MessageAttachment> GetNonBrokerableAttachmentAt(unsigned index);
- // Marks all the descriptors as consumed and closes those which are
- // auto-close.
+ // Similar to GetNonBrokerableAttachmentAt, but there are no ordering
+ // requirements.
+ scoped_refptr<MessageAttachment> GetBrokerableAttachmentAt(unsigned index);
+
+ // This must be called after transmitting the descriptors returned by
+ // PeekDescriptors. It marks all the non-brokerable descriptors as consumed
+ // and closes those which are auto-close.
void CommitAllDescriptors();
+ // Returns a vector of all brokerable attachments.
+ std::vector<scoped_refptr<IPC::BrokerableAttachment>>
+ GetBrokerableAttachments() const;
+
+ // Replaces a placeholder brokerable attachment with |attachment|, matching
+ // them by their id.
+ void ReplacePlaceholderWithAttachment(
+ const scoped_refptr<BrokerableAttachment>& attachment);
+
#if defined(OS_POSIX)
// This is the maximum number of descriptors per message. We need to know this
// because the control message kernel interface has to be given a buffer which
@@ -68,6 +108,32 @@
// In debugging mode, it's a fatal error to try and add more than this number
// of descriptors to a MessageAttachmentSet.
static const size_t kMaxDescriptorsPerMessage = 7;
+
+ // ---------------------------------------------------------------------------
+ // Interfaces for transmission...
+
+ // Fill an array with file descriptors without 'consuming' them.
+ // CommitAllDescriptors must be called after these descriptors have been
+ // transmitted.
+ // buffer: (output) a buffer of, at least, size() integers.
+ void PeekDescriptors(base::PlatformFile* buffer) const;
+ // Returns true if any contained file descriptors appear to be handles to a
+ // directory.
+ bool ContainsDirectoryDescriptor() const;
+ // Fetch all filedescriptors with the "auto close" property. Used instead of
+ // CommitAllDescriptors() when closing must be handled manually.
+ void ReleaseFDsToClose(std::vector<base::PlatformFile>* fds);
+
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Interfaces for receiving...
+
+ // Set the contents of the set from the given buffer. This set must be empty
+ // before calling. The auto-close flag is set on all the descriptors so that
+ // unconsumed descriptors are closed on destruction.
+ void AddDescriptorsToOwn(const base::PlatformFile* buffer, unsigned count);
+
#endif // OS_POSIX
// ---------------------------------------------------------------------------
@@ -77,16 +143,17 @@
~MessageAttachmentSet();
- // Return the number of file descriptors
- unsigned num_descriptors() const;
-
+ // All elements either have type TYPE_PLATFORM_FILE or TYPE_MOJO_HANDLE.
std::vector<scoped_refptr<MessageAttachment>> attachments_;
+ // All elements have type TYPE_BROKERABLE_ATTACHMENT.
+ std::vector<scoped_refptr<BrokerableAttachment>> brokerable_attachments_;
+
// This contains the index of the next descriptor which should be consumed.
// It's used in a couple of ways. Firstly, at destruction we can check that
// all the descriptors have been read (with GetNthDescriptor). Secondly, we
// can check that they are read in order.
- unsigned consumed_descriptor_highwater_;
+ mutable unsigned consumed_descriptor_highwater_;
DISALLOW_COPY_AND_ASSIGN(MessageAttachmentSet);
};
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 3c41f04..c1e1b9f 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -29,7 +29,9 @@
FileUtilitiesMsgStart,
DatabaseMsgStart,
DOMStorageMsgStart,
+ IndexedDBMsgStart,
SpeechRecognitionMsgStart,
+ AutofillMsgStart,
SafeBrowsingMsgStart,
P2PMsgStart,
ResourceMsgStart,
@@ -84,6 +86,7 @@
ScreenOrientationMsgStart,
MediaStreamTrackMetricsHostMsgStart,
ChromeExtensionMsgStart,
+ TranslateMsgStart,
PushMessagingMsgStart,
GinJavaBridgeMsgStart,
ChromeUtilityPrintingMsgStart,
@@ -107,11 +110,13 @@
CastCryptoMsgStart,
CastChannelMsgStart,
DataReductionProxyStart,
+ ContentSettingsMsgStart,
ChromeAppBannerMsgStart,
AttachmentBrokerMsgStart,
RenderProcessMsgStart,
PageLoadMetricsMsgStart,
MemoryMsgStart,
+ MediaSessionMsgStart,
IPCTestMsgStart,
ArcInstanceMsgStart,
ArcInstanceHostMsgStart,
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
index bf8daa5..60c12ab 100644
--- a/ipc/ipc_message_utils.cc
+++ b/ipc/ipc_message_utils.cc
@@ -13,7 +13,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "base/unguessable_token.h"
#include "base/values.h"
#include "build/build_config.h"
#include "ipc/ipc_channel_handle.h"
@@ -22,7 +21,6 @@
#include "ipc/ipc_mojo_param_traits.h"
#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
#include "ipc/ipc_platform_file_attachment_posix.h"
#endif
@@ -43,7 +41,7 @@
namespace {
-const int kMaxRecursionDepth = 200;
+const int kMaxRecursionDepth = 100;
template<typename CharType>
void LogBytes(const std::vector<CharType>& data, std::string* out) {
@@ -78,25 +76,25 @@
const base::Value* value,
int recursion) {
if (recursion > kMaxRecursionDepth) {
- LOG(ERROR) << "Max recursion depth hit in GetValueSize.";
+ LOG(WARNING) << "Max recursion depth hit in GetValueSize.";
return;
}
sizer->AddInt();
switch (value->GetType()) {
- case base::Value::Type::NONE:
+ case base::Value::TYPE_NULL:
break;
- case base::Value::Type::BOOLEAN:
+ case base::Value::TYPE_BOOLEAN:
sizer->AddBool();
break;
- case base::Value::Type::INTEGER:
+ case base::Value::TYPE_INTEGER:
sizer->AddInt();
break;
- case base::Value::Type::DOUBLE:
+ case base::Value::TYPE_DOUBLE:
sizer->AddDouble();
break;
- case base::Value::Type::STRING: {
- const base::Value* result;
+ case base::Value::TYPE_STRING: {
+ const base::StringValue* result;
value->GetAsString(&result);
if (value->GetAsString(&result)) {
DCHECK(result);
@@ -109,11 +107,13 @@
}
break;
}
- case base::Value::Type::BINARY: {
- sizer->AddData(static_cast<int>(value->GetSize()));
+ case base::Value::TYPE_BINARY: {
+ const base::BinaryValue* binary =
+ static_cast<const base::BinaryValue*>(value);
+ sizer->AddData(static_cast<int>(binary->GetSize()));
break;
}
- case base::Value::Type::DICTIONARY: {
+ case base::Value::TYPE_DICTIONARY: {
sizer->AddInt();
const base::DictionaryValue* dict =
static_cast<const base::DictionaryValue*>(value);
@@ -124,7 +124,7 @@
}
break;
}
- case base::Value::Type::LIST: {
+ case base::Value::TYPE_LIST: {
sizer->AddInt();
const base::ListValue* list = static_cast<const base::ListValue*>(value);
for (const auto& entry : *list) {
@@ -140,48 +140,50 @@
void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
bool result;
if (recursion > kMaxRecursionDepth) {
- LOG(ERROR) << "Max recursion depth hit in WriteValue.";
+ LOG(WARNING) << "Max recursion depth hit in WriteValue.";
return;
}
- m->WriteInt(static_cast<int>(value->GetType()));
+ m->WriteInt(value->GetType());
switch (value->GetType()) {
- case base::Value::Type::NONE:
+ case base::Value::TYPE_NULL:
break;
- case base::Value::Type::BOOLEAN: {
+ case base::Value::TYPE_BOOLEAN: {
bool val;
result = value->GetAsBoolean(&val);
DCHECK(result);
WriteParam(m, val);
break;
}
- case base::Value::Type::INTEGER: {
+ case base::Value::TYPE_INTEGER: {
int val;
result = value->GetAsInteger(&val);
DCHECK(result);
WriteParam(m, val);
break;
}
- case base::Value::Type::DOUBLE: {
+ case base::Value::TYPE_DOUBLE: {
double val;
result = value->GetAsDouble(&val);
DCHECK(result);
WriteParam(m, val);
break;
}
- case base::Value::Type::STRING: {
+ case base::Value::TYPE_STRING: {
std::string val;
result = value->GetAsString(&val);
DCHECK(result);
WriteParam(m, val);
break;
}
- case base::Value::Type::BINARY: {
- m->WriteData(value->GetBuffer(), static_cast<int>(value->GetSize()));
+ case base::Value::TYPE_BINARY: {
+ const base::BinaryValue* binary =
+ static_cast<const base::BinaryValue*>(value);
+ m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
break;
}
- case base::Value::Type::DICTIONARY: {
+ case base::Value::TYPE_DICTIONARY: {
const base::DictionaryValue* dict =
static_cast<const base::DictionaryValue*>(value);
@@ -194,7 +196,7 @@
}
break;
}
- case base::Value::Type::LIST: {
+ case base::Value::TYPE_LIST: {
const base::ListValue* list = static_cast<const base::ListValue*>(value);
WriteParam(m, static_cast<int>(list->GetSize()));
for (const auto& entry : *list) {
@@ -252,7 +254,7 @@
base::Value** value,
int recursion) {
if (recursion > kMaxRecursionDepth) {
- LOG(ERROR) << "Max recursion depth hit in ReadValue.";
+ LOG(WARNING) << "Max recursion depth hit in ReadValue.";
return false;
}
@@ -260,39 +262,39 @@
if (!ReadParam(m, iter, &type))
return false;
- switch (static_cast<base::Value::Type>(type)) {
- case base::Value::Type::NONE:
+ switch (type) {
+ case base::Value::TYPE_NULL:
*value = base::Value::CreateNullValue().release();
break;
- case base::Value::Type::BOOLEAN: {
+ case base::Value::TYPE_BOOLEAN: {
bool val;
if (!ReadParam(m, iter, &val))
return false;
- *value = new base::Value(val);
+ *value = new base::FundamentalValue(val);
break;
}
- case base::Value::Type::INTEGER: {
+ case base::Value::TYPE_INTEGER: {
int val;
if (!ReadParam(m, iter, &val))
return false;
- *value = new base::Value(val);
+ *value = new base::FundamentalValue(val);
break;
}
- case base::Value::Type::DOUBLE: {
+ case base::Value::TYPE_DOUBLE: {
double val;
if (!ReadParam(m, iter, &val))
return false;
- *value = new base::Value(val);
+ *value = new base::FundamentalValue(val);
break;
}
- case base::Value::Type::STRING: {
+ case base::Value::TYPE_STRING: {
std::string val;
if (!ReadParam(m, iter, &val))
return false;
- *value = new base::Value(val);
+ *value = new base::StringValue(val);
break;
}
- case base::Value::Type::BINARY: {
+ case base::Value::TYPE_BINARY: {
const char* data;
int length;
if (!iter->ReadData(&data, &length))
@@ -302,14 +304,14 @@
*value = val.release();
break;
}
- case base::Value::Type::DICTIONARY: {
+ case base::Value::TYPE_DICTIONARY: {
std::unique_ptr<base::DictionaryValue> val(new base::DictionaryValue());
if (!ReadDictionaryValue(m, iter, val.get(), recursion))
return false;
*value = val.release();
break;
}
- case base::Value::Type::LIST: {
+ case base::Value::TYPE_LIST: {
std::unique_ptr<base::ListValue> val(new base::ListValue());
if (!ReadListValue(m, iter, val.get(), recursion))
return false;
@@ -584,6 +586,28 @@
}
}
+void ParamTraits<BrokerableAttachment::AttachmentId>::Write(
+ base::Pickle* m,
+ const param_type& p) {
+ m->WriteBytes(p.nonce, BrokerableAttachment::kNonceSize);
+}
+
+bool ParamTraits<BrokerableAttachment::AttachmentId>::Read(
+ const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r) {
+ const char* data;
+ if (!iter->ReadBytes(&data, BrokerableAttachment::kNonceSize))
+ return false;
+ memcpy(r->nonce, data, BrokerableAttachment::kNonceSize);
+ return true;
+}
+
+void ParamTraits<BrokerableAttachment::AttachmentId>::Log(const param_type& p,
+ std::string* l) {
+ l->append(base::HexEncode(p.nonce, BrokerableAttachment::kNonceSize));
+}
+
void ParamTraits<base::DictionaryValue>::GetSize(base::PickleSizer* sizer,
const param_type& p) {
GetValueSize(sizer, &p, 0);
@@ -598,8 +622,7 @@
base::PickleIterator* iter,
param_type* r) {
int type;
- if (!ReadParam(m, iter, &type) ||
- type != static_cast<int>(base::Value::Type::DICTIONARY))
+ if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY)
return false;
return ReadDictionaryValue(m, iter, r, 0);
@@ -655,14 +678,8 @@
if (!m->ReadAttachment(iter, &attachment))
return false;
- if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
- MessageAttachment::Type::PLATFORM_FILE) {
- return false;
- }
-
*r = base::FileDescriptor(
- static_cast<internal::PlatformFileAttachment*>(attachment.get())
- ->TakePlatformFile(),
+ static_cast<MessageAttachment*>(attachment.get())->TakePlatformFile(),
true);
return true;
}
@@ -815,8 +832,7 @@
base::PickleIterator* iter,
param_type* r) {
int type;
- if (!ReadParam(m, iter, &type) ||
- type != static_cast<int>(base::Value::Type::LIST))
+ if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST)
return false;
return ReadListValue(m, iter, r, 0);
@@ -982,81 +998,47 @@
ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
}
-// If base::UnguessableToken is no longer 128 bits, the IPC serialization logic
-// below should be updated.
-static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
- "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
-
-void ParamTraits<base::UnguessableToken>::GetSize(base::PickleSizer* sizer,
- const param_type& p) {
- sizer->AddBytes(2 * sizeof(uint64_t));
-}
-
-void ParamTraits<base::UnguessableToken>::Write(base::Pickle* m,
- const param_type& p) {
- DCHECK(!p.is_empty());
-
- ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization());
- ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization());
-}
-
-bool ParamTraits<base::UnguessableToken>::Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r) {
- uint64_t high, low;
- if (!ParamTraits<uint64_t>::Read(m, iter, &high) ||
- !ParamTraits<uint64_t>::Read(m, iter, &low))
- return false;
-
- // Receiving a zeroed UnguessableToken is a security issue.
- if (high == 0 && low == 0)
- return false;
-
- *r = base::UnguessableToken::Deserialize(high, low);
- return true;
-}
-
-void ParamTraits<base::UnguessableToken>::Log(const param_type& p,
- std::string* l) {
- l->append(p.ToString());
-}
-
void ParamTraits<IPC::ChannelHandle>::GetSize(base::PickleSizer* sizer,
const param_type& p) {
-#if defined(OS_NACL_SFI)
+ GetParamSize(sizer, p.name);
+#if defined(OS_POSIX)
GetParamSize(sizer, p.socket);
-#else
- GetParamSize(sizer, p.mojo_handle);
#endif
+ GetParamSize(sizer, p.mojo_handle);
}
void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
const param_type& p) {
-#if defined(OS_NACL_SFI)
+#if defined(OS_WIN)
+ // On Windows marshalling pipe handle is not supported.
+ DCHECK(p.pipe.handle == NULL);
+#endif // defined (OS_WIN)
+ WriteParam(m, p.name);
+#if defined(OS_POSIX)
WriteParam(m, p.socket);
-#else
- WriteParam(m, p.mojo_handle);
#endif
+ WriteParam(m, p.mojo_handle);
}
bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
-#if defined(OS_NACL_SFI)
- return ReadParam(m, iter, &r->socket);
-#else
- return ReadParam(m, iter, &r->mojo_handle);
+ return ReadParam(m, iter, &r->name)
+#if defined(OS_POSIX)
+ && ReadParam(m, iter, &r->socket)
#endif
+ && ReadParam(m, iter, &r->mojo_handle);
}
void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
std::string* l) {
- l->append("ChannelHandle(");
-#if defined(OS_NACL_SFI)
+ l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str()));
+#if defined(OS_POSIX)
+ l->append(", ");
ParamTraits<base::FileDescriptor>::Log(p.socket, l);
-#else
- LogParam(p.mojo_handle, l);
#endif
+ l->append(", ");
+ LogParam(p.mojo_handle, l);
l->append(")");
}
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index 40dd670..6712d3c 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -27,6 +27,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "ipc/brokerable_attachment.h"
#include "ipc/ipc_message_start.h"
#include "ipc/ipc_param_traits.h"
#include "ipc/ipc_sync_message.h"
@@ -39,7 +40,6 @@
class Time;
class TimeDelta;
class TimeTicks;
-class UnguessableToken;
struct FileDescriptor;
#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
@@ -307,37 +307,6 @@
static void Log(const param_type& p, std::string* l);
};
-template <class P, size_t Size>
-struct ParamTraits<P[Size]> {
- using param_type = P[Size];
- static void GetSize(base::PickleSizer* sizer, const param_type& p) {
- for (const P& element : p)
- GetParamSize(sizer, element);
- }
- static void Write(base::Pickle* m, const param_type& p) {
- for (const P& element : p)
- WriteParam(m, element);
- }
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r) {
- for (P& element : *r) {
- if (!ReadParam(m, iter, &element))
- return false;
- }
- return true;
- }
- static void Log(const param_type& p, std::string* l) {
- l->append("[");
- for (const P& element : p) {
- if (&element != &p[0])
- l->append(" ");
- LogParam(element, l);
- }
- l->append("]");
- }
-};
-
// STL ParamTraits -------------------------------------------------------------
template <>
@@ -543,6 +512,17 @@
}
};
+// IPC ParamTraits -------------------------------------------------------------
+template <>
+struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
+ typedef BrokerableAttachment::AttachmentId param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
// Base ParamTraits ------------------------------------------------------------
template <>
@@ -687,17 +667,6 @@
};
template <>
-struct IPC_EXPORT ParamTraits<base::UnguessableToken> {
- typedef base::UnguessableToken param_type;
- static void GetSize(base::PickleSizer* sizer, const param_type& p);
- static void Write(base::Pickle* m, const param_type& p);
- static bool Read(const base::Pickle* m,
- base::PickleIterator* iter,
- param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
struct ParamTraits<std::tuple<>> {
typedef std::tuple<> param_type;
static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
@@ -1130,9 +1099,10 @@
// Generic message subclasses
// defined in ipc_logging.cc
-IPC_EXPORT void GenerateLogData(const Message& message,
- LogData* data,
- bool get_params);
+IPC_EXPORT void GenerateLogData(const std::string& channel,
+ const Message& message,
+ LogData* data, bool get_params);
+
#if defined(IPC_MESSAGE_LOG_ENABLED)
inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
@@ -1159,7 +1129,7 @@
// output parameters at that point. Instead, save its data and log it
// with the outgoing reply message when it's sent.
LogData* data = new LogData;
- GenerateLogData(*msg, data, true);
+ GenerateLogData("", *msg, data, true);
msg->set_dont_log();
reply->set_sync_log_data(data);
}
diff --git a/ipc/ipc_mojo_handle_attachment.cc b/ipc/ipc_mojo_handle_attachment.cc
index e3421c3..819a12b 100644
--- a/ipc/ipc_mojo_handle_attachment.cc
+++ b/ipc/ipc_mojo_handle_attachment.cc
@@ -18,9 +18,16 @@
}
MessageAttachment::Type MojoHandleAttachment::GetType() const {
- return Type::MOJO_HANDLE;
+ return TYPE_MOJO_HANDLE;
}
+#if defined(OS_POSIX)
+base::PlatformFile MojoHandleAttachment::TakePlatformFile() {
+ NOTREACHED();
+ return base::kInvalidPlatformFile;
+}
+#endif // OS_POSIX
+
mojo::ScopedHandle MojoHandleAttachment::TakeHandle() {
return std::move(handle_);
}
diff --git a/ipc/ipc_mojo_handle_attachment.h b/ipc/ipc_mojo_handle_attachment.h
index d615276..6aa1888 100644
--- a/ipc/ipc_mojo_handle_attachment.h
+++ b/ipc/ipc_mojo_handle_attachment.h
@@ -26,6 +26,11 @@
Type GetType() const override;
+#if defined(OS_POSIX)
+ // Should not be called.
+ base::PlatformFile TakePlatformFile() override;
+#endif // OS_POSIX
+
// Returns the owning handle transferring the ownership.
mojo::ScopedHandle TakeHandle();
diff --git a/ipc/ipc_mojo_message_helper.cc b/ipc/ipc_mojo_message_helper.cc
index a87a2d6..8f86945 100644
--- a/ipc/ipc_mojo_message_helper.cc
+++ b/ipc/ipc_mojo_message_helper.cc
@@ -32,7 +32,7 @@
MessageAttachment::Type type =
static_cast<MessageAttachment*>(attachment.get())->GetType();
- if (type != MessageAttachment::Type::MOJO_HANDLE) {
+ if (type != MessageAttachment::TYPE_MOJO_HANDLE) {
LOG(ERROR) << "Unxpected attachment type:" << type;
return false;
}
diff --git a/ipc/ipc_platform_file_attachment_posix.cc b/ipc/ipc_platform_file_attachment_posix.cc
index 7111cfa..b130ab2 100644
--- a/ipc/ipc_platform_file_attachment_posix.cc
+++ b/ipc/ipc_platform_file_attachment_posix.cc
@@ -20,7 +20,7 @@
}
MessageAttachment::Type PlatformFileAttachment::GetType() const {
- return Type::PLATFORM_FILE;
+ return TYPE_PLATFORM_FILE;
}
base::PlatformFile PlatformFileAttachment::TakePlatformFile() {
@@ -30,7 +30,7 @@
base::PlatformFile GetPlatformFile(
scoped_refptr<MessageAttachment> attachment) {
- DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::PLATFORM_FILE);
+ DCHECK_EQ(attachment->GetType(), MessageAttachment::TYPE_PLATFORM_FILE);
return static_cast<PlatformFileAttachment*>(attachment.get())->file();
}
diff --git a/ipc/ipc_platform_file_attachment_posix.h b/ipc/ipc_platform_file_attachment_posix.h
index 9b07900..d1eff60 100644
--- a/ipc/ipc_platform_file_attachment_posix.h
+++ b/ipc/ipc_platform_file_attachment_posix.h
@@ -23,7 +23,7 @@
explicit PlatformFileAttachment(base::ScopedFD file);
Type GetType() const override;
- base::PlatformFile TakePlatformFile();
+ base::PlatformFile TakePlatformFile() override;
base::PlatformFile file() const { return file_; }
bool Owns() const { return owning_.is_valid(); }
diff --git a/ipc/placeholder_brokerable_attachment.cc b/ipc/placeholder_brokerable_attachment.cc
new file mode 100644
index 0000000..e64e398
--- /dev/null
+++ b/ipc/placeholder_brokerable_attachment.cc
@@ -0,0 +1,14 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ipc/placeholder_brokerable_attachment.h"
+
+namespace IPC {
+
+BrokerableAttachment::BrokerableType
+PlaceholderBrokerableAttachment::GetBrokerableType() const {
+ return PLACEHOLDER;
+}
+
+} // namespace IPC
diff --git a/ipc/placeholder_brokerable_attachment.h b/ipc/placeholder_brokerable_attachment.h
new file mode 100644
index 0000000..a8b08ef
--- /dev/null
+++ b/ipc/placeholder_brokerable_attachment.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IPC_PLACEHOLDER_BROKERABLE_ATTACHMENT_H_
+#define IPC_PLACEHOLDER_BROKERABLE_ATTACHMENT_H_
+
+#include "base/macros.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_export.h"
+
+namespace IPC {
+
+// This subclass of BrokerableAttachment has an AttachmentId, and nothing else.
+// It is intended to be replaced by the attachment broker.
+class IPC_EXPORT PlaceholderBrokerableAttachment : public BrokerableAttachment {
+ public:
+ PlaceholderBrokerableAttachment(const AttachmentId& id)
+ : BrokerableAttachment(id){};
+ BrokerableType GetBrokerableType() const override;
+
+ protected:
+ ~PlaceholderBrokerableAttachment() override{};
+ DISALLOW_COPY_AND_ASSIGN(PlaceholderBrokerableAttachment);
+};
+
+} // namespace IPC
+
+#endif // IPC_PLACEHOLDER_BROKERABLE_ATTACHMENT_H_