aw_crash_reporter_client.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 "android_webview/common/crash_reporter/aw_crash_reporter_client.h"
  5. #include <stdint.h>
  6. #include "android_webview/common/aw_descriptors.h"
  7. #include "android_webview/common/aw_paths.h"
  8. #include "android_webview/common/aw_switches.h"
  9. #include "android_webview/common/crash_reporter/crash_keys.h"
  10. #include "android_webview/common_jni_headers/AwCrashReporterClient_jni.h"
  11. #include "base/android/build_info.h"
  12. #include "base/android/java_exception_reporter.h"
  13. #include "base/android/jni_android.h"
  14. #include "base/base_paths_android.h"
  15. #include "base/base_switches.h"
  16. #include "base/bind.h"
  17. #include "base/callback.h"
  18. #include "base/command_line.h"
  19. #include "base/logging.h"
  20. #include "base/no_destructor.h"
  21. #include "base/path_service.h"
  22. #include "base/scoped_native_library.h"
  23. #include "build/build_config.h"
  24. #include "components/crash/core/app/crash_reporter_client.h"
  25. #include "components/crash/core/app/crashpad.h"
  26. #include "components/version_info/android/channel_getter.h"
  27. #include "components/version_info/version_info.h"
  28. #include "components/version_info/version_info_values.h"
  29. using base::android::AttachCurrentThread;
  30. namespace android_webview {
  31. namespace {
  32. class AwCrashReporterClient : public crash_reporter::CrashReporterClient {
  33. public:
  34. AwCrashReporterClient() = default;
  35. AwCrashReporterClient(const AwCrashReporterClient&) = delete;
  36. AwCrashReporterClient& operator=(const AwCrashReporterClient&) = delete;
  37. // crash_reporter::CrashReporterClient implementation.
  38. bool IsRunningUnattended() override { return false; }
  39. bool GetCollectStatsConsent() override {
  40. // TODO(jperaza): Crashpad uses GetCollectStatsConsent() to enable or
  41. // disable upload of crash reports. However, Crashpad does not yet support
  42. // upload on Android, so this return value currently has no effect and
  43. // WebView's own uploader will determine consent before uploading. If and
  44. // when Crashpad supports upload on Android, consent can be determined here,
  45. // or WebView can continue uploading reports itself.
  46. return false;
  47. }
  48. void GetProductNameAndVersion(std::string* product_name,
  49. std::string* version,
  50. std::string* channel) override {
  51. *product_name = "AndroidWebView";
  52. *version = PRODUCT_VERSION;
  53. *channel =
  54. version_info::GetChannelString(version_info::android::GetChannel());
  55. }
  56. bool GetCrashDumpLocation(base::FilePath* crash_dir) override {
  57. return base::PathService::Get(android_webview::DIR_CRASH_DUMPS, crash_dir);
  58. }
  59. void GetSanitizationInformation(const char* const** crash_key_allowlist,
  60. void** target_module,
  61. bool* sanitize_stacks) override {
  62. *crash_key_allowlist = crash_keys::kWebViewCrashKeyAllowList;
  63. #if defined(COMPONENT_BUILD)
  64. *target_module = nullptr;
  65. #else
  66. *target_module = reinterpret_cast<void*>(&EnableCrashReporter);
  67. #endif
  68. *sanitize_stacks = true;
  69. }
  70. unsigned int GetCrashDumpPercentage() override { return 100; }
  71. bool GetBrowserProcessType(std::string* ptype) override {
  72. if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
  73. switches::kWebViewSandboxedRenderer)) {
  74. // In single process mode the renderer and browser are in the same
  75. // process. The process type is "webview" to distinguish this case,
  76. // and for backwards compatibility.
  77. *ptype = "webview";
  78. } else {
  79. // Otherwise, in multi process mode, "browser" suffices.
  80. *ptype = "browser";
  81. }
  82. return true;
  83. }
  84. bool ShouldWriteMinidumpToLog() override { return true; }
  85. bool JavaExceptionFilter(
  86. const base::android::JavaRef<jthrowable>& java_exception) {
  87. return Java_AwCrashReporterClient_stackTraceContainsWebViewCode(
  88. AttachCurrentThread(), java_exception);
  89. }
  90. static AwCrashReporterClient* Get() {
  91. static base::NoDestructor<AwCrashReporterClient> crash_reporter_client;
  92. return crash_reporter_client.get();
  93. }
  94. };
  95. #if defined(ARCH_CPU_X86_FAMILY)
  96. bool SafeToUseSignalHandler() {
  97. // N+ shared library namespacing means that we are unable to dlopen
  98. // libnativebridge (because it isn't in the NDK). However we know
  99. // that, were we able to, the tests below would pass, so just return
  100. // true here.
  101. if (base::android::BuildInfo::GetInstance()->sdk_int() >=
  102. base::android::SDK_VERSION_NOUGAT) {
  103. return true;
  104. }
  105. // On X86/64 there are binary translators that handle SIGSEGV in userspace and
  106. // may get chained after our handler - see http://crbug.com/477444
  107. // We attempt to detect this to work out when it's safe to install breakpad.
  108. // If anything doesn't seem right we assume it's not safe.
  109. // type and mangled name of android::NativeBridgeInitialized
  110. typedef bool (*InitializedFunc)();
  111. const char kInitializedSymbol[] = "_ZN7android23NativeBridgeInitializedEv";
  112. // type and mangled name of android::NativeBridgeGetVersion
  113. typedef uint32_t (*VersionFunc)();
  114. const char kVersionSymbol[] = "_ZN7android22NativeBridgeGetVersionEv";
  115. base::ScopedNativeLibrary lib_native_bridge(
  116. base::FilePath("libnativebridge.so"));
  117. if (!lib_native_bridge.is_valid()) {
  118. DLOG(WARNING) << "Couldn't load libnativebridge";
  119. return false;
  120. }
  121. InitializedFunc NativeBridgeInitialized = reinterpret_cast<InitializedFunc>(
  122. lib_native_bridge.GetFunctionPointer(kInitializedSymbol));
  123. if (NativeBridgeInitialized == nullptr) {
  124. DLOG(WARNING) << "Couldn't tell if native bridge initialized";
  125. return false;
  126. }
  127. if (!NativeBridgeInitialized()) {
  128. // Native process, safe to use breakpad.
  129. return true;
  130. }
  131. VersionFunc NativeBridgeGetVersion = reinterpret_cast<VersionFunc>(
  132. lib_native_bridge.GetFunctionPointer(kVersionSymbol));
  133. if (NativeBridgeGetVersion == nullptr) {
  134. DLOG(WARNING) << "Couldn't get native bridge version";
  135. return false;
  136. }
  137. uint32_t version = NativeBridgeGetVersion();
  138. if (version >= 2) {
  139. // Native bridge at least version 2, safe to use breakpad.
  140. return true;
  141. } else {
  142. DLOG(WARNING) << "Native bridge ver=" << version << "; too low";
  143. return false;
  144. }
  145. }
  146. #endif
  147. bool g_enabled;
  148. } // namespace
  149. void EnableCrashReporter(const std::string& process_type) {
  150. if (g_enabled) {
  151. NOTREACHED() << "EnableCrashReporter called more than once";
  152. return;
  153. }
  154. #if defined(ARCH_CPU_X86_FAMILY)
  155. if (!SafeToUseSignalHandler()) {
  156. LOG(WARNING) << "Can't use breakpad to handle WebView crashes";
  157. return;
  158. }
  159. #endif
  160. AwCrashReporterClient* client = AwCrashReporterClient::Get();
  161. crash_reporter::SetCrashReporterClient(client);
  162. crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
  163. if (process_type.empty()) {
  164. base::android::InitJavaExceptionReporter();
  165. } else {
  166. base::android::InitJavaExceptionReporterForChildProcess();
  167. }
  168. base::android::SetJavaExceptionFilter(base::BindRepeating(
  169. &AwCrashReporterClient::JavaExceptionFilter, base::Unretained(client)));
  170. g_enabled = true;
  171. }
  172. bool CrashReporterEnabled() {
  173. return g_enabled;
  174. }
  175. } // namespace android_webview