• 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 package org.chromium.mojo.bindings;
6 
7 import org.chromium.mojo.bindings.Callbacks.Callback1;
8 import org.chromium.mojo.bindings.Interface.AbstractProxy.HandlerImpl;
9 import org.chromium.mojo.system.Core;
10 import org.chromium.mojo.system.MessagePipeHandle;
11 import org.chromium.mojo.system.MojoException;
12 import org.chromium.mojo.system.Pair;
13 
14 import java.io.Closeable;
15 
16 /**
17  * Base class for mojo generated interfaces.
18  */
19 public interface Interface extends ConnectionErrorHandler, Closeable {
20 
21     /**
22      * The close method is called when the connection to the interface is closed.
23      *
24      * @see java.io.Closeable#close()
25      */
26     @Override
close()27     public void close();
28 
29     /**
30      * A proxy to a mojo interface. This is base class for all generated proxies. It implements the
31      * Interface and each time a method is called, the parameters are serialized and sent to the
32      * {@link MessageReceiverWithResponder}, along with the response callback if needed.
33      */
34     public interface Proxy extends Interface {
35         /**
36          * Class allowing to interact with the proxy itself.
37          */
38         public interface Handler extends Closeable {
39             /**
40              * Sets the {@link ConnectionErrorHandler} that will be notified of errors.
41              */
setErrorHandler(ConnectionErrorHandler errorHandler)42             public void setErrorHandler(ConnectionErrorHandler errorHandler);
43 
44             /**
45              * Unbinds the proxy and passes the handle. Can return null if the proxy is not bound or
46              * if the proxy is not over a message pipe.
47              */
passHandle()48             public MessagePipeHandle passHandle();
49 
50             /**
51              * Returns the version number of the interface that the remote side supports.
52              */
getVersion()53             public int getVersion();
54 
55             /**
56              * Queries the max version that the remote side supports. On completion, the result will
57              * be returned as the input of |callback|. The version number of this interface pointer
58              * will also be updated.
59              */
queryVersion(Callback1<Integer> callback)60             public void queryVersion(Callback1<Integer> callback);
61 
62             /**
63              * If the remote side doesn't support the specified version, it will close its end of
64              * the message pipe asynchronously. The call does nothing if |version| is no greater
65              * than getVersion().
66              * <p>
67              * If you make a call to requireVersion() with a version number X which is not supported
68              * by the remote side, it is guaranteed that all calls to the interface methods after
69              * requireVersion(X) will be ignored.
70              */
requireVersion(int version)71             public void requireVersion(int version);
72         }
73 
74         /**
75          * Returns the {@link Handler} object allowing to interact with the proxy itself.
76          */
getProxyHandler()77         public Handler getProxyHandler();
78     }
79 
80     /**
81      * Base implementation of {@link Proxy}.
82      */
83     abstract class AbstractProxy implements Proxy {
84         /**
85          * Implementation of {@link Handler}.
86          */
87         protected static class HandlerImpl implements Proxy.Handler, ConnectionErrorHandler {
88             /**
89              * The {@link Core} implementation to use.
90              */
91             private final Core mCore;
92 
93             /**
94              * The {@link MessageReceiverWithResponder} that will receive a serialized message for
95              * each method call.
96              */
97             private final MessageReceiverWithResponder mMessageReceiver;
98 
99             /**
100              * The {@link ConnectionErrorHandler} that will be notified of errors.
101              */
102             private ConnectionErrorHandler mErrorHandler = null;
103 
104             /**
105              * The currently known version of the interface.
106              */
107             private int mVersion = 0;
108 
109             /**
110              * Constructor.
111              *
112              * @param core the Core implementation used to create pipes and access the async waiter.
113              * @param messageReceiver the message receiver to send message to.
114              */
HandlerImpl(Core core, MessageReceiverWithResponder messageReceiver)115             protected HandlerImpl(Core core, MessageReceiverWithResponder messageReceiver) {
116                 this.mCore = core;
117                 this.mMessageReceiver = messageReceiver;
118             }
119 
setVersion(int version)120             void setVersion(int version) {
121                 mVersion = version;
122             }
123 
124             /**
125              * Returns the message receiver to send message to.
126              */
getMessageReceiver()127             public MessageReceiverWithResponder getMessageReceiver() {
128                 return mMessageReceiver;
129             }
130 
131             /**
132              * Returns the Core implementation.
133              */
getCore()134             public Core getCore() {
135                 return mCore;
136             }
137 
138             /**
139              * Sets the {@link ConnectionErrorHandler} that will be notified of errors.
140              */
141             @Override
setErrorHandler(ConnectionErrorHandler errorHandler)142             public void setErrorHandler(ConnectionErrorHandler errorHandler) {
143                 this.mErrorHandler = errorHandler;
144             }
145 
146             /**
147              * @see ConnectionErrorHandler#onConnectionError(MojoException)
148              */
149             @Override
onConnectionError(MojoException e)150             public void onConnectionError(MojoException e) {
151                 if (mErrorHandler != null) {
152                     mErrorHandler.onConnectionError(e);
153                 }
154             }
155 
156             /**
157              * @see Closeable#close()
158              */
159             @Override
close()160             public void close() {
161                 mMessageReceiver.close();
162             }
163 
164             /**
165              * @see Interface.Proxy.Handler#passHandle()
166              */
167             @Override
passHandle()168             public MessagePipeHandle passHandle() {
169                 @SuppressWarnings("unchecked")
170                 HandleOwner<MessagePipeHandle> handleOwner =
171                         (HandleOwner<MessagePipeHandle>) mMessageReceiver;
172                 return handleOwner.passHandle();
173             }
174 
175             /**
176              * @see Handler#getVersion()
177              */
178             @Override
getVersion()179             public int getVersion() {
180                 return mVersion;
181             }
182 
183             /**
184              * @see Handler#queryVersion(org.chromium.mojo.bindings.Callbacks.Callback1)
185              */
186             @Override
queryVersion(final Callback1<Integer> callback)187             public void queryVersion(final Callback1<Integer> callback) {
188                 RunMessageParams message = new RunMessageParams();
189                 message.reserved0 = 16;
190                 message.reserved1 = 0;
191                 message.queryVersion = new QueryVersion();
192 
193                 InterfaceControlMessagesHelper.sendRunMessage(getCore(), mMessageReceiver, message,
194                         new Callback1<RunResponseMessageParams>() {
195                             @Override
196                             public void call(RunResponseMessageParams response) {
197                                 mVersion = response.queryVersionResult.version;
198                                 callback.call(mVersion);
199                             }
200                         });
201             }
202 
203             /**
204              * @see Handler#requireVersion(int)
205              */
206             @Override
requireVersion(int version)207             public void requireVersion(int version) {
208                 if (mVersion >= version) {
209                     return;
210                 }
211                 mVersion = version;
212                 RunOrClosePipeMessageParams message = new RunOrClosePipeMessageParams();
213                 message.reserved0 = 16;
214                 message.reserved1 = 0;
215                 message.requireVersion = new RequireVersion();
216                 message.requireVersion.version = version;
217                 InterfaceControlMessagesHelper.sendRunOrClosePipeMessage(
218                         getCore(), mMessageReceiver, message);
219             }
220         }
221 
222         /**
223          * The handler associated with this proxy.
224          */
225         private final HandlerImpl mHandler;
226 
AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver)227         protected AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver) {
228             mHandler = new HandlerImpl(core, messageReceiver);
229         }
230 
231         /**
232          * @see Interface#close()
233          */
234         @Override
close()235         public void close() {
236             mHandler.close();
237         }
238 
239         /**
240          * @see Proxy#getProxyHandler()
241          */
242         @Override
getProxyHandler()243         public HandlerImpl getProxyHandler() {
244             return mHandler;
245         }
246 
247         /**
248          * @see ConnectionErrorHandler#onConnectionError(org.chromium.mojo.system.MojoException)
249          */
250         @Override
onConnectionError(MojoException e)251         public void onConnectionError(MojoException e) {
252             mHandler.onConnectionError(e);
253         }
254     }
255 
256     /**
257      * Base implementation of Stub. Stubs are message receivers that deserialize the payload and
258      * call the appropriate method in the implementation. If the method returns result, the stub
259      * serializes the response and sends it back.
260      *
261      * @param <I> the type of the interface to delegate calls to.
262      */
263     abstract class Stub<I extends Interface> implements MessageReceiverWithResponder {
264 
265         /**
266          * The {@link Core} implementation to use.
267          */
268         private final Core mCore;
269 
270         /**
271          * The implementation to delegate calls to.
272          */
273         private final I mImpl;
274 
275         /**
276          * Constructor.
277          *
278          * @param core the {@link Core} implementation to use.
279          * @param impl the implementation to delegate calls to.
280          */
Stub(Core core, I impl)281         public Stub(Core core, I impl) {
282             mCore = core;
283             mImpl = impl;
284         }
285 
286         /**
287          * Returns the Core implementation.
288          */
getCore()289         protected Core getCore() {
290             return mCore;
291         }
292 
293         /**
294          * Returns the implementation to delegate calls to.
295          */
getImpl()296         protected I getImpl() {
297             return mImpl;
298         }
299 
300         /**
301          * @see org.chromium.mojo.bindings.MessageReceiver#close()
302          */
303         @Override
close()304         public void close() {
305             mImpl.close();
306         }
307 
308     }
309 
310     /**
311      * The |Manager| object enables building of proxies and stubs for a given interface.
312      *
313      * @param <I> the type of the interface the manager can handle.
314      * @param <P> the type of the proxy the manager can handle. To be noted, P always extends I.
315      */
316     abstract class Manager<I extends Interface, P extends Proxy> {
317 
318         /**
319          * Returns the name of the interface. This is an opaque (but human readable) identifier used
320          * by the service provider to identify services.
321          */
getName()322         public abstract String getName();
323 
324         /**
325          * Returns the version of the managed interface.
326          */
getVersion()327         public abstract int getVersion();
328 
329         /**
330          * Binds the given implementation to the handle.
331          */
bind(I impl, MessagePipeHandle handle)332         public void bind(I impl, MessagePipeHandle handle) {
333             // The router (and by consequence the handle) is intentionally leaked. It will close
334             // itself when the connected handle is closed and the proxy receives the connection
335             // error.
336             Router router = new RouterImpl(handle);
337             bind(handle.getCore(), impl, router);
338             router.start();
339         }
340 
341         /**
342          * Binds the given implementation to the InterfaceRequest.
343          */
bind(I impl, InterfaceRequest<I> request)344         public final void bind(I impl, InterfaceRequest<I> request) {
345             bind(impl, request.passHandle());
346         }
347 
348         /**
349          * Returns a Proxy that will send messages to the given |handle|. This implies that the
350          * other end of the handle must be bound to an implementation of the interface.
351          */
attachProxy(MessagePipeHandle handle, int version)352         public final P attachProxy(MessagePipeHandle handle, int version) {
353             RouterImpl router = new RouterImpl(handle);
354             P proxy = attachProxy(handle.getCore(), router);
355             DelegatingConnectionErrorHandler handlers = new DelegatingConnectionErrorHandler();
356             handlers.addConnectionErrorHandler(proxy);
357             router.setErrorHandler(handlers);
358             router.start();
359             ((HandlerImpl) proxy.getProxyHandler()).setVersion(version);
360             return proxy;
361         }
362 
363         /**
364          * Constructs a new |InterfaceRequest| for the interface. This method returns a Pair where
365          * the first element is a proxy, and the second element is the request. The proxy can be
366          * used immediately.
367          */
getInterfaceRequest(Core core)368         public final Pair<P, InterfaceRequest<I>> getInterfaceRequest(Core core) {
369             Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
370             P proxy = attachProxy(handles.first, 0);
371             return Pair.create(proxy, new InterfaceRequest<I>(handles.second));
372         }
373 
asInterfaceRequest(MessagePipeHandle handle)374         public final InterfaceRequest<I> asInterfaceRequest(MessagePipeHandle handle) {
375             return new InterfaceRequest<I>(handle);
376         }
377 
378         /**
379          * Binds the implementation to the given |router|.
380          */
bind(Core core, I impl, Router router)381         final void bind(Core core, I impl, Router router) {
382             router.setErrorHandler(impl);
383             router.setIncomingMessageReceiver(buildStub(core, impl));
384         }
385 
386         /**
387          * Returns a Proxy that will send messages to the given |router|.
388          */
attachProxy(Core core, Router router)389         final P attachProxy(Core core, Router router) {
390             return buildProxy(core, new AutoCloseableRouter(core, router));
391         }
392 
393         /**
394          * Creates a new array of the given |size|.
395          */
buildArray(int size)396         protected abstract I[] buildArray(int size);
397 
398         /**
399          * Constructs a Stub delegating to the given implementation.
400          */
buildStub(Core core, I impl)401         protected abstract Stub<I> buildStub(Core core, I impl);
402 
403         /**
404          * Constructs a Proxy forwarding the calls to the given message receiver.
405          */
buildProxy(Core core, MessageReceiverWithResponder messageReceiver)406         protected abstract P buildProxy(Core core, MessageReceiverWithResponder messageReceiver);
407 
408     }
409 }
410