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