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