• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <queue>
13 
14 #include "base/callback.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/threading/thread_checker.h"
20 #include "mojo/public/cpp/bindings/connector.h"
21 #include "mojo/public/cpp/bindings/lib/filter_chain.h"
22 
23 namespace mojo {
24 namespace internal {
25 
26 // TODO(yzshen): Consider removing this class and use MultiplexRouter in all
27 // cases. crbug.com/594244
28 class Router : public MessageReceiverWithResponder {
29  public:
30   Router(ScopedMessagePipeHandle message_pipe,
31          FilterChain filters,
32          bool expects_sync_requests,
33          scoped_refptr<base::SingleThreadTaskRunner> runner);
34   ~Router() override;
35 
36   // Sets the receiver to handle messages read from the message pipe that do
37   // not have the Message::kFlagIsResponse flag set.
set_incoming_receiver(MessageReceiverWithResponderStatus * receiver)38   void set_incoming_receiver(MessageReceiverWithResponderStatus* receiver) {
39     incoming_receiver_ = receiver;
40   }
41 
42   // Sets the error handler to receive notifications when an error is
43   // encountered while reading from the pipe or waiting to read from the pipe.
set_connection_error_handler(const base::Closure & error_handler)44   void set_connection_error_handler(const base::Closure& error_handler) {
45     error_handler_ = error_handler;
46   }
47 
48   // Returns true if an error was encountered while reading from the pipe or
49   // waiting to read from the pipe.
encountered_error()50   bool encountered_error() const {
51     DCHECK(thread_checker_.CalledOnValidThread());
52     return encountered_error_;
53   }
54 
55   // Is the router bound to a MessagePipe handle?
is_valid()56   bool is_valid() const {
57     DCHECK(thread_checker_.CalledOnValidThread());
58     return connector_.is_valid();
59   }
60 
61   // Please note that this method shouldn't be called unless it results from an
62   // explicit request of the user of bindings (e.g., the user sets an
63   // InterfacePtr to null or closes a Binding).
CloseMessagePipe()64   void CloseMessagePipe() {
65     DCHECK(thread_checker_.CalledOnValidThread());
66     connector_.CloseMessagePipe();
67   }
68 
PassMessagePipe()69   ScopedMessagePipeHandle PassMessagePipe() {
70     DCHECK(thread_checker_.CalledOnValidThread());
71     return connector_.PassMessagePipe();
72   }
73 
RaiseError()74   void RaiseError() {
75     DCHECK(thread_checker_.CalledOnValidThread());
76     connector_.RaiseError();
77   }
78 
79   // MessageReceiver implementation:
80   bool Accept(Message* message) override;
81   bool AcceptWithResponder(Message* message,
82                            MessageReceiver* responder) override;
83 
84   // Blocks the current thread until the first incoming method call, i.e.,
85   // either a call to a client method or a callback method, or |deadline|.
WaitForIncomingMessage(MojoDeadline deadline)86   bool WaitForIncomingMessage(MojoDeadline deadline) {
87     DCHECK(thread_checker_.CalledOnValidThread());
88     return connector_.WaitForIncomingMessage(deadline);
89   }
90 
91   // See Binding for details of pause/resume.
PauseIncomingMethodCallProcessing()92   void PauseIncomingMethodCallProcessing() {
93     DCHECK(thread_checker_.CalledOnValidThread());
94     connector_.PauseIncomingMethodCallProcessing();
95   }
ResumeIncomingMethodCallProcessing()96   void ResumeIncomingMethodCallProcessing() {
97     DCHECK(thread_checker_.CalledOnValidThread());
98     connector_.ResumeIncomingMethodCallProcessing();
99   }
100 
101   // Sets this object to testing mode.
102   // In testing mode:
103   // - the object is more tolerant of unrecognized response messages;
104   // - the connector continues working after seeing errors from its incoming
105   //   receiver.
106   void EnableTestingMode();
107 
handle()108   MessagePipeHandle handle() const { return connector_.handle(); }
109 
110   // Returns true if this Router has any pending callbacks.
has_pending_responders()111   bool has_pending_responders() const {
112     DCHECK(thread_checker_.CalledOnValidThread());
113     return !async_responders_.empty() || !sync_responses_.empty();
114   }
115 
116  private:
117   // Maps from the id of a response to the MessageReceiver that handles the
118   // response.
119   using AsyncResponderMap =
120       std::map<uint64_t, std::unique_ptr<MessageReceiver>>;
121 
122   struct SyncResponseInfo {
123    public:
124     explicit SyncResponseInfo(bool* in_response_received);
125     ~SyncResponseInfo();
126 
127     std::unique_ptr<Message> response;
128 
129     // Points to a stack-allocated variable.
130     bool* response_received;
131 
132    private:
133     DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo);
134   };
135 
136   using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>;
137 
138   class HandleIncomingMessageThunk : public MessageReceiver {
139    public:
140     HandleIncomingMessageThunk(Router* router);
141     ~HandleIncomingMessageThunk() override;
142 
143     // MessageReceiver implementation:
144     bool Accept(Message* message) override;
145 
146    private:
147     Router* router_;
148   };
149 
150   bool HandleIncomingMessage(Message* message);
151   void HandleQueuedMessages();
152   bool HandleMessageInternal(Message* message);
153 
154   void OnConnectionError();
155 
156   HandleIncomingMessageThunk thunk_;
157   FilterChain filters_;
158   Connector connector_;
159   MessageReceiverWithResponderStatus* incoming_receiver_;
160   AsyncResponderMap async_responders_;
161   SyncResponseMap sync_responses_;
162   uint64_t next_request_id_;
163   bool testing_mode_;
164   std::queue<std::unique_ptr<Message>> pending_messages_;
165   // Whether a task has been posted to trigger processing of
166   // |pending_messages_|.
167   bool pending_task_for_messages_;
168   bool encountered_error_;
169   base::Closure error_handler_;
170   base::ThreadChecker thread_checker_;
171   base::WeakPtrFactory<Router> weak_factory_;
172 };
173 
174 }  // namespace internal
175 }  // namespace mojo
176 
177 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
178