aw_browser_terminator.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2016 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/browser/aw_browser_terminator.h"
  5. #include <unistd.h>
  6. #include <memory>
  7. #include "android_webview/browser/aw_browser_process.h"
  8. #include "android_webview/browser/aw_render_process_gone_delegate.h"
  9. #include "android_webview/common/aw_descriptors.h"
  10. #include "base/android/scoped_java_ref.h"
  11. #include "base/logging.h"
  12. #include "base/metrics/histogram_functions.h"
  13. #include "base/strings/stringprintf.h"
  14. #include "components/crash/content/browser/crash_metrics_reporter_android.h"
  15. #include "components/crash/core/app/crashpad.h"
  16. #include "content/public/browser/browser_task_traits.h"
  17. #include "content/public/browser/browser_thread.h"
  18. #include "content/public/browser/child_process_data.h"
  19. #include "content/public/browser/child_process_launcher_utils.h"
  20. #include "content/public/browser/notification_service.h"
  21. #include "content/public/browser/notification_types.h"
  22. #include "content/public/browser/render_process_host.h"
  23. #include "content/public/browser/render_view_host.h"
  24. #include "content/public/browser/render_widget_host.h"
  25. #include "content/public/browser/render_widget_host_iterator.h"
  26. #include "content/public/browser/web_contents.h"
  27. using base::android::ScopedJavaGlobalRef;
  28. using content::BrowserThread;
  29. namespace android_webview {
  30. namespace {
  31. constexpr char kRenderProcessGoneHistogramName[] =
  32. "Android.WebView.OnRenderProcessGoneResult";
  33. // These values are persisted to logs. Entries should not be renumbered and
  34. // numeric values should never be reused.
  35. enum class RenderProcessGoneResult {
  36. kJavaException = 0,
  37. kCrashNotHandled = 1,
  38. kKillNotHandled = 2,
  39. // kAllWebViewsHandled = 3, // Deprecated: use kCrashHandled/kKillHandled
  40. kCrashHandled = 4,
  41. kKillHandled = 5,
  42. kMaxValue = kKillHandled,
  43. };
  44. void GetJavaWebContentsForRenderProcess(
  45. content::RenderProcessHost* rph,
  46. std::vector<ScopedJavaGlobalRef<jobject>>* java_web_contents) {
  47. std::unique_ptr<content::RenderWidgetHostIterator> widgets(
  48. content::RenderWidgetHost::GetRenderWidgetHosts());
  49. while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
  50. content::RenderViewHost* view = content::RenderViewHost::From(widget);
  51. if (view && rph == view->GetProcess()) {
  52. content::WebContents* wc = content::WebContents::FromRenderViewHost(view);
  53. if (wc) {
  54. java_web_contents->push_back(static_cast<ScopedJavaGlobalRef<jobject>>(
  55. wc->GetJavaWebContents()));
  56. }
  57. }
  58. }
  59. }
  60. void OnRenderProcessGone(
  61. const std::vector<ScopedJavaGlobalRef<jobject>>& java_web_contents,
  62. base::ProcessId child_process_pid,
  63. bool crashed) {
  64. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  65. for (auto& java_wc : java_web_contents) {
  66. content::WebContents* wc =
  67. content::WebContents::FromJavaWebContents(java_wc);
  68. if (!wc)
  69. continue;
  70. AwRenderProcessGoneDelegate* delegate =
  71. AwRenderProcessGoneDelegate::FromWebContents(wc);
  72. if (!delegate)
  73. continue;
  74. switch (delegate->OnRenderProcessGone(child_process_pid, crashed)) {
  75. case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kException:
  76. base::UmaHistogramEnumeration(kRenderProcessGoneHistogramName,
  77. RenderProcessGoneResult::kJavaException);
  78. // Let the exception propagate back to the message loop.
  79. base::CurrentUIThread::Get()->Abort();
  80. return;
  81. case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kUnhandled:
  82. if (crashed) {
  83. base::UmaHistogramEnumeration(
  84. kRenderProcessGoneHistogramName,
  85. RenderProcessGoneResult::kCrashNotHandled);
  86. // Keeps this log unchanged, CTS test uses it to detect crash.
  87. std::string message = base::StringPrintf(
  88. "Render process (%d)'s crash wasn't handled by all associated "
  89. "webviews, triggering application crash.",
  90. child_process_pid);
  91. crash_reporter::CrashWithoutDumping(message);
  92. } else {
  93. base::UmaHistogramEnumeration(
  94. kRenderProcessGoneHistogramName,
  95. RenderProcessGoneResult::kKillNotHandled);
  96. // The render process was most likely killed for OOM or switching
  97. // WebView provider, to make WebView backward compatible, kills the
  98. // browser process instead of triggering crash.
  99. LOG(ERROR) << "Render process (" << child_process_pid << ") kill (OOM"
  100. << " or update) wasn't handed by all associated webviews,"
  101. << " killing application.";
  102. kill(getpid(), SIGKILL);
  103. }
  104. NOTREACHED();
  105. break;
  106. case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kHandled:
  107. // Don't log UMA yet. This WebView may be handled, but we need to wait
  108. // until we're out of the loop to know if all WebViews were handled.
  109. break;
  110. }
  111. }
  112. // If we reached this point, it means the crash was handled for all WebViews.
  113. if (crashed) {
  114. base::UmaHistogramEnumeration(kRenderProcessGoneHistogramName,
  115. RenderProcessGoneResult::kCrashHandled);
  116. } else {
  117. base::UmaHistogramEnumeration(kRenderProcessGoneHistogramName,
  118. RenderProcessGoneResult::kKillHandled);
  119. }
  120. // By this point we have moved the minidump to the crash directory, so it can
  121. // now be copied and uploaded.
  122. AwBrowserProcess::TriggerMinidumpUploading();
  123. }
  124. } // namespace
  125. AwBrowserTerminator::AwBrowserTerminator() = default;
  126. AwBrowserTerminator::~AwBrowserTerminator() = default;
  127. void AwBrowserTerminator::OnChildExit(
  128. const crash_reporter::ChildExitObserver::TerminationInfo& info) {
  129. content::RenderProcessHost* rph =
  130. content::RenderProcessHost::FromID(info.process_host_id);
  131. crash_reporter::CrashMetricsReporter::GetInstance()->ChildProcessExited(info);
  132. if (info.normal_termination) {
  133. return;
  134. }
  135. LOG(ERROR) << "Renderer process (" << info.pid << ") crash detected (code "
  136. << info.crash_signo << ").";
  137. std::vector<ScopedJavaGlobalRef<jobject>> java_web_contents;
  138. GetJavaWebContentsForRenderProcess(rph, &java_web_contents);
  139. content::GetUIThreadTaskRunner({base::TaskPriority::HIGHEST})
  140. ->PostTask(FROM_HERE,
  141. base::BindOnce(OnRenderProcessGone, java_web_contents,
  142. info.pid, info.is_crashed()));
  143. }
  144. } // namespace android_webview