Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / public / cpp / bindings / lib / router.cc
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.
4
5 #include "mojo/public/cpp/bindings/lib/router.h"
6
7 namespace mojo {
8 namespace internal {
9
10 // ----------------------------------------------------------------------------
11
12 class ResponderThunk : public MessageReceiver {
13  public:
14   explicit ResponderThunk(const SharedData<Router*>& router)
15       : router_(router) {
16   }
17   virtual ~ResponderThunk() {
18   }
19
20   // MessageReceiver implementation:
21   virtual bool Accept(Message* message) MOJO_OVERRIDE {
22     assert(message->has_flag(kMessageIsResponse));
23
24     bool result = false;
25
26     Router* router = router_.value();
27     if (router)
28       result = router->Accept(message);
29
30     return result;
31   }
32
33   virtual bool AcceptWithResponder(Message* message,
34                                    MessageReceiver* responder) MOJO_OVERRIDE {
35     assert(false);  // not reached!
36     return false;
37   }
38
39  private:
40   SharedData<Router*> router_;
41 };
42
43 // ----------------------------------------------------------------------------
44
45 Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router)
46     : router_(router) {
47 }
48
49 Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
50 }
51
52 bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
53   return router_->HandleIncomingMessage(message);
54 }
55
56 bool Router::HandleIncomingMessageThunk::AcceptWithResponder(
57     Message* message,
58     MessageReceiver* responder) {
59   assert(false);  // not reached!
60   return false;
61 }
62
63 // ----------------------------------------------------------------------------
64
65 Router::Router(ScopedMessagePipeHandle message_pipe, MojoAsyncWaiter* waiter)
66     : connector_(message_pipe.Pass(), waiter),
67       weak_self_(this),
68       incoming_receiver_(NULL),
69       thunk_(this),
70       next_request_id_(0) {
71   connector_.set_incoming_receiver(&thunk_);
72 }
73
74 Router::~Router() {
75   weak_self_.set_value(NULL);
76
77   for (ResponderMap::const_iterator i = responders_.begin();
78        i != responders_.end(); ++i) {
79     delete i->second;
80   }
81 }
82
83 bool Router::Accept(Message* message) {
84   assert(!message->has_flag(kMessageExpectsResponse));
85   return connector_.Accept(message);
86 }
87
88 bool Router::AcceptWithResponder(Message* message,
89                                  MessageReceiver* responder) {
90   assert(message->has_flag(kMessageExpectsResponse));
91
92   // Reserve 0 in case we want it to convey special meaning in the future.
93   uint64_t request_id = next_request_id_++;
94   if (request_id == 0)
95     request_id = next_request_id_++;
96
97   message->set_request_id(request_id);
98   if (!connector_.Accept(message))
99     return false;
100
101   // We assume ownership of |responder|.
102   responders_[request_id] = responder;
103   return true;
104 }
105
106 bool Router::HandleIncomingMessage(Message* message) {
107   if (message->has_flag(kMessageExpectsResponse)) {
108     if (incoming_receiver_) {
109       MessageReceiver* responder = new ResponderThunk(weak_self_);
110       bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
111       if (!ok)
112         delete responder;
113       return ok;
114     }
115
116     // If we receive a request expecting a response when the client is not
117     // listening, then we have no choice but to tear down the pipe.
118     connector_.CloseMessagePipe();
119   } else if (message->has_flag(kMessageIsResponse)) {
120     uint64_t request_id = message->request_id();
121     ResponderMap::iterator it = responders_.find(request_id);
122     if (it == responders_.end()) {
123       assert(false);
124       return false;
125     }
126     MessageReceiver* responder = it->second;
127     responders_.erase(it);
128     bool ok = responder->Accept(message);
129     delete responder;
130     return ok;
131   } else {
132     if (incoming_receiver_)
133       return incoming_receiver_->Accept(message);
134     // OK to drop message on the floor.
135   }
136
137   return false;
138 }
139
140 // ----------------------------------------------------------------------------
141
142 }  // namespace internal
143 }  // namespace mojo