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.system.Core; 8 import org.chromium.mojo.system.MessagePipeHandle; 9 10 import java.util.concurrent.Executor; 11 12 /** 13 * Wrapper around {@link Router} that will close the connection when not referenced anymore. 14 */ 15 class AutoCloseableRouter implements Router { 16 /** 17 * The underlying router. 18 */ 19 private final Router mRouter; 20 21 /** 22 * The executor to close the underlying router. 23 */ 24 private final Executor mExecutor; 25 26 /** 27 * Exception used to track AutoCloseableRouter's allocation location for debugging puproses when 28 * leaked. 29 */ 30 private final Exception mAllocationException; 31 32 /** 33 * Flags to keep track if this router has been correctly closed. 34 */ 35 private boolean mClosed; 36 37 /** 38 * Constructor. 39 */ AutoCloseableRouter(Core core, Router router)40 public AutoCloseableRouter(Core core, Router router) { 41 mRouter = router; 42 mExecutor = ExecutorFactory.getExecutorForCurrentThread(core); 43 mAllocationException = new Exception("AutocloseableRouter allocated at:"); 44 } 45 46 /** 47 * @see Router#setIncomingMessageReceiver(MessageReceiverWithResponder) 48 */ 49 @Override setIncomingMessageReceiver(MessageReceiverWithResponder incomingMessageReceiver)50 public void setIncomingMessageReceiver(MessageReceiverWithResponder incomingMessageReceiver) { 51 mRouter.setIncomingMessageReceiver(incomingMessageReceiver); 52 } 53 54 /** 55 * @see HandleOwner#passHandle() 56 */ 57 @Override passHandle()58 public MessagePipeHandle passHandle() { 59 return mRouter.passHandle(); 60 } 61 62 /** 63 * @see MessageReceiver#accept(Message) 64 */ 65 @Override accept(Message message)66 public boolean accept(Message message) { 67 return mRouter.accept(message); 68 } 69 70 /** 71 * @see MessageReceiverWithResponder#acceptWithResponder(Message, MessageReceiver) 72 */ 73 @Override acceptWithResponder(Message message, MessageReceiver responder)74 public boolean acceptWithResponder(Message message, MessageReceiver responder) { 75 return mRouter.acceptWithResponder(message, responder); 76 77 } 78 79 /** 80 * @see Router#start() 81 */ 82 @Override start()83 public void start() { 84 mRouter.start(); 85 } 86 87 /** 88 * @see Router#setErrorHandler(ConnectionErrorHandler) 89 */ 90 @Override setErrorHandler(ConnectionErrorHandler errorHandler)91 public void setErrorHandler(ConnectionErrorHandler errorHandler) { 92 mRouter.setErrorHandler(errorHandler); 93 } 94 95 /** 96 * @see java.io.Closeable#close() 97 */ 98 @Override close()99 public void close() { 100 mRouter.close(); 101 mClosed = true; 102 } 103 104 /** 105 * @see Object#finalize() 106 */ 107 @Override finalize()108 protected void finalize() throws Throwable { 109 if (!mClosed) { 110 mExecutor.execute(new Runnable() { 111 112 @Override 113 public void run() { 114 close(); 115 } 116 }); 117 throw new IllegalStateException("Warning: Router objects should be explicitly closed " 118 + "when no longer required otherwise you may leak handles.", 119 mAllocationException); 120 } 121 super.finalize(); 122 } 123 } 124