Commit 4256ecec authored by Luis Hector Chavez's avatar Luis Hector Chavez Committed by Commit Bot

[mojo] Add a way to handle unhandled RuntimeExceptions

This change makes it possible to allow interfaces to globally handle
unhandled RuntimeExceptions, in their bindings or in the callbacks.

      delegate can now forward the unhandled exceptions to the crash
      server.

Bug: 810087
Test: Android-on-Chrome OS has the same behavior as before
Test: Android-on-Chrome OS, when setting the DefaultExceptionHandler's
Change-Id: I2b7455a0344a109e1d2416a74ad4a0b98cd007f0
Reviewed-on: https://chromium-review.googlesource.com/1101898Reviewed-by: default avatarKen Rockot <rockot@chromium.org>
Commit-Queue: Luis Hector Chavez <lhchavez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568128}
parent 2fb26899
...@@ -41,6 +41,7 @@ android_library("bindings_java") { ...@@ -41,6 +41,7 @@ android_library("bindings_java") {
"bindings/src/org/chromium/mojo/bindings/DelegatingConnectionErrorHandler.java", "bindings/src/org/chromium/mojo/bindings/DelegatingConnectionErrorHandler.java",
"bindings/src/org/chromium/mojo/bindings/DeserializationException.java", "bindings/src/org/chromium/mojo/bindings/DeserializationException.java",
"bindings/src/org/chromium/mojo/bindings/Encoder.java", "bindings/src/org/chromium/mojo/bindings/Encoder.java",
"bindings/src/org/chromium/mojo/bindings/ExceptionHandler.java",
"bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java", "bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java",
"bindings/src/org/chromium/mojo/bindings/HandleOwner.java", "bindings/src/org/chromium/mojo/bindings/HandleOwner.java",
"bindings/src/org/chromium/mojo/bindings/InterfaceControlMessagesHelper.java", "bindings/src/org/chromium/mojo/bindings/InterfaceControlMessagesHelper.java",
......
...@@ -201,8 +201,16 @@ public class Connector implements MessageReceiver, HandleOwner<MessagePipeHandle ...@@ -201,8 +201,16 @@ public class Connector implements MessageReceiver, HandleOwner<MessagePipeHandle
ReadMessageResult readResult = result.getValue(); ReadMessageResult readResult = result.getValue();
assert readResult != null; assert readResult != null;
if (receiver != null) { if (receiver != null) {
boolean accepted = receiver.accept( boolean accepted;
new Message(ByteBuffer.wrap(readResult.mData), readResult.mHandles)); try {
accepted = receiver.accept(
new Message(ByteBuffer.wrap(readResult.mData), readResult.mHandles));
} catch (RuntimeException e) {
// The DefaultExceptionHandler will decide whether any uncaught exception will
// close the connection or not.
accepted =
ExceptionHandler.DefaultExceptionHandler.getInstance().handleException(e);
}
return new ResultAnd<Boolean>(result.getMojoResult(), accepted); return new ResultAnd<Boolean>(result.getMojoResult(), accepted);
} }
return new ResultAnd<Boolean>(result.getMojoResult(), false); return new ResultAnd<Boolean>(result.getMojoResult(), false);
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.mojo.bindings;
/**
* An {@link ExceptionHandler} is notified of any {@link RuntimeException} happening in the
* bindings or any of the callbacks.
*/
public interface ExceptionHandler {
/**
* Receives a notification that an unhandled {@link RuntimeException} has been thrown in an
* {@link Interface} implementation or one of the {@link Callbacks} internal classes.
*
* Normal implementations should either throw the exception or return whether the connection
* should be kept alive or terminated.
*/
public boolean handleException(RuntimeException e);
/**
* The default ExceptionHandler, which simply throws the exception upon receiving it. It can
* also delegate the handling of the exceptions to another instance of ExceptionHandler.
*/
public static class DefaultExceptionHandler implements ExceptionHandler {
private ExceptionHandler mDelegate;
@Override
public boolean handleException(RuntimeException e) {
if (mDelegate != null) {
return mDelegate.handleException(e);
}
throw e;
}
private DefaultExceptionHandler() {}
/**
* Static class that implements the initialization-on-demand holder idiom.
*/
private static class LazyHolder {
static final DefaultExceptionHandler INSTANCE = new DefaultExceptionHandler();
}
/**
* Gets the singleton instance for the DefaultExceptionHandler.
*/
public static DefaultExceptionHandler getInstance() {
return LazyHolder.INSTANCE;
}
/**
* Sets a delegate ExceptionHandler, in case throwing an exception is not desirable.
*/
public void setDelegate(ExceptionHandler exceptionHandler) {
mDelegate = exceptionHandler;
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment