[go: nahoru, domu]

blob: d64e98b2c382eac1e5aa2711efee908bf49f804b [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_NAMED_MOJO_IPC_SERVER_NAMED_MOJO_IPC_SERVER_H_
#define COMPONENTS_NAMED_MOJO_IPC_SERVER_NAMED_MOJO_IPC_SERVER_H_
#include <memory>
#include <utility>
#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
#include "components/named_mojo_ipc_server/endpoint_options.h"
#include "components/named_mojo_ipc_server/ipc_server.h"
#include "components/named_mojo_ipc_server/named_mojo_message_pipe_server.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace mojo {
class IsolatedConnection;
}
namespace named_mojo_ipc_server {
// Template-less base class to keep implementations in the .cc file. For usage,
// see MojoIpcServer.
class NamedMojoIpcServerBase : public IpcServer {
public:
// Internal use only.
struct PendingConnection;
void StartServer() override;
void StopServer() override;
void Close(mojo::ReceiverId id) override;
// Sets a callback to be run when an invitation is sent. Used by unit tests
// only.
void set_on_server_endpoint_created_callback_for_testing(
const base::RepeatingClosure& callback) {
message_pipe_server_.set_on_server_endpoint_created_callback_for_testing(
callback);
}
protected:
NamedMojoIpcServerBase(
const EndpointOptions& options,
base::RepeatingCallback<void*(std::unique_ptr<ConnectionInfo>)>
impl_provider);
~NamedMojoIpcServerBase() override;
void OnIpcDisconnected();
virtual mojo::ReceiverId TrackMessagePipe(
mojo::ScopedMessagePipeHandle message_pipe,
void* impl,
base::ProcessId peer_pid) = 0;
virtual void UntrackMessagePipe(mojo::ReceiverId id) = 0;
virtual void UntrackAllMessagePipes() = 0;
SEQUENCE_CHECKER(sequence_checker_);
base::RepeatingClosure disconnect_handler_;
private:
void OnMessagePipeReady(mojo::ScopedMessagePipeHandle message_pipe,
base::ProcessId peer_pid,
void* context,
std::unique_ptr<mojo::IsolatedConnection> connection);
using ActiveConnectionMap =
base::flat_map<mojo::ReceiverId,
std::unique_ptr<mojo::IsolatedConnection>>;
NamedMojoMessagePipeServer message_pipe_server_;
// This is only populated if the server uses isolated connections.
ActiveConnectionMap active_connections_;
};
// A helper that uses a NamedPlatformChannel to send out mojo invitations and
// maintains multiple concurrent IPCs. It keeps one outgoing invitation at a
// time and will send a new invitation whenever the previous one has been
// accepted by the client. Please see README.md for the example usage.
template <typename Interface>
class NamedMojoIpcServer final : public NamedMojoIpcServerBase {
public:
// options: Options to start the server endpoint.
// impl_provider: A function that returns a pointer to an implementation,
// or nullptr if the connecting endpoint should be rejected.
NamedMojoIpcServer(
const EndpointOptions& options,
base::RepeatingCallback<Interface*(std::unique_ptr<ConnectionInfo>)>
impl_provider)
: NamedMojoIpcServerBase(
options,
impl_provider.Then(base::BindRepeating([](Interface* impl) {
// Opacify the type for the base class, which takes no template
// parameters.
return reinterpret_cast<void*>(impl);
}))) {
receiver_set_.set_disconnect_handler(base::BindRepeating(
&NamedMojoIpcServer::OnIpcDisconnected, base::Unretained(this)));
}
~NamedMojoIpcServer() override = default;
NamedMojoIpcServer(const NamedMojoIpcServer&) = delete;
NamedMojoIpcServer& operator=(const NamedMojoIpcServer&) = delete;
void set_disconnect_handler(base::RepeatingClosure handler) override {
disconnect_handler_ = handler;
}
mojo::ReceiverId current_receiver() const override {
return receiver_set_.current_receiver();
}
base::ProcessId current_peer_pid() const override {
return receiver_set_.current_context();
}
size_t GetNumberOfActiveConnectionsForTesting() const {
return receiver_set_.size();
}
private:
// NamedMojoIpcServerBase implementation.
mojo::ReceiverId TrackMessagePipe(mojo::ScopedMessagePipeHandle message_pipe,
void* impl,
base::ProcessId peer_pid) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return receiver_set_.Add(
reinterpret_cast<Interface*>(impl),
mojo::PendingReceiver<Interface>(std::move(message_pipe)), peer_pid);
}
void UntrackMessagePipe(mojo::ReceiverId id) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
receiver_set_.Remove(id);
}
void UntrackAllMessagePipes() override { receiver_set_.Clear(); }
mojo::ReceiverSet<Interface, base::ProcessId> receiver_set_;
};
} // namespace named_mojo_ipc_server
#endif // COMPONENTS_NAMED_MOJO_IPC_SERVER_NAMED_MOJO_IPC_SERVER_H_