Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / mojo / public / cpp / bindings / lib / router.cc
blob4fd7d1305ab57e6c8c485c8d0d82fc8c1fc74969
1 // Copyright 2014 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.
5 #include "mojo/public/cpp/bindings/lib/router.h"
7 #include "mojo/public/cpp/environment/logging.h"
9 namespace mojo {
10 namespace internal {
12 // ----------------------------------------------------------------------------
14 class ResponderThunk : public MessageReceiver {
15 public:
16 explicit ResponderThunk(const SharedData<Router*>& router)
17 : router_(router) {
19 virtual ~ResponderThunk() {
22 // MessageReceiver implementation:
23 virtual bool Accept(Message* message) MOJO_OVERRIDE {
24 MOJO_DCHECK(message->has_flag(kMessageIsResponse));
26 bool result = false;
28 Router* router = router_.value();
29 if (router)
30 result = router->Accept(message);
32 return result;
35 private:
36 SharedData<Router*> router_;
39 // ----------------------------------------------------------------------------
41 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router)
42 : router_(router) {
45 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
48 bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
49 return router_->HandleIncomingMessage(message);
52 // ----------------------------------------------------------------------------
54 Router::Router(ScopedMessagePipeHandle message_pipe,
55 FilterChain filters,
56 const MojoAsyncWaiter* waiter)
57 : thunk_(this),
58 filters_(filters.Pass()),
59 connector_(message_pipe.Pass(), waiter),
60 weak_self_(this),
61 incoming_receiver_(NULL),
62 next_request_id_(0),
63 testing_mode_(false) {
64 filters_.SetSink(&thunk_);
65 connector_.set_incoming_receiver(filters_.GetHead());
68 Router::~Router() {
69 weak_self_.set_value(NULL);
71 for (ResponderMap::const_iterator i = responders_.begin();
72 i != responders_.end(); ++i) {
73 delete i->second;
77 bool Router::Accept(Message* message) {
78 MOJO_DCHECK(!message->has_flag(kMessageExpectsResponse));
79 return connector_.Accept(message);
82 bool Router::AcceptWithResponder(Message* message,
83 MessageReceiver* responder) {
84 MOJO_DCHECK(message->has_flag(kMessageExpectsResponse));
86 // Reserve 0 in case we want it to convey special meaning in the future.
87 uint64_t request_id = next_request_id_++;
88 if (request_id == 0)
89 request_id = next_request_id_++;
91 message->set_request_id(request_id);
92 if (!connector_.Accept(message))
93 return false;
95 // We assume ownership of |responder|.
96 responders_[request_id] = responder;
97 return true;
100 void Router::EnableTestingMode() {
101 testing_mode_ = true;
102 connector_.set_enforce_errors_from_incoming_receiver(false);
105 bool Router::HandleIncomingMessage(Message* message) {
106 if (message->has_flag(kMessageExpectsResponse)) {
107 if (incoming_receiver_) {
108 MessageReceiver* responder = new ResponderThunk(weak_self_);
109 bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
110 if (!ok)
111 delete responder;
112 return ok;
115 // If we receive a request expecting a response when the client is not
116 // listening, then we have no choice but to tear down the pipe.
117 connector_.CloseMessagePipe();
118 } else if (message->has_flag(kMessageIsResponse)) {
119 uint64_t request_id = message->request_id();
120 ResponderMap::iterator it = responders_.find(request_id);
121 if (it == responders_.end()) {
122 MOJO_DCHECK(testing_mode_);
123 return false;
125 MessageReceiver* responder = it->second;
126 responders_.erase(it);
127 bool ok = responder->Accept(message);
128 delete responder;
129 return ok;
130 } else {
131 if (incoming_receiver_)
132 return incoming_receiver_->Accept(message);
133 // OK to drop message on the floor.
136 return false;
139 // ----------------------------------------------------------------------------
141 } // namespace internal
142 } // namespace mojo