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