| Index: android_webview/browser/aw_browser_terminator.cc
|
| diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc
|
| index 23c42856fdf84fbebcd58067417c979c8f91c7db..34052e0a0994061b923adf220440b694cdf84f89 100644
|
| --- a/android_webview/browser/aw_browser_terminator.cc
|
| +++ b/android_webview/browser/aw_browser_terminator.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <unistd.h>
|
|
|
| +#include "android_webview/browser/aw_render_process_gone_delegate.h"
|
| #include "android_webview/common/aw_descriptors.h"
|
| #include "android_webview/common/crash_reporter/aw_microdump_crash_reporter.h"
|
| #include "base/bind.h"
|
| @@ -17,11 +18,64 @@
|
| #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 content::BrowserThread;
|
|
|
| namespace android_webview {
|
|
|
| +namespace {
|
| +
|
| +void GetAwRenderProcessGoneDelegatesForRenderProcess(
|
| + int render_process_id,
|
| + std::vector<AwRenderProcessGoneDelegate*>* delegates) {
|
| + content::RenderProcessHost* rph =
|
| + content::RenderProcessHost::FromID(render_process_id);
|
| + if (!rph)
|
| + return;
|
| +
|
| + 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) {
|
| + AwRenderProcessGoneDelegate* delegate =
|
| + AwRenderProcessGoneDelegate::FromWebContents(wc);
|
| + if (delegate)
|
| + delegates->push_back(delegate);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void OnRenderProcessGone(int child_process_id) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + std::vector<AwRenderProcessGoneDelegate*> delegates;
|
| + GetAwRenderProcessGoneDelegatesForRenderProcess(child_process_id, &delegates);
|
| + for (auto delegate : delegates)
|
| + delegate->OnRenderProcessGone(child_process_id);
|
| +}
|
| +
|
| +void OnRenderProcessGoneDetail(int child_process_id, bool crashed) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + std::vector<AwRenderProcessGoneDelegate*> delegates;
|
| + GetAwRenderProcessGoneDelegatesForRenderProcess(child_process_id, &delegates);
|
| + for (auto delegate : delegates) {
|
| + if (!delegate->OnRenderProcessGoneDetail(child_process_id, crashed)) {
|
| + // Keeps this log unchanged, CTS test uses it to detect crash.
|
| + LOG(FATAL) << "Render process's abnormal termination wasn't handled by"
|
| + << " all associated webviews, triggering application crash";
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| AwBrowserTerminator::AwBrowserTerminator() {}
|
|
|
| AwBrowserTerminator::~AwBrowserTerminator() {}
|
| @@ -43,19 +97,23 @@ void AwBrowserTerminator::OnChildStart(int child_process_id,
|
| }
|
|
|
| void AwBrowserTerminator::ProcessTerminationStatus(
|
| + int child_process_id,
|
| std::unique_ptr<base::SyncSocket> pipe) {
|
| + bool crashed = false;
|
| +
|
| + // If the child process hasn't written anything into the pipe. This implies
|
| + // that it was terminated via SIGKILL by the low memory killer.
|
| if (pipe->Peek() >= sizeof(int)) {
|
| int exit_code;
|
| pipe->Receive(&exit_code, sizeof(exit_code));
|
| crash_reporter::SuppressDumpGeneration();
|
| - LOG(FATAL) << "Renderer process crash detected (code " << exit_code
|
| - << "). Terminating browser.";
|
| - } else {
|
| - // The child process hasn't written anything into the pipe. This implies
|
| - // that it was terminated via SIGKILL by the low memory killer, and thus we
|
| - // need to perform a clean exit.
|
| - exit(0);
|
| + LOG(ERROR) << "Renderer process crash detected (code " << exit_code << ").";
|
| + crashed = true;
|
| }
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&OnRenderProcessGoneDetail, child_process_id, crashed));
|
| }
|
|
|
| void AwBrowserTerminator::OnChildExit(
|
| @@ -79,10 +137,12 @@ void AwBrowserTerminator::OnChildExit(
|
| }
|
| if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION)
|
| return;
|
| + OnRenderProcessGone(child_process_id);
|
| DCHECK(pipe->handle() != base::SyncSocket::kInvalidHandle);
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| base::Bind(&AwBrowserTerminator::ProcessTerminationStatus,
|
| + child_process_id,
|
| base::Passed(std::move(pipe))));
|
| }
|
|
|
|
|