123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- // Copyright 2016 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.
- #include "android_webview/browser/aw_browser_terminator.h"
- #include <unistd.h>
- #include <memory>
- #include "android_webview/browser/aw_browser_process.h"
- #include "android_webview/browser/aw_render_process_gone_delegate.h"
- #include "android_webview/common/aw_descriptors.h"
- #include "base/android/scoped_java_ref.h"
- #include "base/logging.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/strings/stringprintf.h"
- #include "components/crash/content/browser/crash_metrics_reporter_android.h"
- #include "components/crash/core/app/crashpad.h"
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/child_process_data.h"
- #include "content/public/browser/child_process_launcher_utils.h"
- #include "content/public/browser/notification_service.h"
- #include "content/public/browser/notification_types.h"
- #include "content/public/browser/render_process_host.h"
- #include "content/public/browser/render_view_host.h"
- #include "content/public/browser/render_widget_host.h"
- #include "content/public/browser/render_widget_host_iterator.h"
- #include "content/public/browser/web_contents.h"
- using base::android::ScopedJavaGlobalRef;
- using content::BrowserThread;
- namespace android_webview {
- namespace {
- constexpr char kRenderProcessGoneHistogramName[] =
- "Android.WebView.OnRenderProcessGoneResult";
- // These values are persisted to logs. Entries should not be renumbered and
- // numeric values should never be reused.
- enum class RenderProcessGoneResult {
- kJavaException = 0,
- kCrashNotHandled = 1,
- kKillNotHandled = 2,
- // kAllWebViewsHandled = 3, // Deprecated: use kCrashHandled/kKillHandled
- kCrashHandled = 4,
- kKillHandled = 5,
- kMaxValue = kKillHandled,
- };
- void GetJavaWebContentsForRenderProcess(
- content::RenderProcessHost* rph,
- std::vector<ScopedJavaGlobalRef<jobject>>* java_web_contents) {
- std::unique_ptr<content::RenderWidgetHostIterator> widgets(
- content::RenderWidgetHost::GetRenderWidgetHosts());
- while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
- content::RenderViewHost* view = content::RenderViewHost::From(widget);
- if (view && rph == view->GetProcess()) {
- content::WebContents* wc = content::WebContents::FromRenderViewHost(view);
- if (wc) {
- java_web_contents->push_back(static_cast<ScopedJavaGlobalRef<jobject>>(
- wc->GetJavaWebContents()));
- }
- }
- }
- }
- void OnRenderProcessGone(
- const std::vector<ScopedJavaGlobalRef<jobject>>& java_web_contents,
- base::ProcessId child_process_pid,
- bool crashed) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (auto& java_wc : java_web_contents) {
- content::WebContents* wc =
- content::WebContents::FromJavaWebContents(java_wc);
- if (!wc)
- continue;
- AwRenderProcessGoneDelegate* delegate =
- AwRenderProcessGoneDelegate::FromWebContents(wc);
- if (!delegate)
- continue;
- switch (delegate->OnRenderProcessGone(child_process_pid, crashed)) {
- case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kException:
- base::UmaHistogramEnumeration(kRenderProcessGoneHistogramName,
- RenderProcessGoneResult::kJavaException);
- // Let the exception propagate back to the message loop.
- base::CurrentUIThread::Get()->Abort();
- return;
- case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kUnhandled:
- if (crashed) {
- base::UmaHistogramEnumeration(
- kRenderProcessGoneHistogramName,
- RenderProcessGoneResult::kCrashNotHandled);
- // Keeps this log unchanged, CTS test uses it to detect crash.
- std::string message = base::StringPrintf(
- "Render process (%d)'s crash wasn't handled by all associated "
- "webviews, triggering application crash.",
- child_process_pid);
- crash_reporter::CrashWithoutDumping(message);
- } else {
- base::UmaHistogramEnumeration(
- kRenderProcessGoneHistogramName,
- RenderProcessGoneResult::kKillNotHandled);
- // The render process was most likely killed for OOM or switching
- // WebView provider, to make WebView backward compatible, kills the
- // browser process instead of triggering crash.
- LOG(ERROR) << "Render process (" << child_process_pid << ") kill (OOM"
- << " or update) wasn't handed by all associated webviews,"
- << " killing application.";
- kill(getpid(), SIGKILL);
- }
- NOTREACHED();
- break;
- case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kHandled:
- // Don't log UMA yet. This WebView may be handled, but we need to wait
- // until we're out of the loop to know if all WebViews were handled.
- break;
- }
- }
- // If we reached this point, it means the crash was handled for all WebViews.
- if (crashed) {
- base::UmaHistogramEnumeration(kRenderProcessGoneHistogramName,
- RenderProcessGoneResult::kCrashHandled);
- } else {
- base::UmaHistogramEnumeration(kRenderProcessGoneHistogramName,
- RenderProcessGoneResult::kKillHandled);
- }
- // By this point we have moved the minidump to the crash directory, so it can
- // now be copied and uploaded.
- AwBrowserProcess::TriggerMinidumpUploading();
- }
- } // namespace
- AwBrowserTerminator::AwBrowserTerminator() = default;
- AwBrowserTerminator::~AwBrowserTerminator() = default;
- void AwBrowserTerminator::OnChildExit(
- const crash_reporter::ChildExitObserver::TerminationInfo& info) {
- content::RenderProcessHost* rph =
- content::RenderProcessHost::FromID(info.process_host_id);
- crash_reporter::CrashMetricsReporter::GetInstance()->ChildProcessExited(info);
- if (info.normal_termination) {
- return;
- }
- LOG(ERROR) << "Renderer process (" << info.pid << ") crash detected (code "
- << info.crash_signo << ").";
- std::vector<ScopedJavaGlobalRef<jobject>> java_web_contents;
- GetJavaWebContentsForRenderProcess(rph, &java_web_contents);
- content::GetUIThreadTaskRunner({base::TaskPriority::HIGHEST})
- ->PostTask(FROM_HERE,
- base::BindOnce(OnRenderProcessGone, java_web_contents,
- info.pid, info.is_crashed()));
- }
- } // namespace android_webview
|