Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: mojo/public/cpp/bindings/lib/interface_endpoint_client.cc

Issue 1455063004: Mojo C++ bindings: introduce MultiplexRouter and related classes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix mac compilation Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h"
10 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
11
12 namespace mojo {
13 namespace internal {
14
15 // ----------------------------------------------------------------------------
16
17 namespace {
18
19 class ResponderThunk : public MessageReceiverWithStatus {
sky 2015/11/19 17:16:27 Please add a description as to what classes do, ev
yzshen1 2015/11/19 22:00:40 Done.
20 public:
21 explicit ResponderThunk(
22 const base::WeakPtr<InterfaceEndpointClient>& endpoint_client)
23 : endpoint_client_(endpoint_client), accept_was_invoked_(false) {}
24 ~ResponderThunk() override {
25 if (!accept_was_invoked_) {
26 // The Mojo application handled a message that was expecting a response
27 // but did not send a response.
28 if (endpoint_client_) {
29 // We raise an error to signal the calling application that an error
30 // condition occurred. Without this the calling application would have
31 // no way of knowing it should stop waiting for a response.
32 //
33 // We raise the error asynchronously and only if |endpoint_client_| is
34 // still alive when the task is run. That way it won't break the case
35 // where the user abandons the interface endpoint client soon after
36 // he/she abandons the callback.
37 base::MessageLoop::current()->PostTask(
38 FROM_HERE,
39 base::Bind(&InterfaceEndpointClient::RaiseError, endpoint_client_));
40 }
41 }
42 }
43
44 // MessageReceiver implementation:
45 bool Accept(Message* message) override {
46 accept_was_invoked_ = true;
47 DCHECK(message->has_flag(kMessageIsResponse));
48
49 bool result = false;
50
51 if (endpoint_client_)
52 result = endpoint_client_->Accept(message);
53
54 return result;
55 }
56
57 // MessageReceiverWithStatus implementation:
58 bool IsValid() override {
59 return endpoint_client_ && !endpoint_client_->encountered_error();
60 }
61
62 private:
63 base::WeakPtr<InterfaceEndpointClient> endpoint_client_;
64 bool accept_was_invoked_;
65 };
sky 2015/11/19 17:16:27 DISALLOW...
yzshen1 2015/11/19 22:00:40 Done.
66
67 } // namespace
68
69 // ----------------------------------------------------------------------------
70
71 InterfaceEndpointClient::HandleIncomingMessageThunk::HandleIncomingMessageThunk(
72 InterfaceEndpointClient* owner)
73 : owner_(owner) {}
74
75 InterfaceEndpointClient::HandleIncomingMessageThunk::
76 ~HandleIncomingMessageThunk() {}
77
78 bool InterfaceEndpointClient::HandleIncomingMessageThunk::Accept(
79 Message* message) {
80 return owner_->HandleValidatedMessage(message);
81 }
82
83 // ----------------------------------------------------------------------------
84
85 InterfaceEndpointClient::InterfaceEndpointClient(
86 ScopedInterfaceEndpointHandle handle,
87 MessageReceiverWithResponderStatus* receiver,
88 scoped_ptr<MessageFilter> payload_validator)
89 : handle_(handle.Pass()),
90 incoming_receiver_(receiver),
91 payload_validator_(payload_validator.Pass()),
92 thunk_(this),
93 next_request_id_(1),
94 encountered_error_(false),
95 weak_ptr_factory_(this) {
96 DCHECK(handle_.is_valid());
97 DCHECK(handle_.is_local());
98
99 // TODO(yzshen): the way to use validator (or message filter in general)
100 // directly is a little awkward.
101 payload_validator_->set_sink(&thunk_);
102
103 handle_.router()->AttachEndpointClient(handle_, this);
104 }
105
106 InterfaceEndpointClient::~InterfaceEndpointClient() {
107 DCHECK(thread_checker_.CalledOnValidThread());
108
109 STLDeleteValues(&responders_);
110
111 handle_.router()->DetachEndpointClient(handle_);
112 }
113
114 ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() {
115 DCHECK(thread_checker_.CalledOnValidThread());
116 DCHECK(!has_pending_responders());
117
118 if (!handle_.is_valid())
119 return ScopedInterfaceEndpointHandle();
120
121 handle_.router()->DetachEndpointClient(handle_);
122
123 return handle_.Pass();
124 }
125
126 void InterfaceEndpointClient::RaiseError() {
127 DCHECK(thread_checker_.CalledOnValidThread());
128
129 handle_.router()->RaiseError();
130 }
131
132 bool InterfaceEndpointClient::Accept(Message* message) {
133 DCHECK(thread_checker_.CalledOnValidThread());
134 DCHECK(!message->has_flag(kMessageExpectsResponse));
135
136 if (encountered_error_)
137 return false;
138
139 return handle_.router()->SendMessage(handle_, message);
140 }
141
142 bool InterfaceEndpointClient::AcceptWithResponder(Message* message,
143 MessageReceiver* responder) {
144 DCHECK(thread_checker_.CalledOnValidThread());
145 DCHECK(message->has_flag(kMessageExpectsResponse));
146
147 if (encountered_error_)
148 return false;
149
150 // Reserve 0 in case we want it to convey special meaning in the future.
151 uint64_t request_id = next_request_id_++;
152 if (request_id == 0)
153 request_id = next_request_id_++;
154
155 message->set_request_id(request_id);
156
157 if (!handle_.router()->SendMessage(handle_, message))
158 return false;
159
160 // We assume ownership of |responder|.
161 responders_[request_id] = responder;
162 return true;
163 }
164
165 bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) {
166 DCHECK(thread_checker_.CalledOnValidThread());
167
168 return payload_validator_->Accept(message);
169 }
170
171 void InterfaceEndpointClient::NotifyError() {
172 DCHECK(thread_checker_.CalledOnValidThread());
173
174 if (encountered_error_)
175 return;
176 encountered_error_ = true;
177 error_handler_.Run();
178 }
179
180 bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) {
181 DCHECK_EQ(handle_.id(), message->interface_id());
182
183 if (message->has_flag(kMessageExpectsResponse)) {
184 if (!incoming_receiver_)
185 return false;
186
187 MessageReceiverWithStatus* responder =
188 new ResponderThunk(weak_ptr_factory_.GetWeakPtr());
189 bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
sky 2015/11/19 17:16:27 It would be nice if AcceptWithResponder took a sco
yzshen1 2015/11/19 22:00:40 Right. I agree. That would require quite some cha
190 if (!ok)
191 delete responder;
192 return ok;
193 } else if (message->has_flag(kMessageIsResponse)) {
194 uint64_t request_id = message->request_id();
195 ResponderMap::iterator it = responders_.find(request_id);
196 if (it == responders_.end())
197 return false;
198 MessageReceiver* responder = it->second;
199 responders_.erase(it);
200 bool ok = responder->Accept(message);
201 delete responder;
202 return ok;
203 } else {
204 if (!incoming_receiver_)
205 return false;
206
207 return incoming_receiver_->Accept(message);
208 }
209 }
210
211 } // namespace internal
212 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698