• 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_INTERFACE_REQUEST_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
7 
8 #include <utility>
9 
10 #include "base/macros.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "mojo/public/cpp/bindings/interface_ptr.h"
14 
15 namespace mojo {
16 
17 // Represents a request from a remote client for an implementation of Interface
18 // over a specified message pipe. The implementor of the interface should
19 // remove the message pipe by calling PassMessagePipe() and bind it to the
20 // implementation. If this is not done, the InterfaceRequest will automatically
21 // close the pipe on destruction. Can also represent the absence of a request
22 // if the client did not provide a message pipe.
23 template <typename Interface>
24 class InterfaceRequest {
25  public:
26   // Constructs an empty InterfaceRequest, representing that the client is not
27   // requesting an implementation of Interface.
InterfaceRequest()28   InterfaceRequest() {}
InterfaceRequest(decltype (nullptr))29   InterfaceRequest(decltype(nullptr)) {}
30 
31   // Takes the message pipe from another InterfaceRequest.
InterfaceRequest(InterfaceRequest && other)32   InterfaceRequest(InterfaceRequest&& other) {
33     handle_ = std::move(other.handle_);
34   }
35   InterfaceRequest& operator=(InterfaceRequest&& other) {
36     handle_ = std::move(other.handle_);
37     return *this;
38   }
39 
40   // Assigning to nullptr resets the InterfaceRequest to an empty state,
41   // closing the message pipe currently bound to it (if any).
decltype(nullptr)42   InterfaceRequest& operator=(decltype(nullptr)) {
43     handle_.reset();
44     return *this;
45   }
46 
47   // Binds the request to a message pipe over which Interface is to be
48   // requested.  If the request is already bound to a message pipe, the current
49   // message pipe will be closed.
Bind(ScopedMessagePipeHandle handle)50   void Bind(ScopedMessagePipeHandle handle) { handle_ = std::move(handle); }
51 
52   // Indicates whether the request currently contains a valid message pipe.
is_pending()53   bool is_pending() const { return handle_.is_valid(); }
54 
55   // Removes the message pipe from the request and returns it.
PassMessagePipe()56   ScopedMessagePipeHandle PassMessagePipe() { return std::move(handle_); }
57 
Equals(const InterfaceRequest & other)58   bool Equals(const InterfaceRequest& other) const {
59     if (this == &other)
60       return true;
61 
62     // Now that the two refer to different objects, they are equivalent if
63     // and only if they are both invalid.
64     return !is_pending() && !other.is_pending();
65   }
66 
67  private:
68   ScopedMessagePipeHandle handle_;
69 
70   DISALLOW_COPY_AND_ASSIGN(InterfaceRequest);
71 };
72 
73 // Makes an InterfaceRequest bound to the specified message pipe. If |handle|
74 // is empty or invalid, the resulting InterfaceRequest will represent the
75 // absence of a request.
76 template <typename Interface>
MakeRequest(ScopedMessagePipeHandle handle)77 InterfaceRequest<Interface> MakeRequest(ScopedMessagePipeHandle handle) {
78   InterfaceRequest<Interface> request;
79   request.Bind(std::move(handle));
80   return std::move(request);
81 }
82 
83 // Creates a new message pipe over which Interface is to be served. Binds the
84 // specified InterfacePtr to one end of the message pipe, and returns an
85 // InterfaceRequest bound to the other. The InterfacePtr should be passed to
86 // the client, and the InterfaceRequest should be passed to whatever will
87 // provide the implementation. The implementation should typically be bound to
88 // the InterfaceRequest using the Binding or StrongBinding classes. The client
89 // may begin to issue calls even before an implementation has been bound, since
90 // messages sent over the pipe will just queue up until they are consumed by
91 // the implementation.
92 //
93 // Example #1: Requesting a remote implementation of an interface.
94 // ===============================================================
95 //
96 // Given the following interface:
97 //
98 //   interface Database {
99 //     OpenTable(Table& table);
100 //   }
101 //
102 // The client would have code similar to the following:
103 //
104 //   DatabasePtr database = ...;  // Connect to database.
105 //   TablePtr table;
106 //   database->OpenTable(GetProxy(&table));
107 //
108 // Upon return from GetProxy, |table| is ready to have methods called on it.
109 //
110 // Example #2: Registering a local implementation with a remote service.
111 // =====================================================================
112 //
113 // Given the following interface
114 //   interface Collector {
115 //     RegisterSource(Source source);
116 //   }
117 //
118 // The client would have code similar to the following:
119 //
120 //   CollectorPtr collector = ...;  // Connect to Collector.
121 //   SourcePtr source;
122 //   InterfaceRequest<Source> source_request = GetProxy(&source);
123 //   collector->RegisterSource(std::move(source));
124 //   CreateSource(std::move(source_request));  // Create implementation locally.
125 //
126 template <typename Interface>
127 InterfaceRequest<Interface> GetProxy(
128     InterfacePtr<Interface>* ptr,
129     scoped_refptr<base::SingleThreadTaskRunner> runner =
130         base::ThreadTaskRunnerHandle::Get()) {
131   MessagePipe pipe;
132   ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u),
133             std::move(runner));
134   return MakeRequest<Interface>(std::move(pipe.handle1));
135 }
136 
137 // Fuses an InterfaceRequest<T> endpoint with an InterfacePtrInfo<T> endpoint.
138 // Returns |true| on success or |false| on failure.
139 template <typename Interface>
FuseInterface(InterfaceRequest<Interface> request,InterfacePtrInfo<Interface> proxy_info)140 bool FuseInterface(InterfaceRequest<Interface> request,
141                    InterfacePtrInfo<Interface> proxy_info) {
142   MojoResult result = FuseMessagePipes(request.PassMessagePipe(),
143                                        proxy_info.PassHandle());
144   return result == MOJO_RESULT_OK;
145 }
146 
147 }  // namespace mojo
148 
149 #endif  // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
150