summaryrefslogtreecommitdiff
path: root/chromium/ipc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-31 16:33:43 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-06 16:33:22 +0000
commitda51f56cc21233c2d30f0fe0d171727c3102b2e0 (patch)
tree4e579ab70ce4b19bee7984237f3ce05a96d59d83 /chromium/ipc
parentc8c2d1901aec01e934adf561a9fdf0cc776cdef8 (diff)
downloadqtwebengine-chromium-da51f56cc21233c2d30f0fe0d171727c3102b2e0.tar.gz
BASELINE: Update Chromium to 65.0.3525.40
Also imports missing submodules Change-Id: I36901b7c6a325cda3d2c10cedb2186c25af3b79b Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/ipc')
-rw-r--r--chromium/ipc/README.md195
-rw-r--r--chromium/ipc/SECURITY_OWNERS12
-rw-r--r--chromium/ipc/ipc_channel_mojo.cc4
-rw-r--r--chromium/ipc/ipc_channel_mojo.h1
-rw-r--r--chromium/ipc/ipc_channel_proxy.h4
-rw-r--r--chromium/ipc/ipc_message.h2
-rw-r--r--chromium/ipc/ipc_message_pipe_reader.cc17
-rw-r--r--chromium/ipc/ipc_message_pipe_reader.h1
-rw-r--r--chromium/ipc/ipc_message_start.h5
-rw-r--r--chromium/ipc/ipc_message_utils.cc14
-rw-r--r--chromium/ipc/ipc_mojo_bootstrap_unittest.cc124
-rw-r--r--chromium/ipc/ipc_platform_file.cc2
-rw-r--r--chromium/ipc/ipc_sync_channel.cc31
-rw-r--r--chromium/ipc/ipc_sync_message.h2
14 files changed, 352 insertions, 62 deletions
diff --git a/chromium/ipc/README.md b/chromium/ipc/README.md
index c30689a29a7..2e0cbe401fd 100644
--- a/chromium/ipc/README.md
+++ b/chromium/ipc/README.md
@@ -237,12 +237,18 @@ For example, any interfaces registered in
can be acquired by a renderer as follows:
``` cpp
-mojom::FooPtr foo;
+mojom::LoggerPtr logger;
content::RenderThread::Get()->GetConnector()->BindInterface(
- content::mojom::kBrowserServiceName, &foo);
-foo->DoSomePrettyCoolIPC();
+ content::mojom::kBrowserServiceName, &logger);
+logger->Log("Message to log here");
```
+Usually `logger` will be saved in a field at construction time, so the
+connection is only created once. There may be situations where you want to
+create one connection per request, e.g. a new instance of the Mojo
+implementation is created with some information about the request, and any
+responses for this request go straight to that instance.
+
### On Other Threads
`Connector` instances can be created and asynchronously associated with each
@@ -255,20 +261,21 @@ which may be used immediately and retained on that thread -- and asynchronously
associate it with the main-thread `Connector` like so:
``` cpp
-class Thinger {
+class Logger {
public:
- explicit Thinger(scoped_refptr<base::TaskRunner> main_thread_task_runner) {
+ explicit Logger(scoped_refptr<base::TaskRunner> main_thread_task_runner) {
service_manager::mojom::ConnectorRequest request;
// Of course we could also retain |connector| if we intend to use it again.
auto connector = service_manager::Connector::Create(&request);
- connector->BindInterface("best_service_ever", &thinger_);
- thinger_->DoTheThing();
+ // Replace service_name with the name of the service to bind on, e.g.
+ // content::mojom::kBrowserServiceName.
+ connector->BindInterface("service_name", &logger_);
+ logger_->Log("Test Message.");
- // Doesn't really matter when this happens, as long as it eventually
- // happens.
+ // Doesn't matter when this happens, as long as it happens eventually.
main_thread_task_runner->PostTask(
- FROM_HERE, base::BindOnce(&Thinger::BindConnectorOnMainThread,
+ FROM_HERE, base::BindOnce(&Logger::BindConnectorOnMainThread,
std::move(request)));
}
@@ -280,9 +287,9 @@ class Thinger {
std::move(request));
}
- mojom::ThingerPtr thinger_;
+ mojom::LoggerPtr logger_;
- DISALLOW_COPY_AND_ASSIGN(Thinger);
+ DISALLOW_COPY_AND_ASSIGN(Logger);
};
```
@@ -339,6 +346,170 @@ interface connection between browser and renderer processes:
As noted above, use of these registries is generally discouraged.
+### Deciding Which Interface Registry to Use
+
+Once you have an implementation of a Mojo interface, the next thing to decide is
+which registry and service to register it on.
+
+For browser/renderer communication, you can register your Mojo interface
+implementation in either the Browser or Renderer process (whichever side the
+interface was implemented on). Usually, this involves calling `AddInterface()`
+on the correct registry, passing a method that takes the Mojo Request object
+(e.g. `sample::mojom::LoggerRequest`) and binding it (e.g.
+`mojo::MakeStrongBinding()`, `bindings_.AddBinding()`, etc). Then the class that
+needs this API can call `BindInterface()` on the connector for that process,
+e.g.
+`RenderThread::Get()->GetConnector()->BindInterface(mojom::kBrowserServiceName, std::move(&mojo_interface_))`.
+
+**NOTE:** `content::ServiceManagerConnection::GetForProcess()` must be called in
+the browser process on the main thread, and its connector can only be used on
+the main thread; but you can clone connectors and move the clones around to
+other threads. A `Connector` is only bound to the thread which first calls into
+it.
+
+Depending on what resources you need access to, the main classes are:
+
+| Renderer Class | Corresponding Browser Class | Explanation |
+|-----------------|-----------------------------|-------------------------------------------------------------------------------------------------------------------|
+| `RenderFrame` | `RenderFrameHost` | A single frame. Use this for frame-to-frame messages. |
+| `RenderView` | `RenderViewHost` | A view (conceptually a 'tab'). You cannot send Mojo messages to a `RenderView` directly, since frames in a tab can
+ be in multiple processes (and the classes are deprecated). Migrate these to `RenderFrame` instead, or see section
+ [Migrating IPC calls to `RenderView` or `RenderViewHost`](#UMigrating-IPC-calls-to-RenderView-or-RenderViewHost). |
+| `RenderProcess` | `RenderProcessHost` | A process, containing multiple frames (probably from the same origin, but not always). |
+
+**NOTE:** Previously, classes that ended with `Host` were implemented on the
+browser side; the equivalent classes on the renderer side had the same name
+without the `Host` suffix. We have since deviated from this convention since
+Mojo interfaces are not intended to prescribe where their endpoints live, so
+future classes should omit such suffixes and just describe the interface they
+are providing.
+
+Of course, any combination of the above is possible, e.g. `RenderProcessHost`
+can register a Mojo interface that can be called by a `RenderFrame` (this would
+be a way of the browser communicating with multiple frames at once).
+
+Once you know which class you want the implementation to be registered in, find
+the corresponding `Impl` class (e.g. `RenderProcessImpl`). There should be a
+`RegisterMojoInterfaces()` method where you can add calls to `AddInterface`,
+e.g. For a strong binding:
+
+```cpp
+ registry->AddInterface(base::Bind(&Logger::Create, GetID()));
+```
+
+Then in `Logger` we add a static `Create()` method that takes the
+`LoggerRequest` object:
+
+```cpp
+// static
+void Logger::Create(int render_process_id,
+ mojom::LoggerRequest request) {
+ mojo::MakeStrongBinding(std::make_unique<Logger>(render_process_id),
+ std::move(request));
+}
+```
+
+For a `BindingSet`, we can store a `std::unique_ptr<Logger>` on the
+`RenderProcessHost` instead, e.g.:
+
+```cpp
+// render_process_host_impl.h:
+std::unique_ptr<Logger> logger_;
+
+// render_process_host_impl.cc:
+logger_ = std::make_unique<Logger>(GetID());
+registry->AddInterface(base::Bind(&Logger::BindRequest,
+ base::Unretained(logger_.get())));
+```
+
+Then in `Logger` we define the `BindRequest` method:
+
+```h
+class Logger : public sample::mojom::Logger {
+ public:
+ explicit Logger(int render_process_id);
+ ~Logger() override;
+
+ void BindRequest(mojom::LoggerRequest request);
+
+ // sample::mojom::Logger:
+ void Log(const std::string& message) override;
+ void GetTail(GetTailCallback callback) override;
+
+ private:
+ mojo::BindingSet<sample::mojom::Logger> bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(Logger);
+};
+```
+
+```cpp
+void Logger::BindRequest(mojom::LoggerRequest request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+```
+
+#### Setting up Capabilities
+
+Once you've registered your interface, you need to add capabilities (resolved at
+runtime) to the corresponding capabilities manifest json file.
+
+The service manifest files (which contain the capability spec) are located in
+[/content/public/app/mojo/](/content/public/app/mojo/). As a general rule, the
+file you want to edit is the service which *provides* the interface (the side
+which instantiates the implementation), and the part of the file you want to add
+the name of the interface to is the service which *calls* the interface (i.e.
+the side containing `LoggerPtr`).
+
+You can usually just run your Mojo code and look at the error messages. The
+errors look like:
+
+```sh
+[ERROR:service_manager.cc(158)] Connection InterfaceProviderSpec prevented
+service: content_renderer from binding interface: content::mojom::Logger
+exposed by: content_browser
+```
+
+This means something in the renderer process (called "content_renderer") was
+trying to bind to `content::mojom::Logger` in the browser process (called
+"content_browser"). To add a capability for this, we need to find the json file
+with the capabilities for "content_browser", and add our new interface with name
+`content::mojom::Logger` to the "renderer" section.
+
+In this example, the capabilities for "content_browser" are implemented in
+[content_browser_manifest.json](/content/public/app/mojo/content_browser_manifest.json).
+It should look like:
+
+```json
+{
+ "name": "content_browser",
+ "display_name": "Content (browser process)",
+ "interface_provider_specs": {
+ "service_manager:connector": {
+ "provides": {
+ // ...
+ "renderer": [
+ //...
+```
+
+To add permission for `content::mojom::Logger`, add the string
+`"content::mojom::Logger"` to the "renderer" list.
+
+Similarly, if the error was:
+
+```sh
+[ERROR:service_manager.cc(158)] Connection InterfaceProviderSpec prevented
+service: content_browser from binding interface: content::mojom::Logger exposed
+by: content_renderer
+```
+
+We would want the
+`interface_provider_specs.service_manager:connector.provides.browser` section in
+[content_renderer_manifest.json](/content/public/app/mojo/content_renderer_manifest.json)
+(which defines the capabilities for `content_renderer`).
+
+TODO: Add more details on permission manifests here
+
## Using Channel-associated Interfaces
**NOTE**: Channel-associated interfaces are an interim solution to make the
diff --git a/chromium/ipc/SECURITY_OWNERS b/chromium/ipc/SECURITY_OWNERS
index 8bb1091dab6..9fe4dfb1829 100644
--- a/chromium/ipc/SECURITY_OWNERS
+++ b/chromium/ipc/SECURITY_OWNERS
@@ -1,9 +1,16 @@
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
+# Changes to IPC messages require a security review to avoid introducing sandbox
+# escapes. The shared memory implementation code needs review from a security
+# owner. (Shared memory call sites should be reviewed as part of normal IPC
+# security review.)
+#
+# Security team: If you are uncomfortable reviewing a particular bit of code
+# yourself, don't hesitate to seek help from another security team member!
+# Nobody knows everything, and the only way to learn is from experience.
dcheng@chromium.org
estark@chromium.org
kenrb@chromium.org
kerrnel@chromium.org
+kinuko@chromium.org
meacer@chromium.org
mbarbella@chromium.org
mkwst@chromium.org
@@ -11,5 +18,6 @@ nasko@chromium.org
ochang@chromium.org
palmer@chromium.org
rsesek@chromium.org
+sammc@chromium.org
tsepez@chromium.org
wfh@chromium.org
diff --git a/chromium/ipc/ipc_channel_mojo.cc b/chromium/ipc/ipc_channel_mojo.cc
index 2dafc7b1268..d7ce34a9804 100644
--- a/chromium/ipc/ipc_channel_mojo.cc
+++ b/chromium/ipc/ipc_channel_mojo.cc
@@ -259,6 +259,10 @@ void ChannelMojo::OnMessageReceived(const Message& message) {
listener_->OnBadMessageReceived(message);
}
+void ChannelMojo::OnBrokenDataReceived() {
+ listener_->OnBadMessageReceived(Message());
+}
+
// static
MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
Message* message,
diff --git a/chromium/ipc/ipc_channel_mojo.h b/chromium/ipc/ipc_channel_mojo.h
index 340d80cdc7f..aa6ba435568 100644
--- a/chromium/ipc/ipc_channel_mojo.h
+++ b/chromium/ipc/ipc_channel_mojo.h
@@ -89,6 +89,7 @@ class IPC_EXPORT ChannelMojo : public Channel,
// MessagePipeReader::Delegate
void OnPeerPidReceived(int32_t peer_pid) override;
void OnMessageReceived(const Message& message) override;
+ void OnBrokenDataReceived() override;
void OnPipeError() override;
void OnAssociatedInterfaceRequest(
const std::string& name,
diff --git a/chromium/ipc/ipc_channel_proxy.h b/chromium/ipc/ipc_channel_proxy.h
index 779f2f9c934..a333a26c1ac 100644
--- a/chromium/ipc/ipc_channel_proxy.h
+++ b/chromium/ipc/ipc_channel_proxy.h
@@ -259,6 +259,10 @@ class IPC_EXPORT ChannelProxy : public Sender {
return ipc_task_runner_;
}
+ scoped_refptr<base::SingleThreadTaskRunner> listener_task_runner() {
+ return listener_task_runner_;
+ }
+
// Dispatches a message on the listener thread.
void OnDispatchMessage(const Message& message);
diff --git a/chromium/ipc/ipc_message.h b/chromium/ipc/ipc_message.h
index 8a924e21952..d1ea54e1dfd 100644
--- a/chromium/ipc/ipc_message.h
+++ b/chromium/ipc/ipc_message.h
@@ -72,6 +72,8 @@ class IPC_MESSAGE_SUPPORT_EXPORT Message : public base::Pickle {
Message(const Message& other);
Message& operator=(const Message& other);
+ bool IsValid() const { return header_size() == sizeof(Header) && header(); }
+
PriorityValue priority() const {
return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
}
diff --git a/chromium/ipc/ipc_message_pipe_reader.cc b/chromium/ipc/ipc_message_pipe_reader.cc
index ebc18a3a943..4a8ca8f34fc 100644
--- a/chromium/ipc/ipc_message_pipe_reader.cc
+++ b/chromium/ipc/ipc_message_pipe_reader.cc
@@ -50,9 +50,9 @@ void MessagePipeReader::Close() {
}
bool MessagePipeReader::Send(std::unique_ptr<Message> message) {
+ CHECK(message->IsValid());
TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
- "MessagePipeReader::Send",
- message->flags(),
+ "MessagePipeReader::Send", message->flags(),
TRACE_EVENT_FLAG_FLOW_OUT);
base::Optional<std::vector<mojo::native::SerializedHandlePtr>> handles;
MojoResult result = MOJO_RESULT_OK;
@@ -87,9 +87,16 @@ void MessagePipeReader::SetPeerPid(int32_t peer_pid) {
void MessagePipeReader::Receive(
base::span<const uint8_t> data,
base::Optional<std::vector<mojo::native::SerializedHandlePtr>> handles) {
- Message message(
- data.empty() ? "" : reinterpret_cast<const char*>(data.data()),
- static_cast<uint32_t>(data.size()));
+ if (data.empty()) {
+ delegate_->OnBrokenDataReceived();
+ return;
+ }
+ Message message(reinterpret_cast<const char*>(data.data()),
+ static_cast<uint32_t>(data.size()));
+ if (!message.IsValid()) {
+ delegate_->OnBrokenDataReceived();
+ return;
+ }
DVLOG(4) << "Receive " << message.type() << ": " << message.size();
MojoResult write_result =
diff --git a/chromium/ipc/ipc_message_pipe_reader.h b/chromium/ipc/ipc_message_pipe_reader.h
index a155dcfb372..a609f6c0603 100644
--- a/chromium/ipc/ipc_message_pipe_reader.h
+++ b/chromium/ipc/ipc_message_pipe_reader.h
@@ -49,6 +49,7 @@ class IPC_EXPORT MessagePipeReader : public mojom::Channel {
public:
virtual void OnPeerPidReceived(int32_t peer_pid) = 0;
virtual void OnMessageReceived(const Message& message) = 0;
+ virtual void OnBrokenDataReceived() = 0;
virtual void OnPipeError() = 0;
virtual void OnAssociatedInterfaceRequest(
const std::string& name,
diff --git a/chromium/ipc/ipc_message_start.h b/chromium/ipc/ipc_message_start.h
index 74256f04cc1..e24a858ed0b 100644
--- a/chromium/ipc/ipc_message_start.h
+++ b/chromium/ipc/ipc_message_start.h
@@ -18,7 +18,6 @@ enum IPCMessageStart {
ViewMsgStart,
InputMsgStart,
TestMsgStart,
- DevToolsMsgStart,
WorkerMsgStart,
NaClMsgStart,
GpuChannelMsgStart,
@@ -31,10 +30,7 @@ enum IPCMessageStart {
P2PMsgStart,
ResourceMsgStart,
FileSystemMsgStart,
- ChildProcessMsgStart,
- ClipboardMsgStart,
BlobMsgStart,
- AppCacheMsgStart,
AudioMsgStart,
MidiMsgStart,
ChromeMsgStart,
@@ -42,7 +38,6 @@ enum IPCMessageStart {
PrintMsgStart,
SpellCheckMsgStart,
ExtensionMsgStart,
- QuotaMsgStart,
TextInputClientMsgStart,
JavaBridgeMsgStart,
ShellMsgStart,
diff --git a/chromium/ipc/ipc_message_utils.cc b/chromium/ipc/ipc_message_utils.cc
index c8dc9fc39fb..a18b60d5062 100644
--- a/chromium/ipc/ipc_message_utils.cc
+++ b/chromium/ipc/ipc_message_utils.cc
@@ -332,34 +332,34 @@ bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
}
void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
- l->append(base::UintToString(p));
+ l->append(base::NumberToString(p));
}
void ParamTraits<int>::Log(const param_type& p, std::string* l) {
- l->append(base::IntToString(p));
+ l->append(base::NumberToString(p));
}
void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
- l->append(base::UintToString(p));
+ l->append(base::NumberToString(p));
}
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_FUCHSIA) || \
(defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
void ParamTraits<long>::Log(const param_type& p, std::string* l) {
- l->append(base::Int64ToString(static_cast<int64_t>(p)));
+ l->append(base::NumberToString(p));
}
void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
- l->append(base::Uint64ToString(static_cast<uint64_t>(p)));
+ l->append(base::NumberToString(p));
}
#endif
void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
- l->append(base::Int64ToString(static_cast<int64_t>(p)));
+ l->append(base::NumberToString(p));
}
void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
- l->append(base::Uint64ToString(p));
+ l->append(base::NumberToString(p));
}
void ParamTraits<float>::Log(const param_type& p, std::string* l) {
diff --git a/chromium/ipc/ipc_mojo_bootstrap_unittest.cc b/chromium/ipc/ipc_mojo_bootstrap_unittest.cc
index 7bfd77c397f..46dca0efd0e 100644
--- a/chromium/ipc/ipc_mojo_bootstrap_unittest.cc
+++ b/chromium/ipc/ipc_mojo_bootstrap_unittest.cc
@@ -29,12 +29,43 @@ namespace {
constexpr int32_t kTestServerPid = 42;
constexpr int32_t kTestClientPid = 4242;
+class Connection {
+ public:
+ explicit Connection(std::unique_ptr<IPC::MojoBootstrap> bootstrap,
+ int32_t sender_id)
+ : bootstrap_(std::move(bootstrap)) {
+ bootstrap_->Connect(&sender_, &receiver_);
+ sender_->SetPeerPid(sender_id);
+ }
+
+ void TakeReceiver(IPC::mojom::ChannelAssociatedRequest* receiver) {
+ *receiver = std::move(receiver_);
+ }
+
+ IPC::mojom::ChannelAssociatedPtr& GetSender() { return sender_; }
+
+ private:
+ IPC::mojom::ChannelAssociatedPtr sender_;
+ IPC::mojom::ChannelAssociatedRequest receiver_;
+ std::unique_ptr<IPC::MojoBootstrap> bootstrap_;
+};
+
class PeerPidReceiver : public IPC::mojom::Channel {
public:
- PeerPidReceiver(IPC::mojom::ChannelAssociatedRequest request,
- const base::Closure& on_peer_pid_set)
- : binding_(this, std::move(request)), on_peer_pid_set_(on_peer_pid_set) {}
- ~PeerPidReceiver() override = default;
+ enum class MessageExpectation {
+ kNotExpected,
+ kExpectedValid,
+ kExptectedInvalid
+ };
+
+ PeerPidReceiver(
+ IPC::mojom::ChannelAssociatedRequest request,
+ const base::Closure& on_peer_pid_set,
+ MessageExpectation message_expectation = MessageExpectation::kNotExpected)
+ : binding_(this, std::move(request)),
+ on_peer_pid_set_(on_peer_pid_set),
+ message_expectation_(message_expectation) {}
+ ~PeerPidReceiver() override {}
// mojom::Channel:
void SetPeerPid(int32_t pid) override {
@@ -44,7 +75,15 @@ class PeerPidReceiver : public IPC::mojom::Channel {
void Receive(base::span<const uint8_t> data,
base::Optional<std::vector<mojo::native::SerializedHandlePtr>>
- handles) override {}
+ handles) override {
+ ASSERT_NE(MessageExpectation::kNotExpected, message_expectation_);
+
+ IPC::Message message(reinterpret_cast<const char*>(data.data()),
+ static_cast<uint32_t>(data.size()));
+ bool expected_valid =
+ message_expectation_ == MessageExpectation::kExpectedValid;
+ EXPECT_EQ(expected_valid, message.IsValid());
+ }
void GetAssociatedInterface(
const std::string& name,
@@ -55,6 +94,7 @@ class PeerPidReceiver : public IPC::mojom::Channel {
private:
mojo::AssociatedBinding<IPC::mojom::Channel> binding_;
const base::Closure on_peer_pid_set_;
+ MessageExpectation message_expectation_;
int32_t peer_pid_ = -1;
DISALLOW_COPY_AND_ASSIGN(PeerPidReceiver);
@@ -67,15 +107,15 @@ class IPCMojoBootstrapTest : public testing::Test {
TEST_F(IPCMojoBootstrapTest, Connect) {
base::MessageLoop message_loop;
- std::unique_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create(
- helper_.StartChild("IPCMojoBootstrapTestClient"),
- IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
- base::ThreadTaskRunnerHandle::Get());
+ Connection connection(
+ IPC::MojoBootstrap::Create(
+ helper_.StartChild("IPCMojoBootstrapTestClient"),
+ IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get()),
+ kTestServerPid);
- IPC::mojom::ChannelAssociatedPtr sender;
IPC::mojom::ChannelAssociatedRequest receiver;
- bootstrap->Connect(&sender, &receiver);
- sender->SetPeerPid(kTestServerPid);
+ connection.TakeReceiver(&receiver);
base::RunLoop run_loop;
PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
@@ -86,20 +126,40 @@ TEST_F(IPCMojoBootstrapTest, Connect) {
EXPECT_TRUE(helper_.WaitForChildTestShutdown());
}
+TEST_F(IPCMojoBootstrapTest, ReceiveEmptyMessage) {
+ base::MessageLoop message_loop;
+ Connection connection(
+ IPC::MojoBootstrap::Create(
+ helper_.StartChild("IPCMojoBootstrapTestEmptyMessage"),
+ IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get()),
+ kTestServerPid);
+
+ IPC::mojom::ChannelAssociatedRequest receiver;
+ connection.TakeReceiver(&receiver);
+
+ base::RunLoop run_loop;
+ PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure(),
+ PeerPidReceiver::MessageExpectation::kExptectedInvalid);
+ run_loop.Run();
+
+ EXPECT_TRUE(helper_.WaitForChildTestShutdown());
+}
+
// A long running process that connects to us.
MULTIPROCESS_TEST_MAIN_WITH_SETUP(
IPCMojoBootstrapTestClientTestChildMain,
::mojo::edk::test::MultiprocessTestHelper::ChildSetup) {
base::MessageLoop message_loop;
- std::unique_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create(
- std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe),
- IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
- base::ThreadTaskRunnerHandle::Get());
+ Connection connection(
+ IPC::MojoBootstrap::Create(
+ std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe),
+ IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get()),
+ kTestClientPid);
- IPC::mojom::ChannelAssociatedPtr sender;
IPC::mojom::ChannelAssociatedRequest receiver;
- bootstrap->Connect(&sender, &receiver);
- sender->SetPeerPid(kTestClientPid);
+ connection.TakeReceiver(&receiver);
base::RunLoop run_loop;
PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
@@ -110,4 +170,30 @@ MULTIPROCESS_TEST_MAIN_WITH_SETUP(
return 0;
}
+// A long running process that connects to us.
+MULTIPROCESS_TEST_MAIN_WITH_SETUP(
+ IPCMojoBootstrapTestEmptyMessageTestChildMain,
+ ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) {
+ base::MessageLoop message_loop;
+ Connection connection(
+ IPC::MojoBootstrap::Create(
+ std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe),
+ IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get()),
+ kTestClientPid);
+
+ IPC::mojom::ChannelAssociatedRequest receiver;
+ connection.TakeReceiver(&receiver);
+ auto& sender = connection.GetSender();
+
+ uint8_t data = 0;
+ sender->Receive(base::make_span(&data, 0), {});
+
+ base::RunLoop run_loop;
+ PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
+ run_loop.Run();
+
+ return 0;
+}
+
} // namespace
diff --git a/chromium/ipc/ipc_platform_file.cc b/chromium/ipc/ipc_platform_file.cc
index 72ed737b6a8..d8108b3c799 100644
--- a/chromium/ipc/ipc_platform_file.cc
+++ b/chromium/ipc/ipc_platform_file.cc
@@ -9,6 +9,8 @@
#include <unistd.h>
#include "base/posix/eintr_wrapper.h"
+#elif defined(OS_WIN)
+#include <windows.h>
#endif
namespace IPC {
diff --git a/chromium/ipc/ipc_sync_channel.cc b/chromium/ipc/ipc_sync_channel.cc
index 146feb0c498..c4f14dce5cf 100644
--- a/chromium/ipc/ipc_sync_channel.cc
+++ b/chromium/ipc/ipc_sync_channel.cc
@@ -84,14 +84,16 @@ class SyncChannel::ReceivedSyncMsgQueue :
class NestedSendDoneWatcher {
public:
NestedSendDoneWatcher(SyncChannel::SyncContext* context,
- base::RunLoop* run_loop)
+ base::RunLoop* run_loop,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
: sync_msg_queue_(context->received_sync_msgs()),
outer_state_(sync_msg_queue_->top_send_done_event_watcher_),
event_(context->GetSendDoneEvent()),
callback_(
base::BindOnce(&SyncChannel::SyncContext::OnSendDoneEventSignaled,
context,
- run_loop)) {
+ run_loop)),
+ task_runner_(std::move(task_runner)) {
sync_msg_queue_->top_send_done_event_watcher_ = this;
if (outer_state_)
outer_state_->StopWatching();
@@ -111,8 +113,10 @@ class SyncChannel::ReceivedSyncMsgQueue :
}
void StartWatching() {
- watcher_.StartWatching(event_, base::BindOnce(&NestedSendDoneWatcher::Run,
- base::Unretained(this)));
+ watcher_.StartWatching(
+ event_,
+ base::BindOnce(&NestedSendDoneWatcher::Run, base::Unretained(this)),
+ task_runner_);
}
void StopWatching() { watcher_.StopWatching(); }
@@ -123,6 +127,7 @@ class SyncChannel::ReceivedSyncMsgQueue :
base::WaitableEvent* const event_;
base::WaitableEventWatcher::EventCallback callback_;
base::WaitableEventWatcher watcher_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(NestedSendDoneWatcher);
};
@@ -206,9 +211,10 @@ class SyncChannel::ReceivedSyncMsgQueue :
}
for (; it != message_queue_.end(); it++) {
int message_group = it->context->restrict_dispatch_group();
- if (!dispatching_context ||
- message_group == kRestrictDispatchGroup_None ||
- message_group == dispatching_context->restrict_dispatch_group()) {
+ if (message_group == kRestrictDispatchGroup_None ||
+ (dispatching_context &&
+ message_group ==
+ dispatching_context->restrict_dispatch_group())) {
message = it->message;
context = it->context;
it = message_queue_.erase(it);
@@ -492,7 +498,8 @@ void SyncChannel::SyncContext::OnChannelOpened() {
shutdown_watcher_.StartWatching(
shutdown_event_,
base::Bind(&SyncChannel::SyncContext::OnShutdownEventSignaled,
- base::Unretained(this)));
+ base::Unretained(this)),
+ ipc_task_runner());
Context::OnChannelOpened();
}
@@ -689,7 +696,8 @@ void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry,
void SyncChannel::WaitForReplyWithNestedMessageLoop(SyncContext* context) {
base::RunLoop nested_loop(base::RunLoop::Type::kNestableTasksAllowed);
- ReceivedSyncMsgQueue::NestedSendDoneWatcher watcher(context, &nested_loop);
+ ReceivedSyncMsgQueue::NestedSendDoneWatcher watcher(
+ context, &nested_loop, context->listener_task_runner());
nested_loop.Run();
}
@@ -710,8 +718,9 @@ void SyncChannel::StartWatching() {
// immediately if woken up by a message which it's allowed to dispatch.
dispatch_watcher_.StartWatching(
sync_context()->GetDispatchEvent(),
- base::Bind(&SyncChannel::OnDispatchEventSignaled,
- base::Unretained(this)));
+ base::BindOnce(&SyncChannel::OnDispatchEventSignaled,
+ base::Unretained(this)),
+ sync_context()->listener_task_runner());
}
void SyncChannel::OnChannelInit() {
diff --git a/chromium/ipc/ipc_sync_message.h b/chromium/ipc/ipc_sync_message.h
index c9a1287a66d..cfac2ded124 100644
--- a/chromium/ipc/ipc_sync_message.h
+++ b/chromium/ipc/ipc_sync_message.h
@@ -8,7 +8,7 @@
#include <stdint.h>
#if defined(OS_WIN)
-#include <windows.h>
+#include "base/win/windows_types.h"
#endif
#include <memory>