blob: fa3a72ae7f9055736d1001a869344a9716c681ba [file] [log] [blame]
cjhopman060e0072015-05-06 21:37:481// Copyright 2015 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
boliu9b51b512017-02-03 15:35:055#include "base/android/java_exception_reporter.h"
cjhopman060e0072015-05-06 21:37:486
cjhopman060e0072015-05-06 21:37:487#include "base/android/jni_android.h"
wnwen2c307f9f2016-04-11 21:48:188#include "base/android/jni_string.h"
Tobias Sargeant5e78771d2019-09-21 13:49:239#include "base/android/scoped_java_ref.h"
Eric Stevensonc0926cb2019-06-19 15:03:1610#include "base/base_jni_headers/JavaExceptionReporter_jni.h"
Tobias Sargeant5e78771d2019-09-21 13:49:2311#include "base/bind.h"
Eric Secklerb23de2302020-05-26 13:05:3612#include "base/callback.h"
cjhopman060e0072015-05-06 21:37:4813#include "base/debug/dump_without_crashing.h"
Tobias Sargeant5e78771d2019-09-21 13:49:2314#include "base/lazy_instance.h"
cjhopman060e0072015-05-06 21:37:4815
torne86560112016-08-04 15:59:0416using base::android::JavaParamRef;
Tobias Sargeant5e78771d2019-09-21 13:49:2317using base::android::JavaRef;
torne86560112016-08-04 15:59:0418
boliu9b51b512017-02-03 15:35:0519namespace base {
cjhopman060e0072015-05-06 21:37:4820namespace android {
21
Joshua Peraza7814da22018-07-10 21:37:5022namespace {
23
24void (*g_java_exception_callback)(const char*);
25
Tobias Sargeant5e78771d2019-09-21 13:49:2326using JavaExceptionFilter =
27 base::RepeatingCallback<bool(const JavaRef<jthrowable>&)>;
28
29LazyInstance<JavaExceptionFilter>::Leaky g_java_exception_filter;
30
Joshua Peraza7814da22018-07-10 21:37:5031} // namespace
32
cjhopman060e0072015-05-06 21:37:4833void InitJavaExceptionReporter() {
34 JNIEnv* env = base::android::AttachCurrentThread();
Peter Wen5cd0b592020-02-20 03:17:0535 // Since JavaExceptionReporter#installHandler will chain through to the
36 // default handler, the default handler should cause a crash as if it's a
37 // normal java exception. Prefer to crash the browser process in java rather
38 // than native since for webview, the embedding app may have installed its
39 // own JavaExceptionReporter handler and would expect it to be called.
boliu328eda132017-02-10 16:39:5740 constexpr bool crash_after_report = false;
Tobias Sargeant5e78771d2019-09-21 13:49:2341 SetJavaExceptionFilter(
42 base::BindRepeating([](const JavaRef<jthrowable>&) { return true; }));
boliu328eda132017-02-10 16:39:5743 Java_JavaExceptionReporter_installHandler(env, crash_after_report);
44}
45
46void InitJavaExceptionReporterForChildProcess() {
47 JNIEnv* env = base::android::AttachCurrentThread();
48 constexpr bool crash_after_report = true;
Tobias Sargeant5e78771d2019-09-21 13:49:2349 SetJavaExceptionFilter(
50 base::BindRepeating([](const JavaRef<jthrowable>&) { return true; }));
boliu328eda132017-02-10 16:39:5751 Java_JavaExceptionReporter_installHandler(env, crash_after_report);
cjhopman060e0072015-05-06 21:37:4852}
53
Tobias Sargeant5e78771d2019-09-21 13:49:2354void SetJavaExceptionFilter(JavaExceptionFilter java_exception_filter) {
55 g_java_exception_filter.Get() = std::move(java_exception_filter);
56}
57
Joshua Peraza7814da22018-07-10 21:37:5058void SetJavaExceptionCallback(void (*callback)(const char*)) {
59 DCHECK(!g_java_exception_callback);
60 g_java_exception_callback = callback;
61}
62
63void SetJavaException(const char* exception) {
Garfield Tand5d663f2020-09-15 01:30:5664 // No need to print exception because they are already logged via
65 // env->ExceptionDescribe() within jni_android.cc.
66 if (g_java_exception_callback) {
67 g_java_exception_callback(exception);
68 }
Joshua Peraza7814da22018-07-10 21:37:5069}
70
Daniel Bratell7aacf952017-11-21 17:51:2571void JNI_JavaExceptionReporter_ReportJavaException(
72 JNIEnv* env,
Daniel Bratell7aacf952017-11-21 17:51:2573 jboolean crash_after_report,
74 const JavaParamRef<jthrowable>& e) {
boliu328eda132017-02-10 16:39:5775 std::string exception_info = base::android::GetJavaExceptionInfo(env, e);
Tobias Sargeant5e78771d2019-09-21 13:49:2376 bool should_report_exception = g_java_exception_filter.Get().Run(e);
77 if (should_report_exception) {
78 SetJavaException(exception_info.c_str());
79 }
boliu328eda132017-02-10 16:39:5780 if (crash_after_report) {
81 LOG(ERROR) << exception_info;
82 LOG(FATAL) << "Uncaught exception";
83 }
Tobias Sargeant5e78771d2019-09-21 13:49:2384 if (should_report_exception) {
85 base::debug::DumpWithoutCrashing();
86 SetJavaException(nullptr);
87 }
cjhopman060e0072015-05-06 21:37:4888}
89
Daniel Bratell7aacf952017-11-21 17:51:2590void JNI_JavaExceptionReporter_ReportJavaStackTrace(
91 JNIEnv* env,
Tobias Sargeant5e78771d2019-09-21 13:49:2392 const JavaParamRef<jstring>& stack_trace) {
93 SetJavaException(ConvertJavaStringToUTF8(stack_trace).c_str());
wnwen2c307f9f2016-04-11 21:48:1894 base::debug::DumpWithoutCrashing();
Joshua Peraza7814da22018-07-10 21:37:5095 SetJavaException(nullptr);
wnwen2c307f9f2016-04-11 21:48:1896}
97
cjhopman060e0072015-05-06 21:37:4898} // namespace android
boliu9b51b512017-02-03 15:35:0599} // namespace base