# Mojo Basics
This document aims to provide a brief overview of the different concepts in Mojo
and how they work together. For more details about more complex and/or
Chrome-specific Mojo use cases, please consult [Intro to Mojo & Services](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/mojo_and_services.md).
[TOC]
## Interfaces
Mojo provides a [C++-like interface definition language][mojo-idl] for defining
interfaces for making interprocess calls (IPCs):
```
module math.mojom;
interface Math {
// Adds two int32s and returns the result as an int64 (to avoid
// overflow issues).
Add(int32 x, int32 y) => (int64 sum);
};
```
Interfaces are built using the `mojom` (or `mojom_component`) [GN
template][gn-template]:
```
mojom("mojom") {
sources = ["math.mojom"]
}
```
This will generate C++ (and optionally, Java and JavaScript) interfaces. Writing
code to handle IPCs is a simple matter of implementing the generated interface:
```c++
class MathImpl : public math::mojom::Math {
public:
explicit MathImpl(mojo::PendingReceiver<math::mojom::Math> receiver)
: receiver_(this, std::move(receiver)) {}
// math::mojom::Math overrides:
// Note: AddCallback is a type alias for base::OnceCallback<void(int64_t)>.
// The parameters to the callback are the reply parameters specified in the
// Mojo IDL method definition. This is part of the boilerplate generated by
// Mojo: invoking |reply| will send a reply to the caller.
void Add(int32_t x, int32_t y, AddCallback reply) override {
// Note: Mojo always returns results via callback. While it is possible to
// make a sync IPC which blocks on the reply, the handler will always return
// the result via callback.
std::move(reply).Run(static_cast<int64_t>(x) + y);
}
private:
// Wraps a message pipe endpoint that receives incoming messages. See the
// message pipes section below for more information.
mojo::Receiver<math::mojom::Math> receiver_;
};
```
Note: the build process also generates proxy classes (e.g. `MathProxy`) which
encapsulate the details of making the actual cross-process call. These are
used internally and are an implementation detail that can typically be ignored.
## Message Pipes
Interfaces are layered on top of low-level [message pipes][message-pipe]. Each
message pipe has two bidirectional endpoints. The Mojo bindings enforce
additional conventions on top of message pipes, where one endpoint is the
sender/caller, represented as:
```c++
// Wraps a message pipe endpoint for making remote calls. May only be used on
// the sequence where the mojo::Remote was bound.
mojo::Remote<math::mojom::Math> remote_math = ...;
```
And the other endpoint is the receiving/callee, represented as:
```c++
// Usually a class member. Wraps a message pipe endpoint that receives incoming
// messages. Routes and dispatches IPCs to the handler—typically |this|—on the
// sequence where the mojo::Receiver was bound.
mojo::Receiver<math::mojom::Math> receiver_;
```
This allows limited bidirectional communication. For one interface, the sender
(A) may make any number of calls to the receiver (B). (B) may send a single
reply for each call from (A). More expressive APIs are often implemented as a
pair of interfaces (with two underlying message pipes), allowing calls to be
made in either direction between (A) and (B).
Message pipe endpoints are typically created using one of:
### mojo::Remote<T>::BindNewPipeAndPassReceiver
Used when the sender/caller creates the endpoints. One endpoint is retained for
itself to send IPCs, and the other endpoint is returned as an unbound
`mojo::PendingReceiver<T>` for the receiver/callee to bind to a
`mojo::Receiver<T>`.
```c++
mojo::Remote<math::mojom::Math> remote_math;
// BindNewPipeAndPassReceiver() returns a
// mojo::PendingReceiver<math::mojom::Math>. This may be bound to a
// mojo::Receiver<math::mojom::Math> to handle calls received from
// |remote_math|.
LaunchAndBindRemoteMath(remote_math.BindNewPipeAndPassReceiver());
// |remote_math| may be immediately used. The Add() call will be buffered by the
// receiving end and dispatched when mojo::PendingReceiver<math::mojom::Math> is
// bound to a mojo::Receiver<math::mojom::Math>.
remote_math->Add(2, 2, base::BindOnce(...));
```
### mojo::Receiver<T>::BindNewPipeAndPassRemote
Used when the receiver/callee creates the endpoints. One endpoint is retained
for itself to receive IPCs, and the other endpoint is returned as an unbound
`mojo::PendingRemote<T>` for the sender/caller to bind to a `mojo::Remote<T>`.
```c++
class MathImpl : public math::mojom::MathImpl {
// ...addition to the previous MathImpl definition...
mojo::PendingRemote<math::mojom::Math> GetRemoteMath() {
// BindNewPipeAndPassRemote() returns a
// `mojo::PendingRemote<math::mojom::Math>`. This may be bound to a
// `mojo::Remote<math::mojom::Math> which can be used to send IPCs that will
// be handled by |this|.
return receiver_.BindNewPipeAndPassRemote();
}
};
```
### mojo::PendingRemote<T>::InitWithNewPipeAndPassReceiver
Less common, but similar to `mojo::Remote<T>::BindNewPipeAndPassReceiver()`.
Typically used by broker code that needs to hand off a `mojo::PendingRemote<T>`
to the sender/caller side and hand off a `mojo::PendingReceiver<T>` to the
receiver/callee side.
### mojo::Remote<T>/mojo::Receiver<T> and mojo::PendingRemote<T>/mojo::PendingReceiver<T>
Both `mojo::Remote<T>` and `mojo::Receiver<T>` have a corresponding unbound
version: this allows either endpoint to be passed between sequences in the same
process or even between processes over IPC.
```c++
mojo::Remote<math::mojom::MathImpl> remote = ...;
// |pending_remote| is movable and may be passed around. While unbound, the
// endpoint cannot be used to send IPCs. The pending remote may be passed to
// the mojo::Remote<T> constructor or mojo::Remote<T>::Bind() to rebind the
// endpoint.
mojo::PendingRemote<math::mojom::MathImpl> pending_remote = remote.Unbind();
```
```c++
mojo::Receiver<math::mojom::MathImpl> receiver = ...;
// |pending_receiver| is movable and may be passed around. While unbound,
// received IPCs are buffered and not processed. The pending receiver may be
// passed to the mojo::Receiver<T> constructor or mojo::Receiver<T>::Bind() to
// rebind the endpoint.
mojo::PendingReceiver<math::mojom::MathImpl> pending_receiver = receiver.Unbind();
```
[mojo-idl]: https://chromium.googlesource.com/chromium/src/+/main/mojo/public/tools/bindings/README.md
[gn-template]: https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/mojom.gni
[message-pipe]: https://cs.chromium.org/chromium/src/mojo/public/cpp/system/message_pipe.h