blob: 882f584efd3a128dff4475d02d24839c3181ebc4 [file] [log] [blame]
// Copyright 2017 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.chrome.browser.crash;
import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.MainDex;
import org.chromium.chrome.browser.base.SplitCompatUtils;
import org.chromium.components.crash.CrashKeys;
/**
* This UncaughtExceptionHandler will upload the stacktrace when there is an uncaught exception.
*
* This happens before native is loaded, and will replace by JavaExceptionReporter after native
* finishes loading.
*/
@MainDex
public class PureJavaExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Thread.UncaughtExceptionHandler mParent;
private boolean mHandlingException;
private static boolean sIsDisabled;
/** Interface to allow uploading reports. */
public interface JavaExceptionReporter {
void createAndUploadReport(Throwable e);
}
private PureJavaExceptionHandler(Thread.UncaughtExceptionHandler parent) {
mParent = parent;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (!mHandlingException && !sIsDisabled) {
mHandlingException = true;
reportJavaException(e);
}
if (mParent != null) {
mParent.uncaughtException(t, e);
}
}
public static void installHandler() {
if (!sIsDisabled) {
Thread.setDefaultUncaughtExceptionHandler(
new PureJavaExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()));
}
}
@CalledByNative
private static void uninstallHandler() {
// The current handler can be in the middle of an exception handler chain. We do not know
// about handlers before it. If resetting the uncaught exception handler to mParent, we lost
// all the handlers before mParent. In order to disable this handler, globally setting a
// flag to ignore it seems to be the easiest way.
sIsDisabled = true;
CrashKeys.getInstance().flushToNative();
}
private void reportJavaException(Throwable e) {
// PureJavaExceptionReporter may be in the chrome module, so load by reflection from there.
JavaExceptionReporter reporter = (JavaExceptionReporter) SplitCompatUtils.newInstance(
SplitCompatUtils.createChromeContext(ContextUtils.getApplicationContext()),
"org.chromium.chrome.browser.crash.PureJavaExceptionReporter");
reporter.createAndUploadReport(e);
}
}