java_exception_reporter.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // 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. #include "base/android/java_exception_reporter.h"
  5. #include "base/android/jni_android.h"
  6. #include "base/android/jni_string.h"
  7. #include "base/android/scoped_java_ref.h"
  8. #include "base/base_jni_headers/JavaExceptionReporter_jni.h"
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/debug/dump_without_crashing.h"
  12. #include "base/lazy_instance.h"
  13. using base::android::JavaParamRef;
  14. using base::android::JavaRef;
  15. namespace base {
  16. namespace android {
  17. namespace {
  18. void (*g_java_exception_callback)(const char*);
  19. using JavaExceptionFilter =
  20. base::RepeatingCallback<bool(const JavaRef<jthrowable>&)>;
  21. LazyInstance<JavaExceptionFilter>::Leaky g_java_exception_filter =
  22. LAZY_INSTANCE_INITIALIZER;
  23. } // namespace
  24. void InitJavaExceptionReporter() {
  25. JNIEnv* env = base::android::AttachCurrentThread();
  26. // Since JavaExceptionReporter#installHandler will chain through to the
  27. // default handler, the default handler should cause a crash as if it's a
  28. // normal java exception. Prefer to crash the browser process in java rather
  29. // than native since for webview, the embedding app may have installed its
  30. // own JavaExceptionReporter handler and would expect it to be called.
  31. constexpr bool crash_after_report = false;
  32. SetJavaExceptionFilter(
  33. base::BindRepeating([](const JavaRef<jthrowable>&) { return true; }));
  34. Java_JavaExceptionReporter_installHandler(env, crash_after_report);
  35. }
  36. void InitJavaExceptionReporterForChildProcess() {
  37. JNIEnv* env = base::android::AttachCurrentThread();
  38. constexpr bool crash_after_report = true;
  39. SetJavaExceptionFilter(
  40. base::BindRepeating([](const JavaRef<jthrowable>&) { return true; }));
  41. Java_JavaExceptionReporter_installHandler(env, crash_after_report);
  42. }
  43. void SetJavaExceptionFilter(JavaExceptionFilter java_exception_filter) {
  44. g_java_exception_filter.Get() = std::move(java_exception_filter);
  45. }
  46. void SetJavaExceptionCallback(void (*callback)(const char*)) {
  47. DCHECK(!g_java_exception_callback);
  48. g_java_exception_callback = callback;
  49. }
  50. void SetJavaException(const char* exception) {
  51. // No need to print exception because they are already logged via
  52. // env->ExceptionDescribe() within jni_android.cc.
  53. if (g_java_exception_callback) {
  54. g_java_exception_callback(exception);
  55. }
  56. }
  57. void JNI_JavaExceptionReporter_ReportJavaException(
  58. JNIEnv* env,
  59. jboolean crash_after_report,
  60. const JavaParamRef<jthrowable>& e) {
  61. std::string exception_info = base::android::GetJavaExceptionInfo(env, e);
  62. bool should_report_exception = g_java_exception_filter.Get().Run(e);
  63. if (should_report_exception) {
  64. SetJavaException(exception_info.c_str());
  65. }
  66. if (crash_after_report) {
  67. LOG(ERROR) << exception_info;
  68. LOG(FATAL) << "Uncaught exception";
  69. }
  70. if (should_report_exception) {
  71. base::debug::DumpWithoutCrashing();
  72. SetJavaException(nullptr);
  73. }
  74. }
  75. void JNI_JavaExceptionReporter_ReportJavaStackTrace(
  76. JNIEnv* env,
  77. const JavaParamRef<jstring>& stack_trace) {
  78. SetJavaException(ConvertJavaStringToUTF8(stack_trace).c_str());
  79. base::debug::DumpWithoutCrashing();
  80. SetJavaException(nullptr);
  81. }
  82. } // namespace android
  83. } // namespace base