forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterface_bundle.h
138 lines (121 loc) · 5.4 KB
/
interface_bundle.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2020 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 CHROMECAST_MOJO_INTERFACE_BUNDLE_H_
#define CHROMECAST_MOJO_INTERFACE_BUNDLE_H_
#include <string>
#include "base/callback.h"
#include "base/logging.h"
#include "base/sequence_checker.h"
#include "chromecast/mojo/binder_factory.h"
#include "chromecast/mojo/mojom/remote_interfaces.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace chromecast {
// This class essentially combines RemoteInterfaces and BinderRegistry into
// one. On the host side, this class can be created and used like a
// BinderRegistry. InterfaceBundle can also dispense RemoteInterfaces remotes
// for clients to invoke local binders.
//
// This class should only be used on one sequence. Local interfaces will be
// bound to the sequence that the InterfaceBundle is created on, unless a task
// runner is provided in AddBinder().
//
// Implementations that are added via raw pointer (instead of a binder callback)
// will have the Receiver owned by the InterfaceBundle. When the InterfaceBundle
// is destroyed, the connection is severed. All implementations that are added
// by raw pointer must therefore outlive the InterfaceBundle.
//
// =============================================================================
// Example Usage
// =============================================================================
//
// Add implementations to the bundle, no Binding boilerplate required:
//
// InterfaceBundle bundle;
// bundle.AddInterface<mojom::Foo>(GetFooImpl());
// bundle.AddInterface<mojom::Bar>(GetBarImpl());
//
// Dispense a RemoteInterfaces, which can be used by clients:
//
// mojo::Remote<mojom::RemoteInterfaces> provider(bundle.CreateRemote());
// mojo::Remote<mojom::Bar> bar;
// provider->BindNewPipe(&bar);
// bar->DoBarStuff();
class InterfaceBundle : private mojom::RemoteInterfaces {
public:
// Specifies the number of expected clients for a given Receiver.
enum ReceiverType {
MULTIPLE_BINDERS, // Multiple clients, use a ReceiverSet.
SINGLE_BINDER, // Single client, use a Receiver.
};
InterfaceBundle();
InterfaceBundle(const InterfaceBundle&) = delete;
~InterfaceBundle() final;
InterfaceBundle& operator=(const InterfaceBundle&) = delete;
// Adds an implementation for an interface of type <Interface>. When the
// interface is requested via one of the consumer methods below, |interface|
// will receive the method calls.
//
// |interface| *must* outlive the InterfaceBundle, or else mojo method calls
// could be invoked on a destroyed object.
template <typename Interface>
bool AddInterface(Interface* interface,
ReceiverType receiver_type = MULTIPLE_BINDERS) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (local_interfaces_.HasInterface<Interface>()) {
LOG(DFATAL) << "Local interface '" << Interface::Name_ << "' has already "
<< "been added to this bundle.";
return false;
}
if (receiver_type == MULTIPLE_BINDERS) {
local_interfaces_.AddInterface<Interface>(interface);
} else {
local_interfaces_.AddSingleBinderInterface<Interface>(interface);
}
return true;
}
// Similar to BinderRegistry::AddInterface(), AddBinder() allows clients to
// provide their own binder callbacks and task runners. If |task_runner| is
// provided, then |callback| will be invoked on |task_runner| for every
// incoming request to <Interface>. Subsequent calls to <Interface>'s methods
// will post to |task_runner|. If |task_runner| is not provided, the current
// SequencedTaskRunner will receive incoming bind requests and method calls.
template <typename Interface>
bool AddBinder(
const base::RepeatingCallback<void(mojo::PendingReceiver<Interface>)>&
callback,
scoped_refptr<base::SequencedTaskRunner> task_runner = nullptr) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (local_interfaces_.HasInterface<Interface>()) {
LOG(DFATAL) << "Local interface '" << Interface::Name_ << "' has already "
<< "been added to this bundle.";
return false;
}
local_interfaces_.AddBinder<Interface>(callback, task_runner);
return true;
}
template <typename Interface>
void RemoveInterface() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
local_interfaces_.RemoveInterface<Interface>();
}
// Creates a remote reference which can be passed over IPC to a remote client.
mojo::PendingRemote<mojom::RemoteInterfaces> CreateRemote();
// Severs all client connections. This should only be called on teardown.
void Close();
// mojom::RemoteInterfaces implementation:
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle) override;
void AddClient(
mojo::PendingReceiver<mojom::RemoteInterfaces> receiver) override;
private:
// For interfaces that are provided as a local pointer without any binding
// logic, we can use MultiBinderFactory to expose a binding surface.
MultiBinderFactory local_interfaces_;
mojo::ReceiverSet<mojom::RemoteInterfaces> client_receivers_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace chromecast
#endif // CHROMECAST_MOJO_INTERFACE_BUNDLE_H_