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
5package org.chromium.mojo.bindings;
6
7import org.chromium.mojo.bindings.Callbacks.Callback1;
8import org.chromium.mojo.bindings.Interface.AbstractProxy.HandlerImpl;
9import org.chromium.mojo.system.Core;
10import org.chromium.mojo.system.MessagePipeHandle;
11import org.chromium.mojo.system.MojoException;
12import org.chromium.mojo.system.Pair;
13
14import java.io.Closeable;
15
16/**
17 * Base class for mojo generated interfaces.
18 */
19public 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
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             */
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             */
48            public MessagePipeHandle passHandle();
49
50            /**
51             * Returns the version number of the interface that the remote side supports.
52             */
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             */
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             */
71            public void requireVersion(int version);
72        }
73
74        /**
75         * Returns the {@link Handler} object allowing to interact with the proxy itself.
76         */
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             */
115            protected HandlerImpl(Core core, MessageReceiverWithResponder messageReceiver) {
116                this.mCore = core;
117                this.mMessageReceiver = messageReceiver;
118            }
119
120            void setVersion(int version) {
121                mVersion = version;
122            }
123
124            /**
125             * Returns the message receiver to send message to.
126             */
127            public MessageReceiverWithResponder getMessageReceiver() {
128                return mMessageReceiver;
129            }
130
131            /**
132             * Returns the Core implementation.
133             */
134            public Core getCore() {
135                return mCore;
136            }
137
138            /**
139             * Sets the {@link ConnectionErrorHandler} that will be notified of errors.
140             */
141            @Override
142            public void setErrorHandler(ConnectionErrorHandler errorHandler) {
143                this.mErrorHandler = errorHandler;
144            }
145
146            /**
147             * @see ConnectionErrorHandler#onConnectionError(MojoException)
148             */
149            @Override
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
160            public void close() {
161                mMessageReceiver.close();
162            }
163
164            /**
165             * @see Interface.Proxy.Handler#passHandle()
166             */
167            @Override
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
179            public int getVersion() {
180                return mVersion;
181            }
182
183            /**
184             * @see Handler#queryVersion(org.chromium.mojo.bindings.Callbacks.Callback1)
185             */
186            @Override
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
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
227        protected AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver) {
228            mHandler = new HandlerImpl(core, messageReceiver);
229        }
230
231        /**
232         * @see Interface#close()
233         */
234        @Override
235        public void close() {
236            mHandler.close();
237        }
238
239        /**
240         * @see Proxy#getProxyHandler()
241         */
242        @Override
243        public HandlerImpl getProxyHandler() {
244            return mHandler;
245        }
246
247        /**
248         * @see ConnectionErrorHandler#onConnectionError(org.chromium.mojo.system.MojoException)
249         */
250        @Override
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         */
281        public Stub(Core core, I impl) {
282            mCore = core;
283            mImpl = impl;
284        }
285
286        /**
287         * Returns the Core implementation.
288         */
289        protected Core getCore() {
290            return mCore;
291        }
292
293        /**
294         * Returns the implementation to delegate calls to.
295         */
296        protected I getImpl() {
297            return mImpl;
298        }
299
300        /**
301         * @see org.chromium.mojo.bindings.MessageReceiver#close()
302         */
303        @Override
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         */
322        public abstract String getName();
323
324        /**
325         * Returns the version of the managed interface.
326         */
327        public abstract int getVersion();
328
329        /**
330         * Binds the given implementation to the handle.
331         */
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         */
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         */
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         */
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
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         */
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         */
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         */
396        protected abstract I[] buildArray(int size);
397
398        /**
399         * Constructs a Stub delegating to the given implementation.
400         */
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         */
406        protected abstract P buildProxy(Core core, MessageReceiverWithResponder messageReceiver);
407
408    }
409}
410