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 362d070dc7c91050be096f97d171321be6ea963c..fe7de6b87fe7f460e1601e93879a4a28f8dfae18 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 "base/bind.h" |
#include "base/logging.h" |
@@ -16,11 +17,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" |
Tobias Sargeant
2017/01/19 17:28:03
When you rebase, you'll need
crash_reporter::Supp
michaelbai
2017/01/19 17:33:31
Thanks
|
+ << " all associated webviews, triggering application crash"; |
+ } |
+ } |
+} |
+ |
+} // namespace |
+ |
AwBrowserTerminator::AwBrowserTerminator() {} |
AwBrowserTerminator::~AwBrowserTerminator() {} |
@@ -42,18 +96,22 @@ 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)); |
- 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( |
@@ -77,10 +135,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)))); |
} |