#ifndef MOJO_PUBLIC_CPP_BINDINGS_SHARED_ASSOCIATED_REMOTE_H_
#define MOJO_PUBLIC_CPP_BINDINGS_SHARED_ASSOCIATED_REMOTE_H_
#include <tuple>
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/runtime_features.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
namespace mojo {
namespace internal {
template <typename Interface>
struct SharedRemoteTraits<AssociatedRemote<Interface>> {
static void BindDisconnected(AssociatedRemote<Interface>& remote) {
std::ignore = remote.BindNewEndpointAndPassDedicatedReceiver();
}
};
}
template <typename Interface>
class SharedAssociatedRemote {
public:
SharedAssociatedRemote() = default;
explicit SharedAssociatedRemote(
PendingAssociatedRemote<Interface> pending_remote,
scoped_refptr<base::SequencedTaskRunner> bind_task_runner =
base::SequencedTaskRunner::GetCurrentDefault(),
const base::Location& location = base::Location::Current()) {
if (pending_remote.is_valid())
Bind(std::move(pending_remote), std::move(bind_task_runner), location);
}
bool is_bound() const { return remote_ != nullptr; }
explicit operator bool() const { return is_bound(); }
Interface* get() const { return remote_->get(); }
Interface* operator->() const { return get(); }
Interface& operator*() const { return *get(); }
void set_disconnect_handler(
base::OnceClosure handler,
scoped_refptr<base::SequencedTaskRunner> handler_task_runner) {
remote_->set_disconnect_handler(std::move(handler),
std::move(handler_task_runner));
}
void reset() { remote_.reset(); }
void Disconnect() { remote_->Disconnect(); }
mojo::PendingAssociatedReceiver<Interface> BindNewEndpointAndPassReceiver(
scoped_refptr<base::SequencedTaskRunner> bind_task_runner =
base::SequencedTaskRunner::GetCurrentDefault(),
const base::Location& location = base::Location::Current()) {
if (!internal::GetRuntimeFeature_ExpectEnabled<Interface>()) {
return PendingAssociatedReceiver<Interface>();
}
mojo::PendingAssociatedRemote<Interface> remote;
auto receiver = remote.InitWithNewEndpointAndPassReceiver();
Bind(std::move(remote), std::move(bind_task_runner), location);
return receiver;
}
void Bind(PendingAssociatedRemote<Interface> pending_remote,
scoped_refptr<base::SequencedTaskRunner> bind_task_runner =
base::SequencedTaskRunner::GetCurrentDefault(),
const base::Location& location = base::Location::Current()) {
DCHECK(!remote_);
DCHECK(pending_remote.is_valid());
if (!internal::GetRuntimeFeature_ExpectEnabled<Interface>()) {
remote_.reset();
return;
}
remote_ = SharedRemoteBase<AssociatedRemote<Interface>>::Create(
std::move(pending_remote), std::move(bind_task_runner), location);
}
private:
scoped_refptr<SharedRemoteBase<AssociatedRemote<Interface>>> remote_;
};
}
#endif