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.system.Core;
8import org.chromium.mojo.system.MessagePipeHandle;
9import org.chromium.mojo.system.MojoException;
10import org.chromium.mojo.system.Pair;
11
12import java.io.Closeable;
13
14/**
15 * Base class for mojo generated interfaces.
16 */
17public interface Interface extends ConnectionErrorHandler, Closeable {
18
19    /**
20     * The close method is called when the connection to the interface is closed.
21     *
22     * @see java.io.Closeable#close()
23     */
24    @Override
25    public void close();
26
27    /**
28     * A proxy to a mojo interface. This is base class for all generated proxies. It implements the
29     * Interface and each time a method is called, the parameters are serialized and sent to the
30     * {@link MessageReceiverWithResponder}, along with the response callback if needed.
31     */
32    public interface Proxy extends Interface {
33
34        /**
35         * Set the {@link ConnectionErrorHandler} that will be notified of errors.
36         */
37        public void setErrorHandler(ConnectionErrorHandler errorHandler);
38
39    }
40
41    /**
42     * Base implementation of {@link Proxy}.
43     */
44    abstract class AbstractProxy implements Proxy {
45
46        /**
47         * The {@link Core} implementation to use.
48         */
49        private final Core mCore;
50
51        /**
52         * The {@link MessageReceiverWithResponder} that will receive a serialized message for each
53         * method call.
54         */
55        private final MessageReceiverWithResponder mMessageReceiver;
56
57        /**
58         * The {@link ConnectionErrorHandler} that will be notified of errors.
59         */
60        private ConnectionErrorHandler mErrorHandler = null;
61
62        /**
63         * Constructor.
64         *
65         * @param core the Core implementation used to create pipes and access the async waiter.
66         * @param messageReceiver the message receiver to send message to.
67         */
68        protected AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver) {
69            this.mCore = core;
70            this.mMessageReceiver = messageReceiver;
71        }
72
73        /**
74         * Returns the message receiver to send message to.
75         */
76        protected MessageReceiverWithResponder getMessageReceiver() {
77            return mMessageReceiver;
78        }
79
80        /**
81         * Returns the Core implementation.
82         */
83        protected Core getCore() {
84            return mCore;
85        }
86
87        /**
88         * @see Proxy#setErrorHandler(ConnectionErrorHandler)
89         */
90        @Override
91        public void setErrorHandler(ConnectionErrorHandler errorHandler) {
92            this.mErrorHandler = errorHandler;
93        }
94
95        /**
96         * @see ConnectionErrorHandler#onConnectionError(MojoException)
97         */
98        @Override
99        public void onConnectionError(MojoException e) {
100            if (mErrorHandler != null) {
101                mErrorHandler.onConnectionError(e);
102            }
103        }
104
105        /**
106         * @see Closeable#close()
107         */
108        @Override
109        public void close() {
110            mMessageReceiver.close();
111        }
112    }
113
114    /**
115     * Base implementation of Stub. Stubs are message receivers that deserialize the payload and
116     * call the appropriate method in the implementation. If the method returns result, the stub
117     * serializes the response and sends it back.
118     *
119     * @param <I> the type of the interface to delegate calls to.
120     */
121    abstract class Stub<I extends Interface> implements MessageReceiverWithResponder {
122
123        /**
124         * The {@link Core} implementation to use.
125         */
126        private final Core mCore;
127
128        /**
129         * The implementation to delegate calls to.
130         */
131        private final I mImpl;
132
133        /**
134         * Constructor.
135         *
136         * @param core the {@link Core} implementation to use.
137         * @param impl the implementation to delegate calls to.
138         */
139        public Stub(Core core, I impl) {
140            mCore = core;
141            mImpl = impl;
142        }
143
144        /**
145         * Returns the Core implementation.
146         */
147        protected Core getCore() {
148            return mCore;
149        }
150
151        /**
152         * Returns the implementation to delegate calls to.
153         */
154        protected I getImpl() {
155            return mImpl;
156        }
157
158        /**
159         * @see org.chromium.mojo.bindings.MessageReceiver#close()
160         */
161        @Override
162        public void close() {
163            mImpl.close();
164        }
165
166    }
167
168    /**
169     * The |Manager| object enables building of proxies and stubs for a given interface.
170     *
171     * @param <I> the type of the interface the manager can handle.
172     * @param <P> the type of the proxy the manager can handle. To be noted, P always extends I.
173     */
174    abstract class Manager<I extends Interface, P extends Proxy> {
175
176        /**
177         * Returns the name of the interface. This is an opaque (but human readable) identifier used
178         * by the service provider to identify services.
179         */
180        public abstract String getName();
181
182        /**
183         * Binds the given implementation to the handle.
184         */
185        public void bind(I impl, MessagePipeHandle handle) {
186            // The router (and by consequence the handle) is intentionally leaked. It will close
187            // itself when the connected handle is closed and the proxy receives the connection
188            // error.
189            Router router = new RouterImpl(handle);
190            bind(handle.getCore(), impl, router);
191            router.start();
192        }
193
194        /**
195         * Binds the given implementation to the InterfaceRequest.
196         */
197        public final void bind(I impl, InterfaceRequest<I> request) {
198            bind(impl, request.passHandle());
199        }
200
201        /**
202         * Returns a Proxy that will send messages to the given |handle|. This implies that the
203         * other end of the handle must be binded to an implementation of the interface.
204         */
205        public final P attachProxy(MessagePipeHandle handle) {
206            RouterImpl router = new RouterImpl(handle);
207            P proxy = attachProxy(handle.getCore(), router);
208            DelegatingConnectionErrorHandler handlers = new DelegatingConnectionErrorHandler();
209            handlers.addConnectionErrorHandler(proxy);
210            router.setErrorHandler(handlers);
211            router.start();
212            return proxy;
213        }
214
215        /**
216         * Constructs a new |InterfaceRequest| for the interface. This method returns a Pair where
217         * the first element is a proxy, and the second element is the request. The proxy can be
218         * used immediately.
219         */
220        public final Pair<P, InterfaceRequest<I>> getInterfaceRequest(Core core) {
221            Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
222            P proxy = attachProxy(handles.first);
223            return Pair.create(proxy, new InterfaceRequest<I>(handles.second));
224        }
225
226        /**
227         * Binds the implementation to the given |router|.
228         */
229        final void bind(Core core, I impl, Router router) {
230            router.setErrorHandler(impl);
231            router.setIncomingMessageReceiver(buildStub(core, impl));
232        }
233
234        /**
235         * Returns a Proxy that will send messages to the given |router|.
236         */
237        final P attachProxy(Core core, Router router) {
238            return buildProxy(core, new AutoCloseableRouter(core, router));
239        }
240
241        /**
242         * Creates a new array of the given |size|.
243         */
244        protected abstract I[] buildArray(int size);
245
246        /**
247         * Constructs a Stub delegating to the given implementation.
248         */
249        protected abstract Stub<I> buildStub(Core core, I impl);
250
251        /**
252         * Constructs a Proxy forwarding the calls to the given message receiver.
253         */
254        protected abstract P buildProxy(Core core, MessageReceiverWithResponder messageReceiver);
255
256    }
257}
258